From fed773a86c96fc62f18181a1d3ba410b25c2edee Mon Sep 17 00:00:00 2001
From: Fernando Sahmkow <fsahmkow27@gmail.com>
Date: Fri, 14 Jun 2019 18:40:06 -0400
Subject: [PATCH] texture_cache: Implement Irregular Views in surfaces

---
 src/video_core/texture_cache/surface_base.cpp |  3 +++
 src/video_core/texture_cache/surface_base.h   | 25 ++++++++++++++++---
 2 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/src/video_core/texture_cache/surface_base.cpp b/src/video_core/texture_cache/surface_base.cpp
index 8c6edb04f7..97bf9ad7ad 100644
--- a/src/video_core/texture_cache/surface_base.cpp
+++ b/src/video_core/texture_cache/surface_base.cpp
@@ -100,6 +100,9 @@ MatchStructureResult SurfaceBaseImpl::MatchesStructure(const SurfaceParams& rhs)
 
 std::optional<std::pair<u32, u32>> SurfaceBaseImpl::GetLayerMipmap(
     const GPUVAddr candidate_gpu_addr) const {
+    if (gpu_addr == candidate_gpu_addr) {
+        return {{0,0}};
+    }
     if (candidate_gpu_addr < gpu_addr) {
         return {};
     }
diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h
index 58265e9d39..662221adc9 100644
--- a/src/video_core/texture_cache/surface_base.h
+++ b/src/video_core/texture_cache/surface_base.h
@@ -238,6 +238,26 @@ public:
         return GetView(ViewParams(overview_params.target, 0, num_layers, 0, params.num_levels));
     }
 
+    std::optional<TView> EmplaceIrregularView(const SurfaceParams& view_params,
+                                              const GPUVAddr view_addr,
+                                              const std::size_t candidate_size, const u32 mipmap,
+                                              const u32 layer) {
+        const auto layer_mipmap{GetLayerMipmap(view_addr + candidate_size)};
+        if (!layer_mipmap) {
+            return {};
+        }
+        const u32 end_layer{layer_mipmap->first};
+        const u32 end_mipmap{layer_mipmap->second};
+        if (layer != end_layer) {
+            if (mipmap == 0 && end_mipmap == 0) {
+                return GetView(ViewParams(view_params.target, layer, end_layer - layer + 1, 0, 1));
+            }
+            return {};
+        } else {
+            return GetView(ViewParams(view_params.target, layer, 1, mipmap, end_mipmap - mipmap + 1));
+        }
+    }
+
     std::optional<TView> EmplaceView(const SurfaceParams& view_params, const GPUVAddr view_addr,
                                      const std::size_t candidate_size) {
         if (params.target == SurfaceTarget::Texture3D ||
@@ -252,10 +272,7 @@ public:
         const u32 layer{layer_mipmap->first};
         const u32 mipmap{layer_mipmap->second};
         if (GetMipmapSize(mipmap) != candidate_size) {
-            // TODO: The view may cover many mimaps, this case can still go on.
-            // This edge-case can be safely be ignored since it will just result in worse
-            // performance.
-            return {};
+            return EmplaceIrregularView(view_params, view_addr, candidate_size, mipmap, layer);
         }
         return GetView(ViewParams(view_params.target, layer, 1, mipmap, 1));
     }
-- 
GitLab