diff options
| author | 2019-05-21 11:24:20 -0400 | |
|---|---|---|
| committer | 2019-06-20 21:38:33 -0300 | |
| commit | bdf9faab331cd79ca5c5e51c2369fc801e8cecea (patch) | |
| tree | 09b45767f5e9a72319db7b3184dc9b70120d4ea2 | |
| parent | texture_cache: return null surface on invalid address (diff) | |
| download | yuzu-bdf9faab331cd79ca5c5e51c2369fc801e8cecea.tar.gz yuzu-bdf9faab331cd79ca5c5e51c2369fc801e8cecea.tar.xz yuzu-bdf9faab331cd79ca5c5e51c2369fc801e8cecea.zip | |
texture_cache: Handle uncontinuous surfaces.
| -rw-r--r-- | src/video_core/memory_manager.cpp | 5 | ||||
| -rw-r--r-- | src/video_core/texture_cache/surface_base.cpp | 47 | ||||
| -rw-r--r-- | src/video_core/texture_cache/surface_base.h | 34 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 17 |
4 files changed, 82 insertions, 21 deletions
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp index 5d8d126c1..322453116 100644 --- a/src/video_core/memory_manager.cpp +++ b/src/video_core/memory_manager.cpp | |||
| @@ -202,11 +202,12 @@ const u8* MemoryManager::GetPointer(GPUVAddr addr) const { | |||
| 202 | } | 202 | } |
| 203 | 203 | ||
| 204 | bool MemoryManager::IsBlockContinuous(const GPUVAddr start, const std::size_t size) const { | 204 | bool MemoryManager::IsBlockContinuous(const GPUVAddr start, const std::size_t size) const { |
| 205 | const GPUVAddr end = start + size; | 205 | const std::size_t inner_size = size - 1; |
| 206 | const GPUVAddr end = start + inner_size; | ||
| 206 | const auto host_ptr_start = reinterpret_cast<std::uintptr_t>(GetPointer(start)); | 207 | const auto host_ptr_start = reinterpret_cast<std::uintptr_t>(GetPointer(start)); |
| 207 | const auto host_ptr_end = reinterpret_cast<std::uintptr_t>(GetPointer(end)); | 208 | const auto host_ptr_end = reinterpret_cast<std::uintptr_t>(GetPointer(end)); |
| 208 | const auto range = static_cast<std::size_t>(host_ptr_end - host_ptr_start); | 209 | const auto range = static_cast<std::size_t>(host_ptr_end - host_ptr_start); |
| 209 | return range == size; | 210 | return range == inner_size; |
| 210 | } | 211 | } |
| 211 | 212 | ||
| 212 | void MemoryManager::ReadBlock(GPUVAddr src_addr, void* dest_buffer, const std::size_t size) const { | 213 | void MemoryManager::ReadBlock(GPUVAddr src_addr, void* dest_buffer, const std::size_t size) const { |
diff --git a/src/video_core/texture_cache/surface_base.cpp b/src/video_core/texture_cache/surface_base.cpp index d4aa2c54b..7e90960f7 100644 --- a/src/video_core/texture_cache/surface_base.cpp +++ b/src/video_core/texture_cache/surface_base.cpp | |||
| @@ -68,12 +68,27 @@ void SurfaceBaseImpl::SwizzleFunc(MortonSwizzleMode mode, u8* memory, const Surf | |||
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | void SurfaceBaseImpl::LoadBuffer(Tegra::MemoryManager& memory_manager, | 70 | void SurfaceBaseImpl::LoadBuffer(Tegra::MemoryManager& memory_manager, |
| 71 | std::vector<u8>& staging_buffer) { | 71 | StagingCache& staging_cache) { |
| 72 | MICROPROFILE_SCOPE(GPU_Load_Texture); | 72 | MICROPROFILE_SCOPE(GPU_Load_Texture); |
| 73 | const auto host_ptr{memory_manager.GetPointer(gpu_addr)}; | 73 | auto& staging_buffer = staging_cache.GetBuffer(0); |
| 74 | if (!host_ptr) { | 74 | u8* host_ptr; |
| 75 | return; | 75 | is_continuous = memory_manager.IsBlockContinuous(gpu_addr, guest_memory_size); |
| 76 | |||
| 77 | // Handle continuouty | ||
| 78 | if (is_continuous) { | ||
| 79 | // Use physical memory directly | ||
| 80 | host_ptr = memory_manager.GetPointer(gpu_addr); | ||
| 81 | if (!host_ptr) { | ||
| 82 | return; | ||
| 83 | } | ||
| 84 | } else { | ||
| 85 | // Use an extra temporal buffer | ||
| 86 | auto& tmp_buffer = staging_cache.GetBuffer(1); | ||
| 87 | tmp_buffer.resize(guest_memory_size); | ||
| 88 | host_ptr = tmp_buffer.data(); | ||
| 89 | memory_manager.ReadBlockUnsafe(gpu_addr, host_ptr, guest_memory_size); | ||
| 76 | } | 90 | } |
| 91 | |||
| 77 | if (params.is_tiled) { | 92 | if (params.is_tiled) { |
| 78 | ASSERT_MSG(params.block_width == 0, "Block width is defined as {} on texture target {}", | 93 | ASSERT_MSG(params.block_width == 0, "Block width is defined as {} on texture target {}", |
| 79 | params.block_width, static_cast<u32>(params.target)); | 94 | params.block_width, static_cast<u32>(params.target)); |
| @@ -123,12 +138,25 @@ void SurfaceBaseImpl::LoadBuffer(Tegra::MemoryManager& memory_manager, | |||
| 123 | } | 138 | } |
| 124 | 139 | ||
| 125 | void SurfaceBaseImpl::FlushBuffer(Tegra::MemoryManager& memory_manager, | 140 | void SurfaceBaseImpl::FlushBuffer(Tegra::MemoryManager& memory_manager, |
| 126 | std::vector<u8>& staging_buffer) { | 141 | StagingCache& staging_cache) { |
| 127 | MICROPROFILE_SCOPE(GPU_Flush_Texture); | 142 | MICROPROFILE_SCOPE(GPU_Flush_Texture); |
| 128 | const auto host_ptr{memory_manager.GetPointer(gpu_addr)}; | 143 | auto& staging_buffer = staging_cache.GetBuffer(0); |
| 129 | if (!host_ptr) { | 144 | u8* host_ptr; |
| 130 | return; | 145 | |
| 146 | // Handle continuouty | ||
| 147 | if (is_continuous) { | ||
| 148 | // Use physical memory directly | ||
| 149 | host_ptr = memory_manager.GetPointer(gpu_addr); | ||
| 150 | if (!host_ptr) { | ||
| 151 | return; | ||
| 152 | } | ||
| 153 | } else { | ||
| 154 | // Use an extra temporal buffer | ||
| 155 | auto& tmp_buffer = staging_cache.GetBuffer(1); | ||
| 156 | tmp_buffer.resize(guest_memory_size); | ||
| 157 | host_ptr = tmp_buffer.data(); | ||
| 131 | } | 158 | } |
| 159 | |||
| 132 | if (params.is_tiled) { | 160 | if (params.is_tiled) { |
| 133 | ASSERT_MSG(params.block_width == 0, "Block width is defined as {}", params.block_width); | 161 | ASSERT_MSG(params.block_width == 0, "Block width is defined as {}", params.block_width); |
| 134 | for (u32 level = 0; level < params.num_levels; ++level) { | 162 | for (u32 level = 0; level < params.num_levels; ++level) { |
| @@ -154,6 +182,9 @@ void SurfaceBaseImpl::FlushBuffer(Tegra::MemoryManager& memory_manager, | |||
| 154 | } | 182 | } |
| 155 | } | 183 | } |
| 156 | } | 184 | } |
| 185 | if (!is_continuous) { | ||
| 186 | memory_manager.WriteBlockUnsafe(gpu_addr, host_ptr, guest_memory_size); | ||
| 187 | } | ||
| 157 | } | 188 | } |
| 158 | 189 | ||
| 159 | } // namespace VideoCommon | 190 | } // namespace VideoCommon |
diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index 210f27907..dacbc97c7 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h | |||
| @@ -32,11 +32,28 @@ enum class MatchStructureResult : u32 { | |||
| 32 | None = 2, | 32 | None = 2, |
| 33 | }; | 33 | }; |
| 34 | 34 | ||
| 35 | class StagingCache { | ||
| 36 | public: | ||
| 37 | StagingCache() {} | ||
| 38 | ~StagingCache() = default; | ||
| 39 | |||
| 40 | std::vector<u8>& GetBuffer(std::size_t index) { | ||
| 41 | return staging_buffer[index]; | ||
| 42 | } | ||
| 43 | |||
| 44 | void SetSize(std::size_t size) { | ||
| 45 | staging_buffer.resize(size); | ||
| 46 | } | ||
| 47 | |||
| 48 | private: | ||
| 49 | std::vector<std::vector<u8>> staging_buffer; | ||
| 50 | }; | ||
| 51 | |||
| 35 | class SurfaceBaseImpl { | 52 | class SurfaceBaseImpl { |
| 36 | public: | 53 | public: |
| 37 | void LoadBuffer(Tegra::MemoryManager& memory_manager, std::vector<u8>& staging_buffer); | 54 | void LoadBuffer(Tegra::MemoryManager& memory_manager, StagingCache& staging_cache); |
| 38 | 55 | ||
| 39 | void FlushBuffer(Tegra::MemoryManager& memory_manager, std::vector<u8>& staging_buffer); | 56 | void FlushBuffer(Tegra::MemoryManager& memory_manager, StagingCache& staging_cache); |
| 40 | 57 | ||
| 41 | GPUVAddr GetGpuAddr() const { | 58 | GPUVAddr GetGpuAddr() const { |
| 42 | return gpu_addr; | 59 | return gpu_addr; |
| @@ -93,6 +110,14 @@ public: | |||
| 93 | return mipmap_sizes[level]; | 110 | return mipmap_sizes[level]; |
| 94 | } | 111 | } |
| 95 | 112 | ||
| 113 | void MarkAsContinuous(const bool is_continuous) { | ||
| 114 | this->is_continuous = is_continuous; | ||
| 115 | } | ||
| 116 | |||
| 117 | bool IsContinuous() const { | ||
| 118 | return is_continuous; | ||
| 119 | } | ||
| 120 | |||
| 96 | bool IsLinear() const { | 121 | bool IsLinear() const { |
| 97 | return !params.is_tiled; | 122 | return !params.is_tiled; |
| 98 | } | 123 | } |
| @@ -122,8 +147,8 @@ public: | |||
| 122 | MatchStructureResult MatchesStructure(const SurfaceParams& rhs) const { | 147 | MatchStructureResult MatchesStructure(const SurfaceParams& rhs) const { |
| 123 | // Buffer surface Check | 148 | // Buffer surface Check |
| 124 | if (params.IsBuffer()) { | 149 | if (params.IsBuffer()) { |
| 125 | const std::size_t wd1 = params.width*params.GetBytesPerPixel(); | 150 | const std::size_t wd1 = params.width * params.GetBytesPerPixel(); |
| 126 | const std::size_t wd2 = rhs.width*rhs.GetBytesPerPixel(); | 151 | const std::size_t wd2 = rhs.width * rhs.GetBytesPerPixel(); |
| 127 | if (wd1 == wd2) { | 152 | if (wd1 == wd2) { |
| 128 | return MatchStructureResult::FullMatch; | 153 | return MatchStructureResult::FullMatch; |
| 129 | } | 154 | } |
| @@ -193,6 +218,7 @@ protected: | |||
| 193 | CacheAddr cache_addr{}; | 218 | CacheAddr cache_addr{}; |
| 194 | CacheAddr cache_addr_end{}; | 219 | CacheAddr cache_addr_end{}; |
| 195 | VAddr cpu_addr{}; | 220 | VAddr cpu_addr{}; |
| 221 | bool is_continuous{}; | ||
| 196 | 222 | ||
| 197 | std::vector<std::size_t> mipmap_sizes; | 223 | std::vector<std::size_t> mipmap_sizes; |
| 198 | std::vector<std::size_t> mipmap_offsets; | 224 | std::vector<std::size_t> mipmap_offsets; |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 24c87127d..ab4e094ea 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -220,6 +220,7 @@ protected: | |||
| 220 | SetEmptyColorBuffer(i); | 220 | SetEmptyColorBuffer(i); |
| 221 | } | 221 | } |
| 222 | SetEmptyDepthBuffer(); | 222 | SetEmptyDepthBuffer(); |
| 223 | staging_cache.SetSize(2); | ||
| 223 | } | 224 | } |
| 224 | 225 | ||
| 225 | ~TextureCache() = default; | 226 | ~TextureCache() = default; |
| @@ -244,6 +245,8 @@ protected: | |||
| 244 | gpu_addr); | 245 | gpu_addr); |
| 245 | return; | 246 | return; |
| 246 | } | 247 | } |
| 248 | bool continuouty = memory_manager->IsBlockContinuous(gpu_addr, size); | ||
| 249 | surface->MarkAsContinuous(continuouty); | ||
| 247 | surface->SetCacheAddr(cache_ptr); | 250 | surface->SetCacheAddr(cache_ptr); |
| 248 | surface->SetCpuAddr(*cpu_addr); | 251 | surface->SetCpuAddr(*cpu_addr); |
| 249 | RegisterInnerCache(surface); | 252 | RegisterInnerCache(surface); |
| @@ -611,9 +614,9 @@ private: | |||
| 611 | } | 614 | } |
| 612 | 615 | ||
| 613 | void LoadSurface(const TSurface& surface) { | 616 | void LoadSurface(const TSurface& surface) { |
| 614 | staging_buffer.resize(surface->GetHostSizeInBytes()); | 617 | staging_cache.GetBuffer(0).resize(surface->GetHostSizeInBytes()); |
| 615 | surface->LoadBuffer(*memory_manager, staging_buffer); | 618 | surface->LoadBuffer(*memory_manager, staging_cache); |
| 616 | surface->UploadTexture(staging_buffer); | 619 | surface->UploadTexture(staging_cache.GetBuffer(0)); |
| 617 | surface->MarkAsModified(false, Tick()); | 620 | surface->MarkAsModified(false, Tick()); |
| 618 | } | 621 | } |
| 619 | 622 | ||
| @@ -621,9 +624,9 @@ private: | |||
| 621 | if (!surface->IsModified()) { | 624 | if (!surface->IsModified()) { |
| 622 | return; | 625 | return; |
| 623 | } | 626 | } |
| 624 | staging_buffer.resize(surface->GetHostSizeInBytes()); | 627 | staging_cache.GetBuffer(0).resize(surface->GetHostSizeInBytes()); |
| 625 | surface->DownloadTexture(staging_buffer); | 628 | surface->DownloadTexture(staging_cache.GetBuffer(0)); |
| 626 | surface->FlushBuffer(*memory_manager, staging_buffer); | 629 | surface->FlushBuffer(*memory_manager, staging_cache); |
| 627 | surface->MarkAsModified(false, Tick()); | 630 | surface->MarkAsModified(false, Tick()); |
| 628 | } | 631 | } |
| 629 | 632 | ||
| @@ -723,7 +726,7 @@ private: | |||
| 723 | render_targets; | 726 | render_targets; |
| 724 | FramebufferTargetInfo depth_buffer; | 727 | FramebufferTargetInfo depth_buffer; |
| 725 | 728 | ||
| 726 | std::vector<u8> staging_buffer; | 729 | StagingCache staging_cache; |
| 727 | std::recursive_mutex mutex; | 730 | std::recursive_mutex mutex; |
| 728 | }; | 731 | }; |
| 729 | 732 | ||