Skip to content

Commit 1df97b9

Browse files
authored
Fix recreateBytesPlane0 and add test (KhronosGroup#856)
of correct result for all valid VkFormats. Modify mkvkformatfiles to generate the list of valid format names to populate the table that drives the new test. Fix dfdutils Doxygen config file to include queries.c in the input.
1 parent b464992 commit 1df97b9

10 files changed

Lines changed: 1526 additions & 41 deletions

File tree

cmake/mkvk.cmake

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ if (NOT IOS AND NOT ANDROID)
2222
# # I haven't investigated why.
2323
# find_package(Vulkan REQUIRED)
2424

25-
# This file is included from so has the same scope as the including file.
26-
# If we change Vulkan_INCLUDE_DIR, other users will be effected.
25+
# This file is included from its parent so has the same scope as the
26+
# including file. If we change Vulkan_INCLUDE_DIR, other users will
27+
# be affected.
2728
set(mkvk_vulkan_include_dir lib/dfdutils)
2829
else()
2930
# Skip mkvk. There is no need to use iOS or Android to regenerate
@@ -59,6 +60,7 @@ list(APPEND mkvkformatfiles_output
5960
"${PROJECT_SOURCE_DIR}/lib/vkformat_enum.h"
6061
"${PROJECT_SOURCE_DIR}/lib/vkformat_typesize.c"
6162
"${PROJECT_SOURCE_DIR}/lib/vkformat_check.c"
63+
"${PROJECT_SOURCE_DIR}/lib/vkformat_list.c"
6264
"${PROJECT_SOURCE_DIR}/lib/vkformat_str.c")
6365

6466
# CAUTION: When a COMMAND contains VAR="Value" CMake messes up the escaping

lib/dfdutils/dfd.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,12 @@ getDFDComponentInfoUnpacked(const uint32_t* DFD, uint32_t* numComponents,
198198
/* Return the number of components described by a DFD. */
199199
uint32_t getDFDNumComponents(const uint32_t* DFD);
200200

201-
/* Recreate and return the value of bytesPlane0 as it should be for the data
201+
/* Reconstruct and return the value of bytesPlane0 as it should be for the data
202202
* post-inflation from variable-rate compression.
203203
*/
204+
uint32_t
205+
reconstructDFDBytesPlane0FromSamples(const uint32_t* DFD);
206+
/* Deprecated. For backward compatibility. */
204207
void
205208
recreateBytesPlane0FromSampleInfo(const uint32_t* DFD, uint32_t* bytesPlane0);
206209

lib/dfdutils/dfdutils.doxy

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,7 @@ INPUT = LICENSE.adoc \
943943
dfd2vk.c \
944944
interpretdfd.c \
945945
printdfd.c \
946+
queries.c \
946947
vk2dfd.c
947948

948949
# This tag can be used to specify the character encoding of the source files

lib/dfdutils/queries.c

Lines changed: 67 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,15 @@ getDFDComponentInfoUnpacked(const uint32_t* DFD, uint32_t* numComponents,
4141
{
4242
const uint32_t *BDFDB = DFD+1;
4343
uint32_t numSamples = KHR_DFDSAMPLECOUNT(BDFDB);
44-
uint32_t sampleCounter;
44+
uint32_t sampleNumber;
4545
uint32_t currentChannel = ~0U; /* Don't start matched. */
4646

4747
/* This is specifically for unpacked formats which means the size of */
4848
/* each component is the same. */
4949
*numComponents = 0;
50-
for (sampleCounter = 0; sampleCounter < numSamples; ++sampleCounter) {
51-
uint32_t sampleByteLength = (KHR_DFDSVAL(BDFDB, sampleCounter, BITLENGTH) + 1) >> 3U;
52-
uint32_t sampleChannel = KHR_DFDSVAL(BDFDB, sampleCounter, CHANNELID);
50+
for (sampleNumber = 0; sampleNumber < numSamples; ++sampleNumber) {
51+
uint32_t sampleByteLength = (KHR_DFDSVAL(BDFDB, sampleNumber, BITLENGTH) + 1) >> 3U;
52+
uint32_t sampleChannel = KHR_DFDSVAL(BDFDB, sampleNumber, CHANNELID);
5353

5454
if (sampleChannel == currentChannel) {
5555
/* Continuation of the same channel. */
@@ -85,10 +85,10 @@ uint32_t getDFDNumComponents(const uint32_t* DFD)
8585
uint32_t currentChannel = ~0U; /* Don't start matched. */
8686
uint32_t numComponents = 0;
8787
uint32_t numSamples = KHR_DFDSAMPLECOUNT(BDFDB);
88-
uint32_t sampleCounter;
88+
uint32_t sampleNumber;
8989

90-
for (sampleCounter = 0; sampleCounter < numSamples; ++sampleCounter) {
91-
uint32_t sampleChannel = KHR_DFDSVAL(BDFDB, sampleCounter, CHANNELID);
90+
for (sampleNumber = 0; sampleNumber < numSamples; ++sampleNumber) {
91+
uint32_t sampleChannel = KHR_DFDSVAL(BDFDB, sampleNumber, CHANNELID);
9292
if (sampleChannel != currentChannel) {
9393
numComponents++;
9494
currentChannel = sampleChannel;
@@ -97,50 +97,83 @@ uint32_t getDFDNumComponents(const uint32_t* DFD)
9797
return numComponents;
9898
}
9999

100+
100101
/**
101102
* @~English
102-
* @brief Recreate the value of bytesPlane0 from sample info.
103+
* @brief Reconstruct the value of bytesPlane0 from sample info.
103104
*
104-
* This can be use to recreate the value of bytesPlane0 for data that
105-
* has been variable-rate compressed so has bytesPlane0 = 0. For DFDs
106-
* that are valid for KTX files. Little-endian data only and no multi-plane
107-
* formats.
105+
* Reconstruct the value for data that has been variable-rate compressed so
106+
* has bytesPlane0 = 0. For DFDs that are valid for KTX files. Little-endian
107+
* data only and no multi-plane formats.
108108
*
109109
* @param DFD Pointer to a Data Format Descriptor for which,
110110
* described as 32-bit words in native endianness.
111111
* Note that this is the whole descriptor, not just
112112
* the basic descriptor block.
113-
* @param bytesPlane0 pointer to a 32-bit word in which the recreated
114-
* value of bytesPlane0 will be written.
115113
*/
116-
void
117-
recreateBytesPlane0FromSampleInfo(const uint32_t* DFD, uint32_t* bytesPlane0)
114+
uint32_t
115+
reconstructDFDBytesPlane0FromSamples(const uint32_t* DFD)
118116
{
119117
const uint32_t *BDFDB = DFD+1;
120118
uint32_t numSamples = KHR_DFDSAMPLECOUNT(BDFDB);
121-
uint32_t sampleCounter;
119+
uint32_t sampleNumber;
122120

123121
uint32_t bitsPlane0 = 0;
124-
uint32_t* bitOffsets = malloc(sizeof(uint32_t) * numSamples);
125-
memset(bitOffsets, -1, sizeof(uint32_t) * numSamples);
126-
for (sampleCounter = 0; sampleCounter < numSamples; ++sampleCounter) {
127-
uint32_t sampleBitOffset = KHR_DFDSVAL(BDFDB, sampleCounter, BITOFFSET);
128-
/* The sample bitLength field stores the bit length - 1. */
129-
uint32_t sampleBitLength = KHR_DFDSVAL(BDFDB, sampleCounter, BITLENGTH) + 1;
130-
uint32_t i;
131-
for (i = 0; i < numSamples; i++) {
132-
if (sampleBitOffset == bitOffsets[i]) {
133-
// This sample is being repeated as in e.g. RGB9E5.
134-
break;
122+
int32_t largestOffset = 0;
123+
uint32_t sampleNumberWithLargestOffset = 0;
124+
125+
// Special case these depth{,-stencil} formats. The unused bits are
126+
// in the MSBs so have no visibility in the DFD therefore the max offset
127+
// algorithm below returns a value that is too small.
128+
if (KHR_DFDSVAL(BDFDB, 0, CHANNELID) == KHR_DF_CHANNEL_COMMON_DEPTH) {
129+
if (numSamples == 1) {
130+
if (KHR_DFDSVAL(BDFDB, 0, BITLENGTH) + 1 == 24) {
131+
// X8_D24_UNORM_PACK32,
132+
return 4;
133+
}
134+
} else if (numSamples == 2) {
135+
if (KHR_DFDSVAL(BDFDB, 0, BITLENGTH) + 1 == 16) {
136+
// D16_UNORM_S8_UINT
137+
return 4;
138+
}
139+
if (KHR_DFDSVAL(BDFDB, 0, BITLENGTH) + 1 == 32
140+
&& KHR_DFDSVAL(BDFDB, 1, CHANNELID) == KHR_DF_CHANNEL_COMMON_STENCIL) {
141+
// D32_SFLOAT_S8_UINT
142+
return 8;
135143
}
136144
}
137-
if (i == numSamples) {
138-
// Previously unseen bitOffset. Bump size.
139-
bitsPlane0 += sampleBitLength;
140-
bitOffsets[sampleCounter] = sampleBitOffset;
145+
}
146+
for (sampleNumber = 0; sampleNumber < numSamples; ++sampleNumber) {
147+
int32_t sampleBitOffset = KHR_DFDSVAL(BDFDB, sampleNumber, BITOFFSET);
148+
if (sampleBitOffset > largestOffset) {
149+
largestOffset = sampleBitOffset;
150+
sampleNumberWithLargestOffset = sampleNumber;
141151
}
142152
}
143-
free(bitOffsets);
144-
*bytesPlane0 = bitsPlane0 >> 3U;
153+
154+
/* The sample bitLength field stores the bit length - 1. */
155+
uint32_t sampleBitLength = KHR_DFDSVAL(BDFDB, sampleNumberWithLargestOffset, BITLENGTH) + 1;
156+
bitsPlane0 = largestOffset + sampleBitLength;
157+
return bitsPlane0 >> 3U;
145158
}
146159

160+
/**
161+
* @~English
162+
* @brief Reconstruct the value of bytesPlane0 from sample info.
163+
*
164+
* @see reconstructDFDBytesPlane0FromSamples for details.
165+
* @deprecated For backward comparibility only. Use
166+
* reconstructDFDBytesPlane0FromSamples.
167+
*
168+
* @param DFD Pointer to a Data Format Descriptor for which,
169+
* described as 32-bit words in native endianness.
170+
* Note that this is the whole descriptor, not just
171+
* the basic descriptor block.
172+
* @param bytesPlane0 pointer to a 32-bit word in which the recreated
173+
* value of bytesPlane0 will be written.
174+
*/
175+
void
176+
recreateBytesPlane0FromSampleInfo(const uint32_t* DFD, uint32_t* bytesPlane0)
177+
{
178+
*bytesPlane0 = reconstructDFDBytesPlane0FromSamples(DFD);
179+
}

lib/internalexport.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ EXPORTS
4343
ktxTexture2_GetImageOffset
4444
ktxTexture2_calcLevelOffset
4545
ktxTexture2_destruct
46+
reconstructDFDBytesPlane0FromSamples
4647
vk2dfd
4748
vkFormatString
4849
vkFormatTypeSize

lib/internalexport_mingw.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ EXPORTS
4343
ktxTexture2_GetImageOffset
4444
ktxTexture2_calcLevelOffset
4545
ktxTexture2_destruct
46+
reconstructDFDBytesPlane0FromSamples
4647
vk2dfd
4748
vkFormatString
4849
vkFormatTypeSize

lib/mkvkformatfiles

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,16 @@
22
# Copyright 2019-2024 Mark Callow
33
# SPDX-License-Identifier: Apache-2.0
44

5-
# This script creates 3 files from vulkan/vulkan_core.h:
5+
# This script creates 5 files from vulkan/vulkan_core.h:
66
#
77
# - vkformat_enum.h, the VkFormat enum declaration for those who don't
88
# want to include vulkan_core.h.
9+
# - vkformat_list.inl, a list of VkFormat enum names for use in
10+
# initializing tables, etc.
911
# - vkformat_str.c, a switch statement for converting VkFormat enums to
1012
# to strings corresponding to the format names.
13+
# - vkformat_typesize.c, function to return the type-size for each
14+
# format.
1115
# - vkformat_check.c, 2 functions: 1 to checking if a format is prohibited in
1216
# KTX2 and the other to see if a format is valid.
1317
# KTX2.
@@ -24,6 +28,7 @@ BEGIN {
2428
copyright = "/*" ORS
2529
banner = ""
2630
format_decl = ""
31+
format_name_list = ""
2732
core_formats = ""
2833
extension_formats = ""
2934
end_range = ""
@@ -41,6 +46,7 @@ BEGIN {
4146
}
4247
format_hdr = output_dir "vkformat_enum.h"
4348
format_typesize = output_dir "vkformat_typesize.c"
49+
format_inl = output_dir "vkformat_list.inl"
4450
format_strings = output_dir "vkformat_str.c"
4551
format_check = output_dir "vkformat_check.c"
4652
if (ENVIRON["Vulkan_INCLUDE_DIR"]) {
@@ -83,6 +89,9 @@ $2 == "VK_HEADER_VERSION" {
8389
if (enum_val+0 > max_std_format_enum) {
8490
max_std_format_enum = enum_val+0;
8591
}
92+
if ($1 !~ /UNDEFINED/) {
93+
format_name_list = format_name_list $1 "," ORS
94+
}
8695
}
8796
}
8897
if ($1 ~ /}/) {
@@ -103,6 +112,7 @@ $2 == "VK_HEADER_VERSION" {
103112
# Extract valid formats with values > VK_FORMAT_END_RANGE.
104113
/VK_FORMAT_[^F].* = 1000/ && ! /PLANE/ && !/420/ {
105114
valid = valid " case " $1 ":" ORS;
115+
format_name_list = format_name_list $1 "," ORS
106116
}
107117

108118
function removePrefix(string, prefix) {
@@ -170,6 +180,7 @@ function write_source_file(body, filename) {
170180
END {
171181
# vkformat_enum.h
172182
write_header_file("_VKFORMAT_ENUM_H_", "VULKAN_CORE_H_", format_decl ORS end_range, format_hdr);
183+
write_source_file(format_name_list ORS, format_inl)
173184

174185
# vkformat_typesize.c
175186
begin_vktypesize = ORS

0 commit comments

Comments
 (0)