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; | ||||
| } | ||||
|  | ||||
| GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_cache_, | ||||
|                                    BufferCache& buffer_cache_, Tegra::MemoryManager& gpu_memory_, | ||||
|                                    Tegra::Engines::Maxwell3D& maxwell3d_, | ||||
|                                    ProgramManager& program_manager_, StateTracker& state_tracker_, | ||||
|                                    ShaderWorker* thread_worker, | ||||
|                                    VideoCore::ShaderNotify* shader_notify, | ||||
|                                    std::array<std::string, 5> sources, | ||||
|                                    const std::array<const Shader::Info*, 5>& infos, | ||||
|                                    const VideoCommon::TransformFeedbackState* xfb_state) | ||||
|     : texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, gpu_memory{gpu_memory_}, | ||||
|       maxwell3d{maxwell3d_}, program_manager{program_manager_}, state_tracker{state_tracker_} { | ||||
| GraphicsPipeline::GraphicsPipeline( | ||||
|     const Device& device, TextureCache& texture_cache_, BufferCache& buffer_cache_, | ||||
|     Tegra::MemoryManager& gpu_memory_, Tegra::Engines::Maxwell3D& maxwell3d_, | ||||
|     ProgramManager& program_manager_, StateTracker& state_tracker_, ShaderWorker* thread_worker, | ||||
|     VideoCore::ShaderNotify* shader_notify, std::array<std::string, 5> sources, | ||||
|     const std::array<const Shader::Info*, 5>& infos, const GraphicsPipelineKey& key_) | ||||
|     : texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, | ||||
|       gpu_memory{gpu_memory_}, maxwell3d{maxwell3d_}, program_manager{program_manager_}, | ||||
|       state_tracker{state_tracker_}, key{key_} { | ||||
|     if (shader_notify) { | ||||
|         shader_notify->MarkShaderBuilding(); | ||||
|     } | ||||
| @@ -241,10 +239,10 @@ GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_c | ||||
|     writes_global_memory &= !use_storage_buffers; | ||||
|     configure_func = ConfigureFunc(stage_infos, enabled_stages_mask); | ||||
|  | ||||
|     if (assembly_shaders && xfb_state) { | ||||
|         GenerateTransformFeedbackState(*xfb_state); | ||||
|     if (assembly_shaders && key.xfb_enabled) { | ||||
|         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()) { | ||||
|             program.handle = glCreateProgram(); | ||||
|         } | ||||
| @@ -505,15 +503,14 @@ void GraphicsPipeline::ConfigureTransformFeedbackImpl() const { | ||||
|                                        xfb_streams.data(), GL_INTERLEAVED_ATTRIBS); | ||||
| } | ||||
|  | ||||
| void GraphicsPipeline::GenerateTransformFeedbackState( | ||||
|     const VideoCommon::TransformFeedbackState& xfb_state) { | ||||
| void GraphicsPipeline::GenerateTransformFeedbackState() { | ||||
|     // TODO(Rodrigo): Inject SKIP_COMPONENTS*_NV when required. An unimplemented message will signal | ||||
|     // when this is required. | ||||
|     GLint* cursor{xfb_attribs.data()}; | ||||
|     GLint* current_stream{xfb_streams.data()}; | ||||
|  | ||||
|     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"); | ||||
|         if (layout.varying_count == 0) { | ||||
|             continue; | ||||
| @@ -528,7 +525,7 @@ void GraphicsPipeline::GenerateTransformFeedbackState( | ||||
|         } | ||||
|         ++current_stream; | ||||
|  | ||||
|         const auto& locations = xfb_state.varyings[feedback]; | ||||
|         const auto& locations = key.xfb_state.varyings[feedback]; | ||||
|         std::optional<u8> current_index; | ||||
|         for (u32 offset = 0; offset < layout.varying_count; ++offset) { | ||||
|             const u8 location = locations[offset]; | ||||
|   | ||||
| @@ -73,7 +73,7 @@ public: | ||||
|                               ShaderWorker* thread_worker, VideoCore::ShaderNotify* shader_notify, | ||||
|                               std::array<std::string, 5> sources, | ||||
|                               const std::array<const Shader::Info*, 5>& infos, | ||||
|                               const VideoCommon::TransformFeedbackState* xfb_state); | ||||
|                               const GraphicsPipelineKey& key_); | ||||
|  | ||||
|     void Configure(bool 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 { | ||||
|         return writes_global_memory; | ||||
|     } | ||||
| @@ -106,7 +110,7 @@ private: | ||||
|  | ||||
|     void ConfigureTransformFeedbackImpl() const; | ||||
|  | ||||
|     void GenerateTransformFeedbackState(const VideoCommon::TransformFeedbackState& xfb_state); | ||||
|     void GenerateTransformFeedbackState(); | ||||
|  | ||||
|     TextureCache& texture_cache; | ||||
|     BufferCache& buffer_cache; | ||||
| @@ -114,6 +118,7 @@ private: | ||||
|     Tegra::Engines::Maxwell3D& maxwell3d; | ||||
|     ProgramManager& program_manager; | ||||
|     StateTracker& state_tracker; | ||||
|     const GraphicsPipelineKey key; | ||||
|  | ||||
|     void (*configure_func)(GraphicsPipeline*, bool){}; | ||||
|  | ||||
|   | ||||
| @@ -298,6 +298,7 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading, | ||||
|  | ||||
| GraphicsPipeline* ShaderCache::CurrentGraphicsPipeline() { | ||||
|     if (!RefreshStages(graphics_key.unique_hashes)) { | ||||
|         current_pipeline = nullptr; | ||||
|         return nullptr; | ||||
|     } | ||||
|     const auto& regs{maxwell3d.regs}; | ||||
| @@ -313,15 +314,23 @@ GraphicsPipeline* ShaderCache::CurrentGraphicsPipeline() { | ||||
|     if (graphics_key.xfb_enabled) { | ||||
|         SetXfbState(graphics_key.xfb_state, regs); | ||||
|     } | ||||
|     const auto [pair, is_new]{graphics_cache.try_emplace(graphics_key)}; | ||||
|     auto& program{pair->second}; | ||||
|     if (is_new) { | ||||
|         program = CreateGraphicsPipeline(); | ||||
|     if (current_pipeline && graphics_key == current_pipeline->Key()) { | ||||
|         return current_pipeline->IsBuilt() ? current_pipeline : nullptr; | ||||
|     } | ||||
|     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 program.get(); | ||||
|     return pipeline.get(); | ||||
| } | ||||
|  | ||||
| ComputePipeline* ShaderCache::CurrentComputePipeline() { | ||||
| @@ -432,8 +441,7 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( | ||||
|     auto* const thread_worker{build_in_parallel ? workers.get() : nullptr}; | ||||
|     return std::make_unique<GraphicsPipeline>(device, texture_cache, buffer_cache, gpu_memory, | ||||
|                                               maxwell3d, program_manager, state_tracker, | ||||
|                                               thread_worker, &shader_notify, sources, infos, | ||||
|                                               key.xfb_enabled != 0 ? &key.xfb_state : nullptr); | ||||
|                                               thread_worker, &shader_notify, sources, infos, key); | ||||
|  | ||||
| } catch (Shader::Exception& exception) { | ||||
|     LOG_ERROR(Render_OpenGL, "{}", exception.what()); | ||||
|   | ||||
| @@ -53,6 +53,8 @@ public: | ||||
|     [[nodiscard]] ComputePipeline* CurrentComputePipeline(); | ||||
|  | ||||
| private: | ||||
|     GraphicsPipeline* CurrentGraphicsPipelineSlowPath(); | ||||
|  | ||||
|     std::unique_ptr<GraphicsPipeline> CreateGraphicsPipeline(); | ||||
|  | ||||
|     std::unique_ptr<GraphicsPipeline> CreateGraphicsPipeline( | ||||
| @@ -75,9 +77,10 @@ private: | ||||
|     ProgramManager& program_manager; | ||||
|     StateTracker& state_tracker; | ||||
|     VideoCore::ShaderNotify& shader_notify; | ||||
|     const bool use_asynchronous_shaders; | ||||
|  | ||||
|     GraphicsPipelineKey graphics_key{}; | ||||
|     const bool use_asynchronous_shaders; | ||||
|     GraphicsPipeline* current_pipeline{}; | ||||
|  | ||||
|     ShaderContext::ShaderPools main_pools; | ||||
|     std::unordered_map<GraphicsPipelineKey, std::unique_ptr<GraphicsPipeline>> graphics_cache; | ||||
|   | ||||
| @@ -146,12 +146,11 @@ private: | ||||
|     BufferCache& buffer_cache; | ||||
|     TextureCache& texture_cache; | ||||
|     VideoCore::ShaderNotify& shader_notify; | ||||
|     bool use_asynchronous_shaders{}; | ||||
|  | ||||
|     GraphicsPipelineCacheKey graphics_key{}; | ||||
|     GraphicsPipeline* current_pipeline{}; | ||||
|  | ||||
|     bool use_asynchronous_shaders{}; | ||||
|  | ||||
|     std::unordered_map<ComputePipelineCacheKey, std::unique_ptr<ComputePipeline>> compute_cache; | ||||
|     std::unordered_map<GraphicsPipelineCacheKey, std::unique_ptr<GraphicsPipeline>> graphics_cache; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user