From 46e1a2ff68447d7ca68deace8c3ee94bdbb310e2 Mon Sep 17 00:00:00 2001 From: Mark Callow <2244683+MarkCallow@users.noreply.github.com> Date: Thu, 15 Apr 2021 04:55:51 -0700 Subject: [PATCH] Handle PVRTC1 minimum 2 block requirement. Fixes issue #390. (#398) --- lib/formatsize.h | 2 ++ lib/gl_format.h | 31 ++++++++++++++++++------------- lib/texture.c | 4 ++-- lib/texture2.c | 10 +++++++--- lib/vk_format.h | 30 ++++++++++++++++++++++++++++++ 5 files changed, 59 insertions(+), 18 deletions(-) diff --git a/lib/formatsize.h b/lib/formatsize.h index f0ba200aa6..7112a3a90d 100644 --- a/lib/formatsize.h +++ b/lib/formatsize.h @@ -41,6 +41,8 @@ typedef struct ktxFormatSize { unsigned int blockWidth; // in texels unsigned int blockHeight; // in texels unsigned int blockDepth; // in texels + unsigned int minBlocksX; // Minimum required number of blocks + unsigned int minBlocksY; } ktxFormatSize; #ifdef __cplusplus diff --git a/lib/gl_format.h b/lib/gl_format.h index 46adbc9e69..e30ec3a8bc 100644 --- a/lib/gl_format.h +++ b/lib/gl_format.h @@ -1,4 +1,4 @@ -/* +/* ================================================================================================ Description : OpenGL formats/types and properties. @@ -1625,6 +1625,7 @@ static inline unsigned int glGetTypeSizeFromType(GLenum type) static inline void glGetFormatSize( const GLenum internalFormat, ktxFormatSize * pFormatSize ) { + pFormatSize->minBlocksX = pFormatSize->minBlocksY = 1; switch ( internalFormat ) { // @@ -2007,27 +2008,31 @@ static inline void glGetFormatSize( const GLenum internalFormat, ktxFormatSize * // // PVRTC // - case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG: // 3-component PVRTC, 16x8 blocks, unsigned normalized - case GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT: // 3-component PVRTC, 16x8 blocks, sRGB - case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: // 4-component PVRTC, 16x8 blocks, unsigned normalized - case GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT: // 4-component PVRTC, 16x8 blocks, sRGB + case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG: // 3-component PVRTC, 8x4 blocks, unsigned normalized + case GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT: // 3-component PVRTC, 8x4 blocks, sRGB + case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: // 4-component PVRTC, 8x4 blocks, unsigned normalized + case GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT: // 4-component PVRTC, 8x4 blocks, sRGB pFormatSize->flags = KTX_FORMAT_SIZE_COMPRESSED_BIT; pFormatSize->paletteSizeInBits = 0; pFormatSize->blockSizeInBits = 64; - pFormatSize->blockWidth = 16; - pFormatSize->blockHeight = 8; + pFormatSize->blockWidth = 8; + pFormatSize->blockHeight = 4; pFormatSize->blockDepth = 1; + pFormatSize->minBlocksX = 2; + pFormatSize->minBlocksY = 2; break; - case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG: // 3-component PVRTC, 8x8 blocks, unsigned normalized - case GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT: // 3-component PVRTC, 8x8 blocks, sRGB - case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: // 4-component PVRTC, 8x8 blocks, unsigned normalized - case GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT: // 4-component PVRTC, 8x8 blocks, sRGB + case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG: // 3-component PVRTC, 4x4 blocks, unsigned normalized + case GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT: // 3-component PVRTC, 4x4 blocks, sRGB + case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: // 4-component PVRTC, 4x4 blocks, unsigned normalized + case GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT: // 4-component PVRTC, 4x4 blocks, sRGB pFormatSize->flags = KTX_FORMAT_SIZE_COMPRESSED_BIT; pFormatSize->paletteSizeInBits = 0; pFormatSize->blockSizeInBits = 64; - pFormatSize->blockWidth = 8; - pFormatSize->blockHeight = 8; + pFormatSize->blockWidth = 4; + pFormatSize->blockHeight = 4; pFormatSize->blockDepth = 1; + pFormatSize->minBlocksX = 2; + pFormatSize->minBlocksY = 2; break; case GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG: // 4-component PVRTC, 8x4 blocks, unsigned normalized case GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV2_IMG: // 4-component PVRTC, 8x4 blocks, sRGB diff --git a/lib/texture.c b/lib/texture.c index 760d446454..e53a34e87a 100644 --- a/lib/texture.c +++ b/lib/texture.c @@ -565,8 +565,8 @@ ktxTexture_calcImageSize(ktxTexture* This, ktx_uint32_t level, = (uint32_t)ceilf(levelWidth / prtctd->_formatSize.blockWidth); blockCount.y = (uint32_t)ceilf(levelHeight / prtctd->_formatSize.blockHeight); - blockCount.x = MAX(1, blockCount.x); - blockCount.y = MAX(1, blockCount.y); + blockCount.x = MAX(prtctd->_formatSize.minBlocksX, blockCount.x); + blockCount.y = MAX(prtctd->_formatSize.minBlocksX, blockCount.y); blockSizeInBytes = prtctd->_formatSize.blockSizeInBits / 8; diff --git a/lib/texture2.c b/lib/texture2.c index 1a524648b9..ad7c573a0d 100644 --- a/lib/texture2.c +++ b/lib/texture2.c @@ -235,9 +235,13 @@ ktxFormatSize_initFromDfd(ktxFormatSize* This, ktx_uint32_t* pDfd) This->blockSizeInBits = KHR_DFDVAL(pBdb, BYTESPLANE0) * 8; This->paletteSizeInBits = 0; // No paletted formats in ktx v2. This->flags = 0; + This->minBlocksX = This->minBlocksY = 1; if (KHR_DFDVAL(pBdb, MODEL) >= KHR_DF_MODEL_DXT1A) { // A block compressed format. Entire block is a single sample. This->flags |= KTX_FORMAT_SIZE_COMPRESSED_BIT; + if (KHR_DFDVAL(pBdb, MODEL) == KHR_DF_MODEL_PVRTC) { + This->minBlocksX = This->minBlocksY = 2; + } } else { // An uncompressed format. @@ -2001,7 +2005,7 @@ ktxTexture2_IterateLoadLevelFaces(ktxTexture2* This, PFNKTXITERCB iterCb, // With the exception of non-array cubemaps the entire level // is passed at once because that is how OpenGL and Vulkan need them. // Vulkan could take all the faces at once too but we iterate - // them separately or OpenGL. + // them separately for OpenGL. if (This->isCubemap && !This->isArray) { ktx_uint8_t* pFace = pData; struct blockCount { @@ -2013,8 +2017,8 @@ ktxTexture2_IterateLoadLevelFaces(ktxTexture2* This, PFNKTXITERCB iterCb, = (uint32_t)ceilf((float)width / prtctd->_formatSize.blockWidth); blockCount.y = (uint32_t)ceilf((float)height / prtctd->_formatSize.blockHeight); - blockCount.x = MAX(1, blockCount.x); - blockCount.y = MAX(1, blockCount.y); + blockCount.x = MAX(prtctd->_formatSize.minBlocksX, blockCount.x); + blockCount.y = MAX(prtctd->_formatSize.minBlocksX, blockCount.y); faceSize = blockCount.x * blockCount.y * prtctd->_formatSize.blockSizeInBits / 8; diff --git a/lib/vk_format.h b/lib/vk_format.h index f5d2696877..26920b4da1 100644 --- a/lib/vk_format.h +++ b/lib/vk_format.h @@ -825,6 +825,7 @@ static inline VkFormat vkGetFormatFromOpenGLInternalFormat( const GLenum interna static inline void vkGetFormatSize( const VkFormat format, ktxFormatSize * pFormatSize ) { + pFormatSize->minBlocksX = pFormatSize->minBlocksY = 1; switch ( format ) { case VK_FORMAT_R4G4_UNORM_PACK8: @@ -1207,8 +1208,37 @@ static inline void vkGetFormatSize( const VkFormat format, ktxFormatSize * pForm pFormatSize->blockHeight = 4; pFormatSize->blockDepth = 1; break; + case VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG: + case VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG: + pFormatSize->flags = KTX_FORMAT_SIZE_COMPRESSED_BIT; + pFormatSize->paletteSizeInBits = 0; + pFormatSize->blockSizeInBits = 8 * 8; + pFormatSize->blockWidth = 8; + pFormatSize->blockHeight = 4; + pFormatSize->blockDepth = 1; + pFormatSize->minBlocksX = 2; + pFormatSize->minBlocksY = 2; + break; + case VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG: + case VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG: + pFormatSize->flags = KTX_FORMAT_SIZE_COMPRESSED_BIT; + pFormatSize->paletteSizeInBits = 0; + pFormatSize->blockSizeInBits = 8 * 8; + pFormatSize->blockWidth = 8; + pFormatSize->blockHeight = 4; + pFormatSize->blockDepth = 1; + break; case VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG: case VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG: + pFormatSize->flags = KTX_FORMAT_SIZE_COMPRESSED_BIT; + pFormatSize->paletteSizeInBits = 0; + pFormatSize->blockSizeInBits = 8 * 8; + pFormatSize->blockWidth = 4; + pFormatSize->blockHeight = 4; + pFormatSize->blockDepth = 1; + pFormatSize->minBlocksX = 2; + pFormatSize->minBlocksY = 2; + break; case VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG: case VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG: pFormatSize->flags = KTX_FORMAT_SIZE_COMPRESSED_BIT;