Merge pull request #1625 from FernandoS27/astc
Implement ASTC Textures 5x5 and fix a bunch of ASTC texture problems
This commit is contained in:
commit
38c1c500ab
|
@ -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,
|
||||
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)};
|
||||
u32 m_depth = (layer_only ? 1U : depth);
|
||||
u32 m_width = MipWidth(mip_level);
|
||||
u32 m_height = MipHeight(mip_level);
|
||||
m_width = uncompressed ? m_width
|
||||
: std::max(1U, (m_width + compression_factor - 1) / compression_factor);
|
||||
m_height = uncompressed
|
||||
? m_height
|
||||
: std::max(1U, (m_height + compression_factor - 1) / compression_factor);
|
||||
m_width = uncompressed ? m_width : std::max(1U, (m_width + tile_x - 1) / tile_x);
|
||||
m_height = uncompressed ? m_height : std::max(1U, (m_height + tile_y - 1) / tile_y);
|
||||
m_depth = std::max(1U, m_depth >> mip_level);
|
||||
u32 m_block_height = MipBlockHeight(mip_level);
|
||||
u32 m_block_depth = MipBlockDepth(mip_level);
|
||||
|
@ -305,6 +303,8 @@ static constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> tex
|
|||
{GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X8_SRGB
|
||||
{GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X5_SRGB
|
||||
{GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X4_SRGB
|
||||
{GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X5
|
||||
{GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X5_SRGB
|
||||
|
||||
// Depth formats
|
||||
{GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, ComponentType::Float, false}, // Z32F
|
||||
|
@ -364,15 +364,18 @@ 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
|
||||
// pixel values.
|
||||
const u32 tile_size{IsFormatBCn(format) ? 4U : 1U};
|
||||
const u32 tile_size_x{GetDefaultBlockWidth(format)};
|
||||
const u32 tile_size_y{GetDefaultBlockHeight(format)};
|
||||
|
||||
if (morton_to_gl) {
|
||||
const std::vector<u8> data = Tegra::Texture::UnswizzleTexture(
|
||||
addr, tile_size, bytes_per_pixel, stride, height, depth, block_height, block_depth);
|
||||
const std::vector<u8> data =
|
||||
Tegra::Texture::UnswizzleTexture(addr, tile_size_x, tile_size_y, bytes_per_pixel,
|
||||
stride, height, depth, block_height, block_depth);
|
||||
const std::size_t size_to_copy{std::min(gl_buffer_size, data.size())};
|
||||
memcpy(gl_buffer, data.data(), size_to_copy);
|
||||
} else {
|
||||
Tegra::Texture::CopySwizzledData(stride / tile_size, height / tile_size, depth,
|
||||
Tegra::Texture::CopySwizzledData((stride + tile_size_x - 1) / tile_size_x,
|
||||
(height + tile_size_y - 1) / tile_size_y, depth,
|
||||
bytes_per_pixel, bytes_per_pixel, Memory::GetPointer(addr),
|
||||
gl_buffer, false, block_height, block_depth);
|
||||
}
|
||||
|
@ -440,6 +443,8 @@ static constexpr GLConversionArray morton_to_gl_fns = {
|
|||
MortonCopy<true, PixelFormat::ASTC_2D_8X8_SRGB>,
|
||||
MortonCopy<true, PixelFormat::ASTC_2D_8X5_SRGB>,
|
||||
MortonCopy<true, PixelFormat::ASTC_2D_5X4_SRGB>,
|
||||
MortonCopy<true, PixelFormat::ASTC_2D_5X5>,
|
||||
MortonCopy<true, PixelFormat::ASTC_2D_5X5_SRGB>,
|
||||
MortonCopy<true, PixelFormat::Z32F>,
|
||||
MortonCopy<true, PixelFormat::Z16>,
|
||||
MortonCopy<true, PixelFormat::Z24S8>,
|
||||
|
@ -508,6 +513,8 @@ static constexpr GLConversionArray gl_to_morton_fns = {
|
|||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
MortonCopy<false, PixelFormat::Z32F>,
|
||||
MortonCopy<false, PixelFormat::Z16>,
|
||||
MortonCopy<false, PixelFormat::Z24S8>,
|
||||
|
@ -897,21 +904,24 @@ static void ConvertG8R8ToR8G8(std::vector<u8>& data, u32 width, u32 height) {
|
|||
* typical desktop GPUs.
|
||||
*/
|
||||
static void ConvertFormatAsNeeded_LoadGLBuffer(std::vector<u8>& data, PixelFormat pixel_format,
|
||||
u32 width, u32 height) {
|
||||
u32 width, u32 height, u32 depth) {
|
||||
switch (pixel_format) {
|
||||
case PixelFormat::ASTC_2D_4X4:
|
||||
case PixelFormat::ASTC_2D_8X8:
|
||||
case PixelFormat::ASTC_2D_8X5:
|
||||
case PixelFormat::ASTC_2D_5X4:
|
||||
case PixelFormat::ASTC_2D_5X5:
|
||||
case PixelFormat::ASTC_2D_4X4_SRGB:
|
||||
case PixelFormat::ASTC_2D_8X8_SRGB:
|
||||
case PixelFormat::ASTC_2D_8X5_SRGB:
|
||||
case PixelFormat::ASTC_2D_5X4_SRGB: {
|
||||
case PixelFormat::ASTC_2D_5X4_SRGB:
|
||||
case PixelFormat::ASTC_2D_5X5_SRGB: {
|
||||
// Convert ASTC pixel formats to RGBA8, as most desktop GPUs do not support ASTC.
|
||||
u32 block_width{};
|
||||
u32 block_height{};
|
||||
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;
|
||||
}
|
||||
case PixelFormat::S8Z24:
|
||||
|
@ -971,7 +981,7 @@ void CachedSurface::LoadGLBuffer() {
|
|||
}
|
||||
for (u32 i = 0; i < params.max_mip_level; 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));
|
||||
|
|
|
@ -139,7 +139,7 @@ struct SurfaceParams {
|
|||
}
|
||||
|
||||
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:
|
||||
|
|
|
@ -297,6 +297,8 @@ PixelFormat PixelFormatFromTextureFormat(Tegra::Texture::TextureFormat format,
|
|||
return is_srgb ? PixelFormat::ASTC_2D_4X4_SRGB : PixelFormat::ASTC_2D_4X4;
|
||||
case Tegra::Texture::TextureFormat::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:
|
||||
return is_srgb ? PixelFormat::ASTC_2D_8X8_SRGB : PixelFormat::ASTC_2D_8X8;
|
||||
case Tegra::Texture::TextureFormat::ASTC_2D_8X5:
|
||||
|
@ -440,10 +442,12 @@ bool IsPixelFormatASTC(PixelFormat format) {
|
|||
switch (format) {
|
||||
case PixelFormat::ASTC_2D_4X4:
|
||||
case PixelFormat::ASTC_2D_5X4:
|
||||
case PixelFormat::ASTC_2D_5X5:
|
||||
case PixelFormat::ASTC_2D_8X8:
|
||||
case PixelFormat::ASTC_2D_8X5:
|
||||
case PixelFormat::ASTC_2D_4X4_SRGB:
|
||||
case PixelFormat::ASTC_2D_5X4_SRGB:
|
||||
case PixelFormat::ASTC_2D_5X5_SRGB:
|
||||
case PixelFormat::ASTC_2D_8X8_SRGB:
|
||||
case PixelFormat::ASTC_2D_8X5_SRGB:
|
||||
return true;
|
||||
|
@ -453,27 +457,7 @@ bool IsPixelFormatASTC(PixelFormat format) {
|
|||
}
|
||||
|
||||
std::pair<u32, u32> GetASTCBlockSize(PixelFormat format) {
|
||||
switch (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();
|
||||
}
|
||||
return {GetDefaultBlockWidth(format), GetDefaultBlockHeight(format)};
|
||||
}
|
||||
|
||||
bool IsFormatBCn(PixelFormat format) {
|
||||
|
|
|
@ -72,19 +72,21 @@ enum class PixelFormat {
|
|||
ASTC_2D_8X8_SRGB = 54,
|
||||
ASTC_2D_8X5_SRGB = 55,
|
||||
ASTC_2D_5X4_SRGB = 56,
|
||||
ASTC_2D_5X5 = 57,
|
||||
ASTC_2D_5X5_SRGB = 58,
|
||||
|
||||
MaxColorFormat,
|
||||
|
||||
// Depth formats
|
||||
Z32F = 57,
|
||||
Z16 = 58,
|
||||
Z32F = 59,
|
||||
Z16 = 60,
|
||||
|
||||
MaxDepthFormat,
|
||||
|
||||
// DepthStencil formats
|
||||
Z24S8 = 59,
|
||||
S8Z24 = 60,
|
||||
Z32FS8 = 61,
|
||||
Z24S8 = 61,
|
||||
S8Z24 = 62,
|
||||
Z32FS8 = 63,
|
||||
|
||||
MaxDepthStencilFormat,
|
||||
|
||||
|
@ -188,6 +190,8 @@ static constexpr u32 GetCompressionFactor(PixelFormat format) {
|
|||
4, // ASTC_2D_8X8_SRGB
|
||||
4, // ASTC_2D_8X5_SRGB
|
||||
4, // ASTC_2D_5X4_SRGB
|
||||
4, // ASTC_2D_5X5
|
||||
4, // ASTC_2D_5X5_SRGB
|
||||
1, // Z32F
|
||||
1, // Z16
|
||||
1, // Z24S8
|
||||
|
@ -199,6 +203,79 @@ static constexpr u32 GetCompressionFactor(PixelFormat 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) {
|
||||
if (format == PixelFormat::Invalid)
|
||||
return 0;
|
||||
|
@ -261,6 +338,8 @@ static constexpr u32 GetDefaultBlockHeight(PixelFormat format) {
|
|||
8, // ASTC_2D_8X8_SRGB
|
||||
5, // ASTC_2D_8X5_SRGB
|
||||
4, // ASTC_2D_5X4_SRGB
|
||||
5, // ASTC_2D_5X5
|
||||
5, // ASTC_2D_5X5_SRGB
|
||||
1, // Z32F
|
||||
1, // Z16
|
||||
1, // Z24S8
|
||||
|
@ -299,7 +378,7 @@ static constexpr u32 GetFormatBpp(PixelFormat format) {
|
|||
128, // BC7U
|
||||
128, // BC6H_UF16
|
||||
128, // BC6H_SF16
|
||||
32, // ASTC_2D_4X4
|
||||
128, // ASTC_2D_4X4
|
||||
16, // G8R8U
|
||||
16, // G8R8S
|
||||
32, // BGRA8
|
||||
|
@ -322,18 +401,20 @@ static constexpr u32 GetFormatBpp(PixelFormat format) {
|
|||
16, // RG8S
|
||||
64, // RG32UI
|
||||
32, // R32UI
|
||||
16, // ASTC_2D_8X8
|
||||
16, // ASTC_2D_8X5
|
||||
32, // ASTC_2D_5X4
|
||||
128, // ASTC_2D_8X8
|
||||
128, // ASTC_2D_8X5
|
||||
128, // ASTC_2D_5X4
|
||||
32, // BGRA8_SRGB
|
||||
64, // DXT1_SRGB
|
||||
128, // DXT23_SRGB
|
||||
128, // DXT45_SRGB
|
||||
128, // BC7U
|
||||
32, // ASTC_2D_4X4_SRGB
|
||||
16, // ASTC_2D_8X8_SRGB
|
||||
16, // ASTC_2D_8X5_SRGB
|
||||
32, // ASTC_2D_5X4_SRGB
|
||||
128, // ASTC_2D_4X4_SRGB
|
||||
128, // ASTC_2D_8X8_SRGB
|
||||
128, // ASTC_2D_8X5_SRGB
|
||||
128, // ASTC_2D_5X4_SRGB
|
||||
128, // ASTC_2D_5X5
|
||||
128, // ASTC_2D_5X5_SRGB
|
||||
32, // Z32F
|
||||
16, // Z16
|
||||
32, // Z24S8
|
||||
|
|
|
@ -1598,9 +1598,10 @@ static void DecompressBlock(uint8_t inBuf[16], const uint32_t blockWidth,
|
|||
namespace Tegra::Texture::ASTC {
|
||||
|
||||
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;
|
||||
std::vector<uint8_t> outData(height * width * 4);
|
||||
std::vector<uint8_t> outData(height * width * depth * 4);
|
||||
for (uint32_t k = 0; k < depth; k++) {
|
||||
for (uint32_t j = 0; j < height; j += block_height) {
|
||||
for (uint32_t i = 0; i < width; i += block_width) {
|
||||
|
||||
|
@ -1621,6 +1622,7 @@ std::vector<uint8_t> Decompress(std::vector<uint8_t>& data, uint32_t width, uint
|
|||
blockIdx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,6 @@
|
|||
namespace Tegra::Texture::ASTC {
|
||||
|
||||
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
|
||||
|
|
|
@ -227,12 +227,14 @@ u32 BytesPerPixel(TextureFormat format) {
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<u8> UnswizzleTexture(VAddr address, u32 tile_size, u32 bytes_per_pixel, u32 width,
|
||||
u32 height, u32 depth, u32 block_height, u32 block_depth) {
|
||||
std::vector<u8> UnswizzleTexture(VAddr address, u32 tile_size_x, u32 tile_size_y,
|
||||
u32 bytes_per_pixel, u32 width, u32 height, u32 depth,
|
||||
u32 block_height, u32 block_depth) {
|
||||
std::vector<u8> unswizzled_data(width * height * depth * bytes_per_pixel);
|
||||
CopySwizzledData(width / tile_size, height / tile_size, depth, bytes_per_pixel, bytes_per_pixel,
|
||||
Memory::GetPointer(address), unswizzled_data.data(), true, block_height,
|
||||
block_depth);
|
||||
CopySwizzledData((width + tile_size_x - 1) / tile_size_x,
|
||||
(height + tile_size_y - 1) / tile_size_y, depth, bytes_per_pixel,
|
||||
bytes_per_pixel, Memory::GetPointer(address), unswizzled_data.data(), true,
|
||||
block_height, block_depth);
|
||||
return unswizzled_data;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@ inline std::size_t GetGOBSize() {
|
|||
/**
|
||||
* Unswizzles a swizzled texture without changing its format.
|
||||
*/
|
||||
std::vector<u8> UnswizzleTexture(VAddr address, u32 tile_size, u32 bytes_per_pixel, u32 width,
|
||||
u32 height, u32 depth,
|
||||
std::vector<u8> UnswizzleTexture(VAddr address, u32 tile_size_x, u32 tile_size_y,
|
||||
u32 bytes_per_pixel, u32 width, u32 height, u32 depth,
|
||||
u32 block_height = TICEntry::DefaultBlockHeight,
|
||||
u32 block_depth = TICEntry::DefaultBlockHeight);
|
||||
|
||||
|
|
|
@ -386,9 +386,9 @@ void GraphicsSurfaceWidget::OnUpdate() {
|
|||
|
||||
// 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.
|
||||
auto unswizzled_data =
|
||||
Tegra::Texture::UnswizzleTexture(*address, 1, Tegra::Texture::BytesPerPixel(surface_format),
|
||||
surface_width, surface_height, 1U);
|
||||
auto unswizzled_data = Tegra::Texture::UnswizzleTexture(
|
||||
*address, 1, 1, Tegra::Texture::BytesPerPixel(surface_format), surface_width,
|
||||
surface_height, 1U);
|
||||
|
||||
auto texture_data = Tegra::Texture::DecodeTexture(unswizzled_data, surface_format,
|
||||
surface_width, surface_height);
|
||||
|
|
Loading…
Reference in a new issue