mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-29 16:45:29 +03:00
Implement simple pipeline transition cache
Avoids the need to hash PipelineState when we can guess the pipeline that will be used next. This could very easily be optimised in the future with generational, usage-based caching if necessary.
This commit is contained in:
parent
302b2fcc3f
commit
388cff3353
@ -505,13 +505,27 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
Pipeline::Pipeline(InterconnectContext &ctx, const PackedPipelineState &packedState, const std::array<ShaderBinary, engine::PipelineCount> &shaderBinaries, span<TextureView *> colorAttachments, TextureView *depthAttachment)
|
Pipeline::Pipeline(InterconnectContext &ctx, const PackedPipelineState &packedState, const std::array<ShaderBinary, engine::PipelineCount> &shaderBinaries, span<TextureView *> colorAttachments, TextureView *depthAttachment)
|
||||||
: shaderStages{MakePipelineShaders(ctx, packedState, shaderBinaries)},
|
: shaderStages{MakePipelineShaders(ctx, packedState, shaderBinaries)},
|
||||||
descriptorSetLayoutBindings{MakePipelineDescriptorSetLayoutBindings(shaderStages)},
|
descriptorSetLayoutBindings{MakePipelineDescriptorSetLayoutBindings(shaderStages)},
|
||||||
compiledPipeline{MakeCompiledPipeline(ctx, packedState, shaderStages, descriptorSetLayoutBindings, colorAttachments, depthAttachment)} {
|
compiledPipeline{MakeCompiledPipeline(ctx, packedState, shaderStages, descriptorSetLayoutBindings, colorAttachments, depthAttachment)},
|
||||||
|
sourcePackedState{packedState} {
|
||||||
}
|
}
|
||||||
|
|
||||||
Pipeline *Pipeline::LookupNext(const PackedPipelineState &packedState) {
|
Pipeline *Pipeline::LookupNext(const PackedPipelineState &packedState) {
|
||||||
|
auto it{std::find_if(transitionCache.begin(), transitionCache.end(), [&packedState](auto pipeline) {
|
||||||
|
if (pipeline && pipeline->sourcePackedState == packedState)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
})};
|
||||||
|
|
||||||
|
if (it != transitionCache.end())
|
||||||
|
return *it;
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pipeline::AddTransition(const PackedPipelineState &packedState, Pipeline *next) {}
|
void Pipeline::AddTransition(Pipeline *next) {
|
||||||
|
transitionCache[transitionCacheNextIdx] = next;
|
||||||
|
transitionCacheNextIdx = (transitionCacheNextIdx + 1) % transitionCache.size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,12 +32,17 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
std::vector<vk::DescriptorSetLayoutBinding> descriptorSetLayoutBindings;
|
std::vector<vk::DescriptorSetLayoutBinding> descriptorSetLayoutBindings;
|
||||||
cache::GraphicsPipelineCache::CompiledPipeline compiledPipeline;
|
cache::GraphicsPipelineCache::CompiledPipeline compiledPipeline;
|
||||||
|
|
||||||
|
std::array<Pipeline *, 4> transitionCache{};
|
||||||
|
size_t transitionCacheNextIdx{};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
PackedPipelineState sourcePackedState;
|
||||||
|
|
||||||
Pipeline(InterconnectContext &ctx, const PackedPipelineState &packedState, const std::array<ShaderBinary, engine::PipelineCount> &shaderBinaries, span<TextureView *> colorAttachments, TextureView *depthAttachment);
|
Pipeline(InterconnectContext &ctx, const PackedPipelineState &packedState, const std::array<ShaderBinary, engine::PipelineCount> &shaderBinaries, span<TextureView *> colorAttachments, TextureView *depthAttachment);
|
||||||
|
|
||||||
Pipeline *LookupNext(const PackedPipelineState &packedState);
|
Pipeline *LookupNext(const PackedPipelineState &packedState);
|
||||||
|
|
||||||
void AddTransition(const PackedPipelineState &packedState, Pipeline *next);
|
void AddTransition(Pipeline *next);
|
||||||
};
|
};
|
||||||
|
|
||||||
class PipelineManager {
|
class PipelineManager {
|
||||||
|
@ -294,6 +294,15 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
entry->cache.insert({blockMapping.data() + blockOffset, CacheEntry{binary, hash}});
|
entry->cache.insert({blockMapping.data() + blockOffset, CacheEntry{binary, hash}});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: this needs to be checked every draw irresspective of pipeline dirtiness
|
||||||
|
bool PipelineStageState::Refresh(InterconnectContext &ctx) {
|
||||||
|
std::scoped_lock lock{trapMutex};
|
||||||
|
if (entry && entry->dirty)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
PipelineStageState::~PipelineStageState() {
|
PipelineStageState::~PipelineStageState() {
|
||||||
std::scoped_lock lock{trapMutex};
|
std::scoped_lock lock{trapMutex};
|
||||||
//for (const auto &mirror : mirrorMap)
|
//for (const auto &mirror : mirrorMap)
|
||||||
@ -504,10 +513,11 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
pipeline = newPipeline;
|
pipeline = newPipeline;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto newPipeline{pipelineManager.FindOrCreate(ctx, packedState, shaderBinaries, colorAttachments, depthAttachment)};
|
auto newPipeline{pipelineManager.FindOrCreate(ctx, packedState, shaderBinaries, colorAttachments, depthAttachment)};
|
||||||
pipeline->AddTransition(packedState, newPipeline);
|
if (pipeline)
|
||||||
|
pipeline->AddTransition(newPipeline);
|
||||||
pipeline = newPipeline;
|
pipeline = newPipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
void Flush(InterconnectContext &ctx, PackedPipelineState &packedState);
|
void Flush(InterconnectContext &ctx, PackedPipelineState &packedState);
|
||||||
};
|
};
|
||||||
|
|
||||||
class PipelineStageState : dirty::ManualDirty {
|
class PipelineStageState : dirty::RefreshableManualDirty {
|
||||||
public:
|
public:
|
||||||
struct EngineRegisters {
|
struct EngineRegisters {
|
||||||
const engine::Pipeline &pipeline;
|
const engine::Pipeline &pipeline;
|
||||||
@ -100,6 +100,8 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
~PipelineStageState();
|
~PipelineStageState();
|
||||||
|
|
||||||
void Flush(InterconnectContext &ctx);
|
void Flush(InterconnectContext &ctx);
|
||||||
|
|
||||||
|
bool Refresh(InterconnectContext &ctx);
|
||||||
};
|
};
|
||||||
|
|
||||||
class VertexInputState : dirty::ManualDirty {
|
class VertexInputState : dirty::ManualDirty {
|
||||||
|
Loading…
Reference in New Issue
Block a user