mirror of https://git.suyu.dev/suyu/suyu
gl_shader_cache: Check previous pipeline before checking hash map
Port optimization from Vulkan.
This commit is contained in:
parent
218dedca1f
commit
f5db8c7440
|
@ -184,17 +184,15 @@ bool GraphicsPipelineKey::operator==(const GraphicsPipelineKey& rhs) const noexc
|
||||||
return std::memcmp(this, &rhs, Size()) == 0;
|
return std::memcmp(this, &rhs, Size()) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_cache_,
|
GraphicsPipeline::GraphicsPipeline(
|
||||||
BufferCache& buffer_cache_, Tegra::MemoryManager& gpu_memory_,
|
const Device& device, TextureCache& texture_cache_, BufferCache& buffer_cache_,
|
||||||
Tegra::Engines::Maxwell3D& maxwell3d_,
|
Tegra::MemoryManager& gpu_memory_, Tegra::Engines::Maxwell3D& maxwell3d_,
|
||||||
ProgramManager& program_manager_, StateTracker& state_tracker_,
|
ProgramManager& program_manager_, StateTracker& state_tracker_, ShaderWorker* thread_worker,
|
||||||
ShaderWorker* thread_worker,
|
VideoCore::ShaderNotify* shader_notify, std::array<std::string, 5> sources,
|
||||||
VideoCore::ShaderNotify* shader_notify,
|
const std::array<const Shader::Info*, 5>& infos, const GraphicsPipelineKey& key_)
|
||||||
std::array<std::string, 5> sources,
|
: texture_cache{texture_cache_}, buffer_cache{buffer_cache_},
|
||||||
const std::array<const Shader::Info*, 5>& infos,
|
gpu_memory{gpu_memory_}, maxwell3d{maxwell3d_}, program_manager{program_manager_},
|
||||||
const VideoCommon::TransformFeedbackState* xfb_state)
|
state_tracker{state_tracker_}, key{key_} {
|
||||||
: texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, gpu_memory{gpu_memory_},
|
|
||||||
maxwell3d{maxwell3d_}, program_manager{program_manager_}, state_tracker{state_tracker_} {
|
|
||||||
if (shader_notify) {
|
if (shader_notify) {
|
||||||
shader_notify->MarkShaderBuilding();
|
shader_notify->MarkShaderBuilding();
|
||||||
}
|
}
|
||||||
|
@ -241,10 +239,10 @@ GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_c
|
||||||
writes_global_memory &= !use_storage_buffers;
|
writes_global_memory &= !use_storage_buffers;
|
||||||
configure_func = ConfigureFunc(stage_infos, enabled_stages_mask);
|
configure_func = ConfigureFunc(stage_infos, enabled_stages_mask);
|
||||||
|
|
||||||
if (assembly_shaders && xfb_state) {
|
if (assembly_shaders && key.xfb_enabled) {
|
||||||
GenerateTransformFeedbackState(*xfb_state);
|
GenerateTransformFeedbackState();
|
||||||
}
|
}
|
||||||
auto func{[this, device, sources, shader_notify, xfb_state](ShaderContext::Context*) mutable {
|
auto func{[this, device, sources, shader_notify](ShaderContext::Context*) mutable {
|
||||||
if (!device.UseAssemblyShaders()) {
|
if (!device.UseAssemblyShaders()) {
|
||||||
program.handle = glCreateProgram();
|
program.handle = glCreateProgram();
|
||||||
}
|
}
|
||||||
|
@ -505,15 +503,14 @@ void GraphicsPipeline::ConfigureTransformFeedbackImpl() const {
|
||||||
xfb_streams.data(), GL_INTERLEAVED_ATTRIBS);
|
xfb_streams.data(), GL_INTERLEAVED_ATTRIBS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsPipeline::GenerateTransformFeedbackState(
|
void GraphicsPipeline::GenerateTransformFeedbackState() {
|
||||||
const VideoCommon::TransformFeedbackState& xfb_state) {
|
|
||||||
// TODO(Rodrigo): Inject SKIP_COMPONENTS*_NV when required. An unimplemented message will signal
|
// TODO(Rodrigo): Inject SKIP_COMPONENTS*_NV when required. An unimplemented message will signal
|
||||||
// when this is required.
|
// when this is required.
|
||||||
GLint* cursor{xfb_attribs.data()};
|
GLint* cursor{xfb_attribs.data()};
|
||||||
GLint* current_stream{xfb_streams.data()};
|
GLint* current_stream{xfb_streams.data()};
|
||||||
|
|
||||||
for (size_t feedback = 0; feedback < Maxwell::NumTransformFeedbackBuffers; ++feedback) {
|
for (size_t feedback = 0; feedback < Maxwell::NumTransformFeedbackBuffers; ++feedback) {
|
||||||
const auto& layout = xfb_state.layouts[feedback];
|
const auto& layout = key.xfb_state.layouts[feedback];
|
||||||
UNIMPLEMENTED_IF_MSG(layout.stride != layout.varying_count * 4, "Stride padding");
|
UNIMPLEMENTED_IF_MSG(layout.stride != layout.varying_count * 4, "Stride padding");
|
||||||
if (layout.varying_count == 0) {
|
if (layout.varying_count == 0) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -528,7 +525,7 @@ void GraphicsPipeline::GenerateTransformFeedbackState(
|
||||||
}
|
}
|
||||||
++current_stream;
|
++current_stream;
|
||||||
|
|
||||||
const auto& locations = xfb_state.varyings[feedback];
|
const auto& locations = key.xfb_state.varyings[feedback];
|
||||||
std::optional<u8> current_index;
|
std::optional<u8> current_index;
|
||||||
for (u32 offset = 0; offset < layout.varying_count; ++offset) {
|
for (u32 offset = 0; offset < layout.varying_count; ++offset) {
|
||||||
const u8 location = locations[offset];
|
const u8 location = locations[offset];
|
||||||
|
|
|
@ -73,7 +73,7 @@ public:
|
||||||
ShaderWorker* thread_worker, VideoCore::ShaderNotify* shader_notify,
|
ShaderWorker* thread_worker, VideoCore::ShaderNotify* shader_notify,
|
||||||
std::array<std::string, 5> sources,
|
std::array<std::string, 5> sources,
|
||||||
const std::array<const Shader::Info*, 5>& infos,
|
const std::array<const Shader::Info*, 5>& infos,
|
||||||
const VideoCommon::TransformFeedbackState* xfb_state);
|
const GraphicsPipelineKey& key_);
|
||||||
|
|
||||||
void Configure(bool is_indexed) {
|
void Configure(bool is_indexed) {
|
||||||
configure_func(this, is_indexed);
|
configure_func(this, is_indexed);
|
||||||
|
@ -85,6 +85,10 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const GraphicsPipelineKey& Key() const noexcept {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool WritesGlobalMemory() const noexcept {
|
[[nodiscard]] bool WritesGlobalMemory() const noexcept {
|
||||||
return writes_global_memory;
|
return writes_global_memory;
|
||||||
}
|
}
|
||||||
|
@ -106,7 +110,7 @@ private:
|
||||||
|
|
||||||
void ConfigureTransformFeedbackImpl() const;
|
void ConfigureTransformFeedbackImpl() const;
|
||||||
|
|
||||||
void GenerateTransformFeedbackState(const VideoCommon::TransformFeedbackState& xfb_state);
|
void GenerateTransformFeedbackState();
|
||||||
|
|
||||||
TextureCache& texture_cache;
|
TextureCache& texture_cache;
|
||||||
BufferCache& buffer_cache;
|
BufferCache& buffer_cache;
|
||||||
|
@ -114,6 +118,7 @@ private:
|
||||||
Tegra::Engines::Maxwell3D& maxwell3d;
|
Tegra::Engines::Maxwell3D& maxwell3d;
|
||||||
ProgramManager& program_manager;
|
ProgramManager& program_manager;
|
||||||
StateTracker& state_tracker;
|
StateTracker& state_tracker;
|
||||||
|
const GraphicsPipelineKey key;
|
||||||
|
|
||||||
void (*configure_func)(GraphicsPipeline*, bool){};
|
void (*configure_func)(GraphicsPipeline*, bool){};
|
||||||
|
|
||||||
|
|
|
@ -298,6 +298,7 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
|
||||||
|
|
||||||
GraphicsPipeline* ShaderCache::CurrentGraphicsPipeline() {
|
GraphicsPipeline* ShaderCache::CurrentGraphicsPipeline() {
|
||||||
if (!RefreshStages(graphics_key.unique_hashes)) {
|
if (!RefreshStages(graphics_key.unique_hashes)) {
|
||||||
|
current_pipeline = nullptr;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
const auto& regs{maxwell3d.regs};
|
const auto& regs{maxwell3d.regs};
|
||||||
|
@ -313,15 +314,23 @@ GraphicsPipeline* ShaderCache::CurrentGraphicsPipeline() {
|
||||||
if (graphics_key.xfb_enabled) {
|
if (graphics_key.xfb_enabled) {
|
||||||
SetXfbState(graphics_key.xfb_state, regs);
|
SetXfbState(graphics_key.xfb_state, regs);
|
||||||
}
|
}
|
||||||
const auto [pair, is_new]{graphics_cache.try_emplace(graphics_key)};
|
if (current_pipeline && graphics_key == current_pipeline->Key()) {
|
||||||
auto& program{pair->second};
|
return current_pipeline->IsBuilt() ? current_pipeline : nullptr;
|
||||||
if (is_new) {
|
|
||||||
program = CreateGraphicsPipeline();
|
|
||||||
}
|
}
|
||||||
if (!program || !program->IsBuilt()) {
|
return CurrentGraphicsPipelineSlowPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphicsPipeline* ShaderCache::CurrentGraphicsPipelineSlowPath() {
|
||||||
|
const auto [pair, is_new]{graphics_cache.try_emplace(graphics_key)};
|
||||||
|
auto& pipeline{pair->second};
|
||||||
|
if (is_new) {
|
||||||
|
pipeline = CreateGraphicsPipeline();
|
||||||
|
}
|
||||||
|
current_pipeline = pipeline.get();
|
||||||
|
if (!pipeline || !pipeline->IsBuilt()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return program.get();
|
return pipeline.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
ComputePipeline* ShaderCache::CurrentComputePipeline() {
|
ComputePipeline* ShaderCache::CurrentComputePipeline() {
|
||||||
|
@ -432,8 +441,7 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline(
|
||||||
auto* const thread_worker{build_in_parallel ? workers.get() : nullptr};
|
auto* const thread_worker{build_in_parallel ? workers.get() : nullptr};
|
||||||
return std::make_unique<GraphicsPipeline>(device, texture_cache, buffer_cache, gpu_memory,
|
return std::make_unique<GraphicsPipeline>(device, texture_cache, buffer_cache, gpu_memory,
|
||||||
maxwell3d, program_manager, state_tracker,
|
maxwell3d, program_manager, state_tracker,
|
||||||
thread_worker, &shader_notify, sources, infos,
|
thread_worker, &shader_notify, sources, infos, key);
|
||||||
key.xfb_enabled != 0 ? &key.xfb_state : nullptr);
|
|
||||||
|
|
||||||
} catch (Shader::Exception& exception) {
|
} catch (Shader::Exception& exception) {
|
||||||
LOG_ERROR(Render_OpenGL, "{}", exception.what());
|
LOG_ERROR(Render_OpenGL, "{}", exception.what());
|
||||||
|
|
|
@ -53,6 +53,8 @@ public:
|
||||||
[[nodiscard]] ComputePipeline* CurrentComputePipeline();
|
[[nodiscard]] ComputePipeline* CurrentComputePipeline();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
GraphicsPipeline* CurrentGraphicsPipelineSlowPath();
|
||||||
|
|
||||||
std::unique_ptr<GraphicsPipeline> CreateGraphicsPipeline();
|
std::unique_ptr<GraphicsPipeline> CreateGraphicsPipeline();
|
||||||
|
|
||||||
std::unique_ptr<GraphicsPipeline> CreateGraphicsPipeline(
|
std::unique_ptr<GraphicsPipeline> CreateGraphicsPipeline(
|
||||||
|
@ -75,9 +77,10 @@ private:
|
||||||
ProgramManager& program_manager;
|
ProgramManager& program_manager;
|
||||||
StateTracker& state_tracker;
|
StateTracker& state_tracker;
|
||||||
VideoCore::ShaderNotify& shader_notify;
|
VideoCore::ShaderNotify& shader_notify;
|
||||||
|
const bool use_asynchronous_shaders;
|
||||||
|
|
||||||
GraphicsPipelineKey graphics_key{};
|
GraphicsPipelineKey graphics_key{};
|
||||||
const bool use_asynchronous_shaders;
|
GraphicsPipeline* current_pipeline{};
|
||||||
|
|
||||||
ShaderContext::ShaderPools main_pools;
|
ShaderContext::ShaderPools main_pools;
|
||||||
std::unordered_map<GraphicsPipelineKey, std::unique_ptr<GraphicsPipeline>> graphics_cache;
|
std::unordered_map<GraphicsPipelineKey, std::unique_ptr<GraphicsPipeline>> graphics_cache;
|
||||||
|
|
|
@ -146,12 +146,11 @@ private:
|
||||||
BufferCache& buffer_cache;
|
BufferCache& buffer_cache;
|
||||||
TextureCache& texture_cache;
|
TextureCache& texture_cache;
|
||||||
VideoCore::ShaderNotify& shader_notify;
|
VideoCore::ShaderNotify& shader_notify;
|
||||||
|
bool use_asynchronous_shaders{};
|
||||||
|
|
||||||
GraphicsPipelineCacheKey graphics_key{};
|
GraphicsPipelineCacheKey graphics_key{};
|
||||||
GraphicsPipeline* current_pipeline{};
|
GraphicsPipeline* current_pipeline{};
|
||||||
|
|
||||||
bool use_asynchronous_shaders{};
|
|
||||||
|
|
||||||
std::unordered_map<ComputePipelineCacheKey, std::unique_ptr<ComputePipeline>> compute_cache;
|
std::unordered_map<ComputePipelineCacheKey, std::unique_ptr<ComputePipeline>> compute_cache;
|
||||||
std::unordered_map<GraphicsPipelineCacheKey, std::unique_ptr<GraphicsPipeline>> graphics_cache;
|
std::unordered_map<GraphicsPipelineCacheKey, std::unique_ptr<GraphicsPipeline>> graphics_cache;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue