Skip to content

Commit eeac620

Browse files
authored
Support for A8 and A1B5G5R5 formats (#785)
The change contains various general enhancements including performance optimizations for PNG exports.
1 parent 7332293 commit eeac620

File tree

13 files changed

+184
-137
lines changed

13 files changed

+184
-137
lines changed

lib/dfdutils/createdfd.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,3 +747,39 @@ uint32_t *createDFDDepthStencil(int depthBits,
747747
}
748748
return DFD;
749749
}
750+
751+
/**
752+
* @~English
753+
* @brief Create a Data Format Descriptor for an alpha-only format.
754+
*
755+
* @param bigEndian Set to 1 for big-endian byte ordering and
756+
0 for little-endian byte ordering.
757+
* @param bytes The number of bytes per channel.
758+
* @param suffix Indicates the format suffix for the type.
759+
*
760+
* @return A data format descriptor in malloc'd data. The caller is responsible
761+
* for freeing the descriptor.
762+
**/
763+
uint32_t *createDFDAlpha(int bigEndian, int bytes,
764+
enum VkSuffix suffix) {
765+
uint32_t *DFD;
766+
int channel = 3; /* alpha channel */
767+
if (bigEndian) {
768+
int channelByte;
769+
/* Number of samples = number of channels * bytes per channel */
770+
DFD = writeHeader(bytes, bytes, suffix, i_COLOR);
771+
/* Loop over the bytes that constitute a channel */
772+
for (channelByte = 0; channelByte < bytes; ++channelByte) {
773+
writeSample(DFD, channelByte, channel,
774+
8, 8 * (bytes - channelByte - 1),
775+
channelByte == bytes-1, channelByte == 0, suffix);
776+
}
777+
} else { /* Little-endian */
778+
/* One sample per channel */
779+
DFD = writeHeader(1, bytes, suffix, i_COLOR);
780+
writeSample(DFD, 0, channel,
781+
8 * bytes, 0,
782+
1, 1, suffix);
783+
}
784+
return DFD;
785+
}

lib/dfdutils/dfd.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ uint32_t *createDFDDepthStencil(int depthBits,
9999
int stencilBits,
100100
int sizeBytes);
101101

102+
/* Create a Data Format Descriptor for an alpha-only format */
103+
uint32_t *createDFDAlpha(int bigEndian, int bytes,
104+
enum VkSuffix suffix);
105+
102106
/** @brief Result of interpreting the data format descriptor. */
103107
enum InterpretDFDResult {
104108
i_LITTLE_ENDIAN_FORMAT_BIT = 0, /*!< Confirmed little-endian (default for 8bpc). */

lib/dfdutils/dfd2vk.inl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ if (KHR_DFDVAL(dfd + 1, MODEL) == KHR_DF_MODEL_RGBSDA) {
5151
} else { /* Four channels, one-bit alpha */
5252
if (B.offset == 0) return VK_FORMAT_A1R5G5B5_UNORM_PACK16;
5353
if (B.offset == 1) return VK_FORMAT_R5G5B5A1_UNORM_PACK16;
54+
if (B.offset == 10) return VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR;
5455
return VK_FORMAT_B5G5R5A1_UNORM_PACK16;
5556
}
5657
} else if (wordBytes == 4) { /* PACK32 */
@@ -74,6 +75,9 @@ if (KHR_DFDVAL(dfd + 1, MODEL) == KHR_DF_MODEL_RGBSDA) {
7475
}
7576
} else { /* Not a packed format */
7677
if (wordBytes == 1) {
78+
if (A.size > 8 && R.size == 0 && G.size == 0 && B.size == 0 && (r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) {
79+
return VK_FORMAT_A8_UNORM_KHR;
80+
}
7781
if (A.size > 0) { /* 4 channels */
7882
if (R.offset == 0) { /* RGBA */
7983
if ((r & i_SRGB_FORMAT_BIT)) return VK_FORMAT_R8G8B8A8_SRGB;

lib/dfdutils/makedfd2vk.pl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ sub checkSuffices {
294294
} else { /* Four channels, one-bit alpha */
295295
if (B.offset == 0) return VK_FORMAT_A1R5G5B5_UNORM_PACK16;
296296
if (B.offset == 1) return VK_FORMAT_R5G5B5A1_UNORM_PACK16;
297+
if (B.offset == 10) return VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR;
297298
return VK_FORMAT_B5G5R5A1_UNORM_PACK16;
298299
}
299300
} else if (wordBytes == 4) { /* PACK32 */
@@ -315,6 +316,11 @@ sub checkSuffices {
315316
for ($byteSize = 1; $byteSize <= 8; $byteSize <<= 1) {
316317
if ($byteSize == 1) {
317318
print " if (wordBytes == $byteSize) {\n";
319+
320+
# Handle the single alpha-only format (unfortunately, the rest of the script could not handle this)
321+
print " if (A.size > 8 && R.size == 0 && G.size == 0 && B.size == 0 && (r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) {\n";
322+
print " return VK_FORMAT_A8_UNORM_KHR;\n";
323+
print " }\n";
318324
} else {
319325
print " } else if (wordBytes == $byteSize) {\n";
320326
}

lib/dfdutils/makevk2dfd.pl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,15 @@
205205
# If we're not packed, do we have a simple RGBA channel size list with a suffix?
206206
# N.B. We don't want to pick up downsampled or planar formats, which have more _-separated fields
207207
# - "$" matches the end of the format identifier
208+
} elsif ($format =~ m/VK_FORMAT_A([0-9]+)_([^_]+)(_[^_]+)?$/) {
209+
# Special case for alpha-only formats
210+
211+
# Extract our "suffix" (e.g. "UNORM") and bytes per channel
212+
$suffix = $2;
213+
$bytesPerChannel = $1 / 8;
214+
215+
# Output the case entry
216+
print "case $format: return createDFDAlpha($bigEndian, $bytesPerChannel, s_$suffix);\n";
208217
} elsif ($format =~ m/VK_FORMAT_([RGBA0-9]+)_([^_]+)$/) {
209218

210219
# Extract our "channels" (e.g. "B8G8R8") and "suffix" (e.g. "UNORM")

lib/dfdutils/vk2dfd.inl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,3 +400,8 @@ case VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT: {
400400
int channels[] = {0,1,2,3}; int bits[] = {4,4,4,4};
401401
return createDFDPacked(0, 4, bits, channels, s_UNORM);
402402
}
403+
case VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR: {
404+
int channels[] = {0,1,2,3}; int bits[] = {5,5,5,1};
405+
return createDFDPacked(0, 4, bits, channels, s_UNORM);
406+
}
407+
case VK_FORMAT_A8_UNORM_KHR: return createDFDAlpha(0, 1, s_UNORM);

lib/dfdutils/vulkan/vulkan_core.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,6 +1124,8 @@ typedef enum VkFormat {
11241124
VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM_KHR = VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM,
11251125
VK_FORMAT_G16_B16R16_2PLANE_422_UNORM_KHR = VK_FORMAT_G16_B16R16_2PLANE_422_UNORM,
11261126
VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM_KHR = VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM,
1127+
VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR = 1000470000,
1128+
VK_FORMAT_A8_UNORM_KHR = 1000470001,
11271129
VK_FORMAT_MAX_ENUM = 0x7FFFFFFF
11281130
} VkFormat;
11291131

lib/vkformat_check.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ isValidFormat(VkFormat format)
150150
case VK_FORMAT_ASTC_6x6x6_SFLOAT_BLOCK_EXT:
151151
case VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT:
152152
case VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT:
153+
case VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR:
154+
case VK_FORMAT_A8_UNORM_KHR:
153155
return true;
154156
default:
155157
return false;

lib/vkformat_enum.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,8 @@ typedef enum VkFormat {
292292
VK_FORMAT_ASTC_6x6x6_SFLOAT_BLOCK_EXT = 1000288029,
293293
VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT = 1000340000,
294294
VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT = 1000340001,
295+
VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR = 1000470000,
296+
VK_FORMAT_A8_UNORM_KHR = 1000470001,
295297
VK_FORMAT_MAX_ENUM = 0x7FFFFFFF
296298
} VkFormat;
297299

lib/vkformat_str.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,10 @@ vkFormatString(VkFormat format)
565565
return "VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT";
566566
case VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT:
567567
return "VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT";
568+
case VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR:
569+
return "VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR";
570+
case VK_FORMAT_A8_UNORM_KHR:
571+
return "VK_FORMAT_A8_UNORM_KHR";
568572
default:
569573
return "VK_UNKNOWN_FORMAT";
570574
}
@@ -1152,5 +1156,9 @@ stringToVkFormat(const char* str)
11521156
return VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT;
11531157
if (ktx_strcasecmp(str, "A4B4G4R4_UNORM_PACK16_EXT") == 0)
11541158
return VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT;
1159+
if (ktx_strcasecmp(str, "A1B5G5R5_UNORM_PACK16_KHR") == 0)
1160+
return VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR;
1161+
if (ktx_strcasecmp(str, "A8_UNORM_KHR") == 0)
1162+
return VK_FORMAT_A8_UNORM_KHR;
11551163
return VK_FORMAT_UNDEFINED;
11561164
}

0 commit comments

Comments
 (0)