summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2019-05-12 20:33:52 -0400
committerGravatar ReinUsesLisp2019-06-20 21:36:12 -0300
commit7731a0e2d15da04eea746b4b8dd5c6c4b29f9f29 (patch)
tree9769d59ddb0076234d26993ee8aca62e7da58554 /src
parentsurface_params: Ensure pitch is always written to avoid surface leaks (diff)
downloadyuzu-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.cpp11
-rw-r--r--src/video_core/surface.h84
-rw-r--r--src/video_core/texture_cache/surface_base.cpp18
-rw-r--r--src/video_core/texture_cache/surface_base.h4
-rw-r--r--src/video_core/texture_cache/surface_params.cpp52
-rw-r--r--src/video_core/texture_cache/surface_params.h27
-rw-r--r--src/video_core/textures/convert.cpp14
-rw-r--r--src/video_core/textures/convert.h7
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
24using VideoCore::Surface::ComponentType; 24using VideoCore::Surface::ComponentType;
25using VideoCore::Surface::PixelFormat; 25using VideoCore::Surface::PixelFormat;
26using VideoCore::Surface::SurfaceCompression;
26using VideoCore::Surface::SurfaceTarget; 27using VideoCore::Surface::SurfaceTarget;
27using VideoCore::Surface::SurfaceType; 28using 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
271void CachedSurface::UploadTextureMipmap(u32 level, std::vector<u8>& staging_buffer) { 272void 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 */
198inline constexpr u32 GetCompressionFactorShift(PixelFormat format) { 198inline 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
441enum class SurfaceCompression : u8 {
442 None = 0,
443 Compressed = 1,
444 Converted = 2,
445 Rearranged = 3,
446};
447
448inline 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
515static 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
441SurfaceTarget SurfaceTargetFromTextureType(Tegra::Texture::TextureType texture_type); 523SurfaceTarget SurfaceTargetFromTextureType(Tegra::Texture::TextureType texture_type);
442 524
443bool SurfaceTargetIsLayered(SurfaceTarget target); 525bool 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
18using Tegra::Texture::ConvertFromGuestToHost; 18using Tegra::Texture::ConvertFromGuestToHost;
19using VideoCore::MortonSwizzleMode; 19using VideoCore::MortonSwizzleMode;
20using VideoCore::Surface::SurfaceCompression;
20 21
21SurfaceBaseImpl::SurfaceBaseImpl(GPUVAddr gpu_addr, const SurfaceParams& params) 22SurfaceBaseImpl::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
188u32 SurfaceParams::GetMipBlockHeight(u32 level) const { 184u32 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
202u32 SurfaceParams::GetMipBlockDepth(u32 level) const { 196u32 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
218std::size_t SurfaceParams::GetGuestMipmapLevelOffset(u32 level) const { 212std::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
228std::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
234std::size_t SurfaceParams::GetGuestMipmapSize(u32 level) const { 236std::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
244std::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
242std::size_t SurfaceParams::GetGuestLayerSize() const { 252std::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
288bool SurfaceParams::operator==(const SurfaceParams& rhs) const { 298bool 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
298std::string SurfaceParams::TargetName() const { 306std::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
17namespace VideoCommon { 18namespace VideoCommon {
18 19
20using VideoCore::Surface::SurfaceCompression;
21
19class SurfaceParams { 22class SurfaceParams {
20public: 23public:
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
65void ConvertFromGuestToHost(u8* data, PixelFormat pixel_format, u32 width, u32 height, u32 depth, 65void 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
13namespace Tegra::Texture { 13namespace Tegra::Texture {
14 14
15void ConvertFromGuestToHost(u8* data, VideoCore::Surface::PixelFormat pixel_format, u32 width, 15void 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
18void ConvertFromHostToGuest(u8* data, VideoCore::Surface::PixelFormat pixel_format, u32 width, 19void 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