diff options
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 24 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 41 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.h | 38 |
3 files changed, 46 insertions, 57 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index c4ce57f1c..56d9c575b 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -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 | ||
| @@ -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 672eb2990..bb53a2821 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | |||
| @@ -565,17 +565,9 @@ void RasterizerCacheOpenGL::LoadSurface(const Surface& surface) { | |||
| 565 | surface->UploadGLTexture(read_framebuffer.handle, draw_framebuffer.handle); | 565 | surface->UploadGLTexture(read_framebuffer.handle, draw_framebuffer.handle); |
| 566 | } | 566 | } |
| 567 | 567 | ||
| 568 | void RasterizerCacheOpenGL::MarkSurfaceAsDirty(const Surface& surface) { | 568 | void RasterizerCacheOpenGL::FlushSurface(const Surface& surface) { |
| 569 | if (Settings::values.use_accurate_framebuffers) { | 569 | surface->DownloadGLTexture(read_framebuffer.handle, draw_framebuffer.handle); |
| 570 | // If enabled, always flush dirty surfaces | 570 | 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 | } | 571 | } |
| 580 | 572 | ||
| 581 | Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params) { | 573 | Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params) { |
| @@ -589,21 +581,22 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params) { | |||
| 589 | return {}; | 581 | return {}; |
| 590 | 582 | ||
| 591 | // Check for an exact match in existing surfaces | 583 | // Check for an exact match in existing surfaces |
| 592 | const auto& surface_key{SurfaceKey::Create(params)}; | 584 | const auto& search{surface_cache.find(params.addr)}; |
| 593 | const auto& search{surface_cache.find(surface_key)}; | ||
| 594 | Surface surface; | 585 | Surface surface; |
| 595 | if (search != surface_cache.end()) { | 586 | if (search != surface_cache.end()) { |
| 596 | surface = search->second; | 587 | surface = search->second; |
| 597 | if (Settings::values.use_accurate_framebuffers) { | 588 | if (surface->GetSurfaceParams() != params || Settings::values.use_accurate_framebuffers) { |
| 598 | // Reload the surface from Switch memory | 589 | FlushSurface(surface); |
| 599 | LoadSurface(surface); | 590 | UnregisterSurface(surface); |
| 591 | } else { | ||
| 592 | return surface; | ||
| 600 | } | 593 | } |
| 601 | } else { | ||
| 602 | surface = std::make_shared<CachedSurface>(params); | ||
| 603 | RegisterSurface(surface); | ||
| 604 | LoadSurface(surface); | ||
| 605 | } | 594 | } |
| 606 | 595 | ||
| 596 | surface = std::make_shared<CachedSurface>(params); | ||
| 597 | RegisterSurface(surface); | ||
| 598 | LoadSurface(surface); | ||
| 599 | |||
| 607 | return surface; | 600 | return surface; |
| 608 | } | 601 | } |
| 609 | 602 | ||
| @@ -652,22 +645,20 @@ void RasterizerCacheOpenGL::InvalidateRegion(Tegra::GPUVAddr addr, size_t size) | |||
| 652 | 645 | ||
| 653 | void RasterizerCacheOpenGL::RegisterSurface(const Surface& surface) { | 646 | void RasterizerCacheOpenGL::RegisterSurface(const Surface& surface) { |
| 654 | const auto& params{surface->GetSurfaceParams()}; | 647 | const auto& params{surface->GetSurfaceParams()}; |
| 655 | const auto& surface_key{SurfaceKey::Create(params)}; | 648 | const auto& search{surface_cache.find(params.addr)}; |
| 656 | const auto& search{surface_cache.find(surface_key)}; | ||
| 657 | 649 | ||
| 658 | if (search != surface_cache.end()) { | 650 | if (search != surface_cache.end()) { |
| 659 | // Registered already | 651 | // Registered already |
| 660 | return; | 652 | return; |
| 661 | } | 653 | } |
| 662 | 654 | ||
| 663 | surface_cache[surface_key] = surface; | 655 | surface_cache[params.addr] = surface; |
| 664 | UpdatePagesCachedCount(params.addr, params.size_in_bytes, 1); | 656 | UpdatePagesCachedCount(params.addr, params.size_in_bytes, 1); |
| 665 | } | 657 | } |
| 666 | 658 | ||
| 667 | void RasterizerCacheOpenGL::UnregisterSurface(const Surface& surface) { | 659 | void RasterizerCacheOpenGL::UnregisterSurface(const Surface& surface) { |
| 668 | const auto& params{surface->GetSurfaceParams()}; | 660 | const auto& params{surface->GetSurfaceParams()}; |
| 669 | const auto& surface_key{SurfaceKey::Create(params)}; | 661 | const auto& search{surface_cache.find(params.addr)}; |
| 670 | const auto& search{surface_cache.find(surface_key)}; | ||
| 671 | 662 | ||
| 672 | if (search == surface_cache.end()) { | 663 | if (search == surface_cache.end()) { |
| 673 | // Unregistered already | 664 | // 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 d00746e8c..5124199b2 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 | } |
| @@ -369,6 +369,18 @@ struct SurfaceParams { | |||
| 369 | Tegra::GPUVAddr zeta_address, | 369 | Tegra::GPUVAddr zeta_address, |
| 370 | Tegra::DepthFormat format); | 370 | Tegra::DepthFormat format); |
| 371 | 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 | } | ||
| 383 | |||
| 372 | Tegra::GPUVAddr addr; | 384 | Tegra::GPUVAddr addr; |
| 373 | bool is_tiled; | 385 | bool is_tiled; |
| 374 | u32 block_height; | 386 | u32 block_height; |
| @@ -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; |
| @@ -469,7 +463,7 @@ private: | |||
| 469 | /// Increase/decrease the number of surface in pages touching the specified region | 463 | /// Increase/decrease the number of surface in pages touching the specified region |
| 470 | void UpdatePagesCachedCount(Tegra::GPUVAddr addr, u64 size, int delta); | 464 | void UpdatePagesCachedCount(Tegra::GPUVAddr addr, u64 size, int delta); |
| 471 | 465 | ||
| 472 | std::unordered_map<SurfaceKey, Surface> surface_cache; | 466 | std::unordered_map<Tegra::GPUVAddr, Surface> surface_cache; |
| 473 | PageMap cached_pages; | 467 | PageMap cached_pages; |
| 474 | 468 | ||
| 475 | OGLFramebuffer read_framebuffer; | 469 | OGLFramebuffer read_framebuffer; |