diff options
Diffstat (limited to 'src')
5 files changed, 41 insertions, 29 deletions
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp index 6b62fa1da..92974ba08 100644 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp | |||
| @@ -184,17 +184,15 @@ bool GraphicsPipelineKey::operator==(const GraphicsPipelineKey& rhs) const noexc | |||
| 184 | return std::memcmp(this, &rhs, Size()) == 0; | 184 | return std::memcmp(this, &rhs, Size()) == 0; |
| 185 | } | 185 | } |
| 186 | 186 | ||
| 187 | GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_cache_, | 187 | GraphicsPipeline::GraphicsPipeline( |
| 188 | BufferCache& buffer_cache_, Tegra::MemoryManager& gpu_memory_, | 188 | const Device& device, TextureCache& texture_cache_, BufferCache& buffer_cache_, |
| 189 | Tegra::Engines::Maxwell3D& maxwell3d_, | 189 | Tegra::MemoryManager& gpu_memory_, Tegra::Engines::Maxwell3D& maxwell3d_, |
| 190 | ProgramManager& program_manager_, StateTracker& state_tracker_, | 190 | ProgramManager& program_manager_, StateTracker& state_tracker_, ShaderWorker* thread_worker, |
| 191 | ShaderWorker* thread_worker, | 191 | VideoCore::ShaderNotify* shader_notify, std::array<std::string, 5> sources, |
| 192 | VideoCore::ShaderNotify* shader_notify, | 192 | const std::array<const Shader::Info*, 5>& infos, const GraphicsPipelineKey& key_) |
| 193 | std::array<std::string, 5> sources, | 193 | : texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, |
| 194 | const std::array<const Shader::Info*, 5>& infos, | 194 | gpu_memory{gpu_memory_}, maxwell3d{maxwell3d_}, program_manager{program_manager_}, |
| 195 | const VideoCommon::TransformFeedbackState* xfb_state) | 195 | state_tracker{state_tracker_}, key{key_} { |
| 196 | : texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, gpu_memory{gpu_memory_}, | ||
| 197 | maxwell3d{maxwell3d_}, program_manager{program_manager_}, state_tracker{state_tracker_} { | ||
| 198 | if (shader_notify) { | 196 | if (shader_notify) { |
| 199 | shader_notify->MarkShaderBuilding(); | 197 | shader_notify->MarkShaderBuilding(); |
| 200 | } | 198 | } |
| @@ -241,10 +239,10 @@ GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_c | |||
| 241 | writes_global_memory &= !use_storage_buffers; | 239 | writes_global_memory &= !use_storage_buffers; |
| 242 | configure_func = ConfigureFunc(stage_infos, enabled_stages_mask); | 240 | configure_func = ConfigureFunc(stage_infos, enabled_stages_mask); |
| 243 | 241 | ||
| 244 | if (assembly_shaders && xfb_state) { | 242 | if (assembly_shaders && key.xfb_enabled) { |
| 245 | GenerateTransformFeedbackState(*xfb_state); | 243 | GenerateTransformFeedbackState(); |
| 246 | } | 244 | } |
| 247 | auto func{[this, device, sources, shader_notify, xfb_state](ShaderContext::Context*) mutable { | 245 | auto func{[this, device, sources, shader_notify](ShaderContext::Context*) mutable { |
| 248 | if (!device.UseAssemblyShaders()) { | 246 | if (!device.UseAssemblyShaders()) { |
| 249 | program.handle = glCreateProgram(); | 247 | program.handle = glCreateProgram(); |
| 250 | } | 248 | } |
| @@ -505,15 +503,14 @@ void GraphicsPipeline::ConfigureTransformFeedbackImpl() const { | |||
| 505 | xfb_streams.data(), GL_INTERLEAVED_ATTRIBS); | 503 | xfb_streams.data(), GL_INTERLEAVED_ATTRIBS); |
| 506 | } | 504 | } |
| 507 | 505 | ||
| 508 | void GraphicsPipeline::GenerateTransformFeedbackState( | 506 | void GraphicsPipeline::GenerateTransformFeedbackState() { |
| 509 | const VideoCommon::TransformFeedbackState& xfb_state) { | ||
| 510 | // TODO(Rodrigo): Inject SKIP_COMPONENTS*_NV when required. An unimplemented message will signal | 507 | // TODO(Rodrigo): Inject SKIP_COMPONENTS*_NV when required. An unimplemented message will signal |
| 511 | // when this is required. | 508 | // when this is required. |
| 512 | GLint* cursor{xfb_attribs.data()}; | 509 | GLint* cursor{xfb_attribs.data()}; |
| 513 | GLint* current_stream{xfb_streams.data()}; | 510 | GLint* current_stream{xfb_streams.data()}; |
| 514 | 511 | ||
| 515 | for (size_t feedback = 0; feedback < Maxwell::NumTransformFeedbackBuffers; ++feedback) { | 512 | for (size_t feedback = 0; feedback < Maxwell::NumTransformFeedbackBuffers; ++feedback) { |
| 516 | const auto& layout = xfb_state.layouts[feedback]; | 513 | const auto& layout = key.xfb_state.layouts[feedback]; |
| 517 | UNIMPLEMENTED_IF_MSG(layout.stride != layout.varying_count * 4, "Stride padding"); | 514 | UNIMPLEMENTED_IF_MSG(layout.stride != layout.varying_count * 4, "Stride padding"); |
| 518 | if (layout.varying_count == 0) { | 515 | if (layout.varying_count == 0) { |
| 519 | continue; | 516 | continue; |
| @@ -528,7 +525,7 @@ void GraphicsPipeline::GenerateTransformFeedbackState( | |||
| 528 | } | 525 | } |
| 529 | ++current_stream; | 526 | ++current_stream; |
| 530 | 527 | ||
| 531 | const auto& locations = xfb_state.varyings[feedback]; | 528 | const auto& locations = key.xfb_state.varyings[feedback]; |
| 532 | std::optional<u8> current_index; | 529 | std::optional<u8> current_index; |
| 533 | for (u32 offset = 0; offset < layout.varying_count; ++offset) { | 530 | for (u32 offset = 0; offset < layout.varying_count; ++offset) { |
| 534 | const u8 location = locations[offset]; | 531 | const u8 location = locations[offset]; |
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.h b/src/video_core/renderer_opengl/gl_graphics_pipeline.h index a3546daa8..a033d4a95 100644 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.h +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.h | |||
| @@ -73,7 +73,7 @@ public: | |||
| 73 | ShaderWorker* thread_worker, VideoCore::ShaderNotify* shader_notify, | 73 | ShaderWorker* thread_worker, VideoCore::ShaderNotify* shader_notify, |
| 74 | std::array<std::string, 5> sources, | 74 | std::array<std::string, 5> sources, |
| 75 | const std::array<const Shader::Info*, 5>& infos, | 75 | const std::array<const Shader::Info*, 5>& infos, |
| 76 | const VideoCommon::TransformFeedbackState* xfb_state); | 76 | const GraphicsPipelineKey& key_); |
| 77 | 77 | ||
| 78 | void Configure(bool is_indexed) { | 78 | void Configure(bool is_indexed) { |
| 79 | configure_func(this, is_indexed); | 79 | configure_func(this, is_indexed); |
| @@ -85,6 +85,10 @@ public: | |||
| 85 | } | 85 | } |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | [[nodiscard]] const GraphicsPipelineKey& Key() const noexcept { | ||
| 89 | return key; | ||
| 90 | } | ||
| 91 | |||
| 88 | [[nodiscard]] bool WritesGlobalMemory() const noexcept { | 92 | [[nodiscard]] bool WritesGlobalMemory() const noexcept { |
| 89 | return writes_global_memory; | 93 | return writes_global_memory; |
| 90 | } | 94 | } |
| @@ -106,7 +110,7 @@ private: | |||
| 106 | 110 | ||
| 107 | void ConfigureTransformFeedbackImpl() const; | 111 | void ConfigureTransformFeedbackImpl() const; |
| 108 | 112 | ||
| 109 | void GenerateTransformFeedbackState(const VideoCommon::TransformFeedbackState& xfb_state); | 113 | void GenerateTransformFeedbackState(); |
| 110 | 114 | ||
| 111 | TextureCache& texture_cache; | 115 | TextureCache& texture_cache; |
| 112 | BufferCache& buffer_cache; | 116 | BufferCache& buffer_cache; |
| @@ -114,6 +118,7 @@ private: | |||
| 114 | Tegra::Engines::Maxwell3D& maxwell3d; | 118 | Tegra::Engines::Maxwell3D& maxwell3d; |
| 115 | ProgramManager& program_manager; | 119 | ProgramManager& program_manager; |
| 116 | StateTracker& state_tracker; | 120 | StateTracker& state_tracker; |
| 121 | const GraphicsPipelineKey key; | ||
| 117 | 122 | ||
| 118 | void (*configure_func)(GraphicsPipeline*, bool){}; | 123 | void (*configure_func)(GraphicsPipeline*, bool){}; |
| 119 | 124 | ||
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 8aaadccc4..c36b0d8cf 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -298,6 +298,7 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading, | |||
| 298 | 298 | ||
| 299 | GraphicsPipeline* ShaderCache::CurrentGraphicsPipeline() { | 299 | GraphicsPipeline* ShaderCache::CurrentGraphicsPipeline() { |
| 300 | if (!RefreshStages(graphics_key.unique_hashes)) { | 300 | if (!RefreshStages(graphics_key.unique_hashes)) { |
| 301 | current_pipeline = nullptr; | ||
| 301 | return nullptr; | 302 | return nullptr; |
| 302 | } | 303 | } |
| 303 | const auto& regs{maxwell3d.regs}; | 304 | const auto& regs{maxwell3d.regs}; |
| @@ -313,15 +314,23 @@ GraphicsPipeline* ShaderCache::CurrentGraphicsPipeline() { | |||
| 313 | if (graphics_key.xfb_enabled) { | 314 | if (graphics_key.xfb_enabled) { |
| 314 | SetXfbState(graphics_key.xfb_state, regs); | 315 | SetXfbState(graphics_key.xfb_state, regs); |
| 315 | } | 316 | } |
| 317 | if (current_pipeline && graphics_key == current_pipeline->Key()) { | ||
| 318 | return current_pipeline->IsBuilt() ? current_pipeline : nullptr; | ||
| 319 | } | ||
| 320 | return CurrentGraphicsPipelineSlowPath(); | ||
| 321 | } | ||
| 322 | |||
| 323 | GraphicsPipeline* ShaderCache::CurrentGraphicsPipelineSlowPath() { | ||
| 316 | const auto [pair, is_new]{graphics_cache.try_emplace(graphics_key)}; | 324 | const auto [pair, is_new]{graphics_cache.try_emplace(graphics_key)}; |
| 317 | auto& program{pair->second}; | 325 | auto& pipeline{pair->second}; |
| 318 | if (is_new) { | 326 | if (is_new) { |
| 319 | program = CreateGraphicsPipeline(); | 327 | pipeline = CreateGraphicsPipeline(); |
| 320 | } | 328 | } |
| 321 | if (!program || !program->IsBuilt()) { | 329 | current_pipeline = pipeline.get(); |
| 330 | if (!pipeline || !pipeline->IsBuilt()) { | ||
| 322 | return nullptr; | 331 | return nullptr; |
| 323 | } | 332 | } |
| 324 | return program.get(); | 333 | return pipeline.get(); |
| 325 | } | 334 | } |
| 326 | 335 | ||
| 327 | ComputePipeline* ShaderCache::CurrentComputePipeline() { | 336 | ComputePipeline* ShaderCache::CurrentComputePipeline() { |
| @@ -432,8 +441,7 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( | |||
| 432 | auto* const thread_worker{build_in_parallel ? workers.get() : nullptr}; | 441 | auto* const thread_worker{build_in_parallel ? workers.get() : nullptr}; |
| 433 | return std::make_unique<GraphicsPipeline>(device, texture_cache, buffer_cache, gpu_memory, | 442 | return std::make_unique<GraphicsPipeline>(device, texture_cache, buffer_cache, gpu_memory, |
| 434 | maxwell3d, program_manager, state_tracker, | 443 | maxwell3d, program_manager, state_tracker, |
| 435 | thread_worker, &shader_notify, sources, infos, | 444 | thread_worker, &shader_notify, sources, infos, key); |
| 436 | key.xfb_enabled != 0 ? &key.xfb_state : nullptr); | ||
| 437 | 445 | ||
| 438 | } catch (Shader::Exception& exception) { | 446 | } catch (Shader::Exception& exception) { |
| 439 | LOG_ERROR(Render_OpenGL, "{}", exception.what()); | 447 | LOG_ERROR(Render_OpenGL, "{}", exception.what()); |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h index ff5707119..16873fcec 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_cache.h | |||
| @@ -53,6 +53,8 @@ public: | |||
| 53 | [[nodiscard]] ComputePipeline* CurrentComputePipeline(); | 53 | [[nodiscard]] ComputePipeline* CurrentComputePipeline(); |
| 54 | 54 | ||
| 55 | private: | 55 | private: |
| 56 | GraphicsPipeline* CurrentGraphicsPipelineSlowPath(); | ||
| 57 | |||
| 56 | std::unique_ptr<GraphicsPipeline> CreateGraphicsPipeline(); | 58 | std::unique_ptr<GraphicsPipeline> CreateGraphicsPipeline(); |
| 57 | 59 | ||
| 58 | std::unique_ptr<GraphicsPipeline> CreateGraphicsPipeline( | 60 | std::unique_ptr<GraphicsPipeline> CreateGraphicsPipeline( |
| @@ -75,9 +77,10 @@ private: | |||
| 75 | ProgramManager& program_manager; | 77 | ProgramManager& program_manager; |
| 76 | StateTracker& state_tracker; | 78 | StateTracker& state_tracker; |
| 77 | VideoCore::ShaderNotify& shader_notify; | 79 | VideoCore::ShaderNotify& shader_notify; |
| 80 | const bool use_asynchronous_shaders; | ||
| 78 | 81 | ||
| 79 | GraphicsPipelineKey graphics_key{}; | 82 | GraphicsPipelineKey graphics_key{}; |
| 80 | const bool use_asynchronous_shaders; | 83 | GraphicsPipeline* current_pipeline{}; |
| 81 | 84 | ||
| 82 | ShaderContext::ShaderPools main_pools; | 85 | ShaderContext::ShaderPools main_pools; |
| 83 | std::unordered_map<GraphicsPipelineKey, std::unique_ptr<GraphicsPipeline>> graphics_cache; | 86 | std::unordered_map<GraphicsPipelineKey, std::unique_ptr<GraphicsPipeline>> graphics_cache; |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h index 42da2960b..efe5a7ed8 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h | |||
| @@ -146,12 +146,11 @@ private: | |||
| 146 | BufferCache& buffer_cache; | 146 | BufferCache& buffer_cache; |
| 147 | TextureCache& texture_cache; | 147 | TextureCache& texture_cache; |
| 148 | VideoCore::ShaderNotify& shader_notify; | 148 | VideoCore::ShaderNotify& shader_notify; |
| 149 | bool use_asynchronous_shaders{}; | ||
| 149 | 150 | ||
| 150 | GraphicsPipelineCacheKey graphics_key{}; | 151 | GraphicsPipelineCacheKey graphics_key{}; |
| 151 | GraphicsPipeline* current_pipeline{}; | 152 | GraphicsPipeline* current_pipeline{}; |
| 152 | 153 | ||
| 153 | bool use_asynchronous_shaders{}; | ||
| 154 | |||
| 155 | std::unordered_map<ComputePipelineCacheKey, std::unique_ptr<ComputePipeline>> compute_cache; | 154 | std::unordered_map<ComputePipelineCacheKey, std::unique_ptr<ComputePipeline>> compute_cache; |
| 156 | std::unordered_map<GraphicsPipelineCacheKey, std::unique_ptr<GraphicsPipeline>> graphics_cache; | 155 | std::unordered_map<GraphicsPipelineCacheKey, std::unique_ptr<GraphicsPipeline>> graphics_cache; |
| 157 | 156 | ||