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

gl_state_tracker: Implement dirty flags for color masks

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

+ 30 - 9
src/video_core/renderer_opengl/gl_rasterizer.cpp

@@ -410,8 +410,9 @@ void RasterizerOpenGL::Clear() {
     }
     if (use_color) {
         // TODO: Signal state tracker about these changes
-        glColorMaski(0, regs.clear_buffers.R, regs.clear_buffers.G, regs.clear_buffers.B,
-                     regs.clear_buffers.A);
+        state_tracker.NotifyColorMask0();
+        glColorMaski(0, regs.clear_buffers.R != 0, regs.clear_buffers.G != 0,
+                     regs.clear_buffers.B != 0, regs.clear_buffers.A != 0);
 
         SyncFramebufferSRGB();
         // TODO(Rodrigo): Determine if clamping is used on clears
@@ -1030,17 +1031,37 @@ void RasterizerOpenGL::SyncRasterizeEnable() {
 }
 
 void RasterizerOpenGL::SyncColorMask() {
-    auto& maxwell3d = system.GPU().Maxwell3D();
-    const auto& regs = maxwell3d.regs;
+    auto& gpu = system.GPU().Maxwell3D();
+    auto& flags = gpu.dirty.flags;
+    if (!flags[Dirty::ColorMasks]) {
+        return;
+    }
+    flags[Dirty::ColorMasks] = false;
+
+    const bool force = flags[Dirty::ColorMaskCommon];
+    flags[Dirty::ColorMaskCommon] = false;
 
+    const auto& regs = gpu.regs;
     if (regs.color_mask_common) {
+        if (!force && !flags[Dirty::ColorMask0]) {
+            return;
+        }
+        flags[Dirty::ColorMask0] = false;
+
         auto& mask = regs.color_mask[0];
-        glColorMask(mask.R, mask.B, mask.G, mask.A);
-    } else {
-        for (std::size_t i = 0; i < Maxwell::NumRenderTargets; ++i) {
-            const auto& mask = regs.color_mask[regs.color_mask_common ? 0 : i];
-            glColorMaski(static_cast<GLuint>(i), mask.R, mask.G, mask.B, mask.A);
+        glColorMask(mask.R != 0, mask.B != 0, mask.G != 0, mask.A != 0);
+        return;
+    }
+
+    // Path without color_mask_common set
+    for (std::size_t i = 0; i < Maxwell::NumRenderTargets; ++i) {
+        if (!force && !flags[Dirty::ColorMask0 + i]) {
+            continue;
         }
+        flags[Dirty::ColorMask0 + i] = false;
+
+        const auto& mask = regs.color_mask[i];
+        glColorMaski(static_cast<GLuint>(i), mask.R != 0, mask.G != 0, mask.B != 0, mask.A != 0);
     }
 }
 

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

@@ -61,6 +61,16 @@ void SetupDirtyRenderTargets(Tables& tables) {
     }
 }
 
+void SetupDirtyColorMasks(Tables& tables) {
+    tables[0][OFF(color_mask_common)] = ColorMaskCommon;
+    for (std::size_t rt = 0; rt < Regs::NumRenderTargets; ++rt) {
+        const std::size_t offset = OFF(color_mask) + rt * NUM(color_mask[0]);
+        FillBlock(tables[0], offset, NUM(color_mask[0]), ColorMask0 + rt);
+    }
+
+    FillBlock(tables[1], OFF(color_mask), NUM(color_mask), ColorMasks);
+}
+
 void SetupDirtyViewports(Tables& tables) {
     for (std::size_t i = 0; i < Regs::NumViewports; ++i) {
         const std::size_t transf_offset = OFF(viewport_transform) + i * NUM(viewport_transform[0]);
@@ -104,6 +114,7 @@ void StateTracker::Initialize() {
 
     auto& tables = dirty.tables;
     SetupDirtyRenderTargets(tables);
+    SetupDirtyColorMasks(tables);
     SetupDirtyViewports(tables);
     SetupDirtyScissors(tables);
 }

+ 11 - 0
src/video_core/renderer_opengl/gl_state_tracker.h

@@ -38,6 +38,11 @@ enum : u8 {
     Scissor0,
     Scissor15 = Scissor0 + 15,
 
+    ColorMaskCommon,
+    ColorMasks,
+    ColorMask0,
+    ColorMask7 = ColorMask0 + 7,
+
     Shaders,
     CullTestEnable,
     FrontFace,
@@ -73,6 +78,12 @@ public:
         flags[OpenGL::Dirty::Scissor0] = true;
     }
 
+    void NotifyColorMask0() {
+        auto& flags = system.GPU().Maxwell3D().dirty.flags;
+        flags[OpenGL::Dirty::ColorMasks] = true;
+        flags[OpenGL::Dirty::ColorMask0] = true;
+    }
+
     void NotifyFramebuffer() {
         auto& flags = system.GPU().Maxwell3D().dirty.flags;
         flags[VideoCommon::Dirty::RenderTargets] = true;

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

@@ -578,6 +578,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
     // TODO: Signal state tracker about these changes
     state_tracker.NotifyViewport0();
     state_tracker.NotifyScissor0();
+    state_tracker.NotifyColorMask0();
     state_tracker.NotifyFramebuffer();
 
     program_manager.UseVertexShader(vertex_program.handle);