gl_shader_cache: Check previous pipeline before checking hash map
Port optimization from Vulkan.
This commit is contained in:
		| @@ -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; | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user