diff options
Diffstat (limited to '')
| -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) { | |||
| 297 | return true; | 297 | return true; |
| 298 | } | 298 | } |
| 299 | 299 | ||
| 300 | void RasterizerOpenGL::Clear() { | 300 | std::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 | |||
| 358 | void 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); |