diff options
Diffstat (limited to 'src/video_core')
| -rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 82 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 10 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 86 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.cpp | 22 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.h | 37 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.cpp | 6 | 
6 files changed, 199 insertions, 44 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 7d3a550f8..cfa98f528 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -159,6 +159,88 @@ void Maxwell3D::InitDirtySettings() {          sizeof(regs.shader_config[0]) * Regs::MaxShaderProgram / sizeof(u32);      set_block(MAXWELL3D_REG_INDEX(shader_config[0]), shader_registers_count,                DIRTY_REGS_POS(shaders)); + +    // State + +    // Viewport +    constexpr u32 viewport_dirty_reg = DIRTY_REGS_POS(viewport); +    constexpr u32 viewport_start = MAXWELL3D_REG_INDEX(viewports); +    constexpr u32 viewport_size = sizeof(regs.viewports) / sizeof(u32); +    set_block(viewport_start, viewport_size, viewport_dirty_reg); +    constexpr u32 view_volume_start = MAXWELL3D_REG_INDEX(view_volume_clip_control); +    constexpr u32 view_volume_size = sizeof(regs.view_volume_clip_control) / sizeof(u32); +    set_block(view_volume_start, view_volume_size, viewport_dirty_reg); + +    // Viewport transformation +    constexpr u32 viewport_trans_start = MAXWELL3D_REG_INDEX(viewport_transform); +    constexpr u32 viewport_trans_size = sizeof(regs.viewport_transform) / sizeof(u32); +    set_block(viewport_trans_start, viewport_trans_size, DIRTY_REGS_POS(viewport_transform)); + +    // Cullmode +    constexpr u32 cull_mode_start = MAXWELL3D_REG_INDEX(cull); +    constexpr u32 cull_mode_size = sizeof(regs.cull) / sizeof(u32); +    set_block(cull_mode_start, cull_mode_size, DIRTY_REGS_POS(cull_mode)); + +    // Screen y control +    dirty_pointers[MAXWELL3D_REG_INDEX(screen_y_control)] = DIRTY_REGS_POS(screen_y_control); + +    // Primitive Restart +    constexpr u32 primitive_restart_start = MAXWELL3D_REG_INDEX(primitive_restart); +    constexpr u32 primitive_restart_size = sizeof(regs.primitive_restart) / sizeof(u32); +    set_block(primitive_restart_start, primitive_restart_size, DIRTY_REGS_POS(primitive_restart)); + +    // Depth Test +    constexpr u32 depth_test_dirty_reg = DIRTY_REGS_POS(depth_test); +    dirty_pointers[MAXWELL3D_REG_INDEX(depth_test_enable)] = depth_test_dirty_reg; +    dirty_pointers[MAXWELL3D_REG_INDEX(depth_write_enabled)] = depth_test_dirty_reg; +    dirty_pointers[MAXWELL3D_REG_INDEX(depth_test_func)] = depth_test_dirty_reg; + +    // Stencil Test +    constexpr u32 stencil_test_dirty_reg = DIRTY_REGS_POS(stencil_test); +    dirty_pointers[MAXWELL3D_REG_INDEX(stencil_enable)] = stencil_test_dirty_reg; +    dirty_pointers[MAXWELL3D_REG_INDEX(stencil_front_func_func)] = stencil_test_dirty_reg; +    dirty_pointers[MAXWELL3D_REG_INDEX(stencil_front_func_ref)] = stencil_test_dirty_reg; +    dirty_pointers[MAXWELL3D_REG_INDEX(stencil_front_func_mask)] = stencil_test_dirty_reg; +    dirty_pointers[MAXWELL3D_REG_INDEX(stencil_front_op_fail)] = stencil_test_dirty_reg; +    dirty_pointers[MAXWELL3D_REG_INDEX(stencil_front_op_zfail)] = stencil_test_dirty_reg; +    dirty_pointers[MAXWELL3D_REG_INDEX(stencil_front_op_zpass)] = stencil_test_dirty_reg; +    dirty_pointers[MAXWELL3D_REG_INDEX(stencil_front_mask)] = stencil_test_dirty_reg; +    dirty_pointers[MAXWELL3D_REG_INDEX(stencil_two_side_enable)] = stencil_test_dirty_reg; +    dirty_pointers[MAXWELL3D_REG_INDEX(stencil_back_func_func)] = stencil_test_dirty_reg; +    dirty_pointers[MAXWELL3D_REG_INDEX(stencil_back_func_ref)] = stencil_test_dirty_reg; +    dirty_pointers[MAXWELL3D_REG_INDEX(stencil_back_func_mask)] = stencil_test_dirty_reg; +    dirty_pointers[MAXWELL3D_REG_INDEX(stencil_back_op_fail)] = stencil_test_dirty_reg; +    dirty_pointers[MAXWELL3D_REG_INDEX(stencil_back_op_zfail)] = stencil_test_dirty_reg; +    dirty_pointers[MAXWELL3D_REG_INDEX(stencil_back_op_zpass)] = stencil_test_dirty_reg; +    dirty_pointers[MAXWELL3D_REG_INDEX(stencil_back_mask)] = stencil_test_dirty_reg; + +    // Color Mask +    constexpr u32 color_mask_dirty_reg = DIRTY_REGS_POS(color_mask); +    dirty_pointers[MAXWELL3D_REG_INDEX(color_mask_common)] = color_mask_dirty_reg; +    set_block(MAXWELL3D_REG_INDEX(color_mask), sizeof(regs.color_mask) / sizeof(u32), +              color_mask_dirty_reg); +    // Blend State +    constexpr u32 blend_state_dirty_reg = DIRTY_REGS_POS(blend_state); +    set_block(MAXWELL3D_REG_INDEX(blend_color), sizeof(regs.blend_color) / sizeof(u32), +              blend_state_dirty_reg); +    dirty_pointers[MAXWELL3D_REG_INDEX(independent_blend_enable)] = blend_state_dirty_reg; +    set_block(MAXWELL3D_REG_INDEX(blend), sizeof(regs.blend) / sizeof(u32), blend_state_dirty_reg); +    set_block(MAXWELL3D_REG_INDEX(independent_blend), sizeof(regs.independent_blend) / sizeof(u32), +              blend_state_dirty_reg); + +    // Scissor State +    constexpr u32 scissor_test_dirty_reg = DIRTY_REGS_POS(scissor_test); +    set_block(MAXWELL3D_REG_INDEX(scissor_test), sizeof(regs.scissor_test) / sizeof(u32), +              scissor_test_dirty_reg); + +    // Polygon Offset +    constexpr u32 polygon_offset_dirty_reg = DIRTY_REGS_POS(polygon_offset); +    dirty_pointers[MAXWELL3D_REG_INDEX(polygon_offset_fill_enable)] = polygon_offset_dirty_reg; +    dirty_pointers[MAXWELL3D_REG_INDEX(polygon_offset_line_enable)] = polygon_offset_dirty_reg; +    dirty_pointers[MAXWELL3D_REG_INDEX(polygon_offset_point_enable)] = polygon_offset_dirty_reg; +    dirty_pointers[MAXWELL3D_REG_INDEX(polygon_offset_units)] = polygon_offset_dirty_reg; +    dirty_pointers[MAXWELL3D_REG_INDEX(polygon_offset_factor)] = polygon_offset_dirty_reg; +    dirty_pointers[MAXWELL3D_REG_INDEX(polygon_offset_clamp)] = polygon_offset_dirty_reg;  }  void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) { diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 318078f36..abc69cc65 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -1148,22 +1148,20 @@ public:                  bool shaders;                  // State                  bool viewport; -                bool clip_enabled;                  bool clip_coefficient;                  bool cull_mode;                  bool primitive_restart;                  bool depth_test;                  bool stencil_test;                  bool blend_state; -                bool logic_op; -                bool fragment_color_clamp; -                bool multi_sample;                  bool scissor_test;                  bool transform_feedback; -                bool point;                  bool color_mask;                  bool polygon_offset; -                bool alpha_test; + +                // Complementary +                bool viewport_transform; +                bool screen_y_control;                  bool memory_general;              }; diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index c2b5cbff4..76f0f98eb 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -936,56 +936,53 @@ void RasterizerOpenGL::SyncClipCoef() {  }  void RasterizerOpenGL::SyncCullMode() { -    const auto& regs = system.GPU().Maxwell3D().regs; +    auto& maxwell3d = system.GPU().Maxwell3D(); -    state.cull.enabled = regs.cull.enabled != 0; +    const auto& regs = maxwell3d.regs; -    if (state.cull.enabled) { -        state.cull.front_face = MaxwellToGL::FrontFace(regs.cull.front_face); -        state.cull.mode = MaxwellToGL::CullFace(regs.cull.cull_face); - -        const bool flip_triangles{regs.screen_y_control.triangle_rast_flip == 0 || -                                  regs.viewport_transform[0].scale_y < 0.0f}; - -        // If the GPU is configured to flip the rasterized triangles, then we need to flip the -        // notion of front and back. Note: We flip the triangles when the value of the register is 0 -        // because OpenGL already does it for us. -        if (flip_triangles) { -            if (state.cull.front_face == GL_CCW) -                state.cull.front_face = GL_CW; -            else if (state.cull.front_face == GL_CW) -                state.cull.front_face = GL_CCW; -        } +    state.cull.enabled = regs.cull.enabled != 0; +    state.cull.front_face = MaxwellToGL::FrontFace(regs.cull.front_face); +    state.cull.mode = MaxwellToGL::CullFace(regs.cull.cull_face); + +    const bool flip_triangles{regs.screen_y_control.triangle_rast_flip == 0 || +                              regs.viewport_transform[0].scale_y < 0.0f}; + +    // If the GPU is configured to flip the rasterized triangles, then we need to flip the +    // notion of front and back. Note: We flip the triangles when the value of the register is 0 +    // because OpenGL already does it for us. +    if (flip_triangles) { +        if (state.cull.front_face == GL_CCW) +            state.cull.front_face = GL_CW; +        else if (state.cull.front_face == GL_CW) +            state.cull.front_face = GL_CCW;      }  }  void RasterizerOpenGL::SyncPrimitiveRestart() { -    const auto& regs = system.GPU().Maxwell3D().regs; +    auto& maxwell3d = system.GPU().Maxwell3D(); +    const auto& regs = maxwell3d.regs;      state.primitive_restart.enabled = regs.primitive_restart.enabled;      state.primitive_restart.index = regs.primitive_restart.index;  }  void RasterizerOpenGL::SyncDepthTestState() { -    const auto& regs = system.GPU().Maxwell3D().regs; +    auto& maxwell3d = system.GPU().Maxwell3D(); +    const auto& regs = maxwell3d.regs;      state.depth.test_enabled = regs.depth_test_enable != 0;      state.depth.write_mask = regs.depth_write_enabled ? GL_TRUE : GL_FALSE; - -    if (!state.depth.test_enabled) -        return; -      state.depth.test_func = MaxwellToGL::ComparisonOp(regs.depth_test_func);  }  void RasterizerOpenGL::SyncStencilTestState() { -    const auto& regs = system.GPU().Maxwell3D().regs; -    state.stencil.test_enabled = regs.stencil_enable != 0; - -    if (!regs.stencil_enable) { +    auto& maxwell3d = system.GPU().Maxwell3D(); +    if (!maxwell3d.dirty.stencil_test) {          return;      } +    const auto& regs = maxwell3d.regs; +    state.stencil.test_enabled = regs.stencil_enable != 0;      state.stencil.front.test_func = MaxwellToGL::ComparisonOp(regs.stencil_front_func_func);      state.stencil.front.test_ref = regs.stencil_front_func_ref;      state.stencil.front.test_mask = regs.stencil_front_func_mask; @@ -1010,10 +1007,17 @@ void RasterizerOpenGL::SyncStencilTestState() {          state.stencil.back.action_depth_fail = GL_KEEP;          state.stencil.back.action_depth_pass = GL_KEEP;      } +    state.MarkDirtyStencilState(true); +    maxwell3d.dirty.stencil_test = false;  }  void RasterizerOpenGL::SyncColorMask() { -    const auto& regs = system.GPU().Maxwell3D().regs; +    auto& maxwell3d = system.GPU().Maxwell3D(); +    if (!maxwell3d.dirty.color_mask) { +        return; +    } +    const auto& regs = maxwell3d.regs; +      const std::size_t count =          regs.independent_blend_enable ? Tegra::Engines::Maxwell3D::Regs::NumRenderTargets : 1;      for (std::size_t i = 0; i < count; i++) { @@ -1024,6 +1028,9 @@ void RasterizerOpenGL::SyncColorMask() {          dest.blue_enabled = (source.B == 0) ? GL_FALSE : GL_TRUE;          dest.alpha_enabled = (source.A == 0) ? GL_FALSE : GL_TRUE;      } + +    state.MarkDirtyColorMask(true); +    maxwell3d.dirty.color_mask = false;  }  void RasterizerOpenGL::SyncMultiSampleState() { @@ -1038,7 +1045,11 @@ void RasterizerOpenGL::SyncFragmentColorClampState() {  }  void RasterizerOpenGL::SyncBlendState() { -    const auto& regs = system.GPU().Maxwell3D().regs; +    auto& maxwell3d = system.GPU().Maxwell3D(); +    if (!maxwell3d.dirty.blend_state) { +        return; +    } +    const auto& regs = maxwell3d.regs;      state.blend_color.red = regs.blend_color.r;      state.blend_color.green = regs.blend_color.g; @@ -1061,6 +1072,8 @@ void RasterizerOpenGL::SyncBlendState() {          for (std::size_t i = 1; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) {              state.blend[i].enabled = false;          } +        maxwell3d.dirty.blend_state = false; +        state.MarkDirtyBlendState(true);          return;      } @@ -1077,6 +1090,9 @@ void RasterizerOpenGL::SyncBlendState() {          blend.src_a_func = MaxwellToGL::BlendFunc(src.factor_source_a);          blend.dst_a_func = MaxwellToGL::BlendFunc(src.factor_dest_a);      } + +    state.MarkDirtyBlendState(true); +    maxwell3d.dirty.blend_state = false;  }  void RasterizerOpenGL::SyncLogicOpState() { @@ -1128,13 +1144,21 @@ void RasterizerOpenGL::SyncPointState() {  }  void RasterizerOpenGL::SyncPolygonOffset() { -    const auto& regs = system.GPU().Maxwell3D().regs; +    auto& maxwell3d = system.GPU().Maxwell3D(); +    if (!maxwell3d.dirty.polygon_offset) { +        return; +    } +    const auto& regs = maxwell3d.regs; +      state.polygon_offset.fill_enable = regs.polygon_offset_fill_enable != 0;      state.polygon_offset.line_enable = regs.polygon_offset_line_enable != 0;      state.polygon_offset.point_enable = regs.polygon_offset_point_enable != 0;      state.polygon_offset.units = regs.polygon_offset_units;      state.polygon_offset.factor = regs.polygon_offset_factor;      state.polygon_offset.clamp = regs.polygon_offset_clamp; + +    state.MarkDirtyPolygonOffset(true); +    maxwell3d.dirty.polygon_offset = false;  }  void RasterizerOpenGL::SyncAlphaTest() { diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index 0eae98afe..cac03dc31 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp @@ -526,7 +526,7 @@ void OpenGLState::ApplySamplers() const {      }  } -void OpenGLState::Apply() const { +void OpenGLState::Apply() {      MICROPROFILE_SCOPE(OpenGL_State);      ApplyFramebufferState();      ApplyVertexArrayState(); @@ -536,19 +536,31 @@ void OpenGLState::Apply() const {      ApplyPointSize();      ApplyFragmentColorClamp();      ApplyMultisample(); +    if (dirty.color_mask) { +        ApplyColorMask(); +        dirty.color_mask = false; +    }      ApplyDepthClamp(); -    ApplyColorMask();      ApplyViewport(); -    ApplyStencilTest(); +    if (dirty.stencil_state) { +        ApplyStencilTest(); +        dirty.stencil_state = false; +    }      ApplySRgb();      ApplyCulling();      ApplyDepth();      ApplyPrimitiveRestart(); -    ApplyBlending(); +    if (dirty.blend_state) { +        ApplyBlending(); +        dirty.blend_state = false; +    }      ApplyLogicOp();      ApplyTextures();      ApplySamplers(); -    ApplyPolygonOffset(); +    if (dirty.polygon_offset) { +        ApplyPolygonOffset(); +        dirty.polygon_offset = false; +    }      ApplyAlphaTest();  } diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index b0140495d..3d0f6747f 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h @@ -196,7 +196,7 @@ public:      }      /// Apply this state as the current OpenGL state -    void Apply() const; +    void Apply();      void ApplyFramebufferState() const;      void ApplyVertexArrayState() const; @@ -237,11 +237,46 @@ public:      /// Viewport does not affects glClearBuffer so emulate viewport using scissor test      void EmulateViewportWithScissor(); +    void MarkDirtyBlendState(const bool is_dirty) { +        dirty.blend_state = is_dirty; +    } + +    void MarkDirtyStencilState(const bool is_dirty) { +        dirty.stencil_state = is_dirty; +    } + +    void MarkDirtyViewportState(const bool is_dirty) { +        dirty.viewport_state = is_dirty; +    } + +    void MarkDirtyPolygonOffset(const bool is_dirty) { +        dirty.polygon_offset = is_dirty; +    } + +    void MarkDirtyColorMask(const bool is_dirty) { +        dirty.color_mask = is_dirty; +    } + +    void AllDirty() { +        dirty.blend_state = true; +        dirty.stencil_state = true; +        dirty.viewport_state = true; +        dirty.polygon_offset = true; +        dirty.color_mask = true; +    } +  private:      static OpenGLState cur_state;      // Workaround for sRGB problems caused by QT not supporting srgb output      static bool s_rgb_used; +    struct { +        bool blend_state; +        bool stencil_state; +        bool viewport_state; +        bool polygon_offset; +        bool color_mask; +    } dirty{};  };  } // namespace OpenGL diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index b1f6bc7c2..8fcd39a69 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp @@ -485,11 +485,15 @@ void TextureCacheOpenGL::ImageBlit(View& src_view, View& dst_view,      const auto& dst_params{dst_view->GetSurfaceParams()};      OpenGLState prev_state{OpenGLState::GetCurState()}; -    SCOPE_EXIT({ prev_state.Apply(); }); +    SCOPE_EXIT({ +        prev_state.AllDirty(); +        prev_state.Apply(); +    });      OpenGLState state;      state.draw.read_framebuffer = src_framebuffer.handle;      state.draw.draw_framebuffer = dst_framebuffer.handle; +    state.AllDirty();      state.Apply();      u32 buffers{};  | 
