Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/libktx/external/dfdutils/createdfd.c
9912 views
1
/* -*- tab-width: 4; -*- */
2
/* vi: set sw=2 ts=4 expandtab: */
3
4
/* Copyright 2019-2020 The Khronos Group Inc.
5
* SPDX-License-Identifier: Apache-2.0
6
*/
7
8
/**
9
* @file
10
* @~English
11
* @brief Utilities for creating data format descriptors.
12
*/
13
14
/*
15
* Author: Andrew Garrard
16
*/
17
18
#include <assert.h>
19
#include <stdlib.h>
20
#include <string.h>
21
#include <KHR/khr_df.h>
22
23
#include "dfd.h"
24
25
typedef enum { i_COLOR, i_NON_COLOR } channels_infotype;
26
27
static uint32_t *writeHeader(int numSamples, int bytes, int suffix,
28
channels_infotype infotype)
29
{
30
uint32_t *DFD = (uint32_t *) malloc(sizeof(uint32_t) *
31
(1 + KHR_DF_WORD_SAMPLESTART +
32
numSamples * KHR_DF_WORD_SAMPLEWORDS));
33
uint32_t* BDFD = DFD+1;
34
DFD[0] = sizeof(uint32_t) *
35
(1 + KHR_DF_WORD_SAMPLESTART +
36
numSamples * KHR_DF_WORD_SAMPLEWORDS);
37
BDFD[KHR_DF_WORD_VENDORID] =
38
(KHR_DF_VENDORID_KHRONOS << KHR_DF_SHIFT_VENDORID) |
39
(KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT << KHR_DF_SHIFT_DESCRIPTORTYPE);
40
BDFD[KHR_DF_WORD_VERSIONNUMBER] =
41
(KHR_DF_VERSIONNUMBER_LATEST << KHR_DF_SHIFT_VERSIONNUMBER) |
42
(((uint32_t)sizeof(uint32_t) *
43
(KHR_DF_WORD_SAMPLESTART +
44
numSamples * KHR_DF_WORD_SAMPLEWORDS)
45
<< KHR_DF_SHIFT_DESCRIPTORBLOCKSIZE));
46
BDFD[KHR_DF_WORD_MODEL] =
47
((KHR_DF_MODEL_RGBSDA << KHR_DF_SHIFT_MODEL) | /* Only supported model */
48
(KHR_DF_FLAG_ALPHA_STRAIGHT << KHR_DF_SHIFT_FLAGS));
49
if (infotype == i_COLOR) {
50
BDFD[KHR_DF_WORD_PRIMARIES] |= KHR_DF_PRIMARIES_BT709 << KHR_DF_SHIFT_PRIMARIES; /* Assumed */
51
} else {
52
BDFD[KHR_DF_WORD_PRIMARIES] |= KHR_DF_PRIMARIES_UNSPECIFIED << KHR_DF_SHIFT_PRIMARIES;
53
}
54
if (suffix == s_SRGB) {
55
BDFD[KHR_DF_WORD_TRANSFER] |= KHR_DF_TRANSFER_SRGB << KHR_DF_SHIFT_TRANSFER;
56
} else {
57
BDFD[KHR_DF_WORD_TRANSFER] |= KHR_DF_TRANSFER_LINEAR << KHR_DF_SHIFT_TRANSFER;
58
}
59
BDFD[KHR_DF_WORD_TEXELBLOCKDIMENSION0] = 0; /* Only 1x1x1x1 texel blocks supported */
60
BDFD[KHR_DF_WORD_BYTESPLANE0] = bytes; /* bytesPlane0 = bytes, bytesPlane3..1 = 0 */
61
BDFD[KHR_DF_WORD_BYTESPLANE4] = 0; /* bytesPlane7..5 = 0 */
62
return DFD;
63
}
64
65
static uint32_t setChannelFlags(uint32_t channel, enum VkSuffix suffix)
66
{
67
switch (suffix) {
68
case s_UNORM: break;
69
case s_SNORM:
70
channel |=
71
KHR_DF_SAMPLE_DATATYPE_SIGNED;
72
break;
73
case s_USCALED: break;
74
case s_SSCALED:
75
channel |=
76
KHR_DF_SAMPLE_DATATYPE_SIGNED;
77
break;
78
case s_UINT: break;
79
case s_SINT:
80
channel |=
81
KHR_DF_SAMPLE_DATATYPE_SIGNED;
82
break;
83
case s_SFLOAT:
84
channel |=
85
KHR_DF_SAMPLE_DATATYPE_FLOAT |
86
KHR_DF_SAMPLE_DATATYPE_SIGNED;
87
break;
88
case s_UFLOAT:
89
channel |=
90
KHR_DF_SAMPLE_DATATYPE_FLOAT;
91
break;
92
case s_SRGB:
93
if (channel == KHR_DF_CHANNEL_RGBSDA_ALPHA) {
94
channel |= KHR_DF_SAMPLE_DATATYPE_LINEAR;
95
}
96
break;
97
case s_SFIXED5:
98
channel |=
99
KHR_DF_SAMPLE_DATATYPE_SIGNED;
100
break;
101
}
102
return channel;
103
}
104
105
static void writeSample(uint32_t *DFD, int sampleNo, int channel,
106
int bits, int offset,
107
int topSample, int bottomSample, enum VkSuffix suffix)
108
{
109
// Use this to avoid type-punning complaints from the gcc optimizer
110
// with -Wall.
111
union {
112
uint32_t i;
113
float f;
114
} lower, upper;
115
uint32_t *sample = DFD + 1 + KHR_DF_WORD_SAMPLESTART + sampleNo * KHR_DF_WORD_SAMPLEWORDS;
116
117
if (channel == 3) channel = KHR_DF_CHANNEL_RGBSDA_ALPHA;
118
channel = setChannelFlags(channel, suffix);
119
120
sample[KHR_DF_SAMPLEWORD_BITOFFSET] =
121
(offset << KHR_DF_SAMPLESHIFT_BITOFFSET) |
122
((bits - 1) << KHR_DF_SAMPLESHIFT_BITLENGTH) |
123
(channel << KHR_DF_SAMPLESHIFT_CHANNELID);
124
125
sample[KHR_DF_SAMPLEWORD_SAMPLEPOSITION_ALL] = 0;
126
127
switch (suffix) {
128
case s_UNORM:
129
case s_SRGB:
130
default:
131
if (bits > 32) {
132
upper.i = 0xFFFFFFFFU;
133
} else {
134
upper.i = (uint32_t)((1U << bits) - 1U);
135
}
136
lower.i = 0U;
137
break;
138
case s_SNORM:
139
if (bits > 32) {
140
upper.i = 0x7FFFFFFF;
141
} else {
142
upper.i = topSample ? (1U << (bits - 1)) - 1 : (1U << bits) - 1;
143
}
144
lower.i = ~upper.i;
145
if (bottomSample) lower.i += 1;
146
break;
147
case s_USCALED:
148
case s_UINT:
149
upper.i = bottomSample ? 1U : 0U;
150
lower.i = 0U;
151
break;
152
case s_SSCALED:
153
case s_SINT:
154
upper.i = bottomSample ? 1U : 0U;
155
lower.i = ~0U;
156
break;
157
case s_SFLOAT:
158
upper.f = 1.0f;
159
lower.f = -1.0f;
160
break;
161
case s_UFLOAT:
162
upper.f = 1.0f;
163
lower.f = 0.0f;
164
break;
165
case s_SFIXED5:
166
assert(bits == 16 && "Format with this suffix must be 16 bits per channel.");
167
upper.i = 32;
168
lower.i = ~upper.i + 1; // -32
169
}
170
sample[KHR_DF_SAMPLEWORD_SAMPLELOWER] = lower.i;
171
sample[KHR_DF_SAMPLEWORD_SAMPLEUPPER] = upper.i;
172
}
173
174
/**
175
* @~English
176
* @brief Create a Data Format Descriptor for an unpacked format.
177
*
178
* @param bigEndian Set to 1 for big-endian byte ordering and
179
0 for little-endian byte ordering.
180
* @param numChannels The number of color channels.
181
* @param bytes The number of bytes per channel.
182
* @param redBlueSwap Normally channels appear in consecutive R, G, B, A order
183
* in memory; redBlueSwap inverts red and blue, allowing
184
* B, G, R, A.
185
* @param suffix Indicates the format suffix for the type.
186
*
187
* @return A data format descriptor in malloc'd data. The caller is responsible
188
* for freeing the descriptor.
189
**/
190
uint32_t *createDFDUnpacked(int bigEndian, int numChannels, int bytes,
191
int redBlueSwap, enum VkSuffix suffix)
192
{
193
uint32_t *DFD;
194
if (bigEndian) {
195
int channelCounter, channelByte;
196
/* Number of samples = number of channels * bytes per channel */
197
DFD = writeHeader(numChannels * bytes, numChannels * bytes, suffix, i_COLOR);
198
/* First loop over the channels */
199
for (channelCounter = 0; channelCounter < numChannels; ++channelCounter) {
200
int channel = channelCounter;
201
if (redBlueSwap && (channel == 0 || channel == 2)) {
202
channel ^= 2;
203
}
204
/* Loop over the bytes that constitute a channel */
205
for (channelByte = 0; channelByte < bytes; ++channelByte) {
206
writeSample(DFD, channelCounter * bytes + channelByte, channel,
207
8, 8 * (channelCounter * bytes + bytes - channelByte - 1),
208
channelByte == bytes-1, channelByte == 0, suffix);
209
}
210
}
211
212
} else { /* Little-endian */
213
214
int sampleCounter;
215
/* One sample per channel */
216
DFD = writeHeader(numChannels, numChannels * bytes, suffix, i_COLOR);
217
for (sampleCounter = 0; sampleCounter < numChannels; ++sampleCounter) {
218
int channel = sampleCounter;
219
if (redBlueSwap && (channel == 0 || channel == 2)) {
220
channel ^= 2;
221
}
222
writeSample(DFD, sampleCounter, channel,
223
8 * bytes, 8 * sampleCounter * bytes,
224
1, 1, suffix);
225
}
226
}
227
return DFD;
228
}
229
230
/**
231
* @~English
232
* @brief Create a Data Format Descriptor for a packed format.
233
*
234
* @param bigEndian Big-endian flag: Set to 1 for big-endian byte ordering and
235
* 0 for little-endian byte ordering.
236
* @param numChannels The number of color channels.
237
* @param bits[] An array of length numChannels.
238
* Each entry is the number of bits composing the channel, in
239
* order starting at bit 0 of the packed type.
240
* @param shiftBits[] An array of length numChannels.
241
* Each entry is the number of bits each channel is shifted
242
* and thus padded with insignificant bits.
243
* @param channels[] An array of length numChannels.
244
* Each entry enumerates the channel type: 0 = red, 1 = green,
245
* 2 = blue, 15 = alpha, in order starting at bit 0 of the
246
* packed type. These values match channel IDs for RGBSDA in
247
* the Khronos Data Format header. To simplify iteration
248
* through channels, channel id 3 is a synonym for alpha.
249
* @param suffix Indicates the format suffix for the type.
250
*
251
* @return A data format descriptor in malloc'd data. The caller is responsible
252
* for freeing the descriptor.
253
**/
254
uint32_t *createDFDPackedShifted(int bigEndian, int numChannels,
255
int bits[], int shiftBits[], int channels[],
256
enum VkSuffix suffix)
257
{
258
uint32_t *DFD = 0;
259
if (numChannels == 6) {
260
/* Special case E5B9G9R9 */
261
DFD = writeHeader(numChannels, 4, s_UFLOAT, i_COLOR);
262
writeSample(DFD, 0, 0,
263
9, 0,
264
1, 1, s_UNORM);
265
KHR_DFDSETSVAL((DFD+1), 0, SAMPLEUPPER, 8448);
266
writeSample(DFD, 1, 0 | KHR_DF_SAMPLE_DATATYPE_EXPONENT,
267
5, 27,
268
1, 1, s_UNORM);
269
KHR_DFDSETSVAL((DFD+1), 1, SAMPLELOWER, 15);
270
KHR_DFDSETSVAL((DFD+1), 1, SAMPLEUPPER, 31);
271
writeSample(DFD, 2, 1,
272
9, 9,
273
1, 1, s_UNORM);
274
KHR_DFDSETSVAL((DFD+1), 2, SAMPLEUPPER, 8448);
275
writeSample(DFD, 3, 1 | KHR_DF_SAMPLE_DATATYPE_EXPONENT,
276
5, 27,
277
1, 1, s_UNORM);
278
KHR_DFDSETSVAL((DFD+1), 3, SAMPLELOWER, 15);
279
KHR_DFDSETSVAL((DFD+1), 3, SAMPLEUPPER, 31);
280
writeSample(DFD, 4, 2,
281
9, 18,
282
1, 1, s_UNORM);
283
KHR_DFDSETSVAL((DFD+1), 4, SAMPLEUPPER, 8448);
284
writeSample(DFD, 5, 2 | KHR_DF_SAMPLE_DATATYPE_EXPONENT,
285
5, 27,
286
1, 1, s_UNORM);
287
KHR_DFDSETSVAL((DFD+1), 5, SAMPLELOWER, 15);
288
KHR_DFDSETSVAL((DFD+1), 5, SAMPLEUPPER, 31);
289
} else if (bigEndian) {
290
/* No packed format is larger than 32 bits. */
291
/* No packed channel crosses more than two bytes. */
292
int totalBits = 0;
293
int bitChannel[32];
294
int beChannelStart[4];
295
int channelCounter;
296
int bitOffset = 0;
297
int BEMask;
298
int numSamples = numChannels;
299
int sampleCounter;
300
for (channelCounter = 0; channelCounter < numChannels; ++channelCounter) {
301
beChannelStart[channelCounter] = totalBits;
302
totalBits += shiftBits[channelCounter] + bits[channelCounter];
303
}
304
BEMask = (totalBits - 1) & 0x18;
305
for (channelCounter = 0; channelCounter < numChannels; ++channelCounter) {
306
bitOffset += shiftBits[channelCounter];
307
bitChannel[bitOffset ^ BEMask] = channelCounter;
308
if (((bitOffset + bits[channelCounter] - 1) & ~7) != (bitOffset & ~7)) {
309
/* Continuation sample */
310
bitChannel[((bitOffset + bits[channelCounter] - 1) & ~7) ^ BEMask] = channelCounter;
311
numSamples++;
312
}
313
bitOffset += bits[channelCounter];
314
}
315
DFD = writeHeader(numSamples, totalBits >> 3, suffix, i_COLOR);
316
317
sampleCounter = 0;
318
for (bitOffset = 0; bitOffset < totalBits;) {
319
if (bitChannel[bitOffset] == -1) {
320
/* Done this bit, so this is the lower half of something. */
321
/* We must therefore jump to the end of the byte and continue. */
322
bitOffset = (bitOffset + 8) & ~7;
323
} else {
324
/* Start of a channel? */
325
int thisChannel = bitChannel[bitOffset];
326
if ((beChannelStart[thisChannel] ^ BEMask) == bitOffset) {
327
/* Must be just one sample if we hit it first. */
328
writeSample(DFD, sampleCounter++, channels[thisChannel],
329
bits[thisChannel], bitOffset,
330
1, 1, suffix);
331
bitOffset += bits[thisChannel];
332
} else {
333
/* Two samples. Move to the end of the first one we hit when we're done. */
334
int firstSampleBits = 8 - (beChannelStart[thisChannel] & 0x7); /* Rest of the byte */
335
int secondSampleBits = bits[thisChannel] - firstSampleBits; /* Rest of the bits */
336
writeSample(DFD, sampleCounter++, channels[thisChannel],
337
firstSampleBits, beChannelStart[thisChannel] ^ BEMask,
338
0, 1, suffix);
339
/* Mark that we've already handled this sample */
340
bitChannel[beChannelStart[thisChannel] ^ BEMask] = -1;
341
writeSample(DFD, sampleCounter++, channels[thisChannel],
342
secondSampleBits, bitOffset,
343
1, 0, suffix);
344
bitOffset += secondSampleBits;
345
}
346
}
347
}
348
349
} else { /* Little-endian */
350
351
int sampleCounter;
352
int totalBits = 0;
353
int bitOffset = 0;
354
for (sampleCounter = 0; sampleCounter < numChannels; ++sampleCounter) {
355
totalBits += shiftBits[sampleCounter] + bits[sampleCounter];
356
}
357
358
/* One sample per channel */
359
DFD = writeHeader(numChannels, totalBits >> 3, suffix, i_COLOR);
360
for (sampleCounter = 0; sampleCounter < numChannels; ++sampleCounter) {
361
bitOffset += shiftBits[sampleCounter];
362
writeSample(DFD, sampleCounter, channels[sampleCounter],
363
bits[sampleCounter], bitOffset,
364
1, 1, suffix);
365
bitOffset += bits[sampleCounter];
366
}
367
}
368
return DFD;
369
}
370
371
/**
372
* @~English
373
* @brief Create a Data Format Descriptor for a packed format.
374
*
375
* @param bigEndian Big-endian flag: Set to 1 for big-endian byte ordering and
376
* 0 for little-endian byte ordering.
377
* @param numChannels The number of color channels.
378
* @param bits[] An array of length numChannels.
379
* Each entry is the number of bits composing the channel, in
380
* order starting at bit 0 of the packed type.
381
* @param channels[] An array of length numChannels.
382
* Each entry enumerates the channel type: 0 = red, 1 = green,
383
* 2 = blue, 15 = alpha, in order starting at bit 0 of the
384
* packed type. These values match channel IDs for RGBSDA in
385
* the Khronos Data Format header. To simplify iteration
386
* through channels, channel id 3 is a synonym for alpha.
387
* @param suffix Indicates the format suffix for the type.
388
*
389
* @return A data format descriptor in malloc'd data. The caller is responsible
390
* for freeing the descriptor.
391
**/
392
uint32_t *createDFDPacked(int bigEndian, int numChannels,
393
int bits[], int channels[],
394
enum VkSuffix suffix) {
395
assert(numChannels <= 6);
396
int shiftBits[] = {0, 0, 0, 0, 0, 0};
397
return createDFDPackedShifted(bigEndian, numChannels, bits, shiftBits, channels, suffix);
398
}
399
400
uint32_t *createDFD422(int bigEndian, int numSamples,
401
int bits[], int shiftBits[], int channels[],
402
int position_xs[], int position_ys[],
403
enum VkSuffix suffix) {
404
assert(!bigEndian); (void) bigEndian;
405
assert(suffix == s_UNORM); (void) suffix;
406
407
int totalBits = 0;
408
for (int i = 0; i < numSamples; ++i)
409
totalBits += shiftBits[i] + bits[i];
410
assert(totalBits % 8 == 0);
411
412
uint32_t BDFDSize = sizeof(uint32_t) * (KHR_DF_WORD_SAMPLESTART + numSamples * KHR_DF_WORD_SAMPLEWORDS);
413
uint32_t DFDSize = sizeof(uint32_t) + BDFDSize;
414
uint32_t *DFD = (uint32_t *) malloc(DFDSize);
415
memset(DFD, 0, DFDSize);
416
DFD[0] = DFDSize;
417
uint32_t *BDFD = DFD + 1;
418
KHR_DFDSETVAL(BDFD, VENDORID, KHR_DF_VENDORID_KHRONOS);
419
KHR_DFDSETVAL(BDFD, DESCRIPTORTYPE, KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT);
420
KHR_DFDSETVAL(BDFD, VERSIONNUMBER, KHR_DF_VERSIONNUMBER_LATEST);
421
KHR_DFDSETVAL(BDFD, DESCRIPTORBLOCKSIZE, BDFDSize);
422
KHR_DFDSETVAL(BDFD, MODEL, KHR_DF_MODEL_YUVSDA);
423
KHR_DFDSETVAL(BDFD, PRIMARIES, KHR_DF_PRIMARIES_UNSPECIFIED);
424
KHR_DFDSETVAL(BDFD, TRANSFER, KHR_DF_TRANSFER_LINEAR);
425
KHR_DFDSETVAL(BDFD, FLAGS, KHR_DF_FLAG_ALPHA_STRAIGHT);
426
KHR_DFDSETVAL(BDFD, TEXELBLOCKDIMENSION0, 2 - 1); // 422 contains 2 x 1 blocks
427
KHR_DFDSETVAL(BDFD, TEXELBLOCKDIMENSION1, 1 - 1);
428
KHR_DFDSETVAL(BDFD, TEXELBLOCKDIMENSION2, 1 - 1);
429
KHR_DFDSETVAL(BDFD, TEXELBLOCKDIMENSION3, 1 - 1);
430
KHR_DFDSETVAL(BDFD, BYTESPLANE0, totalBits / 8);
431
KHR_DFDSETVAL(BDFD, BYTESPLANE1, 0);
432
KHR_DFDSETVAL(BDFD, BYTESPLANE2, 0);
433
KHR_DFDSETVAL(BDFD, BYTESPLANE3, 0);
434
KHR_DFDSETVAL(BDFD, BYTESPLANE4, 0);
435
KHR_DFDSETVAL(BDFD, BYTESPLANE5, 0);
436
KHR_DFDSETVAL(BDFD, BYTESPLANE6, 0);
437
KHR_DFDSETVAL(BDFD, BYTESPLANE7, 0);
438
439
int bitOffset = 0;
440
for (int i = 0; i < numSamples; ++i) {
441
bitOffset += shiftBits[i];
442
KHR_DFDSETSVAL(BDFD, i, BITOFFSET, bitOffset);
443
KHR_DFDSETSVAL(BDFD, i, BITLENGTH, bits[i] - 1);
444
KHR_DFDSETSVAL(BDFD, i, CHANNELID, channels[i]);
445
KHR_DFDSETSVAL(BDFD, i, QUALIFIERS, 0); // None of: FLOAT, SIGNED, EXPONENT, LINEAR
446
KHR_DFDSETSVAL(BDFD, i, SAMPLEPOSITION0, position_xs[i]);
447
KHR_DFDSETSVAL(BDFD, i, SAMPLEPOSITION1, position_ys[i]);
448
KHR_DFDSETSVAL(BDFD, i, SAMPLEPOSITION2, 0);
449
KHR_DFDSETSVAL(BDFD, i, SAMPLEPOSITION3, 0);
450
KHR_DFDSETSVAL(BDFD, i, SAMPLELOWER, 0);
451
KHR_DFDSETSVAL(BDFD, i, SAMPLEUPPER, (1u << bits[i]) - 1u);
452
bitOffset += bits[i];
453
}
454
455
return DFD;
456
}
457
458
static khr_df_model_e compModelMapping[] = {
459
KHR_DF_MODEL_BC1A, /*!< BC1, aka DXT1, no alpha. */
460
KHR_DF_MODEL_BC1A, /*!< BC1, aka DXT1, punch-through alpha. */
461
KHR_DF_MODEL_BC2, /*!< BC2, aka DXT2 and DXT3. */
462
KHR_DF_MODEL_BC3, /*!< BC3, aka DXT4 and DXT5. */
463
KHR_DF_MODEL_BC4, /*!< BC4. */
464
KHR_DF_MODEL_BC5, /*!< BC5. */
465
KHR_DF_MODEL_BC6H, /*!< BC6h HDR format. */
466
KHR_DF_MODEL_BC7, /*!< BC7. */
467
KHR_DF_MODEL_ETC2, /*!< ETC2 no alpha. */
468
KHR_DF_MODEL_ETC2, /*!< ETC2 punch-through alpha. */
469
KHR_DF_MODEL_ETC2, /*!< ETC2 independent alpha. */
470
KHR_DF_MODEL_ETC2, /*!< R11 ETC2 single-channel. */
471
KHR_DF_MODEL_ETC2, /*!< R11G11 ETC2 dual-channel. */
472
KHR_DF_MODEL_ASTC, /*!< ASTC. */
473
KHR_DF_MODEL_ETC1S, /*!< ETC1S. */
474
KHR_DF_MODEL_PVRTC, /*!< PVRTC(1). */
475
KHR_DF_MODEL_PVRTC2 /*!< PVRTC2. */
476
};
477
478
static uint32_t compSampleCount[] = {
479
1U, /*!< BC1, aka DXT1, no alpha. */
480
1U, /*!< BC1, aka DXT1, punch-through alpha. */
481
2U, /*!< BC2, aka DXT2 and DXT3. */
482
2U, /*!< BC3, aka DXT4 and DXT5. */
483
1U, /*!< BC4. */
484
2U, /*!< BC5. */
485
1U, /*!< BC6h HDR format. */
486
1U, /*!< BC7. */
487
1U, /*!< ETC2 no alpha. */
488
2U, /*!< ETC2 punch-through alpha. */
489
2U, /*!< ETC2 independent alpha. */
490
1U, /*!< R11 ETC2 single-channel. */
491
2U, /*!< R11G11 ETC2 dual-channel. */
492
1U, /*!< ASTC. */
493
1U, /*!< ETC1S. */
494
1U, /*!< PVRTC. */
495
1U /*!< PVRTC2. */
496
};
497
498
static khr_df_model_channels_e compFirstChannel[] = {
499
KHR_DF_CHANNEL_BC1A_COLOR, /*!< BC1, aka DXT1, no alpha. */
500
KHR_DF_CHANNEL_BC1A_ALPHAPRESENT, /*!< BC1, aka DXT1, punch-through alpha. */
501
KHR_DF_CHANNEL_BC2_ALPHA, /*!< BC2, aka DXT2 and DXT3. */
502
KHR_DF_CHANNEL_BC3_ALPHA, /*!< BC3, aka DXT4 and DXT5. */
503
KHR_DF_CHANNEL_BC4_DATA, /*!< BC4. */
504
KHR_DF_CHANNEL_BC5_RED, /*!< BC5. */
505
KHR_DF_CHANNEL_BC6H_COLOR, /*!< BC6h HDR format. */
506
KHR_DF_CHANNEL_BC7_COLOR, /*!< BC7. */
507
KHR_DF_CHANNEL_ETC2_COLOR, /*!< ETC2 no alpha. */
508
KHR_DF_CHANNEL_ETC2_COLOR, /*!< ETC2 punch-through alpha. */
509
KHR_DF_CHANNEL_ETC2_ALPHA, /*!< ETC2 independent alpha. */
510
KHR_DF_CHANNEL_ETC2_RED, /*!< R11 ETC2 single-channel. */
511
KHR_DF_CHANNEL_ETC2_RED, /*!< R11G11 ETC2 dual-channel. */
512
KHR_DF_CHANNEL_ASTC_DATA, /*!< ASTC. */
513
KHR_DF_CHANNEL_ETC1S_RGB, /*!< ETC1S. */
514
KHR_DF_CHANNEL_PVRTC_COLOR, /*!< PVRTC. */
515
KHR_DF_CHANNEL_PVRTC2_COLOR /*!< PVRTC2. */
516
};
517
518
static khr_df_model_channels_e compSecondChannel[] = {
519
KHR_DF_CHANNEL_BC1A_COLOR, /*!< BC1, aka DXT1, no alpha. */
520
KHR_DF_CHANNEL_BC1A_ALPHAPRESENT, /*!< BC1, aka DXT1, punch-through alpha. */
521
KHR_DF_CHANNEL_BC2_COLOR, /*!< BC2, aka DXT2 and DXT3. */
522
KHR_DF_CHANNEL_BC3_COLOR, /*!< BC3, aka DXT4 and DXT5. */
523
KHR_DF_CHANNEL_BC4_DATA, /*!< BC4. */
524
KHR_DF_CHANNEL_BC5_GREEN, /*!< BC5. */
525
KHR_DF_CHANNEL_BC6H_COLOR, /*!< BC6h HDR format. */
526
KHR_DF_CHANNEL_BC7_COLOR, /*!< BC7. */
527
KHR_DF_CHANNEL_ETC2_COLOR, /*!< ETC2 no alpha. */
528
KHR_DF_CHANNEL_ETC2_ALPHA, /*!< ETC2 punch-through alpha. */
529
KHR_DF_CHANNEL_ETC2_COLOR, /*!< ETC2 independent alpha. */
530
KHR_DF_CHANNEL_ETC2_RED, /*!< R11 ETC2 single-channel. */
531
KHR_DF_CHANNEL_ETC2_GREEN, /*!< R11G11 ETC2 dual-channel. */
532
KHR_DF_CHANNEL_ASTC_DATA, /*!< ASTC. */
533
KHR_DF_CHANNEL_ETC1S_RGB, /*!< ETC1S. */
534
KHR_DF_CHANNEL_PVRTC_COLOR, /*!< PVRTC. */
535
KHR_DF_CHANNEL_PVRTC2_COLOR /*!< PVRTC2. */
536
};
537
538
static uint32_t compSecondChannelOffset[] = {
539
0U, /*!< BC1, aka DXT1, no alpha. */
540
0U, /*!< BC1, aka DXT1, punch-through alpha. */
541
64U, /*!< BC2, aka DXT2 and DXT3. */
542
64U, /*!< BC3, aka DXT4 and DXT5. */
543
0U, /*!< BC4. */
544
64U, /*!< BC5. */
545
0U, /*!< BC6h HDR format. */
546
0U, /*!< BC7. */
547
0U, /*!< ETC2 no alpha. */
548
0U, /*!< ETC2 punch-through alpha. */
549
64U, /*!< ETC2 independent alpha. */
550
0U, /*!< R11 ETC2 single-channel. */
551
64U, /*!< R11G11 ETC2 dual-channel. */
552
0U, /*!< ASTC. */
553
0U, /*!< ETC1S. */
554
0U, /*!< PVRTC. */
555
0U /*!< PVRTC2. */
556
};
557
558
static uint32_t compChannelBits[] = {
559
64U, /*!< BC1, aka DXT1, no alpha. */
560
64U, /*!< BC1, aka DXT1, punch-through alpha. */
561
64U, /*!< BC2, aka DXT2 and DXT3. */
562
64U, /*!< BC3, aka DXT4 and DXT5. */
563
64U, /*!< BC4. */
564
64U, /*!< BC5. */
565
128U, /*!< BC6h HDR format. */
566
128U, /*!< BC7. */
567
64U, /*!< ETC2 no alpha. */
568
64U, /*!< ETC2 punch-through alpha. */
569
64U, /*!< ETC2 independent alpha. */
570
64U, /*!< R11 ETC2 single-channel. */
571
64U, /*!< R11G11 ETC2 dual-channel. */
572
128U, /*!< ASTC. */
573
64U, /*!< ETC1S. */
574
64U, /*!< PVRTC. */
575
64U /*!< PVRTC2. */
576
};
577
578
static uint32_t compBytes[] = {
579
8U, /*!< BC1, aka DXT1, no alpha. */
580
8U, /*!< BC1, aka DXT1, punch-through alpha. */
581
16U, /*!< BC2, aka DXT2 and DXT3. */
582
16U, /*!< BC3, aka DXT4 and DXT5. */
583
8U, /*!< BC4. */
584
16U, /*!< BC5. */
585
16U, /*!< BC6h HDR format. */
586
16U, /*!< BC7. */
587
8U, /*!< ETC2 no alpha. */
588
8U, /*!< ETC2 punch-through alpha. */
589
16U, /*!< ETC2 independent alpha. */
590
8U, /*!< R11 ETC2 single-channel. */
591
16U, /*!< R11G11 ETC2 dual-channel. */
592
16U, /*!< ASTC. */
593
8U, /*!< ETC1S. */
594
8U, /*!< PVRTC. */
595
8U /*!< PVRTC2. */
596
};
597
598
/**
599
* @~English
600
* @brief Create a Data Format Descriptor for a compressed format.
601
*
602
* @param compScheme Vulkan-style compression scheme enumeration.
603
* @param bwidth Block width in texel coordinates.
604
* @param bheight Block height in texel coordinates.
605
* @param bdepth Block depth in texel coordinates.
606
* @author Mark Callow, Edgewise Consulting.
607
* @param suffix Indicates the format suffix for the type.
608
*
609
* @return A data format descriptor in malloc'd data. The caller is responsible
610
* for freeing the descriptor.
611
**/
612
uint32_t *createDFDCompressed(enum VkCompScheme compScheme, int bwidth, int bheight, int bdepth,
613
enum VkSuffix suffix)
614
{
615
uint32_t *DFD = 0;
616
uint32_t numSamples = compSampleCount[compScheme];
617
uint32_t* BDFD;
618
uint32_t *sample;
619
uint32_t channel;
620
// Use union to avoid type-punning complaints from gcc optimizer
621
// with -Wall.
622
union {
623
uint32_t i;
624
float f;
625
} lower, upper;
626
627
DFD = (uint32_t *) malloc(sizeof(uint32_t) *
628
(1 + KHR_DF_WORD_SAMPLESTART +
629
numSamples * KHR_DF_WORD_SAMPLEWORDS));
630
BDFD = DFD+1;
631
DFD[0] = sizeof(uint32_t) *
632
(1 + KHR_DF_WORD_SAMPLESTART +
633
numSamples * KHR_DF_WORD_SAMPLEWORDS);
634
BDFD[KHR_DF_WORD_VENDORID] =
635
(KHR_DF_VENDORID_KHRONOS << KHR_DF_SHIFT_VENDORID) |
636
(KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT << KHR_DF_SHIFT_DESCRIPTORTYPE);
637
BDFD[KHR_DF_WORD_VERSIONNUMBER] =
638
(KHR_DF_VERSIONNUMBER_LATEST << KHR_DF_SHIFT_VERSIONNUMBER) |
639
(((uint32_t)sizeof(uint32_t) *
640
(KHR_DF_WORD_SAMPLESTART +
641
numSamples * KHR_DF_WORD_SAMPLEWORDS)
642
<< KHR_DF_SHIFT_DESCRIPTORBLOCKSIZE));
643
BDFD[KHR_DF_WORD_MODEL] =
644
((compModelMapping[compScheme] << KHR_DF_SHIFT_MODEL) |
645
(KHR_DF_PRIMARIES_BT709 << KHR_DF_SHIFT_PRIMARIES) | /* Assumed */
646
(KHR_DF_FLAG_ALPHA_STRAIGHT << KHR_DF_SHIFT_FLAGS));
647
648
if (suffix == s_SRGB) {
649
BDFD[KHR_DF_WORD_TRANSFER] |= KHR_DF_TRANSFER_SRGB << KHR_DF_SHIFT_TRANSFER;
650
} else {
651
BDFD[KHR_DF_WORD_TRANSFER] |= KHR_DF_TRANSFER_LINEAR << KHR_DF_SHIFT_TRANSFER;
652
}
653
BDFD[KHR_DF_WORD_TEXELBLOCKDIMENSION0] =
654
(bwidth - 1) | ((bheight - 1) << KHR_DF_SHIFT_TEXELBLOCKDIMENSION1) | ((bdepth - 1) << KHR_DF_SHIFT_TEXELBLOCKDIMENSION2);
655
/* bytesPlane0 = bytes, bytesPlane3..1 = 0 */
656
BDFD[KHR_DF_WORD_BYTESPLANE0] = compBytes[compScheme];
657
BDFD[KHR_DF_WORD_BYTESPLANE4] = 0; /* bytesPlane7..5 = 0 */
658
659
sample = BDFD + KHR_DF_WORD_SAMPLESTART;
660
channel = compFirstChannel[compScheme];
661
channel = setChannelFlags(channel, suffix);
662
663
sample[KHR_DF_SAMPLEWORD_BITOFFSET] =
664
(0 << KHR_DF_SAMPLESHIFT_BITOFFSET) |
665
((compChannelBits[compScheme] - 1) << KHR_DF_SAMPLESHIFT_BITLENGTH) |
666
(channel << KHR_DF_SAMPLESHIFT_CHANNELID);
667
668
sample[KHR_DF_SAMPLEWORD_SAMPLEPOSITION_ALL] = 0;
669
switch (suffix) {
670
case s_UNORM:
671
case s_SRGB:
672
default:
673
upper.i = 0xFFFFFFFFU;
674
lower.i = 0U;
675
break;
676
case s_SNORM:
677
upper.i = 0x7FFFFFFF;
678
lower.i = ~upper.i;
679
break;
680
case s_USCALED:
681
case s_UINT:
682
upper.i = 1U;
683
lower.i = 0U;
684
break;
685
case s_SSCALED:
686
case s_SINT:
687
upper.i = 1U;
688
lower.i = ~0U;
689
break;
690
case s_SFLOAT:
691
upper.f = 1.0f;
692
lower.f = -1.0f;
693
break;
694
case s_UFLOAT:
695
upper.f = 1.0f;
696
lower.f = 0.0f;
697
break;
698
}
699
sample[KHR_DF_SAMPLEWORD_SAMPLELOWER] = lower.i;
700
sample[KHR_DF_SAMPLEWORD_SAMPLEUPPER] = upper.i;
701
702
if (compSampleCount[compScheme] > 1) {
703
sample += KHR_DF_WORD_SAMPLEWORDS;
704
channel = compSecondChannel[compScheme];
705
channel = setChannelFlags(channel, suffix);
706
707
sample[KHR_DF_SAMPLEWORD_BITOFFSET] =
708
(compSecondChannelOffset[compScheme] << KHR_DF_SAMPLESHIFT_BITOFFSET) |
709
((compChannelBits[compScheme] - 1) << KHR_DF_SAMPLESHIFT_BITLENGTH) |
710
(channel << KHR_DF_SAMPLESHIFT_CHANNELID);
711
712
sample[KHR_DF_SAMPLEWORD_SAMPLEPOSITION_ALL] = 0;
713
714
sample[KHR_DF_SAMPLEWORD_SAMPLELOWER] = lower.i;
715
sample[KHR_DF_SAMPLEWORD_SAMPLEUPPER] = upper.i;
716
}
717
return DFD;
718
}
719
720
/**
721
* @~English
722
* @brief Create a Data Format Descriptor for a depth-stencil format.
723
*
724
* @param depthBits The numeber of bits in the depth channel.
725
* @param stencilBits The numeber of bits in the stencil channel.
726
* @param sizeBytes The total byte size of the texel.
727
*
728
* @return A data format descriptor in malloc'd data. The caller is responsible
729
* for freeing the descriptor.
730
**/
731
uint32_t *createDFDDepthStencil(int depthBits,
732
int stencilBits,
733
int sizeBytes)
734
{
735
/* N.B. Little-endian is assumed. */
736
uint32_t *DFD = 0;
737
DFD = writeHeader((depthBits > 0) + (stencilBits > 0),
738
sizeBytes, s_UNORM, i_NON_COLOR);
739
740
/* Handle the special case of D24_UNORM_S8_UINT where the order of the
741
channels is flipped by putting stencil in the LSBs. */
742
if (depthBits == 24 && stencilBits == 8) {
743
writeSample(DFD, 0, KHR_DF_CHANNEL_RGBSDA_STENCIL,
744
8, 0,
745
1, 1, s_UINT);
746
writeSample(DFD, 1, KHR_DF_CHANNEL_RGBSDA_DEPTH,
747
24, 8,
748
1, 1, s_UNORM);
749
return DFD;
750
}
751
752
if (depthBits == 32) {
753
writeSample(DFD, 0, KHR_DF_CHANNEL_RGBSDA_DEPTH,
754
32, 0,
755
1, 1, s_SFLOAT);
756
} else if (depthBits > 0) {
757
writeSample(DFD, 0, KHR_DF_CHANNEL_RGBSDA_DEPTH,
758
depthBits, 0,
759
1, 1, s_UNORM);
760
}
761
if (stencilBits > 0) {
762
if (depthBits > 0) {
763
writeSample(DFD, 1, KHR_DF_CHANNEL_RGBSDA_STENCIL,
764
stencilBits, depthBits,
765
1, 1, s_UINT);
766
} else {
767
writeSample(DFD, 0, KHR_DF_CHANNEL_RGBSDA_STENCIL,
768
stencilBits, 0,
769
1, 1, s_UINT);
770
}
771
}
772
return DFD;
773
}
774
775
/**
776
* @~English
777
* @brief Create a Data Format Descriptor for an alpha-only format.
778
*
779
* @param bigEndian Set to 1 for big-endian byte ordering and
780
0 for little-endian byte ordering.
781
* @param bytes The number of bytes per channel.
782
* @param suffix Indicates the format suffix for the type.
783
*
784
* @return A data format descriptor in malloc'd data. The caller is responsible
785
* for freeing the descriptor.
786
**/
787
uint32_t *createDFDAlpha(int bigEndian, int bytes,
788
enum VkSuffix suffix) {
789
uint32_t *DFD;
790
int channel = 3; /* alpha channel */
791
if (bigEndian) {
792
int channelByte;
793
/* Number of samples = number of channels * bytes per channel */
794
DFD = writeHeader(bytes, bytes, suffix, i_COLOR);
795
/* Loop over the bytes that constitute a channel */
796
for (channelByte = 0; channelByte < bytes; ++channelByte) {
797
writeSample(DFD, channelByte, channel,
798
8, 8 * (bytes - channelByte - 1),
799
channelByte == bytes-1, channelByte == 0, suffix);
800
}
801
} else { /* Little-endian */
802
/* One sample per channel */
803
DFD = writeHeader(1, bytes, suffix, i_COLOR);
804
writeSample(DFD, 0, channel,
805
8 * bytes, 0,
806
1, 1, suffix);
807
}
808
return DFD;
809
}
810
811