Bladeren bron

renderer_opengl: State track assembly programs

ReinUsesLisp 5 jaren geleden
bovenliggende
commit
c5ca4fe451

+ 7 - 20
src/video_core/renderer_opengl/gl_graphics_program.cpp

@@ -42,6 +42,9 @@ GraphicsProgram::GraphicsProgram(TextureCache& texture_cache_, BufferCache& buff
     std::ranges::transform(infos, stage_infos.begin(),
                            [](const Shader::Info* info) { return info ? *info : Shader::Info{}; });
 
+    for (size_t stage = 0; stage < 5; ++stage) {
+        enabled_stages_mask |= (assembly_programs[stage].handle != 0 ? 1 : 0) << stage;
+    }
     u32 num_textures{};
     u32 num_images{};
     for (size_t stage = 0; stage < base_uniform_bindings.size() - 1; ++stage) {
@@ -182,6 +185,9 @@ void GraphicsProgram::Configure(bool is_indexed) {
     const std::span indices_span(image_view_indices.data(), image_view_index);
     texture_cache.FillGraphicsImageViews(indices_span, image_view_ids);
 
+    texture_cache.UpdateRenderTargets(false);
+    state_tracker.BindFramebuffer(texture_cache.GetFramebuffer()->Handle());
+
     ImageId* texture_buffer_index{image_view_ids.data()};
     const auto bind_stage_info{[&](size_t stage) {
         size_t index{};
@@ -240,14 +246,8 @@ void GraphicsProgram::Configure(bool is_indexed) {
     buffer_cache.UpdateGraphicsBuffers(is_indexed);
     buffer_cache.BindHostGeometryBuffers(is_indexed);
 
-    // FIXME: Unhack this
     if (assembly_programs[0].handle != 0) {
-        // TODO: State track this
-        glEnable(GL_VERTEX_PROGRAM_NV);
-        glEnable(GL_FRAGMENT_PROGRAM_NV);
-        glBindProgramARB(GL_VERTEX_PROGRAM_NV, assembly_programs[0].handle);
-        glBindProgramARB(GL_FRAGMENT_PROGRAM_NV, assembly_programs[4].handle);
-        program_manager.BindProgram(0);
+        program_manager.BindAssemblyPrograms(assembly_programs, enabled_stages_mask);
     } else {
         program_manager.BindProgram(program.handle);
     }
@@ -300,19 +300,6 @@ void GraphicsProgram::Configure(bool is_indexed) {
     if (image_binding != 0) {
         glBindImageTextures(0, image_binding, images.data());
     }
-    texture_cache.UpdateRenderTargets(false);
-
-    state_tracker.BindFramebuffer(texture_cache.GetFramebuffer()->Handle());
-    if (assembly_programs[0].handle != 0) {
-        // TODO: State track this
-        glEnable(GL_VERTEX_PROGRAM_NV);
-        glEnable(GL_FRAGMENT_PROGRAM_NV);
-        glBindProgramARB(GL_VERTEX_PROGRAM_NV, assembly_programs[0].handle);
-        glBindProgramARB(GL_FRAGMENT_PROGRAM_NV, assembly_programs[4].handle);
-        program_manager.BindProgram(0);
-    } else {
-        program_manager.BindProgram(program.handle);
-    }
 }
 
 } // namespace OpenGL

+ 1 - 0
src/video_core/renderer_opengl/gl_graphics_program.h

@@ -89,6 +89,7 @@ private:
 
     OGLProgram program;
     std::array<OGLAssemblyProgram, 5> assembly_programs;
+    u32 enabled_stages_mask{};
 
     std::array<Shader::Info, 5> stage_infos{};
     std::array<u32, 5> base_uniform_bindings{};

+ 48 - 3
src/video_core/renderer_opengl/gl_shader_manager.h

@@ -4,24 +4,69 @@
 
 #pragma once
 
+#include <array>
+#include <span>
+
 #include <glad/glad.h>
 
+#include "video_core/renderer_opengl/gl_resource_manager.h"
+
+#pragma optimize("", off)
+
 namespace OpenGL {
 
 class ProgramManager {
+    static constexpr size_t NUM_STAGES = 5;
+
+    static constexpr std::array ASSEMBLY_PROGRAM_ENUMS{
+        GL_VERTEX_PROGRAM_NV,   GL_TESS_CONTROL_PROGRAM_NV, GL_TESS_EVALUATION_PROGRAM_NV,
+        GL_GEOMETRY_PROGRAM_NV, GL_FRAGMENT_PROGRAM_NV,
+    };
+
 public:
     void BindProgram(GLuint program) {
-        if (bound_program == program) {
+        if (current_source_program == program) {
             return;
         }
-        bound_program = program;
+        current_source_program = program;
         glUseProgram(program);
     }
 
+    void BindAssemblyPrograms(std::span<const OGLAssemblyProgram, NUM_STAGES> programs,
+                              u32 stage_mask) {
+        const u32 changed_mask = current_assembly_mask ^ stage_mask;
+        current_assembly_mask = stage_mask;
+
+        if (changed_mask != 0) {
+            for (size_t stage = 0; stage < NUM_STAGES; ++stage) {
+                if (((changed_mask >> stage) & 1) != 0) {
+                    if (((stage_mask >> stage) & 1) != 0) {
+                        glEnable(ASSEMBLY_PROGRAM_ENUMS[stage]);
+                    } else {
+                        glDisable(ASSEMBLY_PROGRAM_ENUMS[stage]);
+                    }
+                }
+            }
+        }
+        for (size_t stage = 0; stage < NUM_STAGES; ++stage) {
+            if (current_assembly_programs[stage] != programs[stage].handle) {
+                current_assembly_programs[stage] = programs[stage].handle;
+                glBindProgramARB(ASSEMBLY_PROGRAM_ENUMS[stage], programs[stage].handle);
+            }
+        }
+        if (current_source_program != 0) {
+            current_source_program = 0;
+            glUseProgram(0);
+        }
+    }
+
     void RestoreGuestCompute() {}
 
 private:
-    GLuint bound_program = 0;
+    GLuint current_source_program = 0;
+
+    u32 current_assembly_mask = 0;
+    std::array<GLuint, NUM_STAGES> current_assembly_programs;
 };
 
 } // namespace OpenGL