diff options
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 16 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 28 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 138 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.h | 47 |
4 files changed, 157 insertions, 72 deletions
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index dbd106c53..3c32f1067 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -487,7 +487,12 @@ public: | |||
| 487 | }; | 487 | }; |
| 488 | } rt_control; | 488 | } rt_control; |
| 489 | 489 | ||
| 490 | INSERT_PADDING_WORDS(0x2B); | 490 | INSERT_PADDING_WORDS(0x2); |
| 491 | |||
| 492 | u32 zeta_width; | ||
| 493 | u32 zeta_height; | ||
| 494 | |||
| 495 | INSERT_PADDING_WORDS(0x27); | ||
| 491 | 496 | ||
| 492 | u32 depth_test_enable; | 497 | u32 depth_test_enable; |
| 493 | 498 | ||
| @@ -540,7 +545,11 @@ public: | |||
| 540 | 545 | ||
| 541 | u32 vb_element_base; | 546 | u32 vb_element_base; |
| 542 | 547 | ||
| 543 | INSERT_PADDING_WORDS(0x49); | 548 | INSERT_PADDING_WORDS(0x40); |
| 549 | |||
| 550 | u32 zeta_enable; | ||
| 551 | |||
| 552 | INSERT_PADDING_WORDS(0x8); | ||
| 544 | 553 | ||
| 545 | struct { | 554 | struct { |
| 546 | u32 tsc_address_high; | 555 | u32 tsc_address_high; |
| @@ -865,6 +874,8 @@ ASSERT_REG_POSITION(clear_depth, 0x364); | |||
| 865 | ASSERT_REG_POSITION(zeta, 0x3F8); | 874 | ASSERT_REG_POSITION(zeta, 0x3F8); |
| 866 | ASSERT_REG_POSITION(vertex_attrib_format[0], 0x458); | 875 | ASSERT_REG_POSITION(vertex_attrib_format[0], 0x458); |
| 867 | ASSERT_REG_POSITION(rt_control, 0x487); | 876 | ASSERT_REG_POSITION(rt_control, 0x487); |
| 877 | ASSERT_REG_POSITION(zeta_width, 0x48a); | ||
| 878 | ASSERT_REG_POSITION(zeta_height, 0x48b); | ||
| 868 | ASSERT_REG_POSITION(depth_test_enable, 0x4B3); | 879 | ASSERT_REG_POSITION(depth_test_enable, 0x4B3); |
| 869 | ASSERT_REG_POSITION(independent_blend_enable, 0x4B9); | 880 | ASSERT_REG_POSITION(independent_blend_enable, 0x4B9); |
| 870 | ASSERT_REG_POSITION(depth_write_enabled, 0x4BA); | 881 | ASSERT_REG_POSITION(depth_write_enabled, 0x4BA); |
| @@ -874,6 +885,7 @@ ASSERT_REG_POSITION(blend, 0x4CF); | |||
| 874 | ASSERT_REG_POSITION(stencil, 0x4E0); | 885 | ASSERT_REG_POSITION(stencil, 0x4E0); |
| 875 | ASSERT_REG_POSITION(screen_y_control, 0x4EB); | 886 | ASSERT_REG_POSITION(screen_y_control, 0x4EB); |
| 876 | ASSERT_REG_POSITION(vb_element_base, 0x50D); | 887 | ASSERT_REG_POSITION(vb_element_base, 0x50D); |
| 888 | ASSERT_REG_POSITION(zeta_enable, 0x54E); | ||
| 877 | ASSERT_REG_POSITION(tsc, 0x557); | 889 | ASSERT_REG_POSITION(tsc, 0x557); |
| 878 | ASSERT_REG_POSITION(tic, 0x55D); | 890 | ASSERT_REG_POSITION(tic, 0x55D); |
| 879 | ASSERT_REG_POSITION(stencil_two_side, 0x565); | 891 | ASSERT_REG_POSITION(stencil_two_side, 0x565); |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 65a2fd5e8..56d9c575b 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -387,7 +387,7 @@ void RasterizerOpenGL::Clear() { | |||
| 387 | } | 387 | } |
| 388 | if (regs.clear_buffers.Z) { | 388 | if (regs.clear_buffers.Z) { |
| 389 | clear_mask |= GL_DEPTH_BUFFER_BIT; | 389 | clear_mask |= GL_DEPTH_BUFFER_BIT; |
| 390 | use_depth_fb = true; | 390 | use_depth_fb = regs.zeta_enable != 0; |
| 391 | 391 | ||
| 392 | // Always enable the depth write when clearing the depth buffer. The depth write mask is | 392 | // Always enable the depth write when clearing the depth buffer. The depth write mask is |
| 393 | // ignored when clearing the buffer in the Switch, but OpenGL obeys it so we set it to true. | 393 | // ignored when clearing the buffer in the Switch, but OpenGL obeys it so we set it to true. |
| @@ -413,11 +413,13 @@ void RasterizerOpenGL::Clear() { | |||
| 413 | glClear(clear_mask); | 413 | glClear(clear_mask); |
| 414 | 414 | ||
| 415 | // Mark framebuffer surfaces as dirty | 415 | // Mark framebuffer surfaces as dirty |
| 416 | if (dirty_color_surface != nullptr) { | 416 | if (Settings::values.use_accurate_framebuffers) { |
| 417 | res_cache.MarkSurfaceAsDirty(dirty_color_surface); | 417 | if (dirty_color_surface != nullptr) { |
| 418 | } | 418 | res_cache.FlushSurface(dirty_color_surface); |
| 419 | if (dirty_depth_surface != nullptr) { | 419 | } |
| 420 | res_cache.MarkSurfaceAsDirty(dirty_depth_surface); | 420 | if (dirty_depth_surface != nullptr) { |
| 421 | res_cache.FlushSurface(dirty_depth_surface); | ||
| 422 | } | ||
| 421 | } | 423 | } |
| 422 | } | 424 | } |
| 423 | 425 | ||
| @@ -431,7 +433,7 @@ void RasterizerOpenGL::DrawArrays() { | |||
| 431 | ScopeAcquireGLContext acquire_context; | 433 | ScopeAcquireGLContext acquire_context; |
| 432 | 434 | ||
| 433 | auto [dirty_color_surface, dirty_depth_surface] = | 435 | auto [dirty_color_surface, dirty_depth_surface] = |
| 434 | ConfigureFramebuffers(true, regs.zeta.Address() != 0); | 436 | ConfigureFramebuffers(true, regs.zeta.Address() != 0 && regs.zeta_enable != 0); |
| 435 | 437 | ||
| 436 | SyncDepthTestState(); | 438 | SyncDepthTestState(); |
| 437 | SyncBlendState(); | 439 | SyncBlendState(); |
| @@ -520,11 +522,13 @@ void RasterizerOpenGL::DrawArrays() { | |||
| 520 | state.Apply(); | 522 | state.Apply(); |
| 521 | 523 | ||
| 522 | // Mark framebuffer surfaces as dirty | 524 | // Mark framebuffer surfaces as dirty |
| 523 | if (dirty_color_surface != nullptr) { | 525 | if (Settings::values.use_accurate_framebuffers) { |
| 524 | res_cache.MarkSurfaceAsDirty(dirty_color_surface); | 526 | if (dirty_color_surface != nullptr) { |
| 525 | } | 527 | res_cache.FlushSurface(dirty_color_surface); |
| 526 | if (dirty_depth_surface != nullptr) { | 528 | } |
| 527 | res_cache.MarkSurfaceAsDirty(dirty_depth_surface); | 529 | if (dirty_depth_surface != nullptr) { |
| 530 | res_cache.FlushSurface(dirty_depth_surface); | ||
| 531 | } | ||
| 528 | } | 532 | } |
| 529 | } | 533 | } |
| 530 | 534 | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 2c43982b0..28f0bc379 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | |||
| @@ -65,9 +65,9 @@ struct FormatTuple { | |||
| 65 | return params; | 65 | return params; |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | /*static*/ SurfaceParams SurfaceParams::CreateForDepthBuffer( | 68 | /*static*/ SurfaceParams SurfaceParams::CreateForDepthBuffer(u32 zeta_width, u32 zeta_height, |
| 69 | const Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig& config, Tegra::GPUVAddr zeta_address, | 69 | Tegra::GPUVAddr zeta_address, |
| 70 | Tegra::DepthFormat format) { | 70 | Tegra::DepthFormat format) { |
| 71 | 71 | ||
| 72 | SurfaceParams params{}; | 72 | SurfaceParams params{}; |
| 73 | params.addr = zeta_address; | 73 | params.addr = zeta_address; |
| @@ -77,9 +77,9 @@ struct FormatTuple { | |||
| 77 | params.component_type = ComponentTypeFromDepthFormat(format); | 77 | params.component_type = ComponentTypeFromDepthFormat(format); |
| 78 | params.type = GetFormatType(params.pixel_format); | 78 | params.type = GetFormatType(params.pixel_format); |
| 79 | params.size_in_bytes = params.SizeInBytes(); | 79 | params.size_in_bytes = params.SizeInBytes(); |
| 80 | params.width = config.width; | 80 | params.width = zeta_width; |
| 81 | params.height = config.height; | 81 | params.height = zeta_height; |
| 82 | params.unaligned_height = config.height; | 82 | params.unaligned_height = zeta_height; |
| 83 | params.size_in_bytes = params.SizeInBytes(); | 83 | params.size_in_bytes = params.SizeInBytes(); |
| 84 | return params; | 84 | return params; |
| 85 | } | 85 | } |
| @@ -254,6 +254,60 @@ static void AllocateSurfaceTexture(GLuint texture, const FormatTuple& format_tup | |||
| 254 | cur_state.Apply(); | 254 | cur_state.Apply(); |
| 255 | } | 255 | } |
| 256 | 256 | ||
| 257 | static bool BlitTextures(GLuint src_tex, const MathUtil::Rectangle<u32>& src_rect, GLuint dst_tex, | ||
| 258 | const MathUtil::Rectangle<u32>& dst_rect, SurfaceType type, | ||
| 259 | GLuint read_fb_handle, GLuint draw_fb_handle) { | ||
| 260 | OpenGLState prev_state{OpenGLState::GetCurState()}; | ||
| 261 | SCOPE_EXIT({ prev_state.Apply(); }); | ||
| 262 | |||
| 263 | OpenGLState state; | ||
| 264 | state.draw.read_framebuffer = read_fb_handle; | ||
| 265 | state.draw.draw_framebuffer = draw_fb_handle; | ||
| 266 | state.Apply(); | ||
| 267 | |||
| 268 | u32 buffers{}; | ||
| 269 | |||
| 270 | if (type == SurfaceType::ColorTexture) { | ||
| 271 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, src_tex, | ||
| 272 | 0); | ||
| 273 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, | ||
| 274 | 0); | ||
| 275 | |||
| 276 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_tex, | ||
| 277 | 0); | ||
| 278 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, | ||
| 279 | 0); | ||
| 280 | |||
| 281 | buffers = GL_COLOR_BUFFER_BIT; | ||
| 282 | } else if (type == SurfaceType::Depth) { | ||
| 283 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); | ||
| 284 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, src_tex, 0); | ||
| 285 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); | ||
| 286 | |||
| 287 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); | ||
| 288 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, dst_tex, 0); | ||
| 289 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); | ||
| 290 | |||
| 291 | buffers = GL_DEPTH_BUFFER_BIT; | ||
| 292 | } else if (type == SurfaceType::DepthStencil) { | ||
| 293 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); | ||
| 294 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, | ||
| 295 | src_tex, 0); | ||
| 296 | |||
| 297 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); | ||
| 298 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, | ||
| 299 | dst_tex, 0); | ||
| 300 | |||
| 301 | buffers = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; | ||
| 302 | } | ||
| 303 | |||
| 304 | glBlitFramebuffer(src_rect.left, src_rect.bottom, src_rect.right, src_rect.top, dst_rect.left, | ||
| 305 | dst_rect.bottom, dst_rect.right, dst_rect.top, buffers, | ||
| 306 | buffers == GL_COLOR_BUFFER_BIT ? GL_LINEAR : GL_NEAREST); | ||
| 307 | |||
| 308 | return true; | ||
| 309 | } | ||
| 310 | |||
| 257 | CachedSurface::CachedSurface(const SurfaceParams& params) : params(params) { | 311 | CachedSurface::CachedSurface(const SurfaceParams& params) : params(params) { |
| 258 | texture.Create(); | 312 | texture.Create(); |
| 259 | const auto& rect{params.GetRect()}; | 313 | const auto& rect{params.GetRect()}; |
| @@ -519,8 +573,8 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces( | |||
| 519 | } | 573 | } |
| 520 | 574 | ||
| 521 | if (using_depth_fb) { | 575 | if (using_depth_fb) { |
| 522 | depth_params = | 576 | depth_params = SurfaceParams::CreateForDepthBuffer(regs.zeta_width, regs.zeta_height, |
| 523 | SurfaceParams::CreateForDepthBuffer(regs.rt[0], regs.zeta.Address(), regs.zeta.format); | 577 | regs.zeta.Address(), regs.zeta.format); |
| 524 | } | 578 | } |
| 525 | 579 | ||
| 526 | MathUtil::Rectangle<u32> color_rect{}; | 580 | MathUtil::Rectangle<u32> color_rect{}; |
| @@ -565,17 +619,9 @@ void RasterizerCacheOpenGL::LoadSurface(const Surface& surface) { | |||
| 565 | surface->UploadGLTexture(read_framebuffer.handle, draw_framebuffer.handle); | 619 | surface->UploadGLTexture(read_framebuffer.handle, draw_framebuffer.handle); |
| 566 | } | 620 | } |
| 567 | 621 | ||
| 568 | void RasterizerCacheOpenGL::MarkSurfaceAsDirty(const Surface& surface) { | 622 | void RasterizerCacheOpenGL::FlushSurface(const Surface& surface) { |
| 569 | if (Settings::values.use_accurate_framebuffers) { | 623 | surface->DownloadGLTexture(read_framebuffer.handle, draw_framebuffer.handle); |
| 570 | // If enabled, always flush dirty surfaces | 624 | surface->FlushGLBuffer(); |
| 571 | surface->DownloadGLTexture(read_framebuffer.handle, draw_framebuffer.handle); | ||
| 572 | surface->FlushGLBuffer(); | ||
| 573 | } else { | ||
| 574 | // Otherwise, don't mark surfaces that we write to as cached, because the resulting loads | ||
| 575 | // and flushes are very slow and do not seem to improve accuracy | ||
| 576 | const auto& params{surface->GetSurfaceParams()}; | ||
| 577 | Memory::RasterizerMarkRegionCached(params.addr, params.size_in_bytes, false); | ||
| 578 | } | ||
| 579 | } | 625 | } |
| 580 | 626 | ||
| 581 | Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params) { | 627 | Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params) { |
| @@ -588,25 +634,53 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params) { | |||
| 588 | if (gpu.memory_manager->GpuToCpuAddress(params.addr) == boost::none) | 634 | if (gpu.memory_manager->GpuToCpuAddress(params.addr) == boost::none) |
| 589 | return {}; | 635 | return {}; |
| 590 | 636 | ||
| 591 | // Check for an exact match in existing surfaces | 637 | // Look up surface in the cache based on address |
| 592 | const auto& surface_key{SurfaceKey::Create(params)}; | 638 | const auto& search{surface_cache.find(params.addr)}; |
| 593 | const auto& search{surface_cache.find(surface_key)}; | ||
| 594 | Surface surface; | 639 | Surface surface; |
| 595 | if (search != surface_cache.end()) { | 640 | if (search != surface_cache.end()) { |
| 596 | surface = search->second; | 641 | surface = search->second; |
| 597 | if (Settings::values.use_accurate_framebuffers) { | 642 | if (Settings::values.use_accurate_framebuffers) { |
| 598 | // Reload the surface from Switch memory | 643 | // If use_accurate_framebuffers is enabled, always load from memory |
| 599 | LoadSurface(surface); | 644 | FlushSurface(surface); |
| 645 | UnregisterSurface(surface); | ||
| 646 | } else if (surface->GetSurfaceParams() != params) { | ||
| 647 | // If surface parameters changed, recreate the surface from the old one | ||
| 648 | return RecreateSurface(surface, params); | ||
| 649 | } else { | ||
| 650 | // Use the cached surface as-is | ||
| 651 | return surface; | ||
| 600 | } | 652 | } |
| 601 | } else { | ||
| 602 | surface = std::make_shared<CachedSurface>(params); | ||
| 603 | RegisterSurface(surface); | ||
| 604 | LoadSurface(surface); | ||
| 605 | } | 653 | } |
| 606 | 654 | ||
| 655 | // No surface found - create a new one | ||
| 656 | surface = std::make_shared<CachedSurface>(params); | ||
| 657 | RegisterSurface(surface); | ||
| 658 | LoadSurface(surface); | ||
| 659 | |||
| 607 | return surface; | 660 | return surface; |
| 608 | } | 661 | } |
| 609 | 662 | ||
| 663 | Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& surface, | ||
| 664 | const SurfaceParams& new_params) { | ||
| 665 | // Verify surface is compatible for blitting | ||
| 666 | const auto& params{surface->GetSurfaceParams()}; | ||
| 667 | ASSERT(params.type == new_params.type); | ||
| 668 | ASSERT(params.pixel_format == new_params.pixel_format); | ||
| 669 | ASSERT(params.component_type == new_params.component_type); | ||
| 670 | |||
| 671 | // Create a new surface with the new parameters, and blit the previous surface to it | ||
| 672 | Surface new_surface{std::make_shared<CachedSurface>(new_params)}; | ||
| 673 | BlitTextures(surface->Texture().handle, params.GetRect(), new_surface->Texture().handle, | ||
| 674 | new_surface->GetSurfaceParams().GetRect(), params.type, read_framebuffer.handle, | ||
| 675 | draw_framebuffer.handle); | ||
| 676 | |||
| 677 | // Update cache accordingly | ||
| 678 | UnregisterSurface(surface); | ||
| 679 | RegisterSurface(new_surface); | ||
| 680 | |||
| 681 | return new_surface; | ||
| 682 | } | ||
| 683 | |||
| 610 | Surface RasterizerCacheOpenGL::TryFindFramebufferSurface(VAddr cpu_addr) const { | 684 | Surface RasterizerCacheOpenGL::TryFindFramebufferSurface(VAddr cpu_addr) const { |
| 611 | // Tries to find the GPU address of a framebuffer based on the CPU address. This is because | 685 | // Tries to find the GPU address of a framebuffer based on the CPU address. This is because |
| 612 | // final output framebuffers are specified by CPU address, but internally our GPU cache uses | 686 | // final output framebuffers are specified by CPU address, but internally our GPU cache uses |
| @@ -652,22 +726,20 @@ void RasterizerCacheOpenGL::InvalidateRegion(Tegra::GPUVAddr addr, size_t size) | |||
| 652 | 726 | ||
| 653 | void RasterizerCacheOpenGL::RegisterSurface(const Surface& surface) { | 727 | void RasterizerCacheOpenGL::RegisterSurface(const Surface& surface) { |
| 654 | const auto& params{surface->GetSurfaceParams()}; | 728 | const auto& params{surface->GetSurfaceParams()}; |
| 655 | const auto& surface_key{SurfaceKey::Create(params)}; | 729 | const auto& search{surface_cache.find(params.addr)}; |
| 656 | const auto& search{surface_cache.find(surface_key)}; | ||
| 657 | 730 | ||
| 658 | if (search != surface_cache.end()) { | 731 | if (search != surface_cache.end()) { |
| 659 | // Registered already | 732 | // Registered already |
| 660 | return; | 733 | return; |
| 661 | } | 734 | } |
| 662 | 735 | ||
| 663 | surface_cache[surface_key] = surface; | 736 | surface_cache[params.addr] = surface; |
| 664 | UpdatePagesCachedCount(params.addr, params.size_in_bytes, 1); | 737 | UpdatePagesCachedCount(params.addr, params.size_in_bytes, 1); |
| 665 | } | 738 | } |
| 666 | 739 | ||
| 667 | void RasterizerCacheOpenGL::UnregisterSurface(const Surface& surface) { | 740 | void RasterizerCacheOpenGL::UnregisterSurface(const Surface& surface) { |
| 668 | const auto& params{surface->GetSurfaceParams()}; | 741 | const auto& params{surface->GetSurfaceParams()}; |
| 669 | const auto& surface_key{SurfaceKey::Create(params)}; | 742 | const auto& search{surface_cache.find(params.addr)}; |
| 670 | const auto& search{surface_cache.find(surface_key)}; | ||
| 671 | 743 | ||
| 672 | if (search == surface_cache.end()) { | 744 | if (search == surface_cache.end()) { |
| 673 | // Unregistered already | 745 | // Unregistered already |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 718c45ce1..b084c4db4 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h | |||
| @@ -10,7 +10,6 @@ | |||
| 10 | #include <vector> | 10 | #include <vector> |
| 11 | #include <boost/icl/interval_map.hpp> | 11 | #include <boost/icl/interval_map.hpp> |
| 12 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 13 | #include "common/hash.h" | ||
| 14 | #include "common/math_util.h" | 13 | #include "common/math_util.h" |
| 15 | #include "video_core/engines/maxwell_3d.h" | 14 | #include "video_core/engines/maxwell_3d.h" |
| 16 | #include "video_core/renderer_opengl/gl_resource_manager.h" | 15 | #include "video_core/renderer_opengl/gl_resource_manager.h" |
| @@ -137,6 +136,7 @@ struct SurfaceParams { | |||
| 137 | ASSERT(static_cast<size_t>(format) < bpp_table.size()); | 136 | ASSERT(static_cast<size_t>(format) < bpp_table.size()); |
| 138 | return bpp_table[static_cast<size_t>(format)]; | 137 | return bpp_table[static_cast<size_t>(format)]; |
| 139 | } | 138 | } |
| 139 | |||
| 140 | u32 GetFormatBpp() const { | 140 | u32 GetFormatBpp() const { |
| 141 | return GetFormatBpp(pixel_format); | 141 | return GetFormatBpp(pixel_format); |
| 142 | } | 142 | } |
| @@ -365,9 +365,21 @@ struct SurfaceParams { | |||
| 365 | const Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig& config); | 365 | const Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig& config); |
| 366 | 366 | ||
| 367 | /// Creates SurfaceParams for a depth buffer configuration | 367 | /// Creates SurfaceParams for a depth buffer configuration |
| 368 | static SurfaceParams CreateForDepthBuffer( | 368 | static SurfaceParams CreateForDepthBuffer(u32 zeta_width, u32 zeta_height, |
| 369 | const Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig& config, | 369 | Tegra::GPUVAddr zeta_address, |
| 370 | Tegra::GPUVAddr zeta_address, Tegra::DepthFormat format); | 370 | Tegra::DepthFormat format); |
| 371 | |||
| 372 | bool operator==(const SurfaceParams& other) const { | ||
| 373 | return std::tie(addr, is_tiled, block_height, pixel_format, component_type, type, width, | ||
| 374 | height, unaligned_height, size_in_bytes) == | ||
| 375 | std::tie(other.addr, other.is_tiled, other.block_height, other.pixel_format, | ||
| 376 | other.component_type, other.type, other.width, other.height, | ||
| 377 | other.unaligned_height, other.size_in_bytes); | ||
| 378 | } | ||
| 379 | |||
| 380 | bool operator!=(const SurfaceParams& other) const { | ||
| 381 | return !operator==(other); | ||
| 382 | } | ||
| 371 | 383 | ||
| 372 | Tegra::GPUVAddr addr; | 384 | Tegra::GPUVAddr addr; |
| 373 | bool is_tiled; | 385 | bool is_tiled; |
| @@ -381,24 +393,6 @@ struct SurfaceParams { | |||
| 381 | size_t size_in_bytes; | 393 | size_t size_in_bytes; |
| 382 | }; | 394 | }; |
| 383 | 395 | ||
| 384 | /// Hashable variation of SurfaceParams, used for a key in the surface cache | ||
| 385 | struct SurfaceKey : Common::HashableStruct<SurfaceParams> { | ||
| 386 | static SurfaceKey Create(const SurfaceParams& params) { | ||
| 387 | SurfaceKey res; | ||
| 388 | res.state = params; | ||
| 389 | return res; | ||
| 390 | } | ||
| 391 | }; | ||
| 392 | |||
| 393 | namespace std { | ||
| 394 | template <> | ||
| 395 | struct hash<SurfaceKey> { | ||
| 396 | size_t operator()(const SurfaceKey& k) const { | ||
| 397 | return k.Hash(); | ||
| 398 | } | ||
| 399 | }; | ||
| 400 | } // namespace std | ||
| 401 | |||
| 402 | class CachedSurface final { | 396 | class CachedSurface final { |
| 403 | public: | 397 | public: |
| 404 | CachedSurface(const SurfaceParams& params); | 398 | CachedSurface(const SurfaceParams& params); |
| @@ -444,8 +438,8 @@ public: | |||
| 444 | SurfaceSurfaceRect_Tuple GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb, | 438 | SurfaceSurfaceRect_Tuple GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb, |
| 445 | const MathUtil::Rectangle<s32>& viewport); | 439 | const MathUtil::Rectangle<s32>& viewport); |
| 446 | 440 | ||
| 447 | /// Marks the specified surface as "dirty", in that it is out of sync with Switch memory | 441 | /// Flushes the surface to Switch memory |
| 448 | void MarkSurfaceAsDirty(const Surface& surface); | 442 | void FlushSurface(const Surface& surface); |
| 449 | 443 | ||
| 450 | /// Tries to find a framebuffer GPU address based on the provided CPU address | 444 | /// Tries to find a framebuffer GPU address based on the provided CPU address |
| 451 | Surface TryFindFramebufferSurface(VAddr cpu_addr) const; | 445 | Surface TryFindFramebufferSurface(VAddr cpu_addr) const; |
| @@ -460,6 +454,9 @@ private: | |||
| 460 | void LoadSurface(const Surface& surface); | 454 | void LoadSurface(const Surface& surface); |
| 461 | Surface GetSurface(const SurfaceParams& params); | 455 | Surface GetSurface(const SurfaceParams& params); |
| 462 | 456 | ||
| 457 | /// Recreates a surface with new parameters | ||
| 458 | Surface RecreateSurface(const Surface& surface, const SurfaceParams& new_params); | ||
| 459 | |||
| 463 | /// Register surface into the cache | 460 | /// Register surface into the cache |
| 464 | void RegisterSurface(const Surface& surface); | 461 | void RegisterSurface(const Surface& surface); |
| 465 | 462 | ||
| @@ -469,7 +466,7 @@ private: | |||
| 469 | /// Increase/decrease the number of surface in pages touching the specified region | 466 | /// Increase/decrease the number of surface in pages touching the specified region |
| 470 | void UpdatePagesCachedCount(Tegra::GPUVAddr addr, u64 size, int delta); | 467 | void UpdatePagesCachedCount(Tegra::GPUVAddr addr, u64 size, int delta); |
| 471 | 468 | ||
| 472 | std::unordered_map<SurfaceKey, Surface> surface_cache; | 469 | std::unordered_map<Tegra::GPUVAddr, Surface> surface_cache; |
| 473 | PageMap cached_pages; | 470 | PageMap cached_pages; |
| 474 | 471 | ||
| 475 | OGLFramebuffer read_framebuffer; | 472 | OGLFramebuffer read_framebuffer; |