Skip to content

Commit

Permalink
Fix handling of combined depth-stencil textures (KhronosGroup#575)
Browse files Browse the repository at this point in the history
Fix required alignment calculations in accordance with the spec. change in
KhronosGroup/KTX-Specification#180.

Remove creation of DFDs for these from dfdutils' vk2dfd as the layouts
defined there are never seen outside Vulkan. Create their dfds, with the
texel block sizes specified by KTX, within the KTX library and tools.

Fix createDFDDepthStencil to set the primaries to UNSPECIFIED for depth, stencil
and depth-stencil formats.

Make vk2dfd.inl visible in project.
  • Loading branch information
MarkCallow authored May 22, 2022
1 parent ad40cf7 commit ef2d574
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 46 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -179,11 +179,11 @@ set(KTX_MAIN_SRC
lib/dfdutils/createdfd.c
lib/dfdutils/colourspaces.c
lib/dfdutils/dfd.h
lib/dfdutils/dfd2vk.inl
lib/dfdutils/interpretdfd.c
lib/dfdutils/printdfd.c
lib/dfdutils/queries.c
lib/dfdutils/vk2dfd.c
lib/dfdutils/vk2dfd.inl
lib/dfdutils/vulkan/vk_platform.h
lib/dfdutils/vulkan/vulkan_core.h
lib/etcdec.cxx
Expand Down
23 changes: 15 additions & 8 deletions lib/dfdutils/createdfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@

#include "dfd.h"

static uint32_t *writeHeader(int numSamples, int bytes, int suffix)
typedef enum { i_COLOR, i_NON_COLOR } channels_infotype;

static uint32_t *writeHeader(int numSamples, int bytes, int suffix,
channels_infotype infotype)
{
uint32_t *DFD = (uint32_t *) malloc(sizeof(uint32_t) *
(1 + KHR_DF_WORD_SAMPLESTART +
Expand All @@ -40,8 +43,12 @@ static uint32_t *writeHeader(int numSamples, int bytes, int suffix)
<< KHR_DF_SHIFT_DESCRIPTORBLOCKSIZE));
BDFD[KHR_DF_WORD_MODEL] =
((KHR_DF_MODEL_RGBSDA << KHR_DF_SHIFT_MODEL) | /* Only supported model */
(KHR_DF_PRIMARIES_BT709 << KHR_DF_SHIFT_PRIMARIES) | /* Assumed */
(KHR_DF_FLAG_ALPHA_STRAIGHT << KHR_DF_SHIFT_FLAGS));
if (infotype == i_COLOR) {
BDFD[KHR_DF_WORD_PRIMARIES] |= KHR_DF_PRIMARIES_BT709 << KHR_DF_SHIFT_PRIMARIES; /* Assumed */
} else {
BDFD[KHR_DF_WORD_PRIMARIES] |= KHR_DF_PRIMARIES_UNSPECIFIED << KHR_DF_SHIFT_PRIMARIES;
}
if (suffix == s_SRGB) {
BDFD[KHR_DF_WORD_TRANSFER] |= KHR_DF_TRANSFER_SRGB << KHR_DF_SHIFT_TRANSFER;
} else {
Expand Down Expand Up @@ -178,7 +185,7 @@ uint32_t *createDFDUnpacked(int bigEndian, int numChannels, int bytes,
if (bigEndian) {
int channelCounter, channelByte;
/* Number of samples = number of channels * bytes per channel */
DFD = writeHeader(numChannels * bytes, numChannels * bytes, suffix);
DFD = writeHeader(numChannels * bytes, numChannels * bytes, suffix, i_COLOR);
/* First loop over the channels */
for (channelCounter = 0; channelCounter < numChannels; ++channelCounter) {
int channel = channelCounter;
Expand All @@ -197,7 +204,7 @@ uint32_t *createDFDUnpacked(int bigEndian, int numChannels, int bytes,

int sampleCounter;
/* One sample per channel */
DFD = writeHeader(numChannels, numChannels * bytes, suffix);
DFD = writeHeader(numChannels, numChannels * bytes, suffix, i_COLOR);
for (sampleCounter = 0; sampleCounter < numChannels; ++sampleCounter) {
int channel = sampleCounter;
if (redBlueSwap && (channel == 0 || channel == 2)) {
Expand Down Expand Up @@ -239,7 +246,7 @@ uint32_t *createDFDPacked(int bigEndian, int numChannels,
uint32_t *DFD = 0;
if (numChannels == 6) {
/* Special case E5B9G9R9 */
DFD = writeHeader(numChannels, 4, s_UFLOAT);
DFD = writeHeader(numChannels, 4, s_UFLOAT, i_COLOR);
writeSample(DFD, 0, 0,
9, 0,
1, 1, s_UNORM);
Expand Down Expand Up @@ -292,7 +299,7 @@ uint32_t *createDFDPacked(int bigEndian, int numChannels,
}
bitOffset += bits[channelCounter];
}
DFD = writeHeader(numSamples, totalBits >> 3, suffix);
DFD = writeHeader(numSamples, totalBits >> 3, suffix, i_COLOR);

sampleCounter = 0;
for (bitOffset = 0; bitOffset < totalBits;) {
Expand Down Expand Up @@ -336,7 +343,7 @@ uint32_t *createDFDPacked(int bigEndian, int numChannels,
}

/* One sample per channel */
DFD = writeHeader(numChannels, totalBits >> 3, suffix);
DFD = writeHeader(numChannels, totalBits >> 3, suffix, i_COLOR);
for (sampleCounter = 0; sampleCounter < numChannels; ++sampleCounter) {
writeSample(DFD, sampleCounter, channels[sampleCounter],
bits[sampleCounter], bitOffset,
Expand Down Expand Up @@ -627,7 +634,7 @@ uint32_t *createDFDDepthStencil(int depthBits,
/* N.B. Little-endian is assumed. */
uint32_t *DFD = 0;
DFD = writeHeader((depthBits > 0) + (stencilBits > 0),
sizeBytes, s_UNORM);
sizeBytes, s_UNORM, i_NON_COLOR);
if (depthBits == 32) {
writeSample(DFD, 0, KHR_DF_CHANNEL_RGBSDA_DEPTH,
32, 0,
Expand Down
32 changes: 4 additions & 28 deletions lib/dfdutils/makevk2dfd.pl
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@
print "/* SPDX-", "License-Identifier: Apache-2.0 */\n\n";
print "/***************************** Do not edit. *****************************\n";
print " Automatically generated by makevk2dfd.pl.\n";
print " *************************************************************************/\n";
print " *************************************************************************/\n\n";
print "/* Vulkan combined depth & stencil formats are not included here\n";
print " * because they do not exist outside a Vulkan device.\n";
print " */\n";

# Loop over each line of input
while ($line = <>) {
Expand Down Expand Up @@ -282,15 +285,6 @@
$foundFormats{$format} = 1;
print "case $format: return createDFDDepthStencil(24,0,4);\n";
}
} elsif ($line =~ m/(VK_FORMAT_D32_SFLOAT_S8_UINT)/) {

# Extract the format identifier from the rest of the line
$format = $1;
if (!exists($foundFormats{$format})) {
# Add the format we've processed to our "done" hash
$foundFormats{$format} = 1;
print "case $format: return createDFDDepthStencil(32,8,5);\n";
}
} elsif ($line =~ m/(VK_FORMAT_D32_SFLOAT)/) {

# Extract the format identifier from the rest of the line
Expand All @@ -309,15 +303,6 @@
$foundFormats{$format} = 1;
print "case $format: return createDFDDepthStencil(0,8,1);\n";
}
} elsif ($line =~ m/(VK_FORMAT_D16_UNORM_S8_UINT)/) {

# Extract the format identifier from the rest of the line
$format = $1;
if (!exists($foundFormats{$format})) {
# Add the format we've processed to our "done" hash
$foundFormats{$format} = 1;
print "case $format: return createDFDDepthStencil(16,8,3);\n";
}
} elsif ($line =~ m/(VK_FORMAT_D16_UNORM)/) {

# Extract the format identifier from the rest of the line
Expand All @@ -327,15 +312,6 @@
$foundFormats{$format} = 1;
print "case $format: return createDFDDepthStencil(16,0,2);\n";
}
} elsif ($line =~ m/(VK_FORMAT_D24_UNORM_S8_UINT)/) {

# Extract the format identifier from the rest of the line
$format = $1;
if (!exists($foundFormats{$format})) {
# Add the format we've processed to our "done" hash
$foundFormats{$format} = 1;
print "case $format: return createDFDDepthStencil(24,8,4);\n";
}
}

# ...and continue to the next line
Expand Down
7 changes: 4 additions & 3 deletions lib/dfdutils/vk2dfd.inl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
/***************************** Do not edit. *****************************
Automatically generated by makevk2dfd.pl.
*************************************************************************/

/* Vulkan combined depth & stencil formats are not included here
* because they do not exist outside a Vulkan device.
*/
case VK_FORMAT_R4G4_UNORM_PACK8: {
int channels[] = {1,0}; int bits[] = {4,4};
return createDFDPacked(0, 2, bits, channels, s_UNORM);
Expand Down Expand Up @@ -218,9 +222,6 @@ case VK_FORMAT_D16_UNORM: return createDFDDepthStencil(16,0,2);
case VK_FORMAT_X8_D24_UNORM_PACK32: return createDFDDepthStencil(24,0,4);
case VK_FORMAT_D32_SFLOAT: return createDFDDepthStencil(32,0,4);
case VK_FORMAT_S8_UINT: return createDFDDepthStencil(0,8,1);
case VK_FORMAT_D16_UNORM_S8_UINT: return createDFDDepthStencil(16,8,3);
case VK_FORMAT_D24_UNORM_S8_UINT: return createDFDDepthStencil(24,8,4);
case VK_FORMAT_D32_SFLOAT_S8_UINT: return createDFDDepthStencil(32,8,5);
case VK_FORMAT_BC1_RGB_UNORM_BLOCK: return createDFDCompressed(c_BC1_RGB, 4, 4, 1, s_UNORM);
case VK_FORMAT_BC1_RGB_SRGB_BLOCK: return createDFDCompressed(c_BC1_RGB, 4, 4, 1, s_SRGB);
case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: return createDFDCompressed(c_BC1_RGBA, 4, 4, 1, s_UNORM);
Expand Down
3 changes: 2 additions & 1 deletion lib/internalexport.def
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ EXPORTS
?get_image_level_info@basisu_transcoder@basist@@QEBA_NPEBXIAEAUbasisu_image_level_info@2@II@Z
?start_transcoding@basisu_transcoder@basist@@QEAA_NPEBXI@Z
?transcode_image_level@basisu_transcoder@basist@@QEBA_NPEBXIIIPEAXIW4transcoder_texture_format@2@IIPEAUbasisu_transcoder_state@2@I@Z
createDFDCompressed
createDFDDepthStencil
createDFDUnpacked
createDFDPacked
createDFDCompressed
findMapping
interpretDFD
isProhibitedFormat
Expand Down
3 changes: 2 additions & 1 deletion lib/internalexport_mingw.def
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ EXPORTS
_ZNK6basist17basisu_transcoder20get_image_level_infoEPKvjRNS_23basisu_image_level_infoEjj
_ZN6basist17basisu_transcoder17start_transcodingEPKvj
_ZNK6basist17basisu_transcoder21transcode_image_levelEPKvjjjPvjNS_25transcoder_texture_formatEjjPNS_23basisu_transcoder_stateEj
createDFDCompressed
createDFDDepthStencil
createDFDUnpacked
createDFDPacked
createDFDCompressed
findMapping
interpretDFD
isProhibitedFormat
Expand Down
38 changes: 34 additions & 4 deletions lib/texture2.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,37 @@ ktxFormatSize_initFromDfd(ktxFormatSize* This, ktx_uint32_t* pDfd)
return true;
}

/**
* @private
* @~English
* @brief Create a DFD for a VkFormat.
*
* This KTX-specific function adds support for combined depth stencil formats
* which are not supported by @e dfdutils' @c vk2dfd function because they
* are not seen outside a Vulkan device. KTX has its own definitions for
* these that enable uploading, with some effort.
*
* @param[in] vkFormat the format for which to create a DFD.
*/
static uint32_t*
ktxVk2dfd(ktx_uint32_t vkFormat)
{
switch(vkFormat) {
case VK_FORMAT_D16_UNORM_S8_UINT:
// 2 16-bit words. D16 in the first. S8 in the 8 LSBs of the second.
return createDFDDepthStencil(16, 8, 4);
case VK_FORMAT_D24_UNORM_S8_UINT:
// 1 32-bit word. D24 in the MSBs. S8 in the LSBs.
return createDFDDepthStencil(24, 8, 4);
case VK_FORMAT_D32_SFLOAT_S8_UINT:
// 2 32-bit words. D32 float in the first word. S8 in LSBs of the
// second.
return createDFDDepthStencil(32, 8, 8);
default:
return vk2dfd(vkFormat);
}
}

/**
* @memberof ktxTexture2 @private
* @~English
Expand Down Expand Up @@ -370,9 +401,10 @@ ktxTexture2_construct(ktxTexture2* This, ktxTextureCreateInfo* createInfo,
memset(This, 0, sizeof(*This));

if (createInfo->vkFormat != VK_FORMAT_UNDEFINED) {
This->pDfd = vk2dfd(createInfo->vkFormat);
This->pDfd = ktxVk2dfd(createInfo->vkFormat);
if (!This->pDfd)
return KTX_INVALID_VALUE; // Format is unknown or unsupported.

#ifdef _DEBUG
// If this fires, an unsupported format or incorrect DFD
// has crept into vk2dfd.
Expand Down Expand Up @@ -1528,10 +1560,8 @@ lcm4(uint32_t a)
ktx_uint32_t alignment;
if (This->supercompressionScheme != KTX_SS_NONE)
alignment = 1;
else if (This->vkFormat != VK_FORMAT_UNDEFINED)
alignment = lcm4(This->_protected->_formatSize.blockSizeInBits / 8);
else
alignment = 16;
alignment = lcm4(This->_protected->_formatSize.blockSizeInBits / 8);
return alignment;
}

Expand Down

0 comments on commit ef2d574

Please sign in to comment.