summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp106
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h5
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);