diff options
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 12 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 29 | ||||
| -rw-r--r-- | src/video_core/rasterizer_interface.h | 3 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 71 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 6 |
5 files changed, 105 insertions, 16 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 9b209a49e..3bca16364 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp | |||
| @@ -126,6 +126,10 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) { | |||
| 126 | DrawArrays(); | 126 | DrawArrays(); |
| 127 | break; | 127 | break; |
| 128 | } | 128 | } |
| 129 | case MAXWELL3D_REG_INDEX(clear_buffers): { | ||
| 130 | ProcessClearBuffers(); | ||
| 131 | break; | ||
| 132 | } | ||
| 129 | case MAXWELL3D_REG_INDEX(query.query_get): { | 133 | case MAXWELL3D_REG_INDEX(query.query_get): { |
| 130 | ProcessQueryGet(); | 134 | ProcessQueryGet(); |
| 131 | break; | 135 | break; |
| @@ -415,5 +419,13 @@ bool Maxwell3D::IsShaderStageEnabled(Regs::ShaderStage stage) const { | |||
| 415 | UNREACHABLE(); | 419 | UNREACHABLE(); |
| 416 | } | 420 | } |
| 417 | 421 | ||
| 422 | void Maxwell3D::ProcessClearBuffers() { | ||
| 423 | ASSERT(regs.clear_buffers.R == regs.clear_buffers.G && | ||
| 424 | regs.clear_buffers.R == regs.clear_buffers.B && | ||
| 425 | regs.clear_buffers.R == regs.clear_buffers.A); | ||
| 426 | |||
| 427 | VideoCore::g_renderer->Rasterizer()->Clear(); | ||
| 428 | } | ||
| 429 | |||
| 418 | } // namespace Engines | 430 | } // namespace Engines |
| 419 | } // namespace Tegra | 431 | } // namespace Tegra |
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 12aec3549..988a6433e 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -436,7 +436,12 @@ public: | |||
| 436 | u32 count; | 436 | u32 count; |
| 437 | } vertex_buffer; | 437 | } vertex_buffer; |
| 438 | 438 | ||
| 439 | INSERT_PADDING_WORDS(0x99); | 439 | INSERT_PADDING_WORDS(1); |
| 440 | |||
| 441 | float clear_color[4]; | ||
| 442 | float clear_depth; | ||
| 443 | |||
| 444 | INSERT_PADDING_WORDS(0x93); | ||
| 440 | 445 | ||
| 441 | struct { | 446 | struct { |
| 442 | u32 address_high; | 447 | u32 address_high; |
| @@ -584,7 +589,21 @@ public: | |||
| 584 | 589 | ||
| 585 | Cull cull; | 590 | Cull cull; |
| 586 | 591 | ||
| 587 | INSERT_PADDING_WORDS(0x77); | 592 | INSERT_PADDING_WORDS(0x2B); |
| 593 | |||
| 594 | union { | ||
| 595 | u32 raw; | ||
| 596 | BitField<0, 1, u32> Z; | ||
| 597 | BitField<1, 1, u32> S; | ||
| 598 | BitField<2, 1, u32> R; | ||
| 599 | BitField<3, 1, u32> G; | ||
| 600 | BitField<4, 1, u32> B; | ||
| 601 | BitField<5, 1, u32> A; | ||
| 602 | BitField<6, 4, u32> RT; | ||
| 603 | BitField<10, 11, u32> layer; | ||
| 604 | } clear_buffers; | ||
| 605 | |||
| 606 | INSERT_PADDING_WORDS(0x4B); | ||
| 588 | 607 | ||
| 589 | struct { | 608 | struct { |
| 590 | u32 query_address_high; | 609 | u32 query_address_high; |
| @@ -766,6 +785,9 @@ private: | |||
| 766 | /// Handles writes to the macro uploading registers. | 785 | /// Handles writes to the macro uploading registers. |
| 767 | void ProcessMacroUpload(u32 data); | 786 | void ProcessMacroUpload(u32 data); |
| 768 | 787 | ||
| 788 | /// Handles a write to the CLEAR_BUFFERS register. | ||
| 789 | void ProcessClearBuffers(); | ||
| 790 | |||
| 769 | /// Handles a write to the QUERY_GET register. | 791 | /// Handles a write to the QUERY_GET register. |
| 770 | void ProcessQueryGet(); | 792 | void ProcessQueryGet(); |
| 771 | 793 | ||
| @@ -788,6 +810,8 @@ ASSERT_REG_POSITION(rt, 0x200); | |||
| 788 | ASSERT_REG_POSITION(viewport_transform[0], 0x280); | 810 | ASSERT_REG_POSITION(viewport_transform[0], 0x280); |
| 789 | ASSERT_REG_POSITION(viewport, 0x300); | 811 | ASSERT_REG_POSITION(viewport, 0x300); |
| 790 | ASSERT_REG_POSITION(vertex_buffer, 0x35D); | 812 | ASSERT_REG_POSITION(vertex_buffer, 0x35D); |
| 813 | ASSERT_REG_POSITION(clear_color[0], 0x360); | ||
| 814 | ASSERT_REG_POSITION(clear_depth, 0x364); | ||
| 791 | ASSERT_REG_POSITION(zeta, 0x3F8); | 815 | ASSERT_REG_POSITION(zeta, 0x3F8); |
| 792 | ASSERT_REG_POSITION(vertex_attrib_format[0], 0x458); | 816 | ASSERT_REG_POSITION(vertex_attrib_format[0], 0x458); |
| 793 | ASSERT_REG_POSITION(rt_control, 0x487); | 817 | ASSERT_REG_POSITION(rt_control, 0x487); |
| @@ -803,6 +827,7 @@ ASSERT_REG_POSITION(code_address, 0x582); | |||
| 803 | ASSERT_REG_POSITION(draw, 0x585); | 827 | ASSERT_REG_POSITION(draw, 0x585); |
| 804 | ASSERT_REG_POSITION(index_array, 0x5F2); | 828 | ASSERT_REG_POSITION(index_array, 0x5F2); |
| 805 | ASSERT_REG_POSITION(cull, 0x646); | 829 | ASSERT_REG_POSITION(cull, 0x646); |
| 830 | ASSERT_REG_POSITION(clear_buffers, 0x674); | ||
| 806 | ASSERT_REG_POSITION(query, 0x6C0); | 831 | ASSERT_REG_POSITION(query, 0x6C0); |
| 807 | ASSERT_REG_POSITION(vertex_array[0], 0x700); | 832 | ASSERT_REG_POSITION(vertex_array[0], 0x700); |
| 808 | ASSERT_REG_POSITION(independent_blend, 0x780); | 833 | ASSERT_REG_POSITION(independent_blend, 0x780); |
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index 145e58334..499e84b89 100644 --- a/src/video_core/rasterizer_interface.h +++ b/src/video_core/rasterizer_interface.h | |||
| @@ -19,6 +19,9 @@ public: | |||
| 19 | /// Draw the current batch of vertex arrays | 19 | /// Draw the current batch of vertex arrays |
| 20 | virtual void DrawArrays() = 0; | 20 | virtual void DrawArrays() = 0; |
| 21 | 21 | ||
| 22 | /// Clear the current framebuffer | ||
| 23 | virtual void Clear() = 0; | ||
| 24 | |||
| 22 | /// Notify rasterizer that the specified Maxwell register has been changed | 25 | /// Notify rasterizer that the specified Maxwell register has been changed |
| 23 | virtual void NotifyMaxwellRegisterChanged(u32 method) = 0; | 26 | virtual void NotifyMaxwellRegisterChanged(u32 method) = 0; |
| 24 | 27 | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index c7b7a5817..43dbf4da9 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -297,11 +297,7 @@ bool RasterizerOpenGL::AccelerateDrawBatch(bool is_indexed) { | |||
| 297 | return true; | 297 | return true; |
| 298 | } | 298 | } |
| 299 | 299 | ||
| 300 | void RasterizerOpenGL::DrawArrays() { | 300 | std::pair<Surface, Surface> RasterizerOpenGL::ConfigureFramebuffers() { |
| 301 | if (accelerate_draw == AccelDraw::Disabled) | ||
| 302 | return; | ||
| 303 | |||
| 304 | MICROPROFILE_SCOPE(OpenGL_Drawing); | ||
| 305 | const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs; | 301 | const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs; |
| 306 | 302 | ||
| 307 | // Sync the depth test state before configuring the framebuffer surfaces. | 303 | // Sync the depth test state before configuring the framebuffer surfaces. |
| @@ -344,11 +340,6 @@ void RasterizerOpenGL::DrawArrays() { | |||
| 344 | BindFramebufferSurfaces(color_surface, depth_surface, has_stencil); | 340 | BindFramebufferSurfaces(color_surface, depth_surface, has_stencil); |
| 345 | 341 | ||
| 346 | SyncViewport(surfaces_rect); | 342 | SyncViewport(surfaces_rect); |
| 347 | SyncBlendState(); | ||
| 348 | SyncCullMode(); | ||
| 349 | |||
| 350 | // TODO(bunnei): Sync framebuffer_scale uniform here | ||
| 351 | // TODO(bunnei): Sync scissorbox uniform(s) here | ||
| 352 | 343 | ||
| 353 | // 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 |
| 354 | // scissor test to prevent drawing outside of the framebuffer region | 345 | // scissor test to prevent drawing outside of the framebuffer region |
| @@ -359,6 +350,58 @@ void RasterizerOpenGL::DrawArrays() { | |||
| 359 | state.scissor.height = draw_rect.GetHeight(); | 350 | state.scissor.height = draw_rect.GetHeight(); |
| 360 | state.Apply(); | 351 | state.Apply(); |
| 361 | 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 | |||
| 374 | // TODO(Subv): Support clearing only partial colors. | ||
| 375 | glClearColor(regs.clear_color[0], regs.clear_color[1], regs.clear_color[2], | ||
| 376 | regs.clear_color[3]); | ||
| 377 | glClearDepth(regs.clear_depth); | ||
| 378 | |||
| 379 | glClear(clear_mask); | ||
| 380 | |||
| 381 | // Mark framebuffer surfaces as dirty | ||
| 382 | if (dirty_color_surface != nullptr) { | ||
| 383 | res_cache.MarkSurfaceAsDirty(dirty_color_surface); | ||
| 384 | } | ||
| 385 | if (dirty_depth_surface != nullptr) { | ||
| 386 | res_cache.MarkSurfaceAsDirty(dirty_depth_surface); | ||
| 387 | } | ||
| 388 | } | ||
| 389 | |||
| 390 | void RasterizerOpenGL::DrawArrays() { | ||
| 391 | if (accelerate_draw == AccelDraw::Disabled) | ||
| 392 | return; | ||
| 393 | |||
| 394 | MICROPROFILE_SCOPE(OpenGL_Drawing); | ||
| 395 | const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs; | ||
| 396 | |||
| 397 | auto [dirty_color_surface, dirty_depth_surface] = ConfigureFramebuffers(); | ||
| 398 | |||
| 399 | SyncBlendState(); | ||
| 400 | SyncCullMode(); | ||
| 401 | |||
| 402 | // TODO(bunnei): Sync framebuffer_scale uniform here | ||
| 403 | // TODO(bunnei): Sync scissorbox uniform(s) here | ||
| 404 | |||
| 362 | // Draw the vertex batch | 405 | // Draw the vertex batch |
| 363 | const bool is_indexed = accelerate_draw == AccelDraw::Indexed; | 406 | const bool is_indexed = accelerate_draw == AccelDraw::Indexed; |
| 364 | 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()}; |
| @@ -439,11 +482,11 @@ void RasterizerOpenGL::DrawArrays() { | |||
| 439 | state.Apply(); | 482 | state.Apply(); |
| 440 | 483 | ||
| 441 | // Mark framebuffer surfaces as dirty | 484 | // Mark framebuffer surfaces as dirty |
| 442 | if (color_surface != nullptr && write_color_fb) { | 485 | if (dirty_color_surface != nullptr) { |
| 443 | res_cache.MarkSurfaceAsDirty(color_surface); | 486 | res_cache.MarkSurfaceAsDirty(dirty_color_surface); |
| 444 | } | 487 | } |
| 445 | if (depth_surface != nullptr && write_depth_fb) { | 488 | if (dirty_depth_surface != nullptr) { |
| 446 | res_cache.MarkSurfaceAsDirty(depth_surface); | 489 | res_cache.MarkSurfaceAsDirty(dirty_depth_surface); |
| 447 | } | 490 | } |
| 448 | } | 491 | } |
| 449 | 492 | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 493aa39e5..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" |
| @@ -28,6 +29,7 @@ public: | |||
| 28 | ~RasterizerOpenGL() override; | 29 | ~RasterizerOpenGL() override; |
| 29 | 30 | ||
| 30 | void DrawArrays() override; | 31 | void DrawArrays() override; |
| 32 | void Clear() override; | ||
| 31 | void NotifyMaxwellRegisterChanged(u32 method) override; | 33 | void NotifyMaxwellRegisterChanged(u32 method) override; |
| 32 | void FlushAll() override; | 34 | void FlushAll() override; |
| 33 | void FlushRegion(Tegra::GPUVAddr addr, u64 size) override; | 35 | void FlushRegion(Tegra::GPUVAddr addr, u64 size) override; |
| @@ -81,6 +83,10 @@ private: | |||
| 81 | u32 border_color_a; | 83 | u32 border_color_a; |
| 82 | }; | 84 | }; |
| 83 | 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 | |||
| 84 | /// Binds the framebuffer color and depth surface | 90 | /// Binds the framebuffer color and depth surface |
| 85 | void BindFramebufferSurfaces(const Surface& color_surface, const Surface& depth_surface, | 91 | void BindFramebufferSurfaces(const Surface& color_surface, const Surface& depth_surface, |
| 86 | bool has_stencil); | 92 | bool has_stencil); |