diff options
| author | 2019-05-12 20:33:52 -0400 | |
|---|---|---|
| committer | 2019-06-20 21:36:12 -0300 | |
| commit | 7731a0e2d15da04eea746b4b8dd5c6c4b29f9f29 (patch) | |
| tree | 9769d59ddb0076234d26993ee8aca62e7da58554 /src | |
| parent | surface_params: Ensure pitch is always written to avoid surface leaks (diff) | |
| download | yuzu-7731a0e2d15da04eea746b4b8dd5c6c4b29f9f29.tar.gz yuzu-7731a0e2d15da04eea746b4b8dd5c6c4b29f9f29.tar.xz yuzu-7731a0e2d15da04eea746b4b8dd5c6c4b29f9f29.zip | |
texture_cache: General Fixes
Fixed ASTC mipmaps loading
Fixed alignment on openGL upload/download
Fixed Block Height Calculation
Removed unalign_height
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.cpp | 11 | ||||
| -rw-r--r-- | src/video_core/surface.h | 84 | ||||
| -rw-r--r-- | src/video_core/texture_cache/surface_base.cpp | 18 | ||||
| -rw-r--r-- | src/video_core/texture_cache/surface_base.h | 4 | ||||
| -rw-r--r-- | src/video_core/texture_cache/surface_params.cpp | 52 | ||||
| -rw-r--r-- | src/video_core/texture_cache/surface_params.h | 27 | ||||
| -rw-r--r-- | src/video_core/textures/convert.cpp | 14 | ||||
| -rw-r--r-- | src/video_core/textures/convert.h | 7 |
8 files changed, 170 insertions, 47 deletions
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index a55097e5f..197c9f02c 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp | |||
| @@ -23,6 +23,7 @@ using VideoCore::MortonSwizzleMode; | |||
| 23 | 23 | ||
| 24 | using VideoCore::Surface::ComponentType; | 24 | using VideoCore::Surface::ComponentType; |
| 25 | using VideoCore::Surface::PixelFormat; | 25 | using VideoCore::Surface::PixelFormat; |
| 26 | using VideoCore::Surface::SurfaceCompression; | ||
| 26 | using VideoCore::Surface::SurfaceTarget; | 27 | using VideoCore::Surface::SurfaceTarget; |
| 27 | using VideoCore::Surface::SurfaceType; | 28 | using VideoCore::Surface::SurfaceType; |
| 28 | 29 | ||
| @@ -242,10 +243,10 @@ void CachedSurface::DownloadTexture(std::vector<u8>& staging_buffer) { | |||
| 242 | MICROPROFILE_SCOPE(OpenGL_Texture_Download); | 243 | MICROPROFILE_SCOPE(OpenGL_Texture_Download); |
| 243 | 244 | ||
| 244 | // TODO(Rodrigo): Optimize alignment | 245 | // TODO(Rodrigo): Optimize alignment |
| 245 | glPixelStorei(GL_PACK_ALIGNMENT, 1); | ||
| 246 | SCOPE_EXIT({ glPixelStorei(GL_PACK_ROW_LENGTH, 0); }); | 246 | SCOPE_EXIT({ glPixelStorei(GL_PACK_ROW_LENGTH, 0); }); |
| 247 | 247 | ||
| 248 | for (u32 level = 0; level < params.num_levels; ++level) { | 248 | for (u32 level = 0; level < params.num_levels; ++level) { |
| 249 | glPixelStorei(GL_PACK_ALIGNMENT, std::min(8U, params.GetRowAlignment(level))); | ||
| 249 | glPixelStorei(GL_PACK_ROW_LENGTH, static_cast<GLint>(params.GetMipWidth(level))); | 250 | glPixelStorei(GL_PACK_ROW_LENGTH, static_cast<GLint>(params.GetMipWidth(level))); |
| 250 | const std::size_t mip_offset = params.GetHostMipmapLevelOffset(level); | 251 | const std::size_t mip_offset = params.GetHostMipmapLevelOffset(level); |
| 251 | if (is_compressed) { | 252 | if (is_compressed) { |
| @@ -270,10 +271,14 @@ void CachedSurface::UploadTexture(std::vector<u8>& staging_buffer) { | |||
| 270 | 271 | ||
| 271 | void CachedSurface::UploadTextureMipmap(u32 level, std::vector<u8>& staging_buffer) { | 272 | void CachedSurface::UploadTextureMipmap(u32 level, std::vector<u8>& staging_buffer) { |
| 272 | // TODO(Rodrigo): Optimize alignment | 273 | // TODO(Rodrigo): Optimize alignment |
| 273 | glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | 274 | glPixelStorei(GL_UNPACK_ALIGNMENT, std::min(8U, params.GetRowAlignment(level))); |
| 274 | glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(params.GetMipWidth(level))); | 275 | glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(params.GetMipWidth(level))); |
| 275 | 276 | ||
| 276 | const std::size_t mip_offset = params.GetHostMipmapLevelOffset(level); | 277 | auto compression_type = params.GetCompressionType(); |
| 278 | |||
| 279 | const std::size_t mip_offset = compression_type == SurfaceCompression::Converted | ||
| 280 | ? params.GetConvertedMipmapOffset(level) | ||
| 281 | : params.GetHostMipmapLevelOffset(level); | ||
| 277 | u8* buffer{staging_buffer.data() + mip_offset}; | 282 | u8* buffer{staging_buffer.data() + mip_offset}; |
| 278 | if (is_compressed) { | 283 | if (is_compressed) { |
| 279 | const auto image_size{static_cast<GLsizei>(params.GetHostMipmapSize(level))}; | 284 | const auto image_size{static_cast<GLsizei>(params.GetHostMipmapSize(level))}; |
diff --git a/src/video_core/surface.h b/src/video_core/surface.h index 8e98033f3..5d49214e5 100644 --- a/src/video_core/surface.h +++ b/src/video_core/surface.h | |||
| @@ -197,7 +197,7 @@ inline constexpr std::array<u32, MaxPixelFormat> compression_factor_shift_table | |||
| 197 | */ | 197 | */ |
| 198 | inline constexpr u32 GetCompressionFactorShift(PixelFormat format) { | 198 | inline constexpr u32 GetCompressionFactorShift(PixelFormat format) { |
| 199 | DEBUG_ASSERT(format != PixelFormat::Invalid); | 199 | DEBUG_ASSERT(format != PixelFormat::Invalid); |
| 200 | DEBUG_ASSERT(static_cast<std::size_t>(format) < compression_factor_table.size()); | 200 | DEBUG_ASSERT(static_cast<std::size_t>(format) < compression_factor_shift_table.size()); |
| 201 | return compression_factor_shift_table[static_cast<std::size_t>(format)]; | 201 | return compression_factor_shift_table[static_cast<std::size_t>(format)]; |
| 202 | } | 202 | } |
| 203 | 203 | ||
| @@ -438,6 +438,88 @@ static constexpr u32 GetBytesPerPixel(PixelFormat pixel_format) { | |||
| 438 | return GetFormatBpp(pixel_format) / CHAR_BIT; | 438 | return GetFormatBpp(pixel_format) / CHAR_BIT; |
| 439 | } | 439 | } |
| 440 | 440 | ||
| 441 | enum class SurfaceCompression : u8 { | ||
| 442 | None = 0, | ||
| 443 | Compressed = 1, | ||
| 444 | Converted = 2, | ||
| 445 | Rearranged = 3, | ||
| 446 | }; | ||
| 447 | |||
| 448 | inline constexpr std::array<SurfaceCompression, MaxPixelFormat> compression_type_table = {{ | ||
| 449 | SurfaceCompression::None, // ABGR8U | ||
| 450 | SurfaceCompression::None, // ABGR8S | ||
| 451 | SurfaceCompression::None, // ABGR8UI | ||
| 452 | SurfaceCompression::None, // B5G6R5U | ||
| 453 | SurfaceCompression::None, // A2B10G10R10U | ||
| 454 | SurfaceCompression::None, // A1B5G5R5U | ||
| 455 | SurfaceCompression::None, // R8U | ||
| 456 | SurfaceCompression::None, // R8UI | ||
| 457 | SurfaceCompression::None, // RGBA16F | ||
| 458 | SurfaceCompression::None, // RGBA16U | ||
| 459 | SurfaceCompression::None, // RGBA16UI | ||
| 460 | SurfaceCompression::None, // R11FG11FB10F | ||
| 461 | SurfaceCompression::None, // RGBA32UI | ||
| 462 | SurfaceCompression::Compressed, // DXT1 | ||
| 463 | SurfaceCompression::Compressed, // DXT23 | ||
| 464 | SurfaceCompression::Compressed, // DXT45 | ||
| 465 | SurfaceCompression::Compressed, // DXN1 | ||
| 466 | SurfaceCompression::Compressed, // DXN2UNORM | ||
| 467 | SurfaceCompression::Compressed, // DXN2SNORM | ||
| 468 | SurfaceCompression::Compressed, // BC7U | ||
| 469 | SurfaceCompression::Compressed, // BC6H_UF16 | ||
| 470 | SurfaceCompression::Compressed, // BC6H_SF16 | ||
| 471 | SurfaceCompression::Converted, // ASTC_2D_4X4 | ||
| 472 | SurfaceCompression::None, // BGRA8 | ||
| 473 | SurfaceCompression::None, // RGBA32F | ||
| 474 | SurfaceCompression::None, // RG32F | ||
| 475 | SurfaceCompression::None, // R32F | ||
| 476 | SurfaceCompression::None, // R16F | ||
| 477 | SurfaceCompression::None, // R16U | ||
| 478 | SurfaceCompression::None, // R16S | ||
| 479 | SurfaceCompression::None, // R16UI | ||
| 480 | SurfaceCompression::None, // R16I | ||
| 481 | SurfaceCompression::None, // RG16 | ||
| 482 | SurfaceCompression::None, // RG16F | ||
| 483 | SurfaceCompression::None, // RG16UI | ||
| 484 | SurfaceCompression::None, // RG16I | ||
| 485 | SurfaceCompression::None, // RG16S | ||
| 486 | SurfaceCompression::None, // RGB32F | ||
| 487 | SurfaceCompression::None, // RGBA8_SRGB | ||
| 488 | SurfaceCompression::None, // RG8U | ||
| 489 | SurfaceCompression::None, // RG8S | ||
| 490 | SurfaceCompression::None, // RG32UI | ||
| 491 | SurfaceCompression::None, // R32UI | ||
| 492 | SurfaceCompression::Converted, // ASTC_2D_8X8 | ||
| 493 | SurfaceCompression::Converted, // ASTC_2D_8X5 | ||
| 494 | SurfaceCompression::Converted, // ASTC_2D_5X4 | ||
| 495 | SurfaceCompression::None, // BGRA8_SRGB | ||
| 496 | SurfaceCompression::Compressed, // DXT1_SRGB | ||
| 497 | SurfaceCompression::Compressed, // DXT23_SRGB | ||
| 498 | SurfaceCompression::Compressed, // DXT45_SRGB | ||
| 499 | SurfaceCompression::Compressed, // BC7U_SRGB | ||
| 500 | SurfaceCompression::Converted, // ASTC_2D_4X4_SRGB | ||
| 501 | SurfaceCompression::Converted, // ASTC_2D_8X8_SRGB | ||
| 502 | SurfaceCompression::Converted, // ASTC_2D_8X5_SRGB | ||
| 503 | SurfaceCompression::Converted, // ASTC_2D_5X4_SRGB | ||
| 504 | SurfaceCompression::Converted, // ASTC_2D_5X5 | ||
| 505 | SurfaceCompression::Converted, // ASTC_2D_5X5_SRGB | ||
| 506 | SurfaceCompression::Converted, // ASTC_2D_10X8 | ||
| 507 | SurfaceCompression::Converted, // ASTC_2D_10X8_SRGB | ||
| 508 | SurfaceCompression::None, // Z32F | ||
| 509 | SurfaceCompression::None, // Z16 | ||
| 510 | SurfaceCompression::None, // Z24S8 | ||
| 511 | SurfaceCompression::Rearranged, // S8Z24 | ||
| 512 | SurfaceCompression::None, // Z32FS8 | ||
| 513 | }}; | ||
| 514 | |||
| 515 | static constexpr SurfaceCompression GetFormatCompressionType(PixelFormat format) { | ||
| 516 | if (format == PixelFormat::Invalid) | ||
| 517 | return SurfaceCompression::None; | ||
| 518 | |||
| 519 | ASSERT(static_cast<std::size_t>(format) < compression_type_table.size()); | ||
| 520 | return compression_type_table[static_cast<std::size_t>(format)]; | ||
| 521 | } | ||
| 522 | |||
| 441 | SurfaceTarget SurfaceTargetFromTextureType(Tegra::Texture::TextureType texture_type); | 523 | SurfaceTarget SurfaceTargetFromTextureType(Tegra::Texture::TextureType texture_type); |
| 442 | 524 | ||
| 443 | bool SurfaceTargetIsLayered(SurfaceTarget target); | 525 | bool SurfaceTargetIsLayered(SurfaceTarget target); |
diff --git a/src/video_core/texture_cache/surface_base.cpp b/src/video_core/texture_cache/surface_base.cpp index 510d1aef5..ceff51043 100644 --- a/src/video_core/texture_cache/surface_base.cpp +++ b/src/video_core/texture_cache/surface_base.cpp | |||
| @@ -17,6 +17,7 @@ MICROPROFILE_DEFINE(GPU_Flush_Texture, "GPU", "Texture Flush", MP_RGB(128, 192, | |||
| 17 | 17 | ||
| 18 | using Tegra::Texture::ConvertFromGuestToHost; | 18 | using Tegra::Texture::ConvertFromGuestToHost; |
| 19 | using VideoCore::MortonSwizzleMode; | 19 | using VideoCore::MortonSwizzleMode; |
| 20 | using VideoCore::Surface::SurfaceCompression; | ||
| 20 | 21 | ||
| 21 | SurfaceBaseImpl::SurfaceBaseImpl(GPUVAddr gpu_addr, const SurfaceParams& params) | 22 | SurfaceBaseImpl::SurfaceBaseImpl(GPUVAddr gpu_addr, const SurfaceParams& params) |
| 22 | : params{params}, mipmap_sizes(params.num_levels), | 23 | : params{params}, mipmap_sizes(params.num_levels), |
| @@ -102,9 +103,20 @@ void SurfaceBaseImpl::LoadBuffer(Tegra::MemoryManager& memory_manager, | |||
| 102 | } | 103 | } |
| 103 | } | 104 | } |
| 104 | 105 | ||
| 105 | for (u32 level = 0; level < params.num_levels; ++level) { | 106 | auto compression_type = params.GetCompressionType(); |
| 106 | const std::size_t host_offset{params.GetHostMipmapLevelOffset(level)}; | 107 | if (compression_type == SurfaceCompression::None || |
| 107 | ConvertFromGuestToHost(staging_buffer.data() + host_offset, params.pixel_format, | 108 | compression_type == SurfaceCompression::Compressed) |
| 109 | return; | ||
| 110 | |||
| 111 | for (u32 level_up = params.num_levels; level_up > 0; --level_up) { | ||
| 112 | const u32 level = level_up - 1; | ||
| 113 | const std::size_t in_host_offset{params.GetHostMipmapLevelOffset(level)}; | ||
| 114 | const std::size_t out_host_offset = compression_type == SurfaceCompression::Rearranged | ||
| 115 | ? in_host_offset | ||
| 116 | : params.GetConvertedMipmapOffset(level); | ||
| 117 | u8* in_buffer = staging_buffer.data() + in_host_offset; | ||
| 118 | u8* out_buffer = staging_buffer.data() + out_host_offset; | ||
| 119 | ConvertFromGuestToHost(in_buffer, out_buffer, params.pixel_format, | ||
| 108 | params.GetMipWidth(level), params.GetMipHeight(level), | 120 | params.GetMipWidth(level), params.GetMipHeight(level), |
| 109 | params.GetMipDepth(level), true, true); | 121 | params.GetMipDepth(level), true, true); |
| 110 | } | 122 | } |
diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index 78db2d665..cb7f22706 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h | |||
| @@ -93,6 +93,10 @@ public: | |||
| 93 | return mipmap_sizes[level]; | 93 | return mipmap_sizes[level]; |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | bool IsLinear() const { | ||
| 97 | return !params.is_tiled; | ||
| 98 | } | ||
| 99 | |||
| 96 | bool MatchFormat(VideoCore::Surface::PixelFormat pixel_format) const { | 100 | bool MatchFormat(VideoCore::Surface::PixelFormat pixel_format) const { |
| 97 | return params.pixel_format == pixel_format; | 101 | return params.pixel_format == pixel_format; |
| 98 | } | 102 | } |
diff --git a/src/video_core/texture_cache/surface_params.cpp b/src/video_core/texture_cache/surface_params.cpp index 8472b69dc..d9d157d02 100644 --- a/src/video_core/texture_cache/surface_params.cpp +++ b/src/video_core/texture_cache/surface_params.cpp | |||
| @@ -76,17 +76,14 @@ SurfaceParams SurfaceParams::CreateForTexture(Core::System& system, | |||
| 76 | params.type = GetFormatType(params.pixel_format); | 76 | params.type = GetFormatType(params.pixel_format); |
| 77 | // TODO: on 1DBuffer we should use the tic info. | 77 | // TODO: on 1DBuffer we should use the tic info. |
| 78 | params.target = TextureType2SurfaceTarget(entry.GetType(), entry.IsArray()); | 78 | params.target = TextureType2SurfaceTarget(entry.GetType(), entry.IsArray()); |
| 79 | params.width = | 79 | params.width = config.tic.Width(); |
| 80 | Common::AlignBits(config.tic.Width(), GetCompressionFactorShift(params.pixel_format)); | 80 | params.height = config.tic.Height(); |
| 81 | params.height = | ||
| 82 | Common::AlignBits(config.tic.Height(), GetCompressionFactorShift(params.pixel_format)); | ||
| 83 | params.depth = config.tic.Depth(); | 81 | params.depth = config.tic.Depth(); |
| 84 | if (params.target == SurfaceTarget::TextureCubemap || | 82 | if (params.target == SurfaceTarget::TextureCubemap || |
| 85 | params.target == SurfaceTarget::TextureCubeArray) { | 83 | params.target == SurfaceTarget::TextureCubeArray) { |
| 86 | params.depth *= 6; | 84 | params.depth *= 6; |
| 87 | } | 85 | } |
| 88 | params.pitch = params.is_tiled ? 0 : config.tic.Pitch(); | 86 | params.pitch = params.is_tiled ? 0 : config.tic.Pitch(); |
| 89 | params.unaligned_height = config.tic.Height(); | ||
| 90 | params.num_levels = config.tic.max_mip_level + 1; | 87 | params.num_levels = config.tic.max_mip_level + 1; |
| 91 | params.is_layered = params.IsLayered(); | 88 | params.is_layered = params.IsLayered(); |
| 92 | return params; | 89 | return params; |
| @@ -108,7 +105,6 @@ SurfaceParams SurfaceParams::CreateForDepthBuffer( | |||
| 108 | params.type = GetFormatType(params.pixel_format); | 105 | params.type = GetFormatType(params.pixel_format); |
| 109 | params.width = zeta_width; | 106 | params.width = zeta_width; |
| 110 | params.height = zeta_height; | 107 | params.height = zeta_height; |
| 111 | params.unaligned_height = zeta_height; | ||
| 112 | params.target = SurfaceTarget::Texture2D; | 108 | params.target = SurfaceTarget::Texture2D; |
| 113 | params.depth = 1; | 109 | params.depth = 1; |
| 114 | params.pitch = 0; | 110 | params.pitch = 0; |
| @@ -141,7 +137,6 @@ SurfaceParams SurfaceParams::CreateForFramebuffer(Core::System& system, std::siz | |||
| 141 | } | 137 | } |
| 142 | params.height = config.height; | 138 | params.height = config.height; |
| 143 | params.depth = 1; | 139 | params.depth = 1; |
| 144 | params.unaligned_height = config.height; | ||
| 145 | params.target = SurfaceTarget::Texture2D; | 140 | params.target = SurfaceTarget::Texture2D; |
| 146 | params.num_levels = 1; | 141 | params.num_levels = 1; |
| 147 | params.is_layered = false; | 142 | params.is_layered = false; |
| @@ -164,7 +159,6 @@ SurfaceParams SurfaceParams::CreateForFermiCopySurface( | |||
| 164 | params.width = config.width; | 159 | params.width = config.width; |
| 165 | params.height = config.height; | 160 | params.height = config.height; |
| 166 | params.pitch = config.pitch; | 161 | params.pitch = config.pitch; |
| 167 | params.unaligned_height = config.height; | ||
| 168 | // TODO(Rodrigo): Try to guess the surface target from depth and layer parameters | 162 | // TODO(Rodrigo): Try to guess the surface target from depth and layer parameters |
| 169 | params.target = SurfaceTarget::Texture2D; | 163 | params.target = SurfaceTarget::Texture2D; |
| 170 | params.depth = 1; | 164 | params.depth = 1; |
| @@ -185,18 +179,18 @@ bool SurfaceParams::IsLayered() const { | |||
| 185 | } | 179 | } |
| 186 | } | 180 | } |
| 187 | 181 | ||
| 182 | // Auto block resizing algorithm from: | ||
| 183 | // https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nv50/nv50_miptree.c | ||
| 188 | u32 SurfaceParams::GetMipBlockHeight(u32 level) const { | 184 | u32 SurfaceParams::GetMipBlockHeight(u32 level) const { |
| 189 | // Auto block resizing algorithm from: | ||
| 190 | // https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nv50/nv50_miptree.c | ||
| 191 | if (level == 0) { | 185 | if (level == 0) { |
| 192 | return this->block_height; | 186 | return this->block_height; |
| 193 | } | 187 | } |
| 194 | 188 | ||
| 195 | const u32 height{GetMipHeight(level)}; | 189 | const u32 height_new{GetMipHeight(level)}; |
| 196 | const u32 default_block_height{GetDefaultBlockHeight()}; | 190 | const u32 default_block_height{GetDefaultBlockHeight()}; |
| 197 | const u32 blocks_in_y{(height + default_block_height - 1) / default_block_height}; | 191 | const u32 blocks_in_y{(height_new + default_block_height - 1) / default_block_height}; |
| 198 | const u32 block_height = Common::Log2Ceil32(blocks_in_y); | 192 | const u32 block_height_new = Common::Log2Ceil32(blocks_in_y); |
| 199 | return std::clamp(block_height, 3U, 8U) - 3U; | 193 | return std::clamp(block_height_new, 3U, 7U) - 3U; |
| 200 | } | 194 | } |
| 201 | 195 | ||
| 202 | u32 SurfaceParams::GetMipBlockDepth(u32 level) const { | 196 | u32 SurfaceParams::GetMipBlockDepth(u32 level) const { |
| @@ -207,12 +201,12 @@ u32 SurfaceParams::GetMipBlockDepth(u32 level) const { | |||
| 207 | return 0; | 201 | return 0; |
| 208 | } | 202 | } |
| 209 | 203 | ||
| 210 | const u32 depth{GetMipDepth(level)}; | 204 | const u32 depth_new{GetMipDepth(level)}; |
| 211 | const u32 block_depth = Common::Log2Ceil32(depth); | 205 | const u32 block_depth_new = Common::Log2Ceil32(depth_new); |
| 212 | if (block_depth > 4) { | 206 | if (block_depth_new > 4) { |
| 213 | return 5 - (GetMipBlockHeight(level) >= 2); | 207 | return 5 - (GetMipBlockHeight(level) >= 2); |
| 214 | } | 208 | } |
| 215 | return block_depth; | 209 | return block_depth_new; |
| 216 | } | 210 | } |
| 217 | 211 | ||
| 218 | std::size_t SurfaceParams::GetGuestMipmapLevelOffset(u32 level) const { | 212 | std::size_t SurfaceParams::GetGuestMipmapLevelOffset(u32 level) const { |
| @@ -231,6 +225,14 @@ std::size_t SurfaceParams::GetHostMipmapLevelOffset(u32 level) const { | |||
| 231 | return offset; | 225 | return offset; |
| 232 | } | 226 | } |
| 233 | 227 | ||
| 228 | std::size_t SurfaceParams::GetConvertedMipmapOffset(u32 level) const { | ||
| 229 | std::size_t offset = 0; | ||
| 230 | for (u32 i = 0; i < level; i++) { | ||
| 231 | offset += GetConvertedMipmapSize(i); | ||
| 232 | } | ||
| 233 | return offset; | ||
| 234 | } | ||
| 235 | |||
| 234 | std::size_t SurfaceParams::GetGuestMipmapSize(u32 level) const { | 236 | std::size_t SurfaceParams::GetGuestMipmapSize(u32 level) const { |
| 235 | return GetInnerMipmapMemorySize(level, false, false); | 237 | return GetInnerMipmapMemorySize(level, false, false); |
| 236 | } | 238 | } |
| @@ -239,6 +241,14 @@ std::size_t SurfaceParams::GetHostMipmapSize(u32 level) const { | |||
| 239 | return GetInnerMipmapMemorySize(level, true, false) * GetNumLayers(); | 241 | return GetInnerMipmapMemorySize(level, true, false) * GetNumLayers(); |
| 240 | } | 242 | } |
| 241 | 243 | ||
| 244 | std::size_t SurfaceParams::GetConvertedMipmapSize(u32 level) const { | ||
| 245 | constexpr std::size_t rgb8_bpp = 4ULL; | ||
| 246 | const std::size_t width_t = GetMipWidth(level); | ||
| 247 | const std::size_t height_t = GetMipHeight(level); | ||
| 248 | const std::size_t depth_t = is_layered ? depth : GetMipDepth(level); | ||
| 249 | return width_t * height_t * depth_t * rgb8_bpp; | ||
| 250 | } | ||
| 251 | |||
| 242 | std::size_t SurfaceParams::GetGuestLayerSize() const { | 252 | std::size_t SurfaceParams::GetGuestLayerSize() const { |
| 243 | return GetLayerSize(false, false); | 253 | return GetLayerSize(false, false); |
| 244 | } | 254 | } |
| @@ -287,12 +297,10 @@ std::size_t SurfaceParams::Hash() const { | |||
| 287 | 297 | ||
| 288 | bool SurfaceParams::operator==(const SurfaceParams& rhs) const { | 298 | bool SurfaceParams::operator==(const SurfaceParams& rhs) const { |
| 289 | return std::tie(is_tiled, block_width, block_height, block_depth, tile_width_spacing, width, | 299 | return std::tie(is_tiled, block_width, block_height, block_depth, tile_width_spacing, width, |
| 290 | height, depth, pitch, unaligned_height, num_levels, pixel_format, | 300 | height, depth, pitch, num_levels, pixel_format, component_type, type, target) == |
| 291 | component_type, type, target) == | ||
| 292 | std::tie(rhs.is_tiled, rhs.block_width, rhs.block_height, rhs.block_depth, | 301 | std::tie(rhs.is_tiled, rhs.block_width, rhs.block_height, rhs.block_depth, |
| 293 | rhs.tile_width_spacing, rhs.width, rhs.height, rhs.depth, rhs.pitch, | 302 | rhs.tile_width_spacing, rhs.width, rhs.height, rhs.depth, rhs.pitch, |
| 294 | rhs.unaligned_height, rhs.num_levels, rhs.pixel_format, rhs.component_type, | 303 | rhs.num_levels, rhs.pixel_format, rhs.component_type, rhs.type, rhs.target); |
| 295 | rhs.type, rhs.target); | ||
| 296 | } | 304 | } |
| 297 | 305 | ||
| 298 | std::string SurfaceParams::TargetName() const { | 306 | std::string SurfaceParams::TargetName() const { |
diff --git a/src/video_core/texture_cache/surface_params.h b/src/video_core/texture_cache/surface_params.h index 7c48782c7..b3082173f 100644 --- a/src/video_core/texture_cache/surface_params.h +++ b/src/video_core/texture_cache/surface_params.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <map> | 7 | #include <map> |
| 8 | 8 | ||
| 9 | #include "common/alignment.h" | 9 | #include "common/alignment.h" |
| 10 | #include "common/bit_util.h" | ||
| 10 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 11 | #include "video_core/engines/fermi_2d.h" | 12 | #include "video_core/engines/fermi_2d.h" |
| 12 | #include "video_core/engines/maxwell_3d.h" | 13 | #include "video_core/engines/maxwell_3d.h" |
| @@ -16,6 +17,8 @@ | |||
| 16 | 17 | ||
| 17 | namespace VideoCommon { | 18 | namespace VideoCommon { |
| 18 | 19 | ||
| 20 | using VideoCore::Surface::SurfaceCompression; | ||
| 21 | |||
| 19 | class SurfaceParams { | 22 | class SurfaceParams { |
| 20 | public: | 23 | public: |
| 21 | /// Creates SurfaceCachedParams from a texture configuration. | 24 | /// Creates SurfaceCachedParams from a texture configuration. |
| @@ -50,17 +53,12 @@ public: | |||
| 50 | 53 | ||
| 51 | std::size_t GetHostSizeInBytes() const { | 54 | std::size_t GetHostSizeInBytes() const { |
| 52 | std::size_t host_size_in_bytes; | 55 | std::size_t host_size_in_bytes; |
| 53 | if (IsPixelFormatASTC(pixel_format)) { | 56 | if (GetCompressionType() == SurfaceCompression::Converted) { |
| 54 | constexpr std::size_t rgb8_bpp = 4ULL; | 57 | constexpr std::size_t rgb8_bpp = 4ULL; |
| 55 | // ASTC is uncompressed in software, in emulated as RGBA8 | 58 | // ASTC is uncompressed in software, in emulated as RGBA8 |
| 56 | host_size_in_bytes = 0; | 59 | host_size_in_bytes = 0; |
| 57 | for (u32 level = 0; level < num_levels; ++level) { | 60 | for (u32 level = 0; level < num_levels; ++level) { |
| 58 | const std::size_t width = | 61 | host_size_in_bytes += GetConvertedMipmapSize(level); |
| 59 | Common::AlignUp(GetMipWidth(level), GetDefaultBlockWidth()); | ||
| 60 | const std::size_t height = | ||
| 61 | Common::AlignUp(GetMipHeight(level), GetDefaultBlockHeight()); | ||
| 62 | const std::size_t depth = is_layered ? this->depth : GetMipDepth(level); | ||
| 63 | host_size_in_bytes += width * height * depth * rgb8_bpp; | ||
| 64 | } | 62 | } |
| 65 | } else { | 63 | } else { |
| 66 | host_size_in_bytes = GetInnerMemorySize(true, false, false); | 64 | host_size_in_bytes = GetInnerMemorySize(true, false, false); |
| @@ -93,6 +91,12 @@ public: | |||
| 93 | /// Returns the block depth of a given mipmap level. | 91 | /// Returns the block depth of a given mipmap level. |
| 94 | u32 GetMipBlockDepth(u32 level) const; | 92 | u32 GetMipBlockDepth(u32 level) const; |
| 95 | 93 | ||
| 94 | u32 GetRowAlignment(u32 level) const { | ||
| 95 | const u32 bpp = | ||
| 96 | GetCompressionType() == SurfaceCompression::Converted ? 4 : GetBytesPerPixel(); | ||
| 97 | return 1U << Common::CountTrailingZeroes32(GetMipWidth(level) * bpp); | ||
| 98 | } | ||
| 99 | |||
| 96 | // Helper used for out of class size calculations | 100 | // Helper used for out of class size calculations |
| 97 | static std::size_t AlignLayered(const std::size_t out_size, const u32 block_height, | 101 | static std::size_t AlignLayered(const std::size_t out_size, const u32 block_height, |
| 98 | const u32 block_depth) { | 102 | const u32 block_depth) { |
| @@ -106,12 +110,16 @@ public: | |||
| 106 | /// Returns the offset in bytes in host memory (linear) of a given mipmap level. | 110 | /// Returns the offset in bytes in host memory (linear) of a given mipmap level. |
| 107 | std::size_t GetHostMipmapLevelOffset(u32 level) const; | 111 | std::size_t GetHostMipmapLevelOffset(u32 level) const; |
| 108 | 112 | ||
| 113 | std::size_t GetConvertedMipmapOffset(u32 level) const; | ||
| 114 | |||
| 109 | /// Returns the size in bytes in guest memory of a given mipmap level. | 115 | /// Returns the size in bytes in guest memory of a given mipmap level. |
| 110 | std::size_t GetGuestMipmapSize(u32 level) const; | 116 | std::size_t GetGuestMipmapSize(u32 level) const; |
| 111 | 117 | ||
| 112 | /// Returns the size in bytes in host memory (linear) of a given mipmap level. | 118 | /// Returns the size in bytes in host memory (linear) of a given mipmap level. |
| 113 | std::size_t GetHostMipmapSize(u32 level) const; | 119 | std::size_t GetHostMipmapSize(u32 level) const; |
| 114 | 120 | ||
| 121 | std::size_t GetConvertedMipmapSize(u32 level) const; | ||
| 122 | |||
| 115 | /// Returns the size of a layer in bytes in guest memory. | 123 | /// Returns the size of a layer in bytes in guest memory. |
| 116 | std::size_t GetGuestLayerSize() const; | 124 | std::size_t GetGuestLayerSize() const; |
| 117 | 125 | ||
| @@ -141,6 +149,10 @@ public: | |||
| 141 | /// Returns true if the pixel format is a depth and/or stencil format. | 149 | /// Returns true if the pixel format is a depth and/or stencil format. |
| 142 | bool IsPixelFormatZeta() const; | 150 | bool IsPixelFormatZeta() const; |
| 143 | 151 | ||
| 152 | SurfaceCompression GetCompressionType() const { | ||
| 153 | return VideoCore::Surface::GetFormatCompressionType(pixel_format); | ||
| 154 | } | ||
| 155 | |||
| 144 | std::string TargetName() const; | 156 | std::string TargetName() const; |
| 145 | 157 | ||
| 146 | bool is_tiled; | 158 | bool is_tiled; |
| @@ -154,7 +166,6 @@ public: | |||
| 154 | u32 height; | 166 | u32 height; |
| 155 | u32 depth; | 167 | u32 depth; |
| 156 | u32 pitch; | 168 | u32 pitch; |
| 157 | u32 unaligned_height; | ||
| 158 | u32 num_levels; | 169 | u32 num_levels; |
| 159 | VideoCore::Surface::PixelFormat pixel_format; | 170 | VideoCore::Surface::PixelFormat pixel_format; |
| 160 | VideoCore::Surface::ComponentType component_type; | 171 | VideoCore::Surface::ComponentType component_type; |
diff --git a/src/video_core/textures/convert.cpp b/src/video_core/textures/convert.cpp index 82050bd51..f3efa7eb0 100644 --- a/src/video_core/textures/convert.cpp +++ b/src/video_core/textures/convert.cpp | |||
| @@ -62,19 +62,19 @@ static void ConvertZ24S8ToS8Z24(u8* data, u32 width, u32 height) { | |||
| 62 | SwapS8Z24ToZ24S8<true>(data, width, height); | 62 | SwapS8Z24ToZ24S8<true>(data, width, height); |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | void ConvertFromGuestToHost(u8* data, PixelFormat pixel_format, u32 width, u32 height, u32 depth, | 65 | void ConvertFromGuestToHost(u8* in_data, u8* out_data, PixelFormat pixel_format, u32 width, |
| 66 | bool convert_astc, bool convert_s8z24) { | 66 | u32 height, u32 depth, bool convert_astc, bool convert_s8z24) { |
| 67 | if (convert_astc && IsPixelFormatASTC(pixel_format)) { | 67 | if (convert_astc && IsPixelFormatASTC(pixel_format)) { |
| 68 | // Convert ASTC pixel formats to RGBA8, as most desktop GPUs do not support ASTC. | 68 | // Convert ASTC pixel formats to RGBA8, as most desktop GPUs do not support ASTC. |
| 69 | u32 block_width{}; | 69 | u32 block_width{}; |
| 70 | u32 block_height{}; | 70 | u32 block_height{}; |
| 71 | std::tie(block_width, block_height) = GetASTCBlockSize(pixel_format); | 71 | std::tie(block_width, block_height) = GetASTCBlockSize(pixel_format); |
| 72 | const std::vector<u8> rgba8_data = | 72 | const std::vector<u8> rgba8_data = Tegra::Texture::ASTC::Decompress( |
| 73 | Tegra::Texture::ASTC::Decompress(data, width, height, depth, block_width, block_height); | 73 | in_data, width, height, depth, block_width, block_height); |
| 74 | std::copy(rgba8_data.begin(), rgba8_data.end(), data); | 74 | std::copy(rgba8_data.begin(), rgba8_data.end(), out_data); |
| 75 | 75 | ||
| 76 | } else if (convert_s8z24 && pixel_format == PixelFormat::S8Z24) { | 76 | } else if (convert_s8z24 && pixel_format == PixelFormat::S8Z24) { |
| 77 | Tegra::Texture::ConvertS8Z24ToZ24S8(data, width, height); | 77 | Tegra::Texture::ConvertS8Z24ToZ24S8(in_data, width, height); |
| 78 | } | 78 | } |
| 79 | } | 79 | } |
| 80 | 80 | ||
| @@ -90,4 +90,4 @@ void ConvertFromHostToGuest(u8* data, PixelFormat pixel_format, u32 width, u32 h | |||
| 90 | } | 90 | } |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | } // namespace Tegra::Texture \ No newline at end of file | 93 | } // namespace Tegra::Texture |
diff --git a/src/video_core/textures/convert.h b/src/video_core/textures/convert.h index 12542e71c..d5d6c77bb 100644 --- a/src/video_core/textures/convert.h +++ b/src/video_core/textures/convert.h | |||
| @@ -12,10 +12,11 @@ enum class PixelFormat; | |||
| 12 | 12 | ||
| 13 | namespace Tegra::Texture { | 13 | namespace Tegra::Texture { |
| 14 | 14 | ||
| 15 | void ConvertFromGuestToHost(u8* data, VideoCore::Surface::PixelFormat pixel_format, u32 width, | 15 | void ConvertFromGuestToHost(u8* in_data, u8* out_data, VideoCore::Surface::PixelFormat pixel_format, |
| 16 | u32 height, u32 depth, bool convert_astc, bool convert_s8z24); | 16 | u32 width, u32 height, u32 depth, bool convert_astc, |
| 17 | bool convert_s8z24); | ||
| 17 | 18 | ||
| 18 | void ConvertFromHostToGuest(u8* data, VideoCore::Surface::PixelFormat pixel_format, u32 width, | 19 | void ConvertFromHostToGuest(u8* data, VideoCore::Surface::PixelFormat pixel_format, u32 width, |
| 19 | u32 height, u32 depth, bool convert_astc, bool convert_s8z24); | 20 | u32 height, u32 depth, bool convert_astc, bool convert_s8z24); |
| 20 | 21 | ||
| 21 | } // namespace Tegra::Texture \ No newline at end of file | 22 | } // namespace Tegra::Texture |