Fix ASTC Decompressor to support depth parameter

This commit is contained in:
FernandoS27 2018-10-29 22:46:09 -04:00
parent aee93f98f9
commit 60a184455c
7 changed files with 131 additions and 65 deletions

View file

@ -58,16 +58,14 @@ void SurfaceParams::InitCacheParameters(Tegra::GPUVAddr gpu_addr_) {
std::size_t SurfaceParams::InnerMipmapMemorySize(u32 mip_level, bool force_gl, bool layer_only, std::size_t SurfaceParams::InnerMipmapMemorySize(u32 mip_level, bool force_gl, bool layer_only,
bool uncompressed) const { bool uncompressed) const {
const u32 compression_factor{GetCompressionFactor(pixel_format)}; const u32 tile_x{GetDefaultBlockWidth(pixel_format)};
const u32 tile_y{GetDefaultBlockHeight(pixel_format)};
const u32 bytes_per_pixel{GetBytesPerPixel(pixel_format)}; const u32 bytes_per_pixel{GetBytesPerPixel(pixel_format)};
u32 m_depth = (layer_only ? 1U : depth); u32 m_depth = (layer_only ? 1U : depth);
u32 m_width = MipWidth(mip_level); u32 m_width = MipWidth(mip_level);
u32 m_height = MipHeight(mip_level); u32 m_height = MipHeight(mip_level);
m_width = uncompressed ? m_width m_width = uncompressed ? m_width : std::max(1U, (m_width + tile_x - 1) / tile_x);
: std::max(1U, (m_width + compression_factor - 1) / compression_factor); m_height = uncompressed ? m_height : std::max(1U, (m_height + tile_y - 1) / tile_y);
m_height = uncompressed
? m_height
: std::max(1U, (m_height + compression_factor - 1) / compression_factor);
m_depth = std::max(1U, m_depth >> mip_level); m_depth = std::max(1U, m_depth >> mip_level);
u32 m_block_height = MipBlockHeight(mip_level); u32 m_block_height = MipBlockHeight(mip_level);
u32 m_block_depth = MipBlockDepth(mip_level); u32 m_block_depth = MipBlockDepth(mip_level);
@ -366,8 +364,8 @@ void MortonCopy(u32 stride, u32 block_height, u32 height, u32 block_depth, u32 d
// With the BCn formats (DXT and DXN), each 4x4 tile is swizzled instead of just individual // With the BCn formats (DXT and DXN), each 4x4 tile is swizzled instead of just individual
// pixel values. // pixel values.
const u32 tile_size_x{SurfaceParams::GetDefaultBlockWidth(format)}; const u32 tile_size_x{GetDefaultBlockWidth(format)};
const u32 tile_size_y{SurfaceParams::GetDefaultBlockHeight(format)}; const u32 tile_size_y{GetDefaultBlockHeight(format)};
if (morton_to_gl) { if (morton_to_gl) {
const std::vector<u8> data = const std::vector<u8> data =
@ -906,7 +904,7 @@ static void ConvertG8R8ToR8G8(std::vector<u8>& data, u32 width, u32 height) {
* typical desktop GPUs. * typical desktop GPUs.
*/ */
static void ConvertFormatAsNeeded_LoadGLBuffer(std::vector<u8>& data, PixelFormat pixel_format, static void ConvertFormatAsNeeded_LoadGLBuffer(std::vector<u8>& data, PixelFormat pixel_format,
u32 width, u32 height) { u32 width, u32 height, u32 depth) {
switch (pixel_format) { switch (pixel_format) {
case PixelFormat::ASTC_2D_4X4: case PixelFormat::ASTC_2D_4X4:
case PixelFormat::ASTC_2D_8X8: case PixelFormat::ASTC_2D_8X8:
@ -922,7 +920,8 @@ static void ConvertFormatAsNeeded_LoadGLBuffer(std::vector<u8>& data, PixelForma
u32 block_width{}; u32 block_width{};
u32 block_height{}; u32 block_height{};
std::tie(block_width, block_height) = GetASTCBlockSize(pixel_format); std::tie(block_width, block_height) = GetASTCBlockSize(pixel_format);
data = Tegra::Texture::ASTC::Decompress(data, width, height, block_width, block_height); data =
Tegra::Texture::ASTC::Decompress(data, width, height, depth, block_width, block_height);
break; break;
} }
case PixelFormat::S8Z24: case PixelFormat::S8Z24:
@ -982,7 +981,7 @@ void CachedSurface::LoadGLBuffer() {
} }
for (u32 i = 0; i < params.max_mip_level; i++) for (u32 i = 0; i < params.max_mip_level; i++)
ConvertFormatAsNeeded_LoadGLBuffer(gl_buffer[i], params.pixel_format, params.MipWidth(i), ConvertFormatAsNeeded_LoadGLBuffer(gl_buffer[i], params.pixel_format, params.MipWidth(i),
params.MipHeight(i)); params.MipHeight(i), params.MipDepth(i));
} }
MICROPROFILE_DEFINE(OpenGL_SurfaceFlush, "OpenGL", "Surface Flush", MP_RGB(128, 192, 64)); MICROPROFILE_DEFINE(OpenGL_SurfaceFlush, "OpenGL", "Surface Flush", MP_RGB(128, 192, 64));

View file

@ -139,7 +139,7 @@ struct SurfaceParams {
} }
u32 MipDepth(u32 mip_level) const { u32 MipDepth(u32 mip_level) const {
return std::max(1U, depth >> mip_level); return is_layered ? depth : std::max(1U, depth >> mip_level);
} }
// Auto block resizing algorithm from: // Auto block resizing algorithm from:

View file

@ -297,6 +297,8 @@ PixelFormat PixelFormatFromTextureFormat(Tegra::Texture::TextureFormat format,
return is_srgb ? PixelFormat::ASTC_2D_4X4_SRGB : PixelFormat::ASTC_2D_4X4; return is_srgb ? PixelFormat::ASTC_2D_4X4_SRGB : PixelFormat::ASTC_2D_4X4;
case Tegra::Texture::TextureFormat::ASTC_2D_5X4: case Tegra::Texture::TextureFormat::ASTC_2D_5X4:
return is_srgb ? PixelFormat::ASTC_2D_5X4_SRGB : PixelFormat::ASTC_2D_5X4; return is_srgb ? PixelFormat::ASTC_2D_5X4_SRGB : PixelFormat::ASTC_2D_5X4;
case Tegra::Texture::TextureFormat::ASTC_2D_5X5:
return is_srgb ? PixelFormat::ASTC_2D_5X5_SRGB : PixelFormat::ASTC_2D_5X5;
case Tegra::Texture::TextureFormat::ASTC_2D_8X8: case Tegra::Texture::TextureFormat::ASTC_2D_8X8:
return is_srgb ? PixelFormat::ASTC_2D_8X8_SRGB : PixelFormat::ASTC_2D_8X8; return is_srgb ? PixelFormat::ASTC_2D_8X8_SRGB : PixelFormat::ASTC_2D_8X8;
case Tegra::Texture::TextureFormat::ASTC_2D_8X5: case Tegra::Texture::TextureFormat::ASTC_2D_8X5:
@ -440,10 +442,12 @@ bool IsPixelFormatASTC(PixelFormat format) {
switch (format) { switch (format) {
case PixelFormat::ASTC_2D_4X4: case PixelFormat::ASTC_2D_4X4:
case PixelFormat::ASTC_2D_5X4: case PixelFormat::ASTC_2D_5X4:
case PixelFormat::ASTC_2D_5X5:
case PixelFormat::ASTC_2D_8X8: case PixelFormat::ASTC_2D_8X8:
case PixelFormat::ASTC_2D_8X5: case PixelFormat::ASTC_2D_8X5:
case PixelFormat::ASTC_2D_4X4_SRGB: case PixelFormat::ASTC_2D_4X4_SRGB:
case PixelFormat::ASTC_2D_5X4_SRGB: case PixelFormat::ASTC_2D_5X4_SRGB:
case PixelFormat::ASTC_2D_5X5_SRGB:
case PixelFormat::ASTC_2D_8X8_SRGB: case PixelFormat::ASTC_2D_8X8_SRGB:
case PixelFormat::ASTC_2D_8X5_SRGB: case PixelFormat::ASTC_2D_8X5_SRGB:
return true; return true;
@ -453,27 +457,7 @@ bool IsPixelFormatASTC(PixelFormat format) {
} }
std::pair<u32, u32> GetASTCBlockSize(PixelFormat format) { std::pair<u32, u32> GetASTCBlockSize(PixelFormat format) {
switch (format) { return {GetDefaultBlockWidth(format), GetDefaultBlockHeight(format)};
case PixelFormat::ASTC_2D_4X4:
return {4, 4};
case PixelFormat::ASTC_2D_5X4:
return {5, 4};
case PixelFormat::ASTC_2D_8X8:
return {8, 8};
case PixelFormat::ASTC_2D_8X5:
return {8, 5};
case PixelFormat::ASTC_2D_4X4_SRGB:
return {4, 4};
case PixelFormat::ASTC_2D_5X4_SRGB:
return {5, 4};
case PixelFormat::ASTC_2D_8X8_SRGB:
return {8, 8};
case PixelFormat::ASTC_2D_8X5_SRGB:
return {8, 5};
default:
LOG_CRITICAL(HW_GPU, "Unhandled format: {}", static_cast<u32>(format));
UNREACHABLE();
}
} }
bool IsFormatBCn(PixelFormat format) { bool IsFormatBCn(PixelFormat format) {

View file

@ -72,19 +72,21 @@ enum class PixelFormat {
ASTC_2D_8X8_SRGB = 54, ASTC_2D_8X8_SRGB = 54,
ASTC_2D_8X5_SRGB = 55, ASTC_2D_8X5_SRGB = 55,
ASTC_2D_5X4_SRGB = 56, ASTC_2D_5X4_SRGB = 56,
ASTC_2D_5X5 = 57,
ASTC_2D_5X5_SRGB = 58,
MaxColorFormat, MaxColorFormat,
// Depth formats // Depth formats
Z32F = 57, Z32F = 59,
Z16 = 58, Z16 = 60,
MaxDepthFormat, MaxDepthFormat,
// DepthStencil formats // DepthStencil formats
Z24S8 = 59, Z24S8 = 61,
S8Z24 = 60, S8Z24 = 62,
Z32FS8 = 61, Z32FS8 = 63,
MaxDepthStencilFormat, MaxDepthStencilFormat,
@ -188,6 +190,8 @@ static constexpr u32 GetCompressionFactor(PixelFormat format) {
4, // ASTC_2D_8X8_SRGB 4, // ASTC_2D_8X8_SRGB
4, // ASTC_2D_8X5_SRGB 4, // ASTC_2D_8X5_SRGB
4, // ASTC_2D_5X4_SRGB 4, // ASTC_2D_5X4_SRGB
4, // ASTC_2D_5X5
4, // ASTC_2D_5X5_SRGB
1, // Z32F 1, // Z32F
1, // Z16 1, // Z16
1, // Z24S8 1, // Z24S8
@ -199,6 +203,79 @@ static constexpr u32 GetCompressionFactor(PixelFormat format) {
return compression_factor_table[static_cast<std::size_t>(format)]; return compression_factor_table[static_cast<std::size_t>(format)];
} }
static constexpr u32 GetDefaultBlockWidth(PixelFormat format) {
if (format == PixelFormat::Invalid)
return 0;
constexpr std::array<u32, MaxPixelFormat> block_width_table = {{
1, // ABGR8U
1, // ABGR8S
1, // ABGR8UI
1, // B5G6R5U
1, // A2B10G10R10U
1, // A1B5G5R5U
1, // R8U
1, // R8UI
1, // RGBA16F
1, // RGBA16U
1, // RGBA16UI
1, // R11FG11FB10F
1, // RGBA32UI
4, // DXT1
4, // DXT23
4, // DXT45
4, // DXN1
4, // DXN2UNORM
4, // DXN2SNORM
4, // BC7U
4, // BC6H_UF16
4, // BC6H_SF16
4, // ASTC_2D_4X4
1, // G8R8U
1, // G8R8S
1, // BGRA8
1, // RGBA32F
1, // RG32F
1, // R32F
1, // R16F
1, // R16U
1, // R16S
1, // R16UI
1, // R16I
1, // RG16
1, // RG16F
1, // RG16UI
1, // RG16I
1, // RG16S
1, // RGB32F
1, // RGBA8_SRGB
1, // RG8U
1, // RG8S
1, // RG32UI
1, // R32UI
8, // ASTC_2D_8X8
8, // ASTC_2D_8X5
5, // ASTC_2D_5X4
1, // BGRA8_SRGB
4, // DXT1_SRGB
4, // DXT23_SRGB
4, // DXT45_SRGB
4, // BC7U_SRGB
4, // ASTC_2D_4X4_SRGB
8, // ASTC_2D_8X8_SRGB
8, // ASTC_2D_8X5_SRGB
5, // ASTC_2D_5X4_SRGB
5, // ASTC_2D_5X5
5, // ASTC_2D_5X5_SRGB
1, // Z32F
1, // Z16
1, // Z24S8
1, // S8Z24
1, // Z32FS8
}};
ASSERT(static_cast<std::size_t>(format) < block_width_table.size());
return block_width_table[static_cast<std::size_t>(format)];
}
static constexpr u32 GetDefaultBlockHeight(PixelFormat format) { static constexpr u32 GetDefaultBlockHeight(PixelFormat format) {
if (format == PixelFormat::Invalid) if (format == PixelFormat::Invalid)
return 0; return 0;
@ -261,6 +338,8 @@ static constexpr u32 GetDefaultBlockHeight(PixelFormat format) {
8, // ASTC_2D_8X8_SRGB 8, // ASTC_2D_8X8_SRGB
5, // ASTC_2D_8X5_SRGB 5, // ASTC_2D_8X5_SRGB
4, // ASTC_2D_5X4_SRGB 4, // ASTC_2D_5X4_SRGB
5, // ASTC_2D_5X5
5, // ASTC_2D_5X5_SRGB
1, // Z32F 1, // Z32F
1, // Z16 1, // Z16
1, // Z24S8 1, // Z24S8
@ -299,7 +378,7 @@ static constexpr u32 GetFormatBpp(PixelFormat format) {
128, // BC7U 128, // BC7U
128, // BC6H_UF16 128, // BC6H_UF16
128, // BC6H_SF16 128, // BC6H_SF16
32, // ASTC_2D_4X4 128, // ASTC_2D_4X4
16, // G8R8U 16, // G8R8U
16, // G8R8S 16, // G8R8S
32, // BGRA8 32, // BGRA8
@ -322,18 +401,20 @@ static constexpr u32 GetFormatBpp(PixelFormat format) {
16, // RG8S 16, // RG8S
64, // RG32UI 64, // RG32UI
32, // R32UI 32, // R32UI
16, // ASTC_2D_8X8 128, // ASTC_2D_8X8
16, // ASTC_2D_8X5 128, // ASTC_2D_8X5
32, // ASTC_2D_5X4 128, // ASTC_2D_5X4
32, // BGRA8_SRGB 32, // BGRA8_SRGB
64, // DXT1_SRGB 64, // DXT1_SRGB
128, // DXT23_SRGB 128, // DXT23_SRGB
128, // DXT45_SRGB 128, // DXT45_SRGB
128, // BC7U 128, // BC7U
32, // ASTC_2D_4X4_SRGB 128, // ASTC_2D_4X4_SRGB
16, // ASTC_2D_8X8_SRGB 128, // ASTC_2D_8X8_SRGB
16, // ASTC_2D_8X5_SRGB 128, // ASTC_2D_8X5_SRGB
32, // ASTC_2D_5X4_SRGB 128, // ASTC_2D_5X4_SRGB
128, // ASTC_2D_5X5
128, // ASTC_2D_5X5_SRGB
32, // Z32F 32, // Z32F
16, // Z16 16, // Z16
32, // Z24S8 32, // Z24S8

View file

@ -1598,27 +1598,29 @@ static void DecompressBlock(uint8_t inBuf[16], const uint32_t blockWidth,
namespace Tegra::Texture::ASTC { namespace Tegra::Texture::ASTC {
std::vector<uint8_t> Decompress(std::vector<uint8_t>& data, uint32_t width, uint32_t height, std::vector<uint8_t> Decompress(std::vector<uint8_t>& data, uint32_t width, uint32_t height,
uint32_t block_width, uint32_t block_height) { uint32_t depth, uint32_t block_width, uint32_t block_height) {
uint32_t blockIdx = 0; uint32_t blockIdx = 0;
std::vector<uint8_t> outData(height * width * 4); std::vector<uint8_t> outData(height * width * depth * 4);
for (uint32_t j = 0; j < height; j += block_height) { for (uint32_t k = 0; k < depth; k++) {
for (uint32_t i = 0; i < width; i += block_width) { for (uint32_t j = 0; j < height; j += block_height) {
for (uint32_t i = 0; i < width; i += block_width) {
uint8_t* blockPtr = data.data() + blockIdx * 16; uint8_t* blockPtr = data.data() + blockIdx * 16;
// Blocks can be at most 12x12 // Blocks can be at most 12x12
uint32_t uncompData[144]; uint32_t uncompData[144];
ASTCC::DecompressBlock(blockPtr, block_width, block_height, uncompData); ASTCC::DecompressBlock(blockPtr, block_width, block_height, uncompData);
uint32_t decompWidth = std::min(block_width, width - i); uint32_t decompWidth = std::min(block_width, width - i);
uint32_t decompHeight = std::min(block_height, height - j); uint32_t decompHeight = std::min(block_height, height - j);
uint8_t* outRow = outData.data() + (j * width + i) * 4; uint8_t* outRow = outData.data() + (j * width + i) * 4;
for (uint32_t jj = 0; jj < decompHeight; jj++) { for (uint32_t jj = 0; jj < decompHeight; jj++) {
memcpy(outRow + jj * width * 4, uncompData + jj * block_width, decompWidth * 4); memcpy(outRow + jj * width * 4, uncompData + jj * block_width, decompWidth * 4);
}
blockIdx++;
} }
blockIdx++;
} }
} }

View file

@ -10,6 +10,6 @@
namespace Tegra::Texture::ASTC { namespace Tegra::Texture::ASTC {
std::vector<uint8_t> Decompress(std::vector<uint8_t>& data, uint32_t width, uint32_t height, std::vector<uint8_t> Decompress(std::vector<uint8_t>& data, uint32_t width, uint32_t height,
uint32_t block_width, uint32_t block_height); uint32_t depth, uint32_t block_width, uint32_t block_height);
} // namespace Tegra::Texture::ASTC } // namespace Tegra::Texture::ASTC

View file

@ -386,9 +386,9 @@ void GraphicsSurfaceWidget::OnUpdate() {
// TODO(bunnei): Will not work with BCn formats that swizzle 4x4 tiles. // TODO(bunnei): Will not work with BCn formats that swizzle 4x4 tiles.
// Needs to be fixed if we plan to use this feature more, otherwise we may remove it. // Needs to be fixed if we plan to use this feature more, otherwise we may remove it.
auto unswizzled_data = auto unswizzled_data = Tegra::Texture::UnswizzleTexture(
Tegra::Texture::UnswizzleTexture(*address, 1, 1, Tegra::Texture::BytesPerPixel(surface_format), *address, 1, 1, Tegra::Texture::BytesPerPixel(surface_format), surface_width,
surface_width, surface_height, 1U); surface_height, 1U);
auto texture_data = Tegra::Texture::DecodeTexture(unswizzled_data, surface_format, auto texture_data = Tegra::Texture::DecodeTexture(unswizzled_data, surface_format,
surface_width, surface_height); surface_width, surface_height);