-
Notifications
You must be signed in to change notification settings - Fork 94
Expand file tree
/
Copy pathKTXLoader.cpp
More file actions
295 lines (259 loc) · 12 KB
/
KTXLoader.cpp
File metadata and controls
295 lines (259 loc) · 12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
/*
* Copyright 2019-2025 Diligent Graphics LLC
* 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
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 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 <vector>
#include "TextureLoaderImpl.hpp"
#include "GraphicsAccessories.hpp"
#include "Align.hpp"
#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)
{
// clang-format off
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;
// clang-format on
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 TextureLoaderImpl::LoadFromKTX(const TextureLoadInfo& TexLoadInfo, const Uint8* pData, size_t DataSize)
{
#ifdef DILIGENT_DEBUG
const Uint8* pOrigDataPtr = pData;
#endif
static constexpr Uint8 KTX10FileIdentifier[12] = {0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A};
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;
m_TexDesc.Format = FindDiligentTextureFormat(Header.GLInternalFormat);
if (m_TexDesc.Format == TEX_FORMAT_UNKNOWN)
LOG_ERROR_AND_THROW("Failed to find appropriate Diligent format for internal gl format ", Header.GLInternalFormat);
m_TexDesc.Width = Header.Width;
if (m_TexDesc.Width == 0)
LOG_ERROR_AND_THROW("Texture width is zero");
m_TexDesc.Height = std::max(Header.Height, 1u);
const uint32_t SrcMipLevels = std::max(Header.NumberOfMipmapLevels, 1u);
m_TexDesc.MipLevels = SrcMipLevels;
if (TexLoadInfo.MipLevels > 0)
m_TexDesc.MipLevels = std::min(m_TexDesc.MipLevels, TexLoadInfo.MipLevels);
const uint32_t NumFaces = std::max(Header.NumberOfFaces, 1u);
const uint32_t ArraySize = std::max(Header.NumberOfArrayElements, 1u) * NumFaces;
if (NumFaces == 1)
{
if (Header.Depth >= 1)
{
m_TexDesc.Type = RESOURCE_DIM_TEX_3D;
m_TexDesc.Depth = m_TexDesc.Depth; // Depth is in union with ArraySize
}
else
{
m_TexDesc.Type = ArraySize > 1 ? RESOURCE_DIM_TEX_2D_ARRAY : RESOURCE_DIM_TEX_2D;
m_TexDesc.ArraySize = ArraySize;
}
}
else if (NumFaces == 6)
{
m_TexDesc.Type = ArraySize > 6 ? RESOURCE_DIM_TEX_CUBE_ARRAY : RESOURCE_DIM_TEX_CUBE;
m_TexDesc.ArraySize = ArraySize;
}
else
{
LOG_ERROR_AND_THROW("Unsupported number of faces (", NumFaces, ")");
}
m_SubResources.resize(size_t{m_TexDesc.MipLevels} * size_t{ArraySize});
// NB: unlike DDS, subresource in KTX are arranged by mip levels first.
for (Uint32 mip = 0; mip < SrcMipLevels; ++mip)
{
pData += sizeof(std::uint32_t);
MipLevelProperties MipInfo = GetMipLevelProperties(m_TexDesc, mip);
for (Uint32 layer = 0; layer < ArraySize; ++layer)
{
if (mip < m_TexDesc.MipLevels)
{
m_SubResources[mip + size_t{layer} * size_t{m_TexDesc.MipLevels}] =
TextureSubResData{pData, MipInfo.RowSize, MipInfo.DepthSliceSize};
}
pData += AlignUp(MipInfo.MipSize, 4u);
}
}
VERIFY(pData - pOrigDataPtr == static_cast<ptrdiff_t>(DataSize), "Unexpected data size");
}
else
{
LOG_ERROR_AND_THROW("ktx2.0 is not currently supported");
}
}
} // namespace Diligent