summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-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) {
297 return true; 297 return true;
298} 298}
299 299
300void RasterizerOpenGL::Clear() { 300std::pair<Surface, Surface> RasterizerOpenGL::ConfigureFramebuffers() {
301 const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs; 301 const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
302 302
303 GLbitfield clear_mask = 0;
304 if (regs.clear_buffers.R && regs.clear_buffers.G && regs.clear_buffers.B &&
305 regs.clear_buffers.A) {
306 clear_mask |= GL_COLOR_BUFFER_BIT;
307 }
308 if (regs.clear_buffers.Z)
309 clear_mask |= GL_DEPTH_BUFFER_BIT;
310
311 if (clear_mask == 0)
312 return;
313
314 // Sync the depth test state before configuring the framebuffer surfaces. 303 // Sync the depth test state before configuring the framebuffer surfaces.
315 SyncDepthTestState(); 304 SyncDepthTestState();
316 305
317 // TODO(bunnei): Implement these 306 // TODO(bunnei): Implement this
318 const bool has_stencil = false; 307 const bool has_stencil = false;
308
319 const bool using_color_fb = true; 309 const bool using_color_fb = true;
320 const bool using_depth_fb = regs.zeta.Address() != 0; 310 const bool using_depth_fb = regs.zeta.Address() != 0;
311
321 const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()}; 312 const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()};
322 313
323 const bool write_color_fb = 314 const bool write_color_fb =
@@ -348,11 +339,8 @@ void RasterizerOpenGL::Clear() {
348 // Bind the framebuffer surfaces 339 // Bind the framebuffer surfaces
349 BindFramebufferSurfaces(color_surface, depth_surface, has_stencil); 340 BindFramebufferSurfaces(color_surface, depth_surface, has_stencil);
350 341
351 // Sync the viewport
352 SyncViewport(surfaces_rect); 342 SyncViewport(surfaces_rect);
353 343
354 // TODO(bunnei): Sync scissorbox uniform(s) here
355
356 // Viewport can have negative offsets or larger dimensions than our framebuffer sub-rect. Enable 344 // Viewport can have negative offsets or larger dimensions than our framebuffer sub-rect. Enable
357 // scissor test to prevent drawing outside of the framebuffer region 345 // scissor test to prevent drawing outside of the framebuffer region
358 state.scissor.enabled = true; 346 state.scissor.enabled = true;
@@ -362,6 +350,27 @@ void RasterizerOpenGL::Clear() {
362 state.scissor.height = draw_rect.GetHeight(); 350 state.scissor.height = draw_rect.GetHeight();
363 state.Apply(); 351 state.Apply();
364 352
353 // Only return the surface to be marked as dirty if writing to it is enabled.
354 return std::make_pair(write_color_fb ? color_surface : nullptr,
355 write_depth_fb ? depth_surface : nullptr);
356}
357
358void RasterizerOpenGL::Clear() {
359 const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
360
361 GLbitfield clear_mask = 0;
362 if (regs.clear_buffers.R && regs.clear_buffers.G && regs.clear_buffers.B &&
363 regs.clear_buffers.A) {
364 clear_mask |= GL_COLOR_BUFFER_BIT;
365 }
366 if (regs.clear_buffers.Z)
367 clear_mask |= GL_DEPTH_BUFFER_BIT;
368
369 if (clear_mask == 0)
370 return;
371
372 auto [dirty_color_surface, dirty_depth_surface] = ConfigureFramebuffers();
373
365 // TODO(Subv): Support clearing only partial colors. 374 // TODO(Subv): Support clearing only partial colors.
366 glClearColor(regs.clear_color[0], regs.clear_color[1], regs.clear_color[2], 375 glClearColor(regs.clear_color[0], regs.clear_color[1], regs.clear_color[2],
367 regs.clear_color[3]); 376 regs.clear_color[3]);
@@ -370,11 +379,11 @@ void RasterizerOpenGL::Clear() {
370 glClear(clear_mask); 379 glClear(clear_mask);
371 380
372 // Mark framebuffer surfaces as dirty 381 // Mark framebuffer surfaces as dirty
373 if (color_surface != nullptr && write_color_fb) { 382 if (dirty_color_surface != nullptr) {
374 res_cache.MarkSurfaceAsDirty(color_surface); 383 res_cache.MarkSurfaceAsDirty(dirty_color_surface);
375 } 384 }
376 if (depth_surface != nullptr && write_depth_fb) { 385 if (dirty_depth_surface != nullptr) {
377 res_cache.MarkSurfaceAsDirty(depth_surface); 386 res_cache.MarkSurfaceAsDirty(dirty_depth_surface);
378 } 387 }
379} 388}
380 389
@@ -385,61 +394,14 @@ void RasterizerOpenGL::DrawArrays() {
385 MICROPROFILE_SCOPE(OpenGL_Drawing); 394 MICROPROFILE_SCOPE(OpenGL_Drawing);
386 const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs; 395 const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
387 396
388 // Sync the depth test state before configuring the framebuffer surfaces. 397 auto [dirty_color_surface, dirty_depth_surface] = ConfigureFramebuffers();
389 SyncDepthTestState();
390
391 // TODO(bunnei): Implement this
392 const bool has_stencil = false;
393
394 const bool using_color_fb = true;
395 const bool using_depth_fb = regs.zeta.Address() != 0;
396
397 const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()};
398
399 const bool write_color_fb =
400 state.color_mask.red_enabled == GL_TRUE || state.color_mask.green_enabled == GL_TRUE ||
401 state.color_mask.blue_enabled == GL_TRUE || state.color_mask.alpha_enabled == GL_TRUE;
402
403 const bool write_depth_fb =
404 (state.depth.test_enabled && state.depth.write_mask == GL_TRUE) ||
405 (has_stencil && state.stencil.test_enabled && state.stencil.write_mask != 0);
406 398
407 Surface color_surface;
408 Surface depth_surface;
409 MathUtil::Rectangle<u32> surfaces_rect;
410 std::tie(color_surface, depth_surface, surfaces_rect) =
411 res_cache.GetFramebufferSurfaces(using_color_fb, using_depth_fb, viewport_rect);
412
413 MathUtil::Rectangle<u32> draw_rect{
414 static_cast<u32>(std::clamp<s32>(static_cast<s32>(surfaces_rect.left) + viewport_rect.left,
415 surfaces_rect.left, surfaces_rect.right)), // Left
416 static_cast<u32>(std::clamp<s32>(static_cast<s32>(surfaces_rect.bottom) + viewport_rect.top,
417 surfaces_rect.bottom, surfaces_rect.top)), // Top
418 static_cast<u32>(std::clamp<s32>(static_cast<s32>(surfaces_rect.left) + viewport_rect.right,
419 surfaces_rect.left, surfaces_rect.right)), // Right
420 static_cast<u32>(
421 std::clamp<s32>(static_cast<s32>(surfaces_rect.bottom) + viewport_rect.bottom,
422 surfaces_rect.bottom, surfaces_rect.top))}; // Bottom
423
424 // Bind the framebuffer surfaces
425 BindFramebufferSurfaces(color_surface, depth_surface, has_stencil);
426
427 SyncViewport(surfaces_rect);
428 SyncBlendState(); 399 SyncBlendState();
429 SyncCullMode(); 400 SyncCullMode();
430 401
431 // TODO(bunnei): Sync framebuffer_scale uniform here 402 // TODO(bunnei): Sync framebuffer_scale uniform here
432 // TODO(bunnei): Sync scissorbox uniform(s) here 403 // TODO(bunnei): Sync scissorbox uniform(s) here
433 404
434 // Viewport can have negative offsets or larger dimensions than our framebuffer sub-rect. Enable
435 // scissor test to prevent drawing outside of the framebuffer region
436 state.scissor.enabled = true;
437 state.scissor.x = draw_rect.left;
438 state.scissor.y = draw_rect.bottom;
439 state.scissor.width = draw_rect.GetWidth();
440 state.scissor.height = draw_rect.GetHeight();
441 state.Apply();
442
443 // Draw the vertex batch 405 // Draw the vertex batch
444 const bool is_indexed = accelerate_draw == AccelDraw::Indexed; 406 const bool is_indexed = accelerate_draw == AccelDraw::Indexed;
445 const u64 index_buffer_size{regs.index_array.count * regs.index_array.FormatSizeInBytes()}; 407 const u64 index_buffer_size{regs.index_array.count * regs.index_array.FormatSizeInBytes()};
@@ -520,11 +482,11 @@ void RasterizerOpenGL::DrawArrays() {
520 state.Apply(); 482 state.Apply();
521 483
522 // Mark framebuffer surfaces as dirty 484 // Mark framebuffer surfaces as dirty
523 if (color_surface != nullptr && write_color_fb) { 485 if (dirty_color_surface != nullptr) {
524 res_cache.MarkSurfaceAsDirty(color_surface); 486 res_cache.MarkSurfaceAsDirty(dirty_color_surface);
525 } 487 }
526 if (depth_surface != nullptr && write_depth_fb) { 488 if (dirty_depth_surface != nullptr) {
527 res_cache.MarkSurfaceAsDirty(depth_surface); 489 res_cache.MarkSurfaceAsDirty(dirty_depth_surface);
528 } 490 }
529} 491}
530 492
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 @@
7#include <array> 7#include <array>
8#include <cstddef> 8#include <cstddef>
9#include <memory> 9#include <memory>
10#include <utility>
10#include <vector> 11#include <vector>
11#include <glad/glad.h> 12#include <glad/glad.h>
12#include "common/common_types.h" 13#include "common/common_types.h"
@@ -82,6 +83,10 @@ private:
82 u32 border_color_a; 83 u32 border_color_a;
83 }; 84 };
84 85
86 /// Configures the color and depth framebuffer states and returns the dirty <Color, Depth>
87 /// surfaces if writing was enabled.
88 std::pair<Surface, Surface> ConfigureFramebuffers();
89
85 /// Binds the framebuffer color and depth surface 90 /// Binds the framebuffer color and depth surface
86 void BindFramebufferSurfaces(const Surface& color_surface, const Surface& depth_surface, 91 void BindFramebufferSurfaces(const Surface& color_surface, const Surface& depth_surface,
87 bool has_stencil); 92 bool has_stencil);