summaryrefslogtreecommitdiffstats
path: root/TextureLoader/src/KTXLoader.cpp
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2019-04-28 21:32:59 +0000
committerEgor Yusov <egor.yusov@gmail.com>2019-04-28 21:32:59 +0000
commit450a6606cedbf45aa888637058af4742d5491b01 (patch)
tree820210d82c58b39f42323f23ada328c919effe60 /TextureLoader/src/KTXLoader.cpp
parentUpdated GLTF loader to use Diligent file system functions (diff)
downloadDiligentTools-450a6606cedbf45aa888637058af4742d5491b01.tar.gz
DiligentTools-450a6606cedbf45aa888637058af4742d5491b01.zip
Implemented loading textures from KTX
Diffstat (limited to 'TextureLoader/src/KTXLoader.cpp')
-rw-r--r--TextureLoader/src/KTXLoader.cpp279
1 files changed, 279 insertions, 0 deletions
diff --git a/TextureLoader/src/KTXLoader.cpp b/TextureLoader/src/KTXLoader.cpp
new file mode 100644
index 0000000..fc679f4
--- /dev/null
+++ b/TextureLoader/src/KTXLoader.cpp
@@ -0,0 +1,279 @@
+/* Copyright 2015-2019 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include <algorithm>
+#include "TextureLoader.h"
+#include "GraphicsAccessories.h"
+#include "Align.h"
+
+#define GL_RGBA32F 0x8814
+#define GL_RGBA32UI 0x8D70
+#define GL_RGBA32I 0x8D82
+#define GL_RGB32F 0x8815
+#define GL_RGB32UI 0x8D71
+#define GL_RGB32I 0x8D83
+#define GL_RGBA16F 0x881A
+#define GL_RGBA16 0x805B
+#define GL_RGBA16UI 0x8D76
+#define GL_RGBA16_SNORM 0x8F9B
+#define GL_RGBA16I 0x8D88
+#define GL_RG32F 0x8230
+#define GL_RG32UI 0x823C
+#define GL_RG32I 0x823B
+#define GL_DEPTH32F_STENCIL8 0x8CAD
+#define GL_RGB10_A2 0x8059
+#define GL_RGB10_A2UI 0x906F
+#define GL_R11F_G11F_B10F 0x8C3A
+#define GL_RGBA8 0x8058
+#define GL_RGBA8UI 0x8D7C
+#define GL_RGBA8_SNORM 0x8F97
+#define GL_RGBA8I 0x8D8E
+#define GL_RG16F 0x822F
+#define GL_RG16 0x822C
+#define GL_RG16UI 0x823A
+#define GL_RG16_SNORM 0x8F99
+#define GL_RG16I 0x8239
+#define GL_R32F 0x822E
+#define GL_DEPTH_COMPONENT32F 0x8CAC
+#define GL_R32UI 0x8236
+#define GL_R32I 0x8235
+#define GL_DEPTH24_STENCIL8 0x88F0
+#define GL_RG8 0x822B
+#define GL_RG8UI 0x8238
+#define GL_RG8_SNORM 0x8F95
+#define GL_RG8I 0x8237
+#define GL_R16F 0x822D
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_R16 0x822A
+#define GL_R16UI 0x8234
+#define GL_R16_SNORM 0x8F98
+#define GL_R16I 0x8233
+#define GL_R8 0x8229
+#define GL_R8UI 0x8232
+#define GL_R8_SNORM 0x8F94
+#define GL_R8I 0x8231
+#define GL_RGB9_E5 0x8C3D
+
+
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
+#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F
+#define GL_COMPRESSED_RED_RGTC1 0x8DBB
+#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
+#define GL_COMPRESSED_RG_RGTC2 0x8DBD
+#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
+#define GL_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C
+#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D
+#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
+#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
+
+namespace Diligent
+{
+
+namespace
+{
+
+TEXTURE_FORMAT FindDiligentTextureFormat(std::uint32_t GLInternalFormat)
+{
+ switch (GLInternalFormat)
+ {
+ case GL_RGBA32F: return TEX_FORMAT_RGBA32_FLOAT;
+ case GL_RGBA32UI: return TEX_FORMAT_RGBA32_UINT;
+ case GL_RGBA32I: return TEX_FORMAT_RGBA32_SINT;
+
+ case GL_RGB32F: return TEX_FORMAT_RGB32_FLOAT;
+ case GL_RGB32UI: return TEX_FORMAT_RGB32_UINT;
+ case GL_RGB32I: return TEX_FORMAT_RGB32_SINT;
+
+ case GL_RGBA16F: return TEX_FORMAT_RGBA16_FLOAT;
+ case GL_RGBA16: return TEX_FORMAT_RGBA16_UNORM;
+ case GL_RGBA16UI: return TEX_FORMAT_RGBA16_UINT;
+ case GL_RGBA16_SNORM: return TEX_FORMAT_RGBA16_SNORM;
+ case GL_RGBA16I: return TEX_FORMAT_RGBA16_SINT;
+
+ case GL_RG32F: return TEX_FORMAT_RG32_FLOAT;
+ case GL_RG32UI: return TEX_FORMAT_RG32_UINT;
+ case GL_RG32I: return TEX_FORMAT_RG32_SINT;
+
+ case GL_DEPTH32F_STENCIL8: return TEX_FORMAT_D32_FLOAT_S8X24_UINT;
+
+ case GL_RGB10_A2: return TEX_FORMAT_RGB10A2_UNORM;
+ case GL_RGB10_A2UI: return TEX_FORMAT_RGB10A2_UINT;
+ case GL_R11F_G11F_B10F: return TEX_FORMAT_R11G11B10_FLOAT;
+
+ case GL_RGBA8: return TEX_FORMAT_RGBA8_UNORM;
+ case GL_RGBA8UI: return TEX_FORMAT_RGBA8_UINT;
+ case GL_RGBA8_SNORM: return TEX_FORMAT_RGBA8_SNORM;
+ case GL_RGBA8I: return TEX_FORMAT_RGBA8_SINT;
+
+ case GL_RG16F: return TEX_FORMAT_RG16_FLOAT;
+ case GL_RG16: return TEX_FORMAT_RG16_UNORM;
+ case GL_RG16UI: return TEX_FORMAT_RG16_UINT;
+ case GL_RG16_SNORM: return TEX_FORMAT_RG16_SNORM;
+ case GL_RG16I: return TEX_FORMAT_RG16_SINT;
+
+ case GL_R32F: return TEX_FORMAT_R32_FLOAT;
+ case GL_DEPTH_COMPONENT32F: return TEX_FORMAT_D32_FLOAT;
+ case GL_R32UI: return TEX_FORMAT_R32_UINT;
+ case GL_R32I: return TEX_FORMAT_R32_SINT;
+
+ case GL_DEPTH24_STENCIL8: return TEX_FORMAT_D24_UNORM_S8_UINT;
+
+ case GL_RG8: return TEX_FORMAT_RG8_UNORM;
+ case GL_RG8UI: return TEX_FORMAT_RG8_UINT;
+ case GL_RG8_SNORM: return TEX_FORMAT_RG8_SNORM;
+ case GL_RG8I: return TEX_FORMAT_RG8_SINT;
+
+ case GL_R16F: return TEX_FORMAT_R16_FLOAT;
+ case GL_DEPTH_COMPONENT16: return TEX_FORMAT_D16_UNORM;
+ case GL_R16: return TEX_FORMAT_R16_UNORM;
+ case GL_R16UI: return TEX_FORMAT_R16_UINT;
+ case GL_R16_SNORM: return TEX_FORMAT_R16_SNORM;
+ case GL_R16I: return TEX_FORMAT_R16_SINT;
+
+ case GL_R8: return TEX_FORMAT_R8_UNORM;
+ case GL_R8UI: return TEX_FORMAT_R8_UINT;
+ case GL_R8_SNORM: return TEX_FORMAT_R8_SNORM;
+ case GL_R8I: return TEX_FORMAT_R8_SINT;
+
+ case GL_RGB9_E5: return TEX_FORMAT_RGB9E5_SHAREDEXP;
+
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: return TEX_FORMAT_BC1_UNORM;
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: return TEX_FORMAT_BC1_UNORM_SRGB;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: return TEX_FORMAT_BC2_UNORM;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: return TEX_FORMAT_BC2_UNORM_SRGB;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: return TEX_FORMAT_BC3_UNORM;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: return TEX_FORMAT_BC3_UNORM_SRGB;
+ case GL_COMPRESSED_RED_RGTC1: return TEX_FORMAT_BC4_UNORM;
+ case GL_COMPRESSED_SIGNED_RED_RGTC1: return TEX_FORMAT_BC4_SNORM;
+ case GL_COMPRESSED_RG_RGTC2: return TEX_FORMAT_BC5_UNORM;
+ case GL_COMPRESSED_SIGNED_RG_RGTC2: return TEX_FORMAT_BC5_SNORM;
+
+ case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: return TEX_FORMAT_BC6H_UF16;
+ case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT: return TEX_FORMAT_BC6H_SF16;
+ case GL_COMPRESSED_RGBA_BPTC_UNORM: return TEX_FORMAT_BC7_UNORM;
+ case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: return TEX_FORMAT_BC7_UNORM_SRGB;
+ default:
+ UNSUPPORTED("Unsupported internal format");
+ return TEX_FORMAT_UNKNOWN;
+ }
+}
+
+} // namespace
+
+
+struct KTX10Header
+{
+ std::uint32_t Endianness;
+ std::uint32_t GLType;
+ std::uint32_t GLTypeSize;
+ std::uint32_t GLFormat;
+ std::uint32_t GLInternalFormat;
+ std::uint32_t GLBaseInternalFormat;
+ std::uint32_t Width;
+ std::uint32_t Height;
+ std::uint32_t Depth;
+ std::uint32_t NumberOfArrayElements;
+ std::uint32_t NumberOfFaces;
+ std::uint32_t NumberOfMipmapLevels;
+ std::uint32_t BytesOfKeyValueData;
+};
+
+void CreateTextureFromKTX( IDataBlob* pKTXData,
+ const TextureLoadInfo& TexLoadInfo,
+ IRenderDevice* pDevice,
+ ITexture** ppTexture )
+{
+ static constexpr Uint8 KTX10FileIdentifier[12] = {0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A};
+ const Uint8* pData = reinterpret_cast<const Uint8*>(pKTXData->GetDataPtr());
+ const auto DataSize = pKTXData->GetSize();
+ if (DataSize >= 12 && memcmp(pData, KTX10FileIdentifier, sizeof(KTX10FileIdentifier)) == 0)
+ {
+ pData += sizeof(KTX10FileIdentifier);
+ const KTX10Header& Header = *reinterpret_cast<KTX10Header const*>(pData);
+ pData += sizeof(KTX10Header);
+ // Skip key value data
+ pData += Header.BytesOfKeyValueData;
+
+ TextureDesc TexDesc;
+ TexDesc.Name = TexLoadInfo.Name;
+ TexDesc.Format = FindDiligentTextureFormat(Header.GLInternalFormat);
+ if (TexDesc.Format == TEX_FORMAT_UNKNOWN)
+ LOG_ERROR_AND_THROW("Failed to find appropriate Diligent format for internal gl format ", Header.GLInternalFormat);
+ TexDesc.Width = Header.Width;
+ TexDesc.Height = std::max(Header.Height, 1u);
+ TexDesc.Depth = std::max(Header.Depth, 1u);
+ TexDesc.MipLevels = std::max(Header.NumberOfMipmapLevels, 1u);
+ TexDesc.BindFlags = TexLoadInfo.BindFlags;
+ TexDesc.Usage = TexLoadInfo.Usage;
+ auto NumFaces = std::max(Header.NumberOfFaces, 1u);
+ if (NumFaces == 6)
+ {
+ TexDesc.ArraySize = std::max(Header.NumberOfArrayElements, 1u) * NumFaces;
+ TexDesc.Type = TexDesc.ArraySize > 6 ? RESOURCE_DIM_TEX_CUBE_ARRAY : RESOURCE_DIM_TEX_CUBE;
+ }
+ else
+ {
+ if (TexDesc.Depth > 1)
+ {
+ TexDesc.ArraySize = 1;
+ TexDesc.Type = RESOURCE_DIM_TEX_3D;
+ }
+ else
+ {
+ TexDesc.ArraySize = std::max(Header.NumberOfArrayElements, 1u);
+ TexDesc.Type = TexDesc.ArraySize > 1 ? RESOURCE_DIM_TEX_2D_ARRAY : RESOURCE_DIM_TEX_2D;
+ }
+ }
+
+ auto ArraySize = (TexDesc.Type != RESOURCE_DIM_TEX_3D ? TexDesc.ArraySize : 1);
+ std::vector<TextureSubResData> SubresData(TexDesc.MipLevels * ArraySize);
+ for (Uint32 mip = 0; mip < TexDesc.MipLevels; ++mip)
+ {
+ pData += sizeof(std::uint32_t);
+ auto MipInfo = GetMipLevelProperties(TexDesc, mip);
+
+ for (Uint32 layer = 0; layer < ArraySize; ++layer)
+ {
+ SubresData[mip + layer * TexDesc.MipLevels] =
+ TextureSubResData{pData, MipInfo.RowSize, MipInfo.DepthSliceSize};
+ pData += Align(MipInfo.MipSize, 4u);
+ }
+ }
+ VERIFY(pData - reinterpret_cast<const Uint8*>(pKTXData->GetDataPtr()) == DataSize, "Unexpected data size");
+
+ TextureData InitData(SubresData.data(), static_cast<Uint32>(SubresData.size()));
+ pDevice->CreateTexture(TexDesc, &InitData, ppTexture);
+ }
+ else
+ {
+ LOG_ERROR_AND_THROW("ktx2.0 is not currently supported");
+ }
+}
+
+}