summaryrefslogtreecommitdiff
path: root/src/video_core/texture_cache
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/texture_cache')
-rw-r--r--src/video_core/texture_cache/texture_cache.h60
1 files changed, 33 insertions, 27 deletions
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 8bfc541d4..658264860 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -652,45 +652,54 @@ private:
652 **/ 652 **/
653 std::optional<std::pair<TSurface, TView>> TryReconstructSurface(std::vector<TSurface>& overlaps, 653 std::optional<std::pair<TSurface, TView>> TryReconstructSurface(std::vector<TSurface>& overlaps,
654 const SurfaceParams& params, 654 const SurfaceParams& params,
655 const GPUVAddr gpu_addr) { 655 GPUVAddr gpu_addr) {
656 if (params.target == SurfaceTarget::Texture3D) { 656 if (params.target == SurfaceTarget::Texture3D) {
657 return {}; 657 return std::nullopt;
658 } 658 }
659 bool modified = false;
660 TSurface new_surface = GetUncachedSurface(gpu_addr, params); 659 TSurface new_surface = GetUncachedSurface(gpu_addr, params);
661 u32 passed_tests = 0; 660 std::size_t passed_tests = 0;
661 bool modified = false;
662
662 for (auto& surface : overlaps) { 663 for (auto& surface : overlaps) {
663 const SurfaceParams& src_params = surface->GetSurfaceParams(); 664 const SurfaceParams& src_params = surface->GetSurfaceParams();
664 if (src_params.is_layered || src_params.num_levels > 1) { 665 const auto mipmap_layer{new_surface->GetLayerMipmap(surface->GetGpuAddr())};
665 // We send this cases to recycle as they are more complex to handle
666 return {};
667 }
668 const std::size_t candidate_size = surface->GetSizeInBytes();
669 auto mipmap_layer{new_surface->GetLayerMipmap(surface->GetGpuAddr())};
670 if (!mipmap_layer) { 666 if (!mipmap_layer) {
671 continue; 667 continue;
672 } 668 }
673 const auto [layer, mipmap] = *mipmap_layer; 669 const auto [base_layer, base_mipmap] = *mipmap_layer;
674 if (new_surface->GetMipmapSize(mipmap) != candidate_size) { 670 if (new_surface->GetMipmapSize(base_mipmap) != surface->GetMipmapSize(0)) {
675 continue; 671 continue;
676 } 672 }
673
674 // Copy all mipmaps and layers
675 const u32 block_width = params.GetDefaultBlockWidth();
676 const u32 block_height = params.GetDefaultBlockHeight();
677 for (u32 mipmap = base_mipmap; mipmap < base_mipmap + src_params.num_levels; ++mipmap) {
678 const u32 width = SurfaceParams::IntersectWidth(src_params, params, 0, mipmap);
679 const u32 height = SurfaceParams::IntersectHeight(src_params, params, 0, mipmap);
680 if (width < block_width || height < block_height) {
681 // Current APIs forbid copying small compressed textures, avoid errors
682 break;
683 }
684 const CopyParams copy_params(0, 0, 0, 0, 0, base_layer, 0, mipmap, width, height,
685 src_params.depth);
686 ImageCopy(surface, new_surface, copy_params);
687 }
688 ++passed_tests;
677 modified |= surface->IsModified(); 689 modified |= surface->IsModified();
678 // Now we got all the data set up
679 const u32 width = SurfaceParams::IntersectWidth(src_params, params, 0, mipmap);
680 const u32 height = SurfaceParams::IntersectHeight(src_params, params, 0, mipmap);
681 const CopyParams copy_params(0, 0, 0, 0, 0, layer, 0, mipmap, width, height, 1);
682 passed_tests++;
683 ImageCopy(surface, new_surface, copy_params);
684 } 690 }
685 if (passed_tests == 0) { 691 if (passed_tests == 0) {
686 return {}; 692 return std::nullopt;
693 }
694 if (Settings::IsGPULevelExtreme() && passed_tests != overlaps.size()) {
687 // In Accurate GPU all tests should pass, else we recycle 695 // In Accurate GPU all tests should pass, else we recycle
688 } else if (Settings::IsGPULevelExtreme() && passed_tests != overlaps.size()) { 696 return std::nullopt;
689 return {};
690 } 697 }
698
691 for (const auto& surface : overlaps) { 699 for (const auto& surface : overlaps) {
692 Unregister(surface); 700 Unregister(surface);
693 } 701 }
702
694 new_surface->MarkAsModified(modified, Tick()); 703 new_surface->MarkAsModified(modified, Tick());
695 Register(new_surface); 704 Register(new_surface);
696 return {{new_surface, new_surface->GetMainView()}}; 705 return {{new_surface, new_surface->GetMainView()}};
@@ -868,12 +877,9 @@ private:
868 // two things either the candidate surface is a supertexture of the overlap 877 // two things either the candidate surface is a supertexture of the overlap
869 // or they don't match in any known way. 878 // or they don't match in any known way.
870 if (!current_surface->IsInside(gpu_addr, gpu_addr + candidate_size)) { 879 if (!current_surface->IsInside(gpu_addr, gpu_addr + candidate_size)) {
871 if (current_surface->GetGpuAddr() == gpu_addr) { 880 const std::optional view = TryReconstructSurface(overlaps, params, gpu_addr);
872 std::optional<std::pair<TSurface, TView>> view = 881 if (view) {
873 TryReconstructSurface(overlaps, params, gpu_addr); 882 return *view;
874 if (view) {
875 return *view;
876 }
877 } 883 }
878 return RecycleSurface(overlaps, params, gpu_addr, preserve_contents, 884 return RecycleSurface(overlaps, params, gpu_addr, preserve_contents,
879 MatchTopologyResult::FullMatch); 885 MatchTopologyResult::FullMatch);