summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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};