From f31e9df21cffb3842a746d03e01fe42356ef3140 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 25 Sep 2017 10:31:49 +0200 Subject: [PATCH] Fixed incorrect pixel byte size computation in KTX --- libraries/ktx/src/khronos/KHR.h | 135 ++++++++++++++++++++++++++++++++ libraries/ktx/src/ktx/KTX.cpp | 17 ++-- libraries/ktx/src/ktx/KTX.h | 2 +- 3 files changed, 145 insertions(+), 9 deletions(-) diff --git a/libraries/ktx/src/khronos/KHR.h b/libraries/ktx/src/khronos/KHR.h index ae23d9cefe..cda22513ee 100644 --- a/libraries/ktx/src/khronos/KHR.h +++ b/libraries/ktx/src/khronos/KHR.h @@ -209,6 +209,137 @@ namespace khronos { COMPRESSED_SIGNED_RG11_EAC = 0x9273, }; + inline uint8_t evalUncompressedBlockBitSize(InternalFormat format) { + switch (format) { + case InternalFormat::R8: + case InternalFormat::R8_SNORM: + return 8; + case InternalFormat::R16: + case InternalFormat::R16_SNORM: + case InternalFormat::RG8: + case InternalFormat::RG8_SNORM: + return 16; + case InternalFormat::RG16: + case InternalFormat::RG16_SNORM: + return 16; + case InternalFormat::R3_G3_B2: + return 8; + case InternalFormat::RGB4: + return 12; + case InternalFormat::RGB5: + case InternalFormat::RGB565: + return 16; + case InternalFormat::RGB8: + case InternalFormat::RGB8_SNORM: + return 24; + case InternalFormat::RGB10: + // TODO: check if this is really the case + return 32; + case InternalFormat::RGB12: + // TODO: check if this is really the case + return 48; + case InternalFormat::RGB16: + case InternalFormat::RGB16_SNORM: + return 48; + case InternalFormat::RGBA2: + return 8; + case InternalFormat::RGBA4: + case InternalFormat::RGB5_A1: + return 16; + case InternalFormat::RGBA8: + case InternalFormat::RGBA8_SNORM: + case InternalFormat::RGB10_A2: + case InternalFormat::RGB10_A2UI: + return 32; + case InternalFormat::RGBA12: + return 48; + case InternalFormat::RGBA16: + case InternalFormat::RGBA16_SNORM: + return 64; + case InternalFormat::SRGB8: + return 24; + case InternalFormat::SRGB8_ALPHA8: + return 32; + case InternalFormat::R16F: + return 16; + case InternalFormat::RG16F: + return 32; + case InternalFormat::RGB16F: + return 48; + case InternalFormat::RGBA16F: + return 64; + case InternalFormat::R32F: + return 32; + case InternalFormat::RG32F: + return 64; + case InternalFormat::RGB32F: + return 96; + case InternalFormat::RGBA32F: + return 128; + case InternalFormat::R11F_G11F_B10F: + case InternalFormat::RGB9_E5: + return 32; + case InternalFormat::R8I: + case InternalFormat::R8UI: + return 8; + case InternalFormat::R16I: + case InternalFormat::R16UI: + return 16; + case InternalFormat::R32I: + case InternalFormat::R32UI: + return 32; + case InternalFormat::RG8I: + case InternalFormat::RG8UI: + return 16; + case InternalFormat::RG16I: + case InternalFormat::RG16UI: + return 32; + case InternalFormat::RG32I: + case InternalFormat::RG32UI: + return 64; + case InternalFormat::RGB8I: + case InternalFormat::RGB8UI: + return 24; + case InternalFormat::RGB16I: + case InternalFormat::RGB16UI: + return 48; + case InternalFormat::RGB32I: + case InternalFormat::RGB32UI: + return 96; + case InternalFormat::RGBA8I: + case InternalFormat::RGBA8UI: + return 32; + case InternalFormat::RGBA16I: + case InternalFormat::RGBA16UI: + return 64; + case InternalFormat::RGBA32I: + case InternalFormat::RGBA32UI: + return 128; + case InternalFormat::DEPTH_COMPONENT16: + return 16; + case InternalFormat::DEPTH_COMPONENT24: + return 24; + case InternalFormat::DEPTH_COMPONENT32: + case InternalFormat::DEPTH_COMPONENT32F: + case InternalFormat::DEPTH24_STENCIL8: + return 32; + case InternalFormat::DEPTH32F_STENCIL8: + // TODO : check if this true + return 40; + case InternalFormat::STENCIL_INDEX1: + return 1; + case InternalFormat::STENCIL_INDEX4: + return 4; + case InternalFormat::STENCIL_INDEX8: + return 8; + case InternalFormat::STENCIL_INDEX16: + return 16; + + default: + return 0; + } + } + template inline uint32_t evalAlignedCompressedBlockCount(uint32_t value) { enum { val = ALIGNMENT && !(ALIGNMENT & (ALIGNMENT - 1)) }; @@ -252,6 +383,10 @@ namespace khronos { } } + inline uint8_t evalCompressedBlockBitSize(InternalFormat format) { + return evalCompressedBlockSize(format) * 8; + } + enum class BaseInternalFormat : uint32_t { // GL 4.4 Table 8.11 DEPTH_COMPONENT = 0x1902, diff --git a/libraries/ktx/src/ktx/KTX.cpp b/libraries/ktx/src/ktx/KTX.cpp index 3b1a12cba7..5bd45549c1 100644 --- a/libraries/ktx/src/ktx/KTX.cpp +++ b/libraries/ktx/src/ktx/KTX.cpp @@ -54,15 +54,13 @@ uint32_t Header::evalPixelOrBlockDepth(uint32_t level) const { return evalMipDimension(level, getPixelDepth()); } -size_t Header::evalPixelOrBlockSize() const { +size_t Header::evalPixelOrBlockBitSize() const { size_t result = 0; + auto format = getGLInternaFormat(); if (isCompressed()) { - auto format = getGLInternaFormat(); - result = khronos::gl::texture::evalCompressedBlockSize(format); + result = khronos::gl::texture::evalCompressedBlockBitSize(format); } else { - // FIXME should really be using the internal format, not the base internal format - auto baseFormat = getGLBaseInternalFormat(); - result = khronos::gl::texture::evalComponentCount(baseFormat); + result = khronos::gl::texture::evalUncompressedBlockBitSize(format); } if (0 == result) { @@ -73,11 +71,14 @@ size_t Header::evalPixelOrBlockSize() const { size_t Header::evalRowSize(uint32_t level) const { auto pixWidth = evalPixelOrBlockWidth(level); - auto pixSize = evalPixelOrBlockSize(); + auto pixSize = evalPixelOrBlockBitSize(); if (pixSize == 0) { return 0; } - return evalPaddedSize(pixWidth * pixSize); + auto totalByteSize = pixWidth * pixSize; + // Round to the nearest upper byte size + totalByteSize = (totalByteSize / 8) + (((totalByteSize % 8) != 0) & 1); + return evalPaddedSize(totalByteSize); } size_t Header::evalFaceSize(uint32_t level) const { diff --git a/libraries/ktx/src/ktx/KTX.h b/libraries/ktx/src/ktx/KTX.h index 8dc4ec7a47..54a8188a42 100644 --- a/libraries/ktx/src/ktx/KTX.h +++ b/libraries/ktx/src/ktx/KTX.h @@ -170,7 +170,7 @@ namespace ktx { uint32_t evalPixelOrBlockHeight(uint32_t level) const; uint32_t evalPixelOrBlockDepth(uint32_t level) const; - size_t evalPixelOrBlockSize() const; + size_t evalPixelOrBlockBitSize() const; size_t evalRowSize(uint32_t level) const; size_t evalFaceSize(uint32_t level) const; size_t evalImageSize(uint32_t level) const;