diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 7 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.cpp | 7 | ||||
| -rw-r--r-- | src/video_core/texture_cache/surface_base.cpp | 42 | ||||
| -rw-r--r-- | src/video_core/texture_cache/surface_base.h | 34 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 121 |
5 files changed, 81 insertions, 130 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 261738830..a25e7486d 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -662,7 +662,7 @@ void RasterizerOpenGL::FlushRegion(VAddr addr, u64 size) { | |||
| 662 | return; | 662 | return; |
| 663 | } | 663 | } |
| 664 | CacheAddr cache_addr = ToCacheAddr(system.Memory().GetPointer(addr)); | 664 | CacheAddr cache_addr = ToCacheAddr(system.Memory().GetPointer(addr)); |
| 665 | texture_cache.FlushRegion(cache_addr, size); | 665 | texture_cache.FlushRegion(addr, size); |
| 666 | buffer_cache.FlushRegion(cache_addr, size); | 666 | buffer_cache.FlushRegion(cache_addr, size); |
| 667 | query_cache.FlushRegion(cache_addr, size); | 667 | query_cache.FlushRegion(cache_addr, size); |
| 668 | } | 668 | } |
| @@ -673,7 +673,7 @@ void RasterizerOpenGL::InvalidateRegion(VAddr addr, u64 size) { | |||
| 673 | return; | 673 | return; |
| 674 | } | 674 | } |
| 675 | CacheAddr cache_addr = ToCacheAddr(system.Memory().GetPointer(addr)); | 675 | CacheAddr cache_addr = ToCacheAddr(system.Memory().GetPointer(addr)); |
| 676 | texture_cache.InvalidateRegion(cache_addr, size); | 676 | texture_cache.InvalidateRegion(addr, size); |
| 677 | shader_cache.InvalidateRegion(cache_addr, size); | 677 | shader_cache.InvalidateRegion(cache_addr, size); |
| 678 | buffer_cache.InvalidateRegion(cache_addr, size); | 678 | buffer_cache.InvalidateRegion(cache_addr, size); |
| 679 | query_cache.InvalidateRegion(cache_addr, size); | 679 | query_cache.InvalidateRegion(cache_addr, size); |
| @@ -718,8 +718,7 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config, | |||
| 718 | 718 | ||
| 719 | MICROPROFILE_SCOPE(OpenGL_CacheManagement); | 719 | MICROPROFILE_SCOPE(OpenGL_CacheManagement); |
| 720 | 720 | ||
| 721 | const auto surface{ | 721 | const auto surface{texture_cache.TryFindFramebufferSurface(framebuffer_addr)}; |
| 722 | texture_cache.TryFindFramebufferSurface(system.Memory().GetPointer(framebuffer_addr))}; | ||
| 723 | if (!surface) { | 722 | if (!surface) { |
| 724 | return {}; | 723 | return {}; |
| 725 | } | 724 | } |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 0ca72eb45..cc76d96ea 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -500,7 +500,7 @@ void RasterizerVulkan::FlushRegion(VAddr addr, u64 size) { | |||
| 500 | return; | 500 | return; |
| 501 | } | 501 | } |
| 502 | CacheAddr cache_addr = ToCacheAddr(system.Memory().GetPointer(addr)); | 502 | CacheAddr cache_addr = ToCacheAddr(system.Memory().GetPointer(addr)); |
| 503 | texture_cache.FlushRegion(cache_addr, size); | 503 | texture_cache.FlushRegion(addr, size); |
| 504 | buffer_cache.FlushRegion(cache_addr, size); | 504 | buffer_cache.FlushRegion(cache_addr, size); |
| 505 | query_cache.FlushRegion(cache_addr, size); | 505 | query_cache.FlushRegion(cache_addr, size); |
| 506 | } | 506 | } |
| @@ -510,7 +510,7 @@ void RasterizerVulkan::InvalidateRegion(VAddr addr, u64 size) { | |||
| 510 | return; | 510 | return; |
| 511 | } | 511 | } |
| 512 | CacheAddr cache_addr = ToCacheAddr(system.Memory().GetPointer(addr)); | 512 | CacheAddr cache_addr = ToCacheAddr(system.Memory().GetPointer(addr)); |
| 513 | texture_cache.InvalidateRegion(cache_addr, size); | 513 | texture_cache.InvalidateRegion(addr, size); |
| 514 | pipeline_cache.InvalidateRegion(cache_addr, size); | 514 | pipeline_cache.InvalidateRegion(cache_addr, size); |
| 515 | buffer_cache.InvalidateRegion(cache_addr, size); | 515 | buffer_cache.InvalidateRegion(cache_addr, size); |
| 516 | query_cache.InvalidateRegion(cache_addr, size); | 516 | query_cache.InvalidateRegion(cache_addr, size); |
| @@ -548,8 +548,7 @@ bool RasterizerVulkan::AccelerateDisplay(const Tegra::FramebufferConfig& config, | |||
| 548 | return false; | 548 | return false; |
| 549 | } | 549 | } |
| 550 | 550 | ||
| 551 | const u8* host_ptr{system.Memory().GetPointer(framebuffer_addr)}; | 551 | const auto surface{texture_cache.TryFindFramebufferSurface(framebuffer_addr)}; |
| 552 | const auto surface{texture_cache.TryFindFramebufferSurface(host_ptr)}; | ||
| 553 | if (!surface) { | 552 | if (!surface) { |
| 554 | return false; | 553 | return false; |
| 555 | } | 554 | } |
diff --git a/src/video_core/texture_cache/surface_base.cpp b/src/video_core/texture_cache/surface_base.cpp index 6fe815135..7af0e792c 100644 --- a/src/video_core/texture_cache/surface_base.cpp +++ b/src/video_core/texture_cache/surface_base.cpp | |||
| @@ -190,22 +190,11 @@ void SurfaceBaseImpl::LoadBuffer(Tegra::MemoryManager& memory_manager, | |||
| 190 | MICROPROFILE_SCOPE(GPU_Load_Texture); | 190 | MICROPROFILE_SCOPE(GPU_Load_Texture); |
| 191 | auto& staging_buffer = staging_cache.GetBuffer(0); | 191 | auto& staging_buffer = staging_cache.GetBuffer(0); |
| 192 | u8* host_ptr; | 192 | u8* host_ptr; |
| 193 | is_continuous = memory_manager.IsBlockContinuous(gpu_addr, guest_memory_size); | 193 | // Use an extra temporal buffer |
| 194 | 194 | auto& tmp_buffer = staging_cache.GetBuffer(1); | |
| 195 | // Handle continuouty | 195 | tmp_buffer.resize(guest_memory_size); |
| 196 | if (is_continuous) { | 196 | host_ptr = tmp_buffer.data(); |
| 197 | // Use physical memory directly | 197 | memory_manager.ReadBlockUnsafe(gpu_addr, host_ptr, guest_memory_size); |
| 198 | host_ptr = memory_manager.GetPointer(gpu_addr); | ||
| 199 | if (!host_ptr) { | ||
| 200 | return; | ||
| 201 | } | ||
| 202 | } else { | ||
| 203 | // Use an extra temporal buffer | ||
| 204 | auto& tmp_buffer = staging_cache.GetBuffer(1); | ||
| 205 | tmp_buffer.resize(guest_memory_size); | ||
| 206 | host_ptr = tmp_buffer.data(); | ||
| 207 | memory_manager.ReadBlockUnsafe(gpu_addr, host_ptr, guest_memory_size); | ||
| 208 | } | ||
| 209 | 198 | ||
| 210 | if (params.is_tiled) { | 199 | if (params.is_tiled) { |
| 211 | ASSERT_MSG(params.block_width == 0, "Block width is defined as {} on texture target {}", | 200 | ASSERT_MSG(params.block_width == 0, "Block width is defined as {} on texture target {}", |
| @@ -257,19 +246,10 @@ void SurfaceBaseImpl::FlushBuffer(Tegra::MemoryManager& memory_manager, | |||
| 257 | auto& staging_buffer = staging_cache.GetBuffer(0); | 246 | auto& staging_buffer = staging_cache.GetBuffer(0); |
| 258 | u8* host_ptr; | 247 | u8* host_ptr; |
| 259 | 248 | ||
| 260 | // Handle continuouty | 249 | // Use an extra temporal buffer |
| 261 | if (is_continuous) { | 250 | auto& tmp_buffer = staging_cache.GetBuffer(1); |
| 262 | // Use physical memory directly | 251 | tmp_buffer.resize(guest_memory_size); |
| 263 | host_ptr = memory_manager.GetPointer(gpu_addr); | 252 | host_ptr = tmp_buffer.data(); |
| 264 | if (!host_ptr) { | ||
| 265 | return; | ||
| 266 | } | ||
| 267 | } else { | ||
| 268 | // Use an extra temporal buffer | ||
| 269 | auto& tmp_buffer = staging_cache.GetBuffer(1); | ||
| 270 | tmp_buffer.resize(guest_memory_size); | ||
| 271 | host_ptr = tmp_buffer.data(); | ||
| 272 | } | ||
| 273 | 253 | ||
| 274 | if (params.is_tiled) { | 254 | if (params.is_tiled) { |
| 275 | ASSERT_MSG(params.block_width == 0, "Block width is defined as {}", params.block_width); | 255 | ASSERT_MSG(params.block_width == 0, "Block width is defined as {}", params.block_width); |
| @@ -300,9 +280,7 @@ void SurfaceBaseImpl::FlushBuffer(Tegra::MemoryManager& memory_manager, | |||
| 300 | } | 280 | } |
| 301 | } | 281 | } |
| 302 | } | 282 | } |
| 303 | if (!is_continuous) { | 283 | memory_manager.WriteBlockUnsafe(gpu_addr, host_ptr, guest_memory_size); |
| 304 | memory_manager.WriteBlockUnsafe(gpu_addr, host_ptr, guest_memory_size); | ||
| 305 | } | ||
| 306 | } | 284 | } |
| 307 | 285 | ||
| 308 | } // namespace VideoCommon | 286 | } // namespace VideoCommon |
diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index d7882a031..a39a8661b 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h | |||
| @@ -68,8 +68,8 @@ public: | |||
| 68 | return gpu_addr; | 68 | return gpu_addr; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | bool Overlaps(const CacheAddr start, const CacheAddr end) const { | 71 | bool Overlaps(const VAddr start, const VAddr end) const { |
| 72 | return (cache_addr < end) && (cache_addr_end > start); | 72 | return (cpu_addr < end) && (cpu_addr_end > start); |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | bool IsInside(const GPUVAddr other_start, const GPUVAddr other_end) { | 75 | bool IsInside(const GPUVAddr other_start, const GPUVAddr other_end) { |
| @@ -86,21 +86,13 @@ public: | |||
| 86 | return cpu_addr; | 86 | return cpu_addr; |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | void SetCpuAddr(const VAddr new_addr) { | 89 | VAddr GetCpuAddrEnd() const { |
| 90 | cpu_addr = new_addr; | 90 | return cpu_addr_end; |
| 91 | } | ||
| 92 | |||
| 93 | CacheAddr GetCacheAddr() const { | ||
| 94 | return cache_addr; | ||
| 95 | } | ||
| 96 | |||
| 97 | CacheAddr GetCacheAddrEnd() const { | ||
| 98 | return cache_addr_end; | ||
| 99 | } | 91 | } |
| 100 | 92 | ||
| 101 | void SetCacheAddr(const CacheAddr new_addr) { | 93 | void SetCpuAddr(const VAddr new_addr) { |
| 102 | cache_addr = new_addr; | 94 | cpu_addr = new_addr; |
| 103 | cache_addr_end = new_addr + guest_memory_size; | 95 | cpu_addr_end = new_addr + guest_memory_size; |
| 104 | } | 96 | } |
| 105 | 97 | ||
| 106 | const SurfaceParams& GetSurfaceParams() const { | 98 | const SurfaceParams& GetSurfaceParams() const { |
| @@ -119,14 +111,6 @@ public: | |||
| 119 | return mipmap_sizes[level]; | 111 | return mipmap_sizes[level]; |
| 120 | } | 112 | } |
| 121 | 113 | ||
| 122 | void MarkAsContinuous(const bool is_continuous) { | ||
| 123 | this->is_continuous = is_continuous; | ||
| 124 | } | ||
| 125 | |||
| 126 | bool IsContinuous() const { | ||
| 127 | return is_continuous; | ||
| 128 | } | ||
| 129 | |||
| 130 | bool IsLinear() const { | 114 | bool IsLinear() const { |
| 131 | return !params.is_tiled; | 115 | return !params.is_tiled; |
| 132 | } | 116 | } |
| @@ -175,10 +159,8 @@ protected: | |||
| 175 | std::size_t guest_memory_size; | 159 | std::size_t guest_memory_size; |
| 176 | std::size_t host_memory_size; | 160 | std::size_t host_memory_size; |
| 177 | GPUVAddr gpu_addr{}; | 161 | GPUVAddr gpu_addr{}; |
| 178 | CacheAddr cache_addr{}; | ||
| 179 | CacheAddr cache_addr_end{}; | ||
| 180 | VAddr cpu_addr{}; | 162 | VAddr cpu_addr{}; |
| 181 | bool is_continuous{}; | 163 | VAddr cpu_addr_end{}; |
| 182 | bool is_converted{}; | 164 | bool is_converted{}; |
| 183 | 165 | ||
| 184 | std::vector<std::size_t> mipmap_sizes; | 166 | std::vector<std::size_t> mipmap_sizes; |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index c8f8d659d..88fe3e25f 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -52,11 +52,9 @@ using RenderTargetConfig = Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig; | |||
| 52 | 52 | ||
| 53 | template <typename TSurface, typename TView> | 53 | template <typename TSurface, typename TView> |
| 54 | class TextureCache { | 54 | class TextureCache { |
| 55 | using IntervalMap = boost::icl::interval_map<CacheAddr, std::set<TSurface>>; | ||
| 56 | using IntervalType = typename IntervalMap::interval_type; | ||
| 57 | 55 | ||
| 58 | public: | 56 | public: |
| 59 | void InvalidateRegion(CacheAddr addr, std::size_t size) { | 57 | void InvalidateRegion(VAddr addr, std::size_t size) { |
| 60 | std::lock_guard lock{mutex}; | 58 | std::lock_guard lock{mutex}; |
| 61 | 59 | ||
| 62 | for (const auto& surface : GetSurfacesInRegion(addr, size)) { | 60 | for (const auto& surface : GetSurfacesInRegion(addr, size)) { |
| @@ -76,7 +74,7 @@ public: | |||
| 76 | guard_samplers = new_guard; | 74 | guard_samplers = new_guard; |
| 77 | } | 75 | } |
| 78 | 76 | ||
| 79 | void FlushRegion(CacheAddr addr, std::size_t size) { | 77 | void FlushRegion(VAddr addr, std::size_t size) { |
| 80 | std::lock_guard lock{mutex}; | 78 | std::lock_guard lock{mutex}; |
| 81 | 79 | ||
| 82 | auto surfaces = GetSurfacesInRegion(addr, size); | 80 | auto surfaces = GetSurfacesInRegion(addr, size); |
| @@ -99,9 +97,9 @@ public: | |||
| 99 | return GetNullSurface(SurfaceParams::ExpectedTarget(entry)); | 97 | return GetNullSurface(SurfaceParams::ExpectedTarget(entry)); |
| 100 | } | 98 | } |
| 101 | 99 | ||
| 102 | const auto host_ptr{system.GPU().MemoryManager().GetPointer(gpu_addr)}; | 100 | const std::optional<VAddr> cpu_addr = |
| 103 | const auto cache_addr{ToCacheAddr(host_ptr)}; | 101 | system.GPU().MemoryManager().GpuToCpuAddress(gpu_addr); |
| 104 | if (!cache_addr) { | 102 | if (!cpu_addr) { |
| 105 | return GetNullSurface(SurfaceParams::ExpectedTarget(entry)); | 103 | return GetNullSurface(SurfaceParams::ExpectedTarget(entry)); |
| 106 | } | 104 | } |
| 107 | 105 | ||
| @@ -110,7 +108,7 @@ public: | |||
| 110 | } | 108 | } |
| 111 | 109 | ||
| 112 | const auto params{SurfaceParams::CreateForTexture(format_lookup_table, tic, entry)}; | 110 | const auto params{SurfaceParams::CreateForTexture(format_lookup_table, tic, entry)}; |
| 113 | const auto [surface, view] = GetSurface(gpu_addr, cache_addr, params, true, false); | 111 | const auto [surface, view] = GetSurface(gpu_addr, *cpu_addr, params, true, false); |
| 114 | if (guard_samplers) { | 112 | if (guard_samplers) { |
| 115 | sampled_textures.push_back(surface); | 113 | sampled_textures.push_back(surface); |
| 116 | } | 114 | } |
| @@ -124,13 +122,13 @@ public: | |||
| 124 | if (!gpu_addr) { | 122 | if (!gpu_addr) { |
| 125 | return GetNullSurface(SurfaceParams::ExpectedTarget(entry)); | 123 | return GetNullSurface(SurfaceParams::ExpectedTarget(entry)); |
| 126 | } | 124 | } |
| 127 | const auto host_ptr{system.GPU().MemoryManager().GetPointer(gpu_addr)}; | 125 | const std::optional<VAddr> cpu_addr = |
| 128 | const auto cache_addr{ToCacheAddr(host_ptr)}; | 126 | system.GPU().MemoryManager().GpuToCpuAddress(gpu_addr); |
| 129 | if (!cache_addr) { | 127 | if (!cpu_addr) { |
| 130 | return GetNullSurface(SurfaceParams::ExpectedTarget(entry)); | 128 | return GetNullSurface(SurfaceParams::ExpectedTarget(entry)); |
| 131 | } | 129 | } |
| 132 | const auto params{SurfaceParams::CreateForImage(format_lookup_table, tic, entry)}; | 130 | const auto params{SurfaceParams::CreateForImage(format_lookup_table, tic, entry)}; |
| 133 | const auto [surface, view] = GetSurface(gpu_addr, cache_addr, params, true, false); | 131 | const auto [surface, view] = GetSurface(gpu_addr, *cpu_addr, params, true, false); |
| 134 | if (guard_samplers) { | 132 | if (guard_samplers) { |
| 135 | sampled_textures.push_back(surface); | 133 | sampled_textures.push_back(surface); |
| 136 | } | 134 | } |
| @@ -159,14 +157,14 @@ public: | |||
| 159 | SetEmptyDepthBuffer(); | 157 | SetEmptyDepthBuffer(); |
| 160 | return {}; | 158 | return {}; |
| 161 | } | 159 | } |
| 162 | const auto host_ptr{system.GPU().MemoryManager().GetPointer(gpu_addr)}; | 160 | const std::optional<VAddr> cpu_addr = |
| 163 | const auto cache_addr{ToCacheAddr(host_ptr)}; | 161 | system.GPU().MemoryManager().GpuToCpuAddress(gpu_addr); |
| 164 | if (!cache_addr) { | 162 | if (!cpu_addr) { |
| 165 | SetEmptyDepthBuffer(); | 163 | SetEmptyDepthBuffer(); |
| 166 | return {}; | 164 | return {}; |
| 167 | } | 165 | } |
| 168 | const auto depth_params{SurfaceParams::CreateForDepthBuffer(system)}; | 166 | const auto depth_params{SurfaceParams::CreateForDepthBuffer(system)}; |
| 169 | auto surface_view = GetSurface(gpu_addr, cache_addr, depth_params, preserve_contents, true); | 167 | auto surface_view = GetSurface(gpu_addr, *cpu_addr, depth_params, preserve_contents, true); |
| 170 | if (depth_buffer.target) | 168 | if (depth_buffer.target) |
| 171 | depth_buffer.target->MarkAsRenderTarget(false, NO_RT); | 169 | depth_buffer.target->MarkAsRenderTarget(false, NO_RT); |
| 172 | depth_buffer.target = surface_view.first; | 170 | depth_buffer.target = surface_view.first; |
| @@ -199,15 +197,15 @@ public: | |||
| 199 | return {}; | 197 | return {}; |
| 200 | } | 198 | } |
| 201 | 199 | ||
| 202 | const auto host_ptr{system.GPU().MemoryManager().GetPointer(gpu_addr)}; | 200 | const std::optional<VAddr> cpu_addr = |
| 203 | const auto cache_addr{ToCacheAddr(host_ptr)}; | 201 | system.GPU().MemoryManager().GpuToCpuAddress(gpu_addr); |
| 204 | if (!cache_addr) { | 202 | if (!cpu_addr) { |
| 205 | SetEmptyColorBuffer(index); | 203 | SetEmptyColorBuffer(index); |
| 206 | return {}; | 204 | return {}; |
| 207 | } | 205 | } |
| 208 | 206 | ||
| 209 | auto surface_view = | 207 | auto surface_view = |
| 210 | GetSurface(gpu_addr, cache_addr, SurfaceParams::CreateForFramebuffer(system, index), | 208 | GetSurface(gpu_addr, *cpu_addr, SurfaceParams::CreateForFramebuffer(system, index), |
| 211 | preserve_contents, true); | 209 | preserve_contents, true); |
| 212 | if (render_targets[index].target) | 210 | if (render_targets[index].target) |
| 213 | render_targets[index].target->MarkAsRenderTarget(false, NO_RT); | 211 | render_targets[index].target->MarkAsRenderTarget(false, NO_RT); |
| @@ -257,27 +255,26 @@ public: | |||
| 257 | const GPUVAddr src_gpu_addr = src_config.Address(); | 255 | const GPUVAddr src_gpu_addr = src_config.Address(); |
| 258 | const GPUVAddr dst_gpu_addr = dst_config.Address(); | 256 | const GPUVAddr dst_gpu_addr = dst_config.Address(); |
| 259 | DeduceBestBlit(src_params, dst_params, src_gpu_addr, dst_gpu_addr); | 257 | DeduceBestBlit(src_params, dst_params, src_gpu_addr, dst_gpu_addr); |
| 260 | const auto dst_host_ptr{system.GPU().MemoryManager().GetPointer(dst_gpu_addr)}; | 258 | const std::optional<VAddr> dst_cpu_addr = |
| 261 | const auto dst_cache_addr{ToCacheAddr(dst_host_ptr)}; | 259 | system.GPU().MemoryManager().GpuToCpuAddress(dst_gpu_addr); |
| 262 | const auto src_host_ptr{system.GPU().MemoryManager().GetPointer(src_gpu_addr)}; | 260 | const std::optional<VAddr> src_cpu_addr = |
| 263 | const auto src_cache_addr{ToCacheAddr(src_host_ptr)}; | 261 | system.GPU().MemoryManager().GpuToCpuAddress(src_gpu_addr); |
| 264 | std::pair<TSurface, TView> dst_surface = | 262 | std::pair<TSurface, TView> dst_surface = |
| 265 | GetSurface(dst_gpu_addr, dst_cache_addr, dst_params, true, false); | 263 | GetSurface(dst_gpu_addr, *dst_cpu_addr, dst_params, true, false); |
| 266 | std::pair<TSurface, TView> src_surface = | 264 | std::pair<TSurface, TView> src_surface = |
| 267 | GetSurface(src_gpu_addr, src_cache_addr, src_params, true, false); | 265 | GetSurface(src_gpu_addr, *src_cpu_addr, src_params, true, false); |
| 268 | ImageBlit(src_surface.second, dst_surface.second, copy_config); | 266 | ImageBlit(src_surface.second, dst_surface.second, copy_config); |
| 269 | dst_surface.first->MarkAsModified(true, Tick()); | 267 | dst_surface.first->MarkAsModified(true, Tick()); |
| 270 | } | 268 | } |
| 271 | 269 | ||
| 272 | TSurface TryFindFramebufferSurface(const u8* host_ptr) { | 270 | TSurface TryFindFramebufferSurface(VAddr addr) { |
| 273 | const CacheAddr cache_addr = ToCacheAddr(host_ptr); | 271 | if (!addr) { |
| 274 | if (!cache_addr) { | ||
| 275 | return nullptr; | 272 | return nullptr; |
| 276 | } | 273 | } |
| 277 | const CacheAddr page = cache_addr >> registry_page_bits; | 274 | const VAddr page = addr >> registry_page_bits; |
| 278 | std::vector<TSurface>& list = registry[page]; | 275 | std::vector<TSurface>& list = registry[page]; |
| 279 | for (auto& surface : list) { | 276 | for (auto& surface : list) { |
| 280 | if (surface->GetCacheAddr() == cache_addr) { | 277 | if (surface->GetCpuAddr() == addr) { |
| 281 | return surface; | 278 | return surface; |
| 282 | } | 279 | } |
| 283 | } | 280 | } |
| @@ -338,18 +335,14 @@ protected: | |||
| 338 | 335 | ||
| 339 | void Register(TSurface surface) { | 336 | void Register(TSurface surface) { |
| 340 | const GPUVAddr gpu_addr = surface->GetGpuAddr(); | 337 | const GPUVAddr gpu_addr = surface->GetGpuAddr(); |
| 341 | const CacheAddr cache_ptr = ToCacheAddr(system.GPU().MemoryManager().GetPointer(gpu_addr)); | ||
| 342 | const std::size_t size = surface->GetSizeInBytes(); | 338 | const std::size_t size = surface->GetSizeInBytes(); |
| 343 | const std::optional<VAddr> cpu_addr = | 339 | const std::optional<VAddr> cpu_addr = |
| 344 | system.GPU().MemoryManager().GpuToCpuAddress(gpu_addr); | 340 | system.GPU().MemoryManager().GpuToCpuAddress(gpu_addr); |
| 345 | if (!cache_ptr || !cpu_addr) { | 341 | if (!cpu_addr) { |
| 346 | LOG_CRITICAL(HW_GPU, "Failed to register surface with unmapped gpu_address 0x{:016x}", | 342 | LOG_CRITICAL(HW_GPU, "Failed to register surface with unmapped gpu_address 0x{:016x}", |
| 347 | gpu_addr); | 343 | gpu_addr); |
| 348 | return; | 344 | return; |
| 349 | } | 345 | } |
| 350 | const bool continuous = system.GPU().MemoryManager().IsBlockContinuous(gpu_addr, size); | ||
| 351 | surface->MarkAsContinuous(continuous); | ||
| 352 | surface->SetCacheAddr(cache_ptr); | ||
| 353 | surface->SetCpuAddr(*cpu_addr); | 346 | surface->SetCpuAddr(*cpu_addr); |
| 354 | RegisterInnerCache(surface); | 347 | RegisterInnerCache(surface); |
| 355 | surface->MarkAsRegistered(true); | 348 | surface->MarkAsRegistered(true); |
| @@ -634,7 +627,7 @@ private: | |||
| 634 | std::optional<std::pair<TSurface, TView>> Manage3DSurfaces(std::vector<TSurface>& overlaps, | 627 | std::optional<std::pair<TSurface, TView>> Manage3DSurfaces(std::vector<TSurface>& overlaps, |
| 635 | const SurfaceParams& params, | 628 | const SurfaceParams& params, |
| 636 | const GPUVAddr gpu_addr, | 629 | const GPUVAddr gpu_addr, |
| 637 | const CacheAddr cache_addr, | 630 | const VAddr cpu_addr, |
| 638 | bool preserve_contents) { | 631 | bool preserve_contents) { |
| 639 | if (params.target == SurfaceTarget::Texture3D) { | 632 | if (params.target == SurfaceTarget::Texture3D) { |
| 640 | bool failed = false; | 633 | bool failed = false; |
| @@ -659,7 +652,7 @@ private: | |||
| 659 | failed = true; | 652 | failed = true; |
| 660 | break; | 653 | break; |
| 661 | } | 654 | } |
| 662 | const u32 offset = static_cast<u32>(surface->GetCacheAddr() - cache_addr); | 655 | const u32 offset = static_cast<u32>(surface->GetCpuAddr() - cpu_addr); |
| 663 | const auto [x, y, z] = params.GetBlockOffsetXYZ(offset); | 656 | const auto [x, y, z] = params.GetBlockOffsetXYZ(offset); |
| 664 | modified |= surface->IsModified(); | 657 | modified |= surface->IsModified(); |
| 665 | const CopyParams copy_params(0, 0, 0, 0, 0, z, 0, 0, params.width, params.height, | 658 | const CopyParams copy_params(0, 0, 0, 0, 0, z, 0, 0, params.width, params.height, |
| @@ -679,7 +672,7 @@ private: | |||
| 679 | } else { | 672 | } else { |
| 680 | for (const auto& surface : overlaps) { | 673 | for (const auto& surface : overlaps) { |
| 681 | if (!surface->MatchTarget(params.target)) { | 674 | if (!surface->MatchTarget(params.target)) { |
| 682 | if (overlaps.size() == 1 && surface->GetCacheAddr() == cache_addr) { | 675 | if (overlaps.size() == 1 && surface->GetCpuAddr() == cpu_addr) { |
| 683 | if (Settings::values.use_accurate_gpu_emulation) { | 676 | if (Settings::values.use_accurate_gpu_emulation) { |
| 684 | return std::nullopt; | 677 | return std::nullopt; |
| 685 | } | 678 | } |
| @@ -688,7 +681,7 @@ private: | |||
| 688 | } | 681 | } |
| 689 | return std::nullopt; | 682 | return std::nullopt; |
| 690 | } | 683 | } |
| 691 | if (surface->GetCacheAddr() != cache_addr) { | 684 | if (surface->GetCpuAddr() != cpu_addr) { |
| 692 | continue; | 685 | continue; |
| 693 | } | 686 | } |
| 694 | if (surface->MatchesStructure(params) == MatchStructureResult::FullMatch) { | 687 | if (surface->MatchesStructure(params) == MatchStructureResult::FullMatch) { |
| @@ -722,13 +715,13 @@ private: | |||
| 722 | * left blank. | 715 | * left blank. |
| 723 | * @param is_render Whether or not the surface is a render target. | 716 | * @param is_render Whether or not the surface is a render target. |
| 724 | **/ | 717 | **/ |
| 725 | std::pair<TSurface, TView> GetSurface(const GPUVAddr gpu_addr, const CacheAddr cache_addr, | 718 | std::pair<TSurface, TView> GetSurface(const GPUVAddr gpu_addr, const VAddr cpu_addr, |
| 726 | const SurfaceParams& params, bool preserve_contents, | 719 | const SurfaceParams& params, bool preserve_contents, |
| 727 | bool is_render) { | 720 | bool is_render) { |
| 728 | // Step 1 | 721 | // Step 1 |
| 729 | // Check Level 1 Cache for a fast structural match. If candidate surface | 722 | // Check Level 1 Cache for a fast structural match. If candidate surface |
| 730 | // matches at certain level we are pretty much done. | 723 | // matches at certain level we are pretty much done. |
| 731 | if (const auto iter = l1_cache.find(cache_addr); iter != l1_cache.end()) { | 724 | if (const auto iter = l1_cache.find(cpu_addr); iter != l1_cache.end()) { |
| 732 | TSurface& current_surface = iter->second; | 725 | TSurface& current_surface = iter->second; |
| 733 | const auto topological_result = current_surface->MatchesTopology(params); | 726 | const auto topological_result = current_surface->MatchesTopology(params); |
| 734 | if (topological_result != MatchTopologyResult::FullMatch) { | 727 | if (topological_result != MatchTopologyResult::FullMatch) { |
| @@ -755,7 +748,7 @@ private: | |||
| 755 | // Step 2 | 748 | // Step 2 |
| 756 | // Obtain all possible overlaps in the memory region | 749 | // Obtain all possible overlaps in the memory region |
| 757 | const std::size_t candidate_size = params.GetGuestSizeInBytes(); | 750 | const std::size_t candidate_size = params.GetGuestSizeInBytes(); |
| 758 | auto overlaps{GetSurfacesInRegion(cache_addr, candidate_size)}; | 751 | auto overlaps{GetSurfacesInRegion(cpu_addr, candidate_size)}; |
| 759 | 752 | ||
| 760 | // If none are found, we are done. we just load the surface and create it. | 753 | // If none are found, we are done. we just load the surface and create it. |
| 761 | if (overlaps.empty()) { | 754 | if (overlaps.empty()) { |
| @@ -777,7 +770,7 @@ private: | |||
| 777 | // Check if it's a 3D texture | 770 | // Check if it's a 3D texture |
| 778 | if (params.block_depth > 0) { | 771 | if (params.block_depth > 0) { |
| 779 | auto surface = | 772 | auto surface = |
| 780 | Manage3DSurfaces(overlaps, params, gpu_addr, cache_addr, preserve_contents); | 773 | Manage3DSurfaces(overlaps, params, gpu_addr, cpu_addr, preserve_contents); |
| 781 | if (surface) { | 774 | if (surface) { |
| 782 | return *surface; | 775 | return *surface; |
| 783 | } | 776 | } |
| @@ -852,16 +845,16 @@ private: | |||
| 852 | * @param params The parameters on the candidate surface. | 845 | * @param params The parameters on the candidate surface. |
| 853 | **/ | 846 | **/ |
| 854 | Deduction DeduceSurface(const GPUVAddr gpu_addr, const SurfaceParams& params) { | 847 | Deduction DeduceSurface(const GPUVAddr gpu_addr, const SurfaceParams& params) { |
| 855 | const auto host_ptr{system.GPU().MemoryManager().GetPointer(gpu_addr)}; | 848 | const std::optional<VAddr> cpu_addr = |
| 856 | const auto cache_addr{ToCacheAddr(host_ptr)}; | 849 | system.GPU().MemoryManager().GpuToCpuAddress(gpu_addr); |
| 857 | 850 | ||
| 858 | if (!cache_addr) { | 851 | if (!cpu_addr) { |
| 859 | Deduction result{}; | 852 | Deduction result{}; |
| 860 | result.type = DeductionType::DeductionFailed; | 853 | result.type = DeductionType::DeductionFailed; |
| 861 | return result; | 854 | return result; |
| 862 | } | 855 | } |
| 863 | 856 | ||
| 864 | if (const auto iter = l1_cache.find(cache_addr); iter != l1_cache.end()) { | 857 | if (const auto iter = l1_cache.find(*cpu_addr); iter != l1_cache.end()) { |
| 865 | TSurface& current_surface = iter->second; | 858 | TSurface& current_surface = iter->second; |
| 866 | const auto topological_result = current_surface->MatchesTopology(params); | 859 | const auto topological_result = current_surface->MatchesTopology(params); |
| 867 | if (topological_result != MatchTopologyResult::FullMatch) { | 860 | if (topological_result != MatchTopologyResult::FullMatch) { |
| @@ -880,7 +873,7 @@ private: | |||
| 880 | } | 873 | } |
| 881 | 874 | ||
| 882 | const std::size_t candidate_size = params.GetGuestSizeInBytes(); | 875 | const std::size_t candidate_size = params.GetGuestSizeInBytes(); |
| 883 | auto overlaps{GetSurfacesInRegion(cache_addr, candidate_size)}; | 876 | auto overlaps{GetSurfacesInRegion(*cpu_addr, candidate_size)}; |
| 884 | 877 | ||
| 885 | if (overlaps.empty()) { | 878 | if (overlaps.empty()) { |
| 886 | Deduction result{}; | 879 | Deduction result{}; |
| @@ -1024,10 +1017,10 @@ private: | |||
| 1024 | } | 1017 | } |
| 1025 | 1018 | ||
| 1026 | void RegisterInnerCache(TSurface& surface) { | 1019 | void RegisterInnerCache(TSurface& surface) { |
| 1027 | const CacheAddr cache_addr = surface->GetCacheAddr(); | 1020 | const VAddr cpu_addr = surface->GetCpuAddr(); |
| 1028 | CacheAddr start = cache_addr >> registry_page_bits; | 1021 | VAddr start = cpu_addr >> registry_page_bits; |
| 1029 | const CacheAddr end = (surface->GetCacheAddrEnd() - 1) >> registry_page_bits; | 1022 | const VAddr end = (surface->GetCpuAddrEnd() - 1) >> registry_page_bits; |
| 1030 | l1_cache[cache_addr] = surface; | 1023 | l1_cache[cpu_addr] = surface; |
| 1031 | while (start <= end) { | 1024 | while (start <= end) { |
| 1032 | registry[start].push_back(surface); | 1025 | registry[start].push_back(surface); |
| 1033 | start++; | 1026 | start++; |
| @@ -1035,10 +1028,10 @@ private: | |||
| 1035 | } | 1028 | } |
| 1036 | 1029 | ||
| 1037 | void UnregisterInnerCache(TSurface& surface) { | 1030 | void UnregisterInnerCache(TSurface& surface) { |
| 1038 | const CacheAddr cache_addr = surface->GetCacheAddr(); | 1031 | const VAddr cpu_addr = surface->GetCpuAddr(); |
| 1039 | CacheAddr start = cache_addr >> registry_page_bits; | 1032 | VAddr start = cpu_addr >> registry_page_bits; |
| 1040 | const CacheAddr end = (surface->GetCacheAddrEnd() - 1) >> registry_page_bits; | 1033 | const VAddr end = (surface->GetCpuAddrEnd() - 1) >> registry_page_bits; |
| 1041 | l1_cache.erase(cache_addr); | 1034 | l1_cache.erase(cpu_addr); |
| 1042 | while (start <= end) { | 1035 | while (start <= end) { |
| 1043 | auto& reg{registry[start]}; | 1036 | auto& reg{registry[start]}; |
| 1044 | reg.erase(std::find(reg.begin(), reg.end(), surface)); | 1037 | reg.erase(std::find(reg.begin(), reg.end(), surface)); |
| @@ -1046,18 +1039,18 @@ private: | |||
| 1046 | } | 1039 | } |
| 1047 | } | 1040 | } |
| 1048 | 1041 | ||
| 1049 | std::vector<TSurface> GetSurfacesInRegion(const CacheAddr cache_addr, const std::size_t size) { | 1042 | std::vector<TSurface> GetSurfacesInRegion(const VAddr cpu_addr, const std::size_t size) { |
| 1050 | if (size == 0) { | 1043 | if (size == 0) { |
| 1051 | return {}; | 1044 | return {}; |
| 1052 | } | 1045 | } |
| 1053 | const CacheAddr cache_addr_end = cache_addr + size; | 1046 | const VAddr cpu_addr_end = cpu_addr + size; |
| 1054 | CacheAddr start = cache_addr >> registry_page_bits; | 1047 | VAddr start = cpu_addr >> registry_page_bits; |
| 1055 | const CacheAddr end = (cache_addr_end - 1) >> registry_page_bits; | 1048 | const VAddr end = (cpu_addr_end - 1) >> registry_page_bits; |
| 1056 | std::vector<TSurface> surfaces; | 1049 | std::vector<TSurface> surfaces; |
| 1057 | while (start <= end) { | 1050 | while (start <= end) { |
| 1058 | std::vector<TSurface>& list = registry[start]; | 1051 | std::vector<TSurface>& list = registry[start]; |
| 1059 | for (auto& surface : list) { | 1052 | for (auto& surface : list) { |
| 1060 | if (!surface->IsPicked() && surface->Overlaps(cache_addr, cache_addr_end)) { | 1053 | if (!surface->IsPicked() && surface->Overlaps(cpu_addr, cpu_addr_end)) { |
| 1061 | surface->MarkAsPicked(true); | 1054 | surface->MarkAsPicked(true); |
| 1062 | surfaces.push_back(surface); | 1055 | surfaces.push_back(surface); |
| 1063 | } | 1056 | } |
| @@ -1146,14 +1139,14 @@ private: | |||
| 1146 | // large in size. | 1139 | // large in size. |
| 1147 | static constexpr u64 registry_page_bits{20}; | 1140 | static constexpr u64 registry_page_bits{20}; |
| 1148 | static constexpr u64 registry_page_size{1 << registry_page_bits}; | 1141 | static constexpr u64 registry_page_size{1 << registry_page_bits}; |
| 1149 | std::unordered_map<CacheAddr, std::vector<TSurface>> registry; | 1142 | std::unordered_map<VAddr, std::vector<TSurface>> registry; |
| 1150 | 1143 | ||
| 1151 | static constexpr u32 DEPTH_RT = 8; | 1144 | static constexpr u32 DEPTH_RT = 8; |
| 1152 | static constexpr u32 NO_RT = 0xFFFFFFFF; | 1145 | static constexpr u32 NO_RT = 0xFFFFFFFF; |
| 1153 | 1146 | ||
| 1154 | // The L1 Cache is used for fast texture lookup before checking the overlaps | 1147 | // The L1 Cache is used for fast texture lookup before checking the overlaps |
| 1155 | // This avoids calculating size and other stuffs. | 1148 | // This avoids calculating size and other stuffs. |
| 1156 | std::unordered_map<CacheAddr, TSurface> l1_cache; | 1149 | std::unordered_map<VAddr, TSurface> l1_cache; |
| 1157 | 1150 | ||
| 1158 | /// The surface reserve is a "backup" cache, this is where we put unique surfaces that have | 1151 | /// The surface reserve is a "backup" cache, this is where we put unique surfaces that have |
| 1159 | /// previously been used. This is to prevent surfaces from being constantly created and | 1152 | /// previously been used. This is to prevent surfaces from being constantly created and |