diff options
| author | 2020-03-14 20:24:54 -0300 | |
|---|---|---|
| committer | 2020-04-01 01:14:04 -0300 | |
| commit | b6571ca9f0be7799856cce76363ab752f478fb4b (patch) | |
| tree | 2f4de71c3540eb1d8d159b0233bebb3fa04d2e6e /src/video_core/texture_cache | |
| parent | gl_device: Detect if ASTC is reported and expose it (diff) | |
| download | yuzu-b6571ca9f0be7799856cce76363ab752f478fb4b.tar.gz yuzu-b6571ca9f0be7799856cce76363ab752f478fb4b.tar.xz yuzu-b6571ca9f0be7799856cce76363ab752f478fb4b.zip | |
video_core: Use native ASTC when available
Diffstat (limited to 'src/video_core/texture_cache')
| -rw-r--r-- | src/video_core/texture_cache/surface_base.cpp | 39 | ||||
| -rw-r--r-- | src/video_core/texture_cache/surface_base.h | 15 | ||||
| -rw-r--r-- | src/video_core/texture_cache/surface_params.cpp | 28 | ||||
| -rw-r--r-- | src/video_core/texture_cache/surface_params.h | 36 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 6 |
5 files changed, 59 insertions, 65 deletions
diff --git a/src/video_core/texture_cache/surface_base.cpp b/src/video_core/texture_cache/surface_base.cpp index 002df414f..6fe815135 100644 --- a/src/video_core/texture_cache/surface_base.cpp +++ b/src/video_core/texture_cache/surface_base.cpp | |||
| @@ -18,15 +18,20 @@ MICROPROFILE_DEFINE(GPU_Flush_Texture, "GPU", "Texture Flush", MP_RGB(128, 192, | |||
| 18 | 18 | ||
| 19 | using Tegra::Texture::ConvertFromGuestToHost; | 19 | using Tegra::Texture::ConvertFromGuestToHost; |
| 20 | using VideoCore::MortonSwizzleMode; | 20 | using VideoCore::MortonSwizzleMode; |
| 21 | using VideoCore::Surface::SurfaceCompression; | 21 | using VideoCore::Surface::IsPixelFormatASTC; |
| 22 | using VideoCore::Surface::PixelFormat; | ||
| 22 | 23 | ||
| 23 | StagingCache::StagingCache() = default; | 24 | StagingCache::StagingCache() = default; |
| 24 | 25 | ||
| 25 | StagingCache::~StagingCache() = default; | 26 | StagingCache::~StagingCache() = default; |
| 26 | 27 | ||
| 27 | SurfaceBaseImpl::SurfaceBaseImpl(GPUVAddr gpu_addr, const SurfaceParams& params) | 28 | SurfaceBaseImpl::SurfaceBaseImpl(GPUVAddr gpu_addr, const SurfaceParams& params, |
| 28 | : params{params}, host_memory_size{params.GetHostSizeInBytes()}, gpu_addr{gpu_addr}, | 29 | bool is_astc_supported) |
| 29 | mipmap_sizes(params.num_levels), mipmap_offsets(params.num_levels) { | 30 | : params{params}, gpu_addr{gpu_addr}, mipmap_sizes(params.num_levels), |
| 31 | mipmap_offsets(params.num_levels) { | ||
| 32 | is_converted = IsPixelFormatASTC(params.pixel_format) && !is_astc_supported; | ||
| 33 | host_memory_size = params.GetHostSizeInBytes(is_converted); | ||
| 34 | |||
| 30 | std::size_t offset = 0; | 35 | std::size_t offset = 0; |
| 31 | for (u32 level = 0; level < params.num_levels; ++level) { | 36 | for (u32 level = 0; level < params.num_levels; ++level) { |
| 32 | const std::size_t mipmap_size{params.GetGuestMipmapSize(level)}; | 37 | const std::size_t mipmap_size{params.GetGuestMipmapSize(level)}; |
| @@ -164,7 +169,7 @@ void SurfaceBaseImpl::SwizzleFunc(MortonSwizzleMode mode, u8* memory, const Surf | |||
| 164 | 169 | ||
| 165 | std::size_t guest_offset{mipmap_offsets[level]}; | 170 | std::size_t guest_offset{mipmap_offsets[level]}; |
| 166 | if (params.is_layered) { | 171 | if (params.is_layered) { |
| 167 | std::size_t host_offset{0}; | 172 | std::size_t host_offset = 0; |
| 168 | const std::size_t guest_stride = layer_size; | 173 | const std::size_t guest_stride = layer_size; |
| 169 | const std::size_t host_stride = params.GetHostLayerSize(level); | 174 | const std::size_t host_stride = params.GetHostLayerSize(level); |
| 170 | for (u32 layer = 0; layer < params.depth; ++layer) { | 175 | for (u32 layer = 0; layer < params.depth; ++layer) { |
| @@ -206,7 +211,7 @@ void SurfaceBaseImpl::LoadBuffer(Tegra::MemoryManager& memory_manager, | |||
| 206 | ASSERT_MSG(params.block_width == 0, "Block width is defined as {} on texture target {}", | 211 | ASSERT_MSG(params.block_width == 0, "Block width is defined as {} on texture target {}", |
| 207 | params.block_width, static_cast<u32>(params.target)); | 212 | params.block_width, static_cast<u32>(params.target)); |
| 208 | for (u32 level = 0; level < params.num_levels; ++level) { | 213 | for (u32 level = 0; level < params.num_levels; ++level) { |
| 209 | const std::size_t host_offset{params.GetHostMipmapLevelOffset(level)}; | 214 | const std::size_t host_offset{params.GetHostMipmapLevelOffset(level, false)}; |
| 210 | SwizzleFunc(MortonSwizzleMode::MortonToLinear, host_ptr, params, | 215 | SwizzleFunc(MortonSwizzleMode::MortonToLinear, host_ptr, params, |
| 211 | staging_buffer.data() + host_offset, level); | 216 | staging_buffer.data() + host_offset, level); |
| 212 | } | 217 | } |
| @@ -219,7 +224,7 @@ void SurfaceBaseImpl::LoadBuffer(Tegra::MemoryManager& memory_manager, | |||
| 219 | const u32 height{(params.height + block_height - 1) / block_height}; | 224 | const u32 height{(params.height + block_height - 1) / block_height}; |
| 220 | const u32 copy_size{width * bpp}; | 225 | const u32 copy_size{width * bpp}; |
| 221 | if (params.pitch == copy_size) { | 226 | if (params.pitch == copy_size) { |
| 222 | std::memcpy(staging_buffer.data(), host_ptr, params.GetHostSizeInBytes()); | 227 | std::memcpy(staging_buffer.data(), host_ptr, params.GetHostSizeInBytes(false)); |
| 223 | } else { | 228 | } else { |
| 224 | const u8* start{host_ptr}; | 229 | const u8* start{host_ptr}; |
| 225 | u8* write_to{staging_buffer.data()}; | 230 | u8* write_to{staging_buffer.data()}; |
| @@ -231,19 +236,15 @@ void SurfaceBaseImpl::LoadBuffer(Tegra::MemoryManager& memory_manager, | |||
| 231 | } | 236 | } |
| 232 | } | 237 | } |
| 233 | 238 | ||
| 234 | auto compression_type = params.GetCompressionType(); | 239 | if (!is_converted && params.pixel_format != PixelFormat::S8Z24) { |
| 235 | if (compression_type == SurfaceCompression::None || | ||
| 236 | compression_type == SurfaceCompression::Compressed) | ||
| 237 | return; | 240 | return; |
| 241 | } | ||
| 238 | 242 | ||
| 239 | for (u32 level_up = params.num_levels; level_up > 0; --level_up) { | 243 | for (u32 level = params.num_levels; level--;) { |
| 240 | const u32 level = level_up - 1; | 244 | const std::size_t in_host_offset{params.GetHostMipmapLevelOffset(level, false)}; |
| 241 | const std::size_t in_host_offset{params.GetHostMipmapLevelOffset(level)}; | 245 | const std::size_t out_host_offset{params.GetHostMipmapLevelOffset(level, is_converted)}; |
| 242 | const std::size_t out_host_offset = compression_type == SurfaceCompression::Rearranged | 246 | u8* const in_buffer = staging_buffer.data() + in_host_offset; |
| 243 | ? in_host_offset | 247 | u8* const out_buffer = staging_buffer.data() + out_host_offset; |
| 244 | : params.GetConvertedMipmapOffset(level); | ||
| 245 | u8* in_buffer = staging_buffer.data() + in_host_offset; | ||
| 246 | u8* out_buffer = staging_buffer.data() + out_host_offset; | ||
| 247 | ConvertFromGuestToHost(in_buffer, out_buffer, params.pixel_format, | 248 | ConvertFromGuestToHost(in_buffer, out_buffer, params.pixel_format, |
| 248 | params.GetMipWidth(level), params.GetMipHeight(level), | 249 | params.GetMipWidth(level), params.GetMipHeight(level), |
| 249 | params.GetMipDepth(level), true, true); | 250 | params.GetMipDepth(level), true, true); |
| @@ -273,7 +274,7 @@ void SurfaceBaseImpl::FlushBuffer(Tegra::MemoryManager& memory_manager, | |||
| 273 | if (params.is_tiled) { | 274 | if (params.is_tiled) { |
| 274 | ASSERT_MSG(params.block_width == 0, "Block width is defined as {}", params.block_width); | 275 | ASSERT_MSG(params.block_width == 0, "Block width is defined as {}", params.block_width); |
| 275 | for (u32 level = 0; level < params.num_levels; ++level) { | 276 | for (u32 level = 0; level < params.num_levels; ++level) { |
| 276 | const std::size_t host_offset{params.GetHostMipmapLevelOffset(level)}; | 277 | const std::size_t host_offset{params.GetHostMipmapLevelOffset(level, false)}; |
| 277 | SwizzleFunc(MortonSwizzleMode::LinearToMorton, host_ptr, params, | 278 | SwizzleFunc(MortonSwizzleMode::LinearToMorton, host_ptr, params, |
| 278 | staging_buffer.data() + host_offset, level); | 279 | staging_buffer.data() + host_offset, level); |
| 279 | } | 280 | } |
diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index 5f79bb0aa..d7882a031 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h | |||
| @@ -131,6 +131,10 @@ public: | |||
| 131 | return !params.is_tiled; | 131 | return !params.is_tiled; |
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | bool IsConverted() const { | ||
| 135 | return is_converted; | ||
| 136 | } | ||
| 137 | |||
| 134 | bool MatchFormat(VideoCore::Surface::PixelFormat pixel_format) const { | 138 | bool MatchFormat(VideoCore::Surface::PixelFormat pixel_format) const { |
| 135 | return params.pixel_format == pixel_format; | 139 | return params.pixel_format == pixel_format; |
| 136 | } | 140 | } |
| @@ -160,7 +164,8 @@ public: | |||
| 160 | } | 164 | } |
| 161 | 165 | ||
| 162 | protected: | 166 | protected: |
| 163 | explicit SurfaceBaseImpl(GPUVAddr gpu_addr, const SurfaceParams& params); | 167 | explicit SurfaceBaseImpl(GPUVAddr gpu_addr, const SurfaceParams& params, |
| 168 | bool is_astc_supported); | ||
| 164 | ~SurfaceBaseImpl() = default; | 169 | ~SurfaceBaseImpl() = default; |
| 165 | 170 | ||
| 166 | virtual void DecorateSurfaceName() = 0; | 171 | virtual void DecorateSurfaceName() = 0; |
| @@ -168,12 +173,13 @@ protected: | |||
| 168 | const SurfaceParams params; | 173 | const SurfaceParams params; |
| 169 | std::size_t layer_size; | 174 | std::size_t layer_size; |
| 170 | std::size_t guest_memory_size; | 175 | std::size_t guest_memory_size; |
| 171 | const std::size_t host_memory_size; | 176 | std::size_t host_memory_size; |
| 172 | GPUVAddr gpu_addr{}; | 177 | GPUVAddr gpu_addr{}; |
| 173 | CacheAddr cache_addr{}; | 178 | CacheAddr cache_addr{}; |
| 174 | CacheAddr cache_addr_end{}; | 179 | CacheAddr cache_addr_end{}; |
| 175 | VAddr cpu_addr{}; | 180 | VAddr cpu_addr{}; |
| 176 | bool is_continuous{}; | 181 | bool is_continuous{}; |
| 182 | bool is_converted{}; | ||
| 177 | 183 | ||
| 178 | std::vector<std::size_t> mipmap_sizes; | 184 | std::vector<std::size_t> mipmap_sizes; |
| 179 | std::vector<std::size_t> mipmap_offsets; | 185 | std::vector<std::size_t> mipmap_offsets; |
| @@ -288,8 +294,9 @@ public: | |||
| 288 | } | 294 | } |
| 289 | 295 | ||
| 290 | protected: | 296 | protected: |
| 291 | explicit SurfaceBase(const GPUVAddr gpu_addr, const SurfaceParams& params) | 297 | explicit SurfaceBase(const GPUVAddr gpu_addr, const SurfaceParams& params, |
| 292 | : SurfaceBaseImpl(gpu_addr, params) {} | 298 | bool is_astc_supported) |
| 299 | : SurfaceBaseImpl(gpu_addr, params, is_astc_supported) {} | ||
| 293 | 300 | ||
| 294 | ~SurfaceBase() = default; | 301 | ~SurfaceBase() = default; |
| 295 | 302 | ||
diff --git a/src/video_core/texture_cache/surface_params.cpp b/src/video_core/texture_cache/surface_params.cpp index 9931c5ef7..47b2aafbd 100644 --- a/src/video_core/texture_cache/surface_params.cpp +++ b/src/video_core/texture_cache/surface_params.cpp | |||
| @@ -309,28 +309,26 @@ std::size_t SurfaceParams::GetGuestMipmapLevelOffset(u32 level) const { | |||
| 309 | return offset; | 309 | return offset; |
| 310 | } | 310 | } |
| 311 | 311 | ||
| 312 | std::size_t SurfaceParams::GetHostMipmapLevelOffset(u32 level) const { | 312 | std::size_t SurfaceParams::GetHostMipmapLevelOffset(u32 level, bool is_converted) const { |
| 313 | std::size_t offset = 0; | 313 | std::size_t offset = 0; |
| 314 | for (u32 i = 0; i < level; i++) { | 314 | if (is_converted) { |
| 315 | offset += GetInnerMipmapMemorySize(i, true, false) * GetNumLayers(); | 315 | for (u32 i = 0; i < level; ++i) { |
| 316 | } | 316 | offset += GetConvertedMipmapSize(i) * GetNumLayers(); |
| 317 | return offset; | 317 | } |
| 318 | } | 318 | } else { |
| 319 | 319 | for (u32 i = 0; i < level; ++i) { | |
| 320 | std::size_t SurfaceParams::GetConvertedMipmapOffset(u32 level) const { | 320 | offset += GetInnerMipmapMemorySize(i, true, false) * GetNumLayers(); |
| 321 | std::size_t offset = 0; | 321 | } |
| 322 | for (u32 i = 0; i < level; i++) { | ||
| 323 | offset += GetConvertedMipmapSize(i); | ||
| 324 | } | 322 | } |
| 325 | return offset; | 323 | return offset; |
| 326 | } | 324 | } |
| 327 | 325 | ||
| 328 | std::size_t SurfaceParams::GetConvertedMipmapSize(u32 level) const { | 326 | std::size_t SurfaceParams::GetConvertedMipmapSize(u32 level) const { |
| 329 | constexpr std::size_t rgba8_bpp = 4ULL; | 327 | constexpr std::size_t rgba8_bpp = 4ULL; |
| 330 | const std::size_t width_t = GetMipWidth(level); | 328 | const std::size_t mip_width = GetMipWidth(level); |
| 331 | const std::size_t height_t = GetMipHeight(level); | 329 | const std::size_t mip_height = GetMipHeight(level); |
| 332 | const std::size_t depth_t = is_layered ? depth : GetMipDepth(level); | 330 | const std::size_t mip_depth = is_layered ? 1 : GetMipDepth(level); |
| 333 | return width_t * height_t * depth_t * rgba8_bpp; | 331 | return mip_width * mip_height * mip_depth * rgba8_bpp; |
| 334 | } | 332 | } |
| 335 | 333 | ||
| 336 | std::size_t SurfaceParams::GetLayerSize(bool as_host_size, bool uncompressed) const { | 334 | std::size_t SurfaceParams::GetLayerSize(bool as_host_size, bool uncompressed) const { |
diff --git a/src/video_core/texture_cache/surface_params.h b/src/video_core/texture_cache/surface_params.h index 995cc3818..24957df8d 100644 --- a/src/video_core/texture_cache/surface_params.h +++ b/src/video_core/texture_cache/surface_params.h | |||
| @@ -20,8 +20,6 @@ namespace VideoCommon { | |||
| 20 | 20 | ||
| 21 | class FormatLookupTable; | 21 | class FormatLookupTable; |
| 22 | 22 | ||
| 23 | using VideoCore::Surface::SurfaceCompression; | ||
| 24 | |||
| 25 | class SurfaceParams { | 23 | class SurfaceParams { |
| 26 | public: | 24 | public: |
| 27 | /// Creates SurfaceCachedParams from a texture configuration. | 25 | /// Creates SurfaceCachedParams from a texture configuration. |
| @@ -67,16 +65,14 @@ public: | |||
| 67 | return GetInnerMemorySize(false, false, false); | 65 | return GetInnerMemorySize(false, false, false); |
| 68 | } | 66 | } |
| 69 | 67 | ||
| 70 | std::size_t GetHostSizeInBytes() const { | 68 | std::size_t GetHostSizeInBytes(bool is_converted) const { |
| 71 | std::size_t host_size_in_bytes; | 69 | if (!is_converted) { |
| 72 | if (GetCompressionType() == SurfaceCompression::Converted) { | 70 | return GetInnerMemorySize(true, false, false); |
| 73 | // ASTC is uncompressed in software, in emulated as RGBA8 | 71 | } |
| 74 | host_size_in_bytes = 0; | 72 | // ASTC is uncompressed in software, in emulated as RGBA8 |
| 75 | for (u32 level = 0; level < num_levels; ++level) { | 73 | std::size_t host_size_in_bytes = 0; |
| 76 | host_size_in_bytes += GetConvertedMipmapSize(level); | 74 | for (u32 level = 0; level < num_levels; ++level) { |
| 77 | } | 75 | host_size_in_bytes += GetConvertedMipmapSize(level) * GetNumLayers(); |
| 78 | } else { | ||
| 79 | host_size_in_bytes = GetInnerMemorySize(true, false, false); | ||
| 80 | } | 76 | } |
| 81 | return host_size_in_bytes; | 77 | return host_size_in_bytes; |
| 82 | } | 78 | } |
| @@ -107,9 +103,8 @@ public: | |||
| 107 | u32 GetMipBlockDepth(u32 level) const; | 103 | u32 GetMipBlockDepth(u32 level) const; |
| 108 | 104 | ||
| 109 | /// Returns the best possible row/pitch alignment for the surface. | 105 | /// Returns the best possible row/pitch alignment for the surface. |
| 110 | u32 GetRowAlignment(u32 level) const { | 106 | u32 GetRowAlignment(u32 level, bool is_converted) const { |
| 111 | const u32 bpp = | 107 | const u32 bpp = is_converted ? 4 : GetBytesPerPixel(); |
| 112 | GetCompressionType() == SurfaceCompression::Converted ? 4 : GetBytesPerPixel(); | ||
| 113 | return 1U << Common::CountTrailingZeroes32(GetMipWidth(level) * bpp); | 108 | return 1U << Common::CountTrailingZeroes32(GetMipWidth(level) * bpp); |
| 114 | } | 109 | } |
| 115 | 110 | ||
| @@ -117,11 +112,7 @@ public: | |||
| 117 | std::size_t GetGuestMipmapLevelOffset(u32 level) const; | 112 | std::size_t GetGuestMipmapLevelOffset(u32 level) const; |
| 118 | 113 | ||
| 119 | /// Returns the offset in bytes in host memory (linear) of a given mipmap level. | 114 | /// Returns the offset in bytes in host memory (linear) of a given mipmap level. |
| 120 | std::size_t GetHostMipmapLevelOffset(u32 level) const; | 115 | std::size_t GetHostMipmapLevelOffset(u32 level, bool is_converted) const; |
| 121 | |||
| 122 | /// Returns the offset in bytes in host memory (linear) of a given mipmap level | ||
| 123 | /// for a texture that is converted in host gpu. | ||
| 124 | std::size_t GetConvertedMipmapOffset(u32 level) const; | ||
| 125 | 116 | ||
| 126 | /// Returns the size in bytes in guest memory of a given mipmap level. | 117 | /// Returns the size in bytes in guest memory of a given mipmap level. |
| 127 | std::size_t GetGuestMipmapSize(u32 level) const { | 118 | std::size_t GetGuestMipmapSize(u32 level) const { |
| @@ -196,11 +187,6 @@ public: | |||
| 196 | pixel_format < VideoCore::Surface::PixelFormat::MaxDepthStencilFormat; | 187 | pixel_format < VideoCore::Surface::PixelFormat::MaxDepthStencilFormat; |
| 197 | } | 188 | } |
| 198 | 189 | ||
| 199 | /// Returns how the compression should be handled for this texture. | ||
| 200 | SurfaceCompression GetCompressionType() const { | ||
| 201 | return VideoCore::Surface::GetFormatCompressionType(pixel_format); | ||
| 202 | } | ||
| 203 | |||
| 204 | /// Returns is the surface is a TextureBuffer type of surface. | 190 | /// Returns is the surface is a TextureBuffer type of surface. |
| 205 | bool IsBuffer() const { | 191 | bool IsBuffer() const { |
| 206 | return target == VideoCore::Surface::SurfaceTarget::TextureBuffer; | 192 | return target == VideoCore::Surface::SurfaceTarget::TextureBuffer; |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 6cdbe63d0..c8f8d659d 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -289,8 +289,9 @@ public: | |||
| 289 | } | 289 | } |
| 290 | 290 | ||
| 291 | protected: | 291 | protected: |
| 292 | TextureCache(Core::System& system, VideoCore::RasterizerInterface& rasterizer) | 292 | explicit TextureCache(Core::System& system, VideoCore::RasterizerInterface& rasterizer, |
| 293 | : system{system}, rasterizer{rasterizer} { | 293 | bool is_astc_supported) |
| 294 | : system{system}, is_astc_supported{is_astc_supported}, rasterizer{rasterizer} { | ||
| 294 | for (std::size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) { | 295 | for (std::size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) { |
| 295 | SetEmptyColorBuffer(i); | 296 | SetEmptyColorBuffer(i); |
| 296 | } | 297 | } |
| @@ -381,6 +382,7 @@ protected: | |||
| 381 | } | 382 | } |
| 382 | 383 | ||
| 383 | Core::System& system; | 384 | Core::System& system; |
| 385 | const bool is_astc_supported; | ||
| 384 | 386 | ||
| 385 | private: | 387 | private: |
| 386 | enum class RecycleStrategy : u32 { | 388 | enum class RecycleStrategy : u32 { |