summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2019-10-16 10:47:44 -0400
committerGravatar FernandoS272019-11-20 14:59:35 -0400
commitcc81c0ce64a5cc1f550ca796fda38e445660649a (patch)
treec9d2c27f143dcda1b164e2e4bc5edac96cef3bc8
parentMerge pull request #3142 from ReinUsesLisp/depbar-log (diff)
downloadyuzu-cc81c0ce64a5cc1f550ca796fda38e445660649a.tar.gz
yuzu-cc81c0ce64a5cc1f550ca796fda38e445660649a.tar.xz
yuzu-cc81c0ce64a5cc1f550ca796fda38e445660649a.zip
Texture_Cache: Redo invalid Surfaces handling.
This commit aims to redo the full setup of invalid textures and guarantee correct behavior across backends in the case of finding one by using black dummy textures that match the target of the expected texture.
-rw-r--r--src/video_core/texture_cache/surface_params.cpp10
-rw-r--r--src/video_core/texture_cache/surface_params.h8
-rw-r--r--src/video_core/texture_cache/texture_cache.h115
3 files changed, 101 insertions, 32 deletions
diff --git a/src/video_core/texture_cache/surface_params.cpp b/src/video_core/texture_cache/surface_params.cpp
index 858e17e08..a4f1edd9a 100644
--- a/src/video_core/texture_cache/surface_params.cpp
+++ b/src/video_core/texture_cache/surface_params.cpp
@@ -246,6 +246,16 @@ SurfaceParams SurfaceParams::CreateForFermiCopySurface(
246 return params; 246 return params;
247} 247}
248 248
249VideoCore::Surface::SurfaceTarget SurfaceParams::ExpectedTarget(
250 const VideoCommon::Shader::Sampler& entry) {
251 return TextureTypeToSurfaceTarget(entry.GetType(), entry.IsArray());
252}
253
254VideoCore::Surface::SurfaceTarget SurfaceParams::ExpectedTarget(
255 const VideoCommon::Shader::Image& entry) {
256 return ImageTypeToSurfaceTarget(entry.GetType());
257}
258
249bool SurfaceParams::IsLayered() const { 259bool SurfaceParams::IsLayered() const {
250 switch (target) { 260 switch (target) {
251 case SurfaceTarget::Texture1DArray: 261 case SurfaceTarget::Texture1DArray:
diff --git a/src/video_core/texture_cache/surface_params.h b/src/video_core/texture_cache/surface_params.h
index 709aa0dc2..129817ad3 100644
--- a/src/video_core/texture_cache/surface_params.h
+++ b/src/video_core/texture_cache/surface_params.h
@@ -45,6 +45,14 @@ public:
45 static SurfaceParams CreateForFermiCopySurface( 45 static SurfaceParams CreateForFermiCopySurface(
46 const Tegra::Engines::Fermi2D::Regs::Surface& config); 46 const Tegra::Engines::Fermi2D::Regs::Surface& config);
47 47
48 /// Obtains the texture target from a shader's sampler entry.
49 static VideoCore::Surface::SurfaceTarget ExpectedTarget(
50 const VideoCommon::Shader::Sampler& entry);
51
52 /// Obtains the texture target from a shader's sampler entry.
53 static VideoCore::Surface::SurfaceTarget ExpectedTarget(
54 const VideoCommon::Shader::Image& entry);
55
48 std::size_t Hash() const { 56 std::size_t Hash() const {
49 return static_cast<std::size_t>( 57 return static_cast<std::size_t>(
50 Common::CityHash64(reinterpret_cast<const char*>(this), sizeof(*this))); 58 Common::CityHash64(reinterpret_cast<const char*>(this), sizeof(*this)));
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 41309ebea..02d2e9136 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -95,10 +95,16 @@ public:
95 std::lock_guard lock{mutex}; 95 std::lock_guard lock{mutex};
96 const auto gpu_addr{tic.Address()}; 96 const auto gpu_addr{tic.Address()};
97 if (!gpu_addr) { 97 if (!gpu_addr) {
98 return {}; 98 return GetNullSurface(SurfaceParams::ExpectedTarget(entry));
99 }
100
101 const auto host_ptr{system.GPU().MemoryManager().GetPointer(gpu_addr)};
102 const auto cache_addr{ToCacheAddr(host_ptr)};
103 if (!cache_addr) {
104 return GetNullSurface(SurfaceParams::ExpectedTarget(entry));
99 } 105 }
100 const auto params{SurfaceParams::CreateForTexture(format_lookup_table, tic, entry)}; 106 const auto params{SurfaceParams::CreateForTexture(format_lookup_table, tic, entry)};
101 const auto [surface, view] = GetSurface(gpu_addr, params, true, false); 107 const auto [surface, view] = GetSurface(gpu_addr, cache_addr, params, true, false);
102 if (guard_samplers) { 108 if (guard_samplers) {
103 sampled_textures.push_back(surface); 109 sampled_textures.push_back(surface);
104 } 110 }
@@ -110,10 +116,15 @@ public:
110 std::lock_guard lock{mutex}; 116 std::lock_guard lock{mutex};
111 const auto gpu_addr{tic.Address()}; 117 const auto gpu_addr{tic.Address()};
112 if (!gpu_addr) { 118 if (!gpu_addr) {
113 return {}; 119 return GetNullSurface(SurfaceParams::ExpectedTarget(entry));
120 }
121 const auto host_ptr{system.GPU().MemoryManager().GetPointer(gpu_addr)};
122 const auto cache_addr{ToCacheAddr(host_ptr)};
123 if (!cache_addr) {
124 return GetNullSurface(SurfaceParams::ExpectedTarget(entry));
114 } 125 }
115 const auto params{SurfaceParams::CreateForImage(format_lookup_table, tic, entry)}; 126 const auto params{SurfaceParams::CreateForImage(format_lookup_table, tic, entry)};
116 const auto [surface, view] = GetSurface(gpu_addr, params, true, false); 127 const auto [surface, view] = GetSurface(gpu_addr, cache_addr, params, true, false);
117 if (guard_samplers) { 128 if (guard_samplers) {
118 sampled_textures.push_back(surface); 129 sampled_textures.push_back(surface);
119 } 130 }
@@ -143,11 +154,17 @@ public:
143 SetEmptyDepthBuffer(); 154 SetEmptyDepthBuffer();
144 return {}; 155 return {};
145 } 156 }
157 const auto host_ptr{system.GPU().MemoryManager().GetPointer(gpu_addr)};
158 const auto cache_addr{ToCacheAddr(host_ptr)};
159 if (!cache_addr) {
160 SetEmptyDepthBuffer();
161 return {};
162 }
146 const auto depth_params{SurfaceParams::CreateForDepthBuffer( 163 const auto depth_params{SurfaceParams::CreateForDepthBuffer(
147 system, regs.zeta_width, regs.zeta_height, regs.zeta.format, 164 system, regs.zeta_width, regs.zeta_height, regs.zeta.format,
148 regs.zeta.memory_layout.block_width, regs.zeta.memory_layout.block_height, 165 regs.zeta.memory_layout.block_width, regs.zeta.memory_layout.block_height,
149 regs.zeta.memory_layout.block_depth, regs.zeta.memory_layout.type)}; 166 regs.zeta.memory_layout.block_depth, regs.zeta.memory_layout.type)};
150 auto surface_view = GetSurface(gpu_addr, depth_params, preserve_contents, true); 167 auto surface_view = GetSurface(gpu_addr, cache_addr, depth_params, preserve_contents, true);
151 if (depth_buffer.target) 168 if (depth_buffer.target)
152 depth_buffer.target->MarkAsRenderTarget(false, NO_RT); 169 depth_buffer.target->MarkAsRenderTarget(false, NO_RT);
153 depth_buffer.target = surface_view.first; 170 depth_buffer.target = surface_view.first;
@@ -180,8 +197,16 @@ public:
180 return {}; 197 return {};
181 } 198 }
182 199
183 auto surface_view = GetSurface(gpu_addr, SurfaceParams::CreateForFramebuffer(system, index), 200 const auto host_ptr{system.GPU().MemoryManager().GetPointer(gpu_addr)};
184 preserve_contents, true); 201 const auto cache_addr{ToCacheAddr(host_ptr)};
202 if (!cache_addr) {
203 SetEmptyColorBuffer(index);
204 return {};
205 }
206
207 auto surface_view =
208 GetSurface(gpu_addr, cache_addr, SurfaceParams::CreateForFramebuffer(system, index),
209 preserve_contents, true);
185 if (render_targets[index].target) 210 if (render_targets[index].target)
186 render_targets[index].target->MarkAsRenderTarget(false, NO_RT); 211 render_targets[index].target->MarkAsRenderTarget(false, NO_RT);
187 render_targets[index].target = surface_view.first; 212 render_targets[index].target = surface_view.first;
@@ -230,8 +255,14 @@ public:
230 const GPUVAddr src_gpu_addr = src_config.Address(); 255 const GPUVAddr src_gpu_addr = src_config.Address();
231 const GPUVAddr dst_gpu_addr = dst_config.Address(); 256 const GPUVAddr dst_gpu_addr = dst_config.Address();
232 DeduceBestBlit(src_params, dst_params, src_gpu_addr, dst_gpu_addr); 257 DeduceBestBlit(src_params, dst_params, src_gpu_addr, dst_gpu_addr);
233 std::pair<TSurface, TView> dst_surface = GetSurface(dst_gpu_addr, dst_params, true, false); 258 const auto dst_host_ptr{system.GPU().MemoryManager().GetPointer(dst_gpu_addr)};
234 std::pair<TSurface, TView> src_surface = GetSurface(src_gpu_addr, src_params, true, false); 259 const auto dst_cache_addr{ToCacheAddr(dst_host_ptr)};
260 const auto src_host_ptr{system.GPU().MemoryManager().GetPointer(src_gpu_addr)};
261 const auto src_cache_addr{ToCacheAddr(src_host_ptr)};
262 std::pair<TSurface, TView> dst_surface =
263 GetSurface(dst_gpu_addr, dst_cache_addr, dst_params, true, false);
264 std::pair<TSurface, TView> src_surface =
265 GetSurface(src_gpu_addr, src_cache_addr, src_params, true, false);
235 ImageBlit(src_surface.second, dst_surface.second, copy_config); 266 ImageBlit(src_surface.second, dst_surface.second, copy_config);
236 dst_surface.first->MarkAsModified(true, Tick()); 267 dst_surface.first->MarkAsModified(true, Tick());
237 } 268 }
@@ -347,13 +378,6 @@ protected:
347 return new_surface; 378 return new_surface;
348 } 379 }
349 380
350 std::pair<TSurface, TView> GetFermiSurface(
351 const Tegra::Engines::Fermi2D::Regs::Surface& config) {
352 SurfaceParams params = SurfaceParams::CreateForFermiCopySurface(config);
353 const GPUVAddr gpu_addr = config.Address();
354 return GetSurface(gpu_addr, params, true, false);
355 }
356
357 Core::System& system; 381 Core::System& system;
358 382
359private: 383private:
@@ -614,22 +638,9 @@ private:
614 * left blank. 638 * left blank.
615 * @param is_render Whether or not the surface is a render target. 639 * @param is_render Whether or not the surface is a render target.
616 **/ 640 **/
617 std::pair<TSurface, TView> GetSurface(const GPUVAddr gpu_addr, const SurfaceParams& params, 641 std::pair<TSurface, TView> GetSurface(const GPUVAddr gpu_addr, const CacheAddr cache_addr,
618 bool preserve_contents, bool is_render) { 642 const SurfaceParams& params, bool preserve_contents,
619 const auto host_ptr{system.GPU().MemoryManager().GetPointer(gpu_addr)}; 643 bool is_render) {
620 const auto cache_addr{ToCacheAddr(host_ptr)};
621
622 // Step 0: guarantee a valid surface
623 if (!cache_addr) {
624 // Return a null surface if it's invalid
625 SurfaceParams new_params = params;
626 new_params.width = 1;
627 new_params.height = 1;
628 new_params.depth = 1;
629 new_params.block_height = 0;
630 new_params.block_depth = 0;
631 return InitializeSurface(gpu_addr, new_params, false);
632 }
633 644
634 // Step 1 645 // Step 1
635 // Check Level 1 Cache for a fast structural match. If candidate surface 646 // Check Level 1 Cache for a fast structural match. If candidate surface
@@ -794,6 +805,41 @@ private:
794 } 805 }
795 806
796 /** 807 /**
808 * Gets a null surface based on a target texture.
809 * @param target The target of the null surface.
810 */
811 TView GetNullSurface(SurfaceTarget target) {
812 const u32 i_target = static_cast<u32>(target);
813 if (const auto it = invalid_cache.find(i_target); it != invalid_cache.end()) {
814 return it->second->GetMainView();
815 }
816 SurfaceParams params{};
817 params.target = target;
818 params.is_tiled = false;
819 params.srgb_conversion = false;
820 params.is_layered = false;
821 params.block_width = 0;
822 params.block_height = 0;
823 params.block_depth = 0;
824 params.tile_width_spacing = 1;
825 params.width = 1;
826 params.height = 1;
827 params.depth = 1;
828 params.pitch = 4;
829 params.num_levels = 1;
830 params.emulated_levels = 1;
831 params.pixel_format = VideoCore::Surface::PixelFormat::RGBA16F;
832 params.type = VideoCore::Surface::SurfaceType::ColorTexture;
833 auto surface = CreateSurface(0ULL, params);
834 invalid_memory.clear();
835 invalid_memory.resize(surface->GetHostSizeInBytes(), 0U);
836 surface->UploadTexture(invalid_memory);
837 surface->MarkAsModified(false, Tick());
838 invalid_cache.emplace(i_target, surface);
839 return surface->GetMainView();
840 }
841
842 /**
797 * Gets the a source and destination starting address and parameters, 843 * Gets the a source and destination starting address and parameters,
798 * and tries to deduce if they are supposed to be depth textures. If so, their 844 * and tries to deduce if they are supposed to be depth textures. If so, their
799 * parameters are modified and fixed into so. 845 * parameters are modified and fixed into so.
@@ -991,6 +1037,11 @@ private:
991 1037
992 std::vector<TSurface> sampled_textures; 1038 std::vector<TSurface> sampled_textures;
993 1039
1040 /// This cache stores null surfaces in order to be used as a placeholder
1041 /// for invalid texture calls.
1042 std::unordered_map<u32, TSurface> invalid_cache;
1043 std::vector<u8> invalid_memory;
1044
994 StagingCache staging_cache; 1045 StagingCache staging_cache;
995 std::recursive_mutex mutex; 1046 std::recursive_mutex mutex;
996}; 1047};