Просмотр исходного кода

gl_state_tracker: Implement dirty flags for blending

ReinUsesLisp 6 лет назад
Родитель
Сommit
b01dd7d1c8

+ 36 - 13
src/video_core/renderer_opengl/gl_rasterizer.cpp

@@ -458,6 +458,7 @@ void RasterizerOpenGL::Clear() {
     }
 
     // TODO: Signal state tracker about these changes
+    state_tracker.NotifyBlend0();
     // TODO(Rodrigo): Find out if these changes affect clearing
     glClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE);
     glDisablei(GL_BLEND, 0);
@@ -1102,31 +1103,53 @@ void RasterizerOpenGL::SyncFragmentColorClampState() {
 }
 
 void RasterizerOpenGL::SyncBlendState() {
-    auto& maxwell3d = system.GPU().Maxwell3D();
-    const auto& regs = maxwell3d.regs;
+    auto& gpu = system.GPU().Maxwell3D();
+    auto& flags = gpu.dirty.flags;
+    const auto& regs = gpu.regs;
+
+    if (flags[Dirty::BlendColor]) {
+        flags[Dirty::BlendColor] = false;
+        glBlendColor(regs.blend_color.r, regs.blend_color.g, regs.blend_color.b,
+                     regs.blend_color.a);
+    }
 
-    glBlendColor(regs.blend_color.r, regs.blend_color.g, regs.blend_color.b, regs.blend_color.a);
+    // TODO(Rodrigo): Revisit blending, there are several registers we are not reading
+
+    if (!flags[Dirty::BlendStates]) {
+        return;
+    }
+    flags[Dirty::BlendStates] = false;
 
     if (!regs.independent_blend_enable) {
-        const auto& src = regs.blend;
-        oglEnable(GL_BLEND, src.enable[0]);
-        if (!src.enable[0]) {
+        if (!regs.blend.enable[0]) {
+            glDisable(GL_BLEND);
             return;
         }
-        glBlendFuncSeparate(MaxwellToGL::BlendFunc(src.factor_source_rgb),
-                            MaxwellToGL::BlendFunc(src.factor_dest_rgb),
-                            MaxwellToGL::BlendFunc(src.factor_source_a),
-                            MaxwellToGL::BlendFunc(src.factor_dest_a));
-        glBlendEquationSeparate(MaxwellToGL::BlendEquation(src.equation_rgb),
-                                MaxwellToGL::BlendEquation(src.equation_a));
+        glEnable(GL_BLEND);
+        glBlendFuncSeparate(MaxwellToGL::BlendFunc(regs.blend.factor_source_rgb),
+                            MaxwellToGL::BlendFunc(regs.blend.factor_dest_rgb),
+                            MaxwellToGL::BlendFunc(regs.blend.factor_source_a),
+                            MaxwellToGL::BlendFunc(regs.blend.factor_dest_a));
+        glBlendEquationSeparate(MaxwellToGL::BlendEquation(regs.blend.equation_rgb),
+                                MaxwellToGL::BlendEquation(regs.blend.equation_a));
         return;
     }
 
+    const bool force = flags[Dirty::BlendIndependentEnabled];
+    flags[Dirty::BlendIndependentEnabled] = false;
+
     for (std::size_t i = 0; i < Maxwell::NumRenderTargets; ++i) {
-        oglEnablei(GL_BLEND, regs.blend.enable[i], static_cast<GLuint>(i));
+        if (!force && !flags[Dirty::BlendState0 + i]) {
+            continue;
+        }
+        flags[Dirty::BlendState0 + i] = false;
+
         if (!regs.blend.enable[i]) {
+            glDisablei(GL_BLEND, static_cast<GLuint>(i));
             continue;
         }
+        glEnablei(GL_BLEND, static_cast<GLuint>(i));
+
         const auto& src = regs.independent_blend[i];
         glBlendFuncSeparatei(static_cast<GLuint>(i), MaxwellToGL::BlendFunc(src.factor_source_rgb),
                              MaxwellToGL::BlendFunc(src.factor_dest_rgb),

+ 16 - 0
src/video_core/renderer_opengl/gl_state_tracker.cpp

@@ -129,6 +129,21 @@ void SetupDirtyShaders(Tables& tables) {
               Shaders);
 }
 
+void SetupDirtyBlend(Tables& tables) {
+    FillBlock(tables[0], OFF(blend_color), NUM(blend_color), BlendColor);
+
+    tables[0][OFF(independent_blend_enable)] = BlendIndependentEnabled;
+
+    for (std::size_t i = 0; i < Regs::NumRenderTargets; ++i) {
+        const std::size_t offset = OFF(independent_blend) + i * NUM(independent_blend[0]);
+        FillBlock(tables[0], offset, NUM(independent_blend[0]), BlendState0 + i);
+
+        tables[0][OFF(blend.enable) + i] = static_cast<u8>(BlendState0 + i);
+    }
+    FillBlock(tables[1], OFF(independent_blend), NUM(independent_blend), BlendStates);
+    FillBlock(tables[1], OFF(blend), NUM(blend), BlendStates);
+}
+
 void SetupDirtyMisc(Tables& tables) {
     tables[0][OFF(clip_distance_enabled)] = ClipDistances;
 }
@@ -147,6 +162,7 @@ void StateTracker::Initialize() {
     SetupDirtyVertexArrays(tables);
     SetupDirtyVertexFormat(tables);
     SetupDirtyShaders(tables);
+    SetupDirtyBlend(tables);
     SetupDirtyMisc(tables);
 
     auto& store = dirty.on_write_stores;

+ 13 - 1
src/video_core/renderer_opengl/gl_state_tracker.h

@@ -47,8 +47,15 @@ enum : u8 {
     ColorMask0,
     ColorMask7 = ColorMask0 + 7,
 
+    BlendColor,
+    BlendIndependentEnabled,
+    BlendStates,
+    BlendState0,
+    BlendState7 = BlendState0 + 7,
+
     Shaders,
     ClipDistances,
+
     CullTestEnable,
     FrontFace,
     CullFace,
@@ -56,7 +63,6 @@ enum : u8 {
     DepthTest,
     StencilTest,
     ColorMask,
-    BlendState,
     PolygonOffset,
 
     Last
@@ -103,6 +109,12 @@ public:
         flags[OpenGL::Dirty::ColorMask0] = true;
     }
 
+    void NotifyBlend0() {
+        auto& flags = system.GPU().Maxwell3D().dirty.flags;
+        flags[OpenGL::Dirty::BlendStates] = true;
+        flags[OpenGL::Dirty::BlendState0] = true;
+    }
+
     void NotifyFramebuffer() {
         auto& flags = system.GPU().Maxwell3D().dirty.flags;
         flags[VideoCommon::Dirty::RenderTargets] = true;

+ 1 - 0
src/video_core/renderer_opengl/gl_texture_cache.cpp

@@ -520,6 +520,7 @@ void TextureCacheOpenGL::ImageBlit(View& src_view, View& dst_view,
 
     // TODO: Signal state tracker about these changes
     state_tracker.NotifyScissor0();
+    state_tracker.NotifyBlend0();
     state_tracker.NotifyFramebuffer();
 
     if (dst_params.srgb_conversion) {

+ 1 - 0
src/video_core/renderer_opengl/renderer_opengl.cpp

@@ -580,6 +580,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
     state_tracker.NotifyViewport0();
     state_tracker.NotifyScissor0();
     state_tracker.NotifyColorMask0();
+    state_tracker.NotifyBlend0();
     state_tracker.NotifyFramebuffer();
 
     program_manager.UseVertexShader(vertex_program.handle);