Преглед изворни кода

gl_shader_cache: Check previous pipeline before checking hash map

Port optimization from Vulkan.
ReinUsesLisp пре 5 година
родитељ
комит
f5db8c7440

+ 15 - 18
src/video_core/renderer_opengl/gl_graphics_pipeline.cpp

@@ -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];

+ 7 - 2
src/video_core/renderer_opengl/gl_graphics_pipeline.h

@@ -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){};
 

+ 14 - 6
src/video_core/renderer_opengl/gl_shader_cache.cpp

@@ -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);
     }
+    if (current_pipeline && graphics_key == current_pipeline->Key()) {
+        return current_pipeline->IsBuilt() ? current_pipeline : nullptr;
+    }
+    return CurrentGraphicsPipelineSlowPath();
+}
+
+GraphicsPipeline* ShaderCache::CurrentGraphicsPipelineSlowPath() {
     const auto [pair, is_new]{graphics_cache.try_emplace(graphics_key)};
-    auto& program{pair->second};
+    auto& pipeline{pair->second};
     if (is_new) {
-        program = CreateGraphicsPipeline();
+        pipeline = CreateGraphicsPipeline();
     }
-    if (!program || !program->IsBuilt()) {
+    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());

+ 4 - 1
src/video_core/renderer_opengl/gl_shader_cache.h

@@ -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;

+ 1 - 2
src/video_core/renderer_vulkan/vk_pipeline_cache.h

@@ -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;