diff options
Diffstat (limited to 'src/video_core/renderer_opengl')
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 106 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 5 |
2 files changed, 39 insertions, 72 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 08c4df5dc..32906be7e 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -297,27 +297,18 @@ bool RasterizerOpenGL::AccelerateDrawBatch(bool is_indexed) { return true; } -void RasterizerOpenGL::Clear() { +std::pair<Surface, Surface> RasterizerOpenGL::ConfigureFramebuffers() { const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs; - GLbitfield clear_mask = 0; - if (regs.clear_buffers.R && regs.clear_buffers.G && regs.clear_buffers.B && - regs.clear_buffers.A) { - clear_mask |= GL_COLOR_BUFFER_BIT; - } - if (regs.clear_buffers.Z) - clear_mask |= GL_DEPTH_BUFFER_BIT; - - if (clear_mask == 0) - return; - // Sync the depth test state before configuring the framebuffer surfaces. SyncDepthTestState(); - // TODO(bunnei): Implement these + // TODO(bunnei): Implement this const bool has_stencil = false; + const bool using_color_fb = true; const bool using_depth_fb = regs.zeta.Address() != 0; + const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()}; const bool write_color_fb = @@ -348,11 +339,8 @@ void RasterizerOpenGL::Clear() { // Bind the framebuffer surfaces BindFramebufferSurfaces(color_surface, depth_surface, has_stencil); - // Sync the viewport SyncViewport(surfaces_rect); - // TODO(bunnei): Sync scissorbox uniform(s) here - // Viewport can have negative offsets or larger dimensions than our framebuffer sub-rect. Enable // scissor test to prevent drawing outside of the framebuffer region state.scissor.enabled = true; @@ -362,6 +350,27 @@ void RasterizerOpenGL::Clear() { state.scissor.height = draw_rect.GetHeight(); state.Apply(); + // Only return the surface to be marked as dirty if writing to it is enabled. + return std::make_pair(write_color_fb ? color_surface : nullptr, + write_depth_fb ? depth_surface : nullptr); +} + +void RasterizerOpenGL::Clear() { + const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs; + + GLbitfield clear_mask = 0; + if (regs.clear_buffers.R && regs.clear_buffers.G && regs.clear_buffers.B && + regs.clear_buffers.A) { + clear_mask |= GL_COLOR_BUFFER_BIT; + } + if (regs.clear_buffers.Z) + clear_mask |= GL_DEPTH_BUFFER_BIT; + + if (clear_mask == 0) + return; + + auto [dirty_color_surface, dirty_depth_surface] = ConfigureFramebuffers(); + // TODO(Subv): Support clearing only partial colors. glClearColor(regs.clear_color[0], regs.clear_color[1], regs.clear_color[2], regs.clear_color[3]); @@ -370,11 +379,11 @@ void RasterizerOpenGL::Clear() { glClear(clear_mask); // Mark framebuffer surfaces as dirty - if (color_surface != nullptr && write_color_fb) { - res_cache.MarkSurfaceAsDirty(color_surface); + if (dirty_color_surface != nullptr) { + res_cache.MarkSurfaceAsDirty(dirty_color_surface); } - if (depth_surface != nullptr && write_depth_fb) { - res_cache.MarkSurfaceAsDirty(depth_surface); + if (dirty_depth_surface != nullptr) { + res_cache.MarkSurfaceAsDirty(dirty_depth_surface); } } @@ -385,61 +394,14 @@ void RasterizerOpenGL::DrawArrays() { MICROPROFILE_SCOPE(OpenGL_Drawing); const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs; - // Sync the depth test state before configuring the framebuffer surfaces. - SyncDepthTestState(); - - // TODO(bunnei): Implement this - const bool has_stencil = false; - - const bool using_color_fb = true; - const bool using_depth_fb = regs.zeta.Address() != 0; - - const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()}; - - const bool write_color_fb = - state.color_mask.red_enabled == GL_TRUE || state.color_mask.green_enabled == GL_TRUE || - state.color_mask.blue_enabled == GL_TRUE || state.color_mask.alpha_enabled == GL_TRUE; - - const bool write_depth_fb = - (state.depth.test_enabled && state.depth.write_mask == GL_TRUE) || - (has_stencil && state.stencil.test_enabled && state.stencil.write_mask != 0); + auto [dirty_color_surface, dirty_depth_surface] = ConfigureFramebuffers(); - Surface color_surface; - Surface depth_surface; - MathUtil::Rectangle<u32> surfaces_rect; - std::tie(color_surface, depth_surface, surfaces_rect) = - res_cache.GetFramebufferSurfaces(using_color_fb, using_depth_fb, viewport_rect); - - MathUtil::Rectangle<u32> draw_rect{ - static_cast<u32>(std::clamp<s32>(static_cast<s32>(surfaces_rect.left) + viewport_rect.left, - surfaces_rect.left, surfaces_rect.right)), // Left - static_cast<u32>(std::clamp<s32>(static_cast<s32>(surfaces_rect.bottom) + viewport_rect.top, - surfaces_rect.bottom, surfaces_rect.top)), // Top - static_cast<u32>(std::clamp<s32>(static_cast<s32>(surfaces_rect.left) + viewport_rect.right, - surfaces_rect.left, surfaces_rect.right)), // Right - static_cast<u32>( - std::clamp<s32>(static_cast<s32>(surfaces_rect.bottom) + viewport_rect.bottom, - surfaces_rect.bottom, surfaces_rect.top))}; // Bottom - - // Bind the framebuffer surfaces - BindFramebufferSurfaces(color_surface, depth_surface, has_stencil); - - SyncViewport(surfaces_rect); SyncBlendState(); SyncCullMode(); // TODO(bunnei): Sync framebuffer_scale uniform here // TODO(bunnei): Sync scissorbox uniform(s) here - // Viewport can have negative offsets or larger dimensions than our framebuffer sub-rect. Enable - // scissor test to prevent drawing outside of the framebuffer region - state.scissor.enabled = true; - state.scissor.x = draw_rect.left; - state.scissor.y = draw_rect.bottom; - state.scissor.width = draw_rect.GetWidth(); - state.scissor.height = draw_rect.GetHeight(); - state.Apply(); - // Draw the vertex batch const bool is_indexed = accelerate_draw == AccelDraw::Indexed; const u64 index_buffer_size{regs.index_array.count * regs.index_array.FormatSizeInBytes()}; @@ -520,11 +482,11 @@ void RasterizerOpenGL::DrawArrays() { state.Apply(); // Mark framebuffer surfaces as dirty - if (color_surface != nullptr && write_color_fb) { - res_cache.MarkSurfaceAsDirty(color_surface); + if (dirty_color_surface != nullptr) { + res_cache.MarkSurfaceAsDirty(dirty_color_surface); } - if (depth_surface != nullptr && write_depth_fb) { - res_cache.MarkSurfaceAsDirty(depth_surface); + if (dirty_depth_surface != nullptr) { + res_cache.MarkSurfaceAsDirty(dirty_depth_surface); } } diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 0b1e139b0..7738f40b1 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -7,6 +7,7 @@ #include <array> #include <cstddef> #include <memory> +#include <utility> #include <vector> #include <glad/glad.h> #include "common/common_types.h" @@ -82,6 +83,10 @@ private: u32 border_color_a; }; + /// Configures the color and depth framebuffer states and returns the dirty <Color, Depth> + /// surfaces if writing was enabled. + std::pair<Surface, Surface> ConfigureFramebuffers(); + /// Binds the framebuffer color and depth surface void BindFramebufferSurfaces(const Surface& color_surface, const Surface& depth_surface, bool has_stencil); |