diff --git a/CMakeLists.txt b/CMakeLists.txt index 3ba2edc2a9..430cee458f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -359,7 +359,7 @@ elseif(APPLE) # Set a common RUNTIME_OUTPUT_DIR for all targets, so that # INSTALL RPATH is functional in build directory as well. # BUILD_WITH_INSTALL_RPATH is necessary for working code signing. - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${KTX_BUILD_DIR}/$) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY $<1:${KTX_BUILD_DIR}/$>) endif() endif() diff --git a/lib/dfdutils/createdfd.c b/lib/dfdutils/createdfd.c index ea00d8d745..6eef281613 100644 --- a/lib/dfdutils/createdfd.c +++ b/lib/dfdutils/createdfd.c @@ -15,7 +15,9 @@ * Author: Andrew Garrard */ +#include #include +#include #include #include "dfd.h" @@ -228,6 +230,8 @@ uint32_t *createDFDUnpacked(int bigEndian, int numChannels, int bytes, * @param bits[] An array of length numChannels. * Each entry is the number of bits composing the channel, in * order starting at bit 0 of the packed type. + * @param paddings[] An array of length numChannels. + * Each entry is the number of padding bits after each channel. * @param channels[] An array of length numChannels. * Each entry enumerates the channel type: 0 = red, 1 = green, * 2 = blue, 15 = alpha, in order starting at bit 0 of the @@ -239,9 +243,9 @@ uint32_t *createDFDUnpacked(int bigEndian, int numChannels, int bytes, * @return A data format descriptor in malloc'd data. The caller is responsible * for freeing the descriptor. **/ -uint32_t *createDFDPacked(int bigEndian, int numChannels, - int bits[], int channels[], - enum VkSuffix suffix) +uint32_t *createDFDPackedPadded(int bigEndian, int numChannels, + int bits[], int paddings[], int channels[], + enum VkSuffix suffix) { uint32_t *DFD = 0; if (numChannels == 6) { @@ -287,7 +291,7 @@ uint32_t *createDFDPacked(int bigEndian, int numChannels, int sampleCounter; for (channelCounter = 0; channelCounter < numChannels; ++channelCounter) { beChannelStart[channelCounter] = totalBits; - totalBits += bits[channelCounter]; + totalBits += bits[channelCounter] + paddings[channelCounter]; } BEMask = (totalBits - 1) & 0x18; for (channelCounter = 0; channelCounter < numChannels; ++channelCounter) { @@ -297,7 +301,7 @@ uint32_t *createDFDPacked(int bigEndian, int numChannels, bitChannel[((bitOffset + bits[channelCounter] - 1) & ~7) ^ BEMask] = channelCounter; numSamples++; } - bitOffset += bits[channelCounter]; + bitOffset += bits[channelCounter] + paddings[channelCounter]; } DFD = writeHeader(numSamples, totalBits >> 3, suffix, i_COLOR); @@ -339,7 +343,7 @@ uint32_t *createDFDPacked(int bigEndian, int numChannels, int totalBits = 0; int bitOffset = 0; for (sampleCounter = 0; sampleCounter < numChannels; ++sampleCounter) { - totalBits += bits[sampleCounter]; + totalBits += bits[sampleCounter] + paddings[sampleCounter]; } /* One sample per channel */ @@ -348,12 +352,98 @@ uint32_t *createDFDPacked(int bigEndian, int numChannels, writeSample(DFD, sampleCounter, channels[sampleCounter], bits[sampleCounter], bitOffset, 1, 1, suffix); - bitOffset += bits[sampleCounter]; + bitOffset += bits[sampleCounter] + paddings[sampleCounter]; } } return DFD; } +/** + * @~English + * @brief Create a Data Format Descriptor for a packed format. + * + * @param bigEndian Big-endian flag: Set to 1 for big-endian byte ordering and + * 0 for little-endian byte ordering. + * @param numChannels The number of color channels. + * @param bits[] An array of length numChannels. + * Each entry is the number of bits composing the channel, in + * order starting at bit 0 of the packed type. + * @param channels[] An array of length numChannels. + * Each entry enumerates the channel type: 0 = red, 1 = green, + * 2 = blue, 15 = alpha, in order starting at bit 0 of the + * packed type. These values match channel IDs for RGBSDA in + * the Khronos Data Format header. To simplify iteration + * through channels, channel id 3 is a synonym for alpha. + * @param suffix Indicates the format suffix for the type. + * + * @return A data format descriptor in malloc'd data. The caller is responsible + * for freeing the descriptor. + **/ +uint32_t *createDFDPacked(int bigEndian, int numChannels, + int bits[], int channels[], + enum VkSuffix suffix) { + assert(numChannels <= 6); + int paddings[] = {0, 0, 0, 0, 0, 0}; + return createDFDPackedPadded(bigEndian, numChannels, bits, paddings, channels, suffix); +} + +uint32_t *createDFD422(int bigEndian, int numSamples, + int bits[], int paddings[], int channels[], + int position_xs[], int position_ys[], + enum VkSuffix suffix) { + assert(!bigEndian); (void) bigEndian; + assert(suffix == s_UNORM); (void) suffix; + + int totalBits = 0; + for (int i = 0; i < numSamples; ++i) + totalBits += bits[i] + paddings[i]; + assert(totalBits % 8 == 0); + + uint32_t BDFDSize = sizeof(uint32_t) * (KHR_DF_WORD_SAMPLESTART + numSamples * KHR_DF_WORD_SAMPLEWORDS); + uint32_t DFDSize = sizeof(uint32_t) + BDFDSize; + uint32_t *DFD = (uint32_t *) malloc(DFDSize); + memset(DFD, 0, DFDSize); + DFD[0] = DFDSize; + uint32_t *BDFD = DFD + 1; + KHR_DFDSETVAL(BDFD, VENDORID, KHR_DF_VENDORID_KHRONOS); + KHR_DFDSETVAL(BDFD, DESCRIPTORTYPE, KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT); + KHR_DFDSETVAL(BDFD, VERSIONNUMBER, KHR_DF_VERSIONNUMBER_LATEST); + KHR_DFDSETVAL(BDFD, DESCRIPTORBLOCKSIZE, BDFDSize); + KHR_DFDSETVAL(BDFD, MODEL, KHR_DF_MODEL_YUVSDA); + KHR_DFDSETVAL(BDFD, PRIMARIES, KHR_DF_PRIMARIES_UNSPECIFIED); + KHR_DFDSETVAL(BDFD, TRANSFER, KHR_DF_TRANSFER_LINEAR); + KHR_DFDSETVAL(BDFD, FLAGS, KHR_DF_FLAG_ALPHA_STRAIGHT); + KHR_DFDSETVAL(BDFD, TEXELBLOCKDIMENSION0, 2 - 1); // 422 contains 2 x 1 blocks + KHR_DFDSETVAL(BDFD, TEXELBLOCKDIMENSION1, 1 - 1); + KHR_DFDSETVAL(BDFD, TEXELBLOCKDIMENSION2, 1 - 1); + KHR_DFDSETVAL(BDFD, TEXELBLOCKDIMENSION3, 1 - 1); + KHR_DFDSETVAL(BDFD, BYTESPLANE0, totalBits / 8); + KHR_DFDSETVAL(BDFD, BYTESPLANE1, 0); + KHR_DFDSETVAL(BDFD, BYTESPLANE2, 0); + KHR_DFDSETVAL(BDFD, BYTESPLANE3, 0); + KHR_DFDSETVAL(BDFD, BYTESPLANE4, 0); + KHR_DFDSETVAL(BDFD, BYTESPLANE5, 0); + KHR_DFDSETVAL(BDFD, BYTESPLANE6, 0); + KHR_DFDSETVAL(BDFD, BYTESPLANE7, 0); + + int bitOffset = 0; + for (int i = 0; i < numSamples; ++i) { + KHR_DFDSETSVAL(BDFD, i, BITOFFSET, bitOffset); + KHR_DFDSETSVAL(BDFD, i, BITLENGTH, bits[i] - 1); + KHR_DFDSETSVAL(BDFD, i, CHANNELID, channels[i]); + KHR_DFDSETSVAL(BDFD, i, QUALIFIERS, 0); // None of: FLOAT, SIGNED, EXPONENT, LINEAR + KHR_DFDSETSVAL(BDFD, i, SAMPLEPOSITION0, position_xs[i]); + KHR_DFDSETSVAL(BDFD, i, SAMPLEPOSITION1, position_ys[i]); + KHR_DFDSETSVAL(BDFD, i, SAMPLEPOSITION2, 0); + KHR_DFDSETSVAL(BDFD, i, SAMPLEPOSITION3, 0); + KHR_DFDSETSVAL(BDFD, i, SAMPLELOWER, 0); + KHR_DFDSETSVAL(BDFD, i, SAMPLEUPPER, (1u << bits[i]) - 1u); + bitOffset += bits[i] + paddings[i]; + } + + return DFD; +} + static khr_df_model_e compModelMapping[] = { KHR_DF_MODEL_BC1A, /*!< BC1, aka DXT1, no alpha. */ KHR_DF_MODEL_BC1A, /*!< BC1, aka DXT1, punch-through alpha. */ diff --git a/lib/dfdutils/dfd.h b/lib/dfdutils/dfd.h index 5ddf387adc..41c81a41f0 100644 --- a/lib/dfdutils/dfd.h +++ b/lib/dfdutils/dfd.h @@ -73,11 +73,22 @@ uint32_t* vk2dfd(enum VkFormat format); uint32_t *createDFDUnpacked(int bigEndian, int numChannels, int bytes, int redBlueSwap, enum VkSuffix suffix); +/* Create a Data Format Descriptor for a packed padded format. */ +uint32_t *createDFDPackedPadded(int bigEndian, int numChannels, + int bits[], int paddings[], int channels[], + enum VkSuffix suffix); + /* Create a Data Format Descriptor for a packed format. */ uint32_t *createDFDPacked(int bigEndian, int numChannels, int bits[], int channels[], enum VkSuffix suffix); +/* Create a Data Format Descriptor for a 4:2:2 format. */ +uint32_t *createDFD422(int bigEndian, int numChannels, + int bits[], int paddings[], int channels[], + int position_xs[], int position_ys[], + enum VkSuffix suffix); + /* Create a Data Format Descriptor for a compressed format. */ uint32_t *createDFDCompressed(enum VkCompScheme compScheme, int bwidth, int bheight, int bdepth, @@ -91,13 +102,15 @@ uint32_t *createDFDDepthStencil(int depthBits, /** @brief Result of interpreting the data format descriptor. */ enum InterpretDFDResult { i_LITTLE_ENDIAN_FORMAT_BIT = 0, /*!< Confirmed little-endian (default for 8bpc). */ - i_BIG_ENDIAN_FORMAT_BIT = 1, /*!< Confirmed big-endian. */ - i_PACKED_FORMAT_BIT = 2, /*!< Packed format. */ - i_SRGB_FORMAT_BIT = 4, /*!< sRGB transfer function. */ - i_NORMALIZED_FORMAT_BIT = 8, /*!< Normalized (UNORM or SNORM). */ - i_SIGNED_FORMAT_BIT = 16, /*!< Format is signed. */ - i_FLOAT_FORMAT_BIT = 32, /*!< Format is floating point. */ - i_UNSUPPORTED_ERROR_BIT = 64, /*!< Format not successfully interpreted. */ + i_BIG_ENDIAN_FORMAT_BIT = 1u << 0u, /*!< Confirmed big-endian. */ + i_PACKED_FORMAT_BIT = 1u << 1u, /*!< Packed format. */ + i_SRGB_FORMAT_BIT = 1u << 2u, /*!< sRGB transfer function. */ + i_NORMALIZED_FORMAT_BIT = 1u << 3u, /*!< Normalized (UNORM or SNORM). */ + i_SIGNED_FORMAT_BIT = 1u << 4u, /*!< Format is signed. */ + i_FLOAT_FORMAT_BIT = 1u << 5u, /*!< Format is floating point. */ + i_COMPRESSED_FORMAT_BIT = 1u << 6u, /*!< Format is block compressed (422). */ + i_YUVSDA_FORMAT_BIT = 1u << 7u, /*!< Color model is YUVSDA. */ + i_UNSUPPORTED_ERROR_BIT = 1u << 8u, /*!< Format not successfully interpreted. */ /** "NONTRIVIAL_ENDIANNESS" means not big-endian, not little-endian * (a channel has bits that are not consecutive in either order). **/ i_UNSUPPORTED_NONTRIVIAL_ENDIANNESS = i_UNSUPPORTED_ERROR_BIT, @@ -110,7 +123,9 @@ enum InterpretDFDResult { i_UNSUPPORTED_CHANNEL_TYPES = i_UNSUPPORTED_ERROR_BIT + 3, /** Only channels with the same flags are supported * (e.g. we don't support float red with integer green). */ - i_UNSUPPORTED_MIXED_CHANNELS = i_UNSUPPORTED_ERROR_BIT + 4 + i_UNSUPPORTED_MIXED_CHANNELS = i_UNSUPPORTED_ERROR_BIT + 4, + /** Only 2x1 block is supported for YUVSDA model. */ + i_UNSUPPORTED_BLOCK_DIMENSIONS = i_UNSUPPORTED_ERROR_BIT + 5, }; /** @brief Interpretation of a channel from the data format descriptor. */ diff --git a/lib/dfdutils/interpretdfd.c b/lib/dfdutils/interpretdfd.c index d7b6f4a655..5cdd939398 100644 --- a/lib/dfdutils/interpretdfd.c +++ b/lib/dfdutils/interpretdfd.c @@ -17,6 +17,14 @@ #include #include "dfd.h" +static uint32_t bit_ceil(uint32_t x) { + x -= 1; + for (uint32_t i = 0; i < sizeof(x) * 8; ++i) + if (1u << i > x) + return 1u << i; + return 0; +} + /** * @~English * @brief Interpret a Data Format Descriptor for a simple format. @@ -54,14 +62,15 @@ enum InterpretDFDResult interpretDFD(const uint32_t *DFD, const uint32_t *BDFDB = DFD+1; uint32_t numSamples = KHR_DFDSAMPLECOUNT(BDFDB); + if (numSamples == 0) + return i_UNSUPPORTED_CHANNEL_TYPES; uint32_t sampleCounter; int determinedEndianness = 0; - int determinedNormalizedness = 0; - int determinedSignedness = 0; - int determinedFloatness = 0; enum InterpretDFDResult result = 0; /* Build this up incrementally. */ + bool isDepthStencil = false; + /* Clear these so following code doesn't get confused. */ R->offset = R->size = 0; G->offset = G->size = 0; @@ -76,85 +85,6 @@ enum InterpretDFDResult interpretDFD(const uint32_t *DFD, if ((BDFDB[KHR_DF_WORD_BYTESPLANE0] & ~KHR_DF_MASK_BYTESPLANE0) || BDFDB[KHR_DF_WORD_BYTESPLANE4]) return i_UNSUPPORTED_MULTIPLE_PLANES; - /* Only support the RGB color model. */ - /* We could expand this to allow "UNSPECIFIED" as well. */ - if (KHR_DFDVAL(BDFDB, MODEL) != KHR_DF_MODEL_RGBSDA) return i_UNSUPPORTED_CHANNEL_TYPES; - - /* We only pay attention to sRGB. */ - if (KHR_DFDVAL(BDFDB, TRANSFER) == KHR_DF_TRANSFER_SRGB) result |= i_SRGB_FORMAT_BIT; - - /* We only support samples at coordinate 0,0,0,0. */ - /* (We could confirm this from texel_block_dimensions in 1.2, but */ - /* the interpretation might change in later versions.) */ - for (sampleCounter = 0; sampleCounter < numSamples; ++sampleCounter) { - if (KHR_DFDSVAL(BDFDB, sampleCounter, SAMPLEPOSITION_ALL)) - return i_UNSUPPORTED_MULTIPLE_SAMPLE_LOCATIONS; - } - - /* Set flags and check for consistency. */ - for (sampleCounter = 0; sampleCounter < numSamples; ++sampleCounter) { - /* Note: We're ignoring 9995, which is weird and worth special-casing */ - /* rather than trying to generalise to all float formats. */ - if (!determinedFloatness) { - if (KHR_DFDSVAL(BDFDB, sampleCounter, QUALIFIERS) - & KHR_DF_SAMPLE_DATATYPE_FLOAT) { - result |= i_FLOAT_FORMAT_BIT; - } - determinedFloatness = 1; - } else { - /* Check whether we disagree with our predetermined floatness. */ - /* Note that this could justifiably happen with (say) D24S8. */ - if (KHR_DFDSVAL(BDFDB, sampleCounter, QUALIFIERS) - & KHR_DF_SAMPLE_DATATYPE_FLOAT) { - if (!(result & i_FLOAT_FORMAT_BIT)) return i_UNSUPPORTED_MIXED_CHANNELS; - } else { - if ((result & i_FLOAT_FORMAT_BIT)) return i_UNSUPPORTED_MIXED_CHANNELS; - } - } - if (!determinedSignedness) { - if (KHR_DFDSVAL(BDFDB, sampleCounter, QUALIFIERS) - & KHR_DF_SAMPLE_DATATYPE_SIGNED) { - result |= i_SIGNED_FORMAT_BIT; - } - determinedSignedness = 1; - } else { - /* Check whether we disagree with our predetermined signedness. */ - if (KHR_DFDSVAL(BDFDB, sampleCounter, QUALIFIERS) - & KHR_DF_SAMPLE_DATATYPE_SIGNED) { - if (!(result & i_SIGNED_FORMAT_BIT)) return i_UNSUPPORTED_MIXED_CHANNELS; - } else { - if ((result & i_SIGNED_FORMAT_BIT)) return i_UNSUPPORTED_MIXED_CHANNELS; - } - } - /* We define "unnormalized" as "sample_upper = 1". */ - /* We don't check whether any non-1 normalization value is correct */ - /* (i.e. set to the maximum bit value, and check min value) on */ - /* the assumption that we're looking at a format which *came* from */ - /* an API we can support. */ - if (!determinedNormalizedness) { - /* The ambiguity here is if the bottom bit is a single-bit value, */ - /* as in RGBA 5:5:5:1, so we defer the decision if the channel only has one bit. */ - if (KHR_DFDSVAL(BDFDB, sampleCounter, BITLENGTH) > 0) { - if ((result & i_FLOAT_FORMAT_BIT)) { - if (*(float *)(void *)&BDFDB[KHR_DF_WORD_SAMPLESTART + - KHR_DF_WORD_SAMPLEWORDS * sampleCounter + - KHR_DF_SAMPLEWORD_SAMPLEUPPER] != 1.0f) { - result |= i_NORMALIZED_FORMAT_BIT; - } - } else { - if (KHR_DFDSVAL(BDFDB, sampleCounter, SAMPLEUPPER) != 1U) { - result |= i_NORMALIZED_FORMAT_BIT; - } - } - determinedNormalizedness = 1; - } - } - /* Note: We don't check for inconsistent normalization, because */ - /* channels composed of multiple samples will have 0 in the */ - /* lower/upper range. */ - /* This heuristic should handle 64-bit integers, too. */ - } - /* If this is a packed format, we work out our offsets differently. */ /* We assume a packed format has channels that aren't byte-aligned. */ /* If we have a format in which every channel is byte-aligned *and* packed, */ @@ -162,196 +92,315 @@ enum InterpretDFDResult interpretDFD(const uint32_t *DFD, /* version in this case, and if hardware has to pack it and swizzle, */ /* that's up to the hardware to special-case. */ for (sampleCounter = 0; sampleCounter < numSamples; ++sampleCounter) { - if (KHR_DFDSVAL(BDFDB, sampleCounter, BITOFFSET) & 0x7U) { + uint32_t offset = KHR_DFDSVAL(BDFDB, sampleCounter, BITOFFSET); + uint32_t length = KHR_DFDSVAL(BDFDB, sampleCounter, BITLENGTH) + 1; + if ((offset & 0x7U) || ((offset + length) & 0x7U)) { result |= i_PACKED_FORMAT_BIT; /* Once we're packed, we're packed, no need to keep checking. */ break; } } - /* Remember: the canonical ordering of samples is to start with */ - /* the lowest bit of the channel/location which touches bit 0 of */ - /* the data, when the latter is concatenated in little-endian order, */ - /* and then progress until all the bits of that channel/location */ - /* have been processed. Multiple channels sharing the same source */ - /* bits are processed in channel ID order. (I should clarify this */ - /* for partially-shared data, but it doesn't really matter so long */ - /* as everything is consecutive, except to make things canonical.) */ - /* Note: For standard formats we could determine big/little-endianness */ - /* simply from whether the first sample starts in bit 0; technically */ - /* it's possible to have a format with unaligned channels wherein the */ - /* first channel starts at bit 0 and is one byte, yet other channels */ - /* take more bytes or aren't aligned (e.g. D24S8), but this should be */ - /* irrelevant for the formats that we support. */ - if ((result & i_PACKED_FORMAT_BIT)) { - /* A packed format. */ - uint32_t currentChannel = ~0U; /* Don't start matched. */ - uint32_t currentBitOffset = 0; - uint32_t currentByteOffset = 0; - uint32_t currentBitLength = 0; - *wordBytes = (BDFDB[KHR_DF_WORD_BYTESPLANE0] & 0xFFU); - for (sampleCounter = 0; sampleCounter < numSamples; ++sampleCounter) { - uint32_t sampleBitOffset = KHR_DFDSVAL(BDFDB, sampleCounter, BITOFFSET); - uint32_t sampleByteOffset = sampleBitOffset >> 3U; - /* The sample bitLength field stores the bit length - 1. */ - uint32_t sampleBitLength = KHR_DFDSVAL(BDFDB, sampleCounter, BITLENGTH) + 1; - uint32_t sampleChannel = KHR_DFDSVAL(BDFDB, sampleCounter, CHANNELID); - InterpretedDFDChannel *sampleChannelPtr; - switch (sampleChannel) { - case KHR_DF_CHANNEL_RGBSDA_RED: - sampleChannelPtr = R; - break; - case KHR_DF_CHANNEL_RGBSDA_GREEN: - sampleChannelPtr = G; - break; - case KHR_DF_CHANNEL_RGBSDA_BLUE: - sampleChannelPtr = B; - break; - case KHR_DF_CHANNEL_RGBSDA_DEPTH: - sampleChannelPtr = R; - break; - case KHR_DF_CHANNEL_RGBSDA_STENCIL: - sampleChannelPtr = G; + // Check data types. + bool hasSigned = false; + bool hasFloat = false; + bool hasNormalized = false; + + // Note: We're ignoring 9995, which is weird and worth special-casing + // rather than trying to generalise to all float formats. + for (uint32_t i = 0; i < numSamples; ++i) { + const bool isSigned = (KHR_DFDSVAL(BDFDB, i, QUALIFIERS) & KHR_DF_SAMPLE_DATATYPE_SIGNED) != 0; + const bool isFloat = (KHR_DFDSVAL(BDFDB, i, QUALIFIERS) & KHR_DF_SAMPLE_DATATYPE_FLOAT) != 0; + + // We define "unnormalized" as "sample_upper = 1" or "sample_upper = 1.0f". + // We don't check whether any non-1 normalization value is correct + // (i.e. set to the maximum bit value, and check min value) on + // the assumption that we're looking at a format which *came* from + // an API we can support. + const bool isNormalized = isFloat ? + *(float*) (void*) &BDFDB[KHR_DF_WORD_SAMPLESTART + + KHR_DF_WORD_SAMPLEWORDS * sampleCounter + + KHR_DF_SAMPLEWORD_SAMPLEUPPER] != 1.0f : + KHR_DFDSVAL(BDFDB, i, SAMPLEUPPER) != 1U; + + hasSigned |= isSigned; + hasFloat |= isFloat; + // By our definition the normalizedness of a single bit channel (like in RGBA 5:5:5:1) + // is ambiguous. Ignore these during normalized checks. + if (KHR_DFDSVAL(BDFDB, sampleCounter, BITLENGTH) > 0) + hasNormalized |= isNormalized; + } + result |= hasSigned ? i_SIGNED_FORMAT_BIT : 0; + result |= hasFloat ? i_FLOAT_FORMAT_BIT : 0; + result |= hasNormalized ? i_NORMALIZED_FORMAT_BIT : 0; + + // Checks based on color model + if (KHR_DFDVAL(BDFDB, MODEL) == KHR_DF_MODEL_YUVSDA) { + result |= i_NORMALIZED_FORMAT_BIT; + result |= i_COMPRESSED_FORMAT_BIT; + result |= i_YUVSDA_FORMAT_BIT; + + for (uint32_t i = 0; i < numSamples; ++i) { + switch (KHR_DFDSVAL(BDFDB, i, CHANNELID)) { + case KHR_DF_CHANNEL_YUVSDA_Y: + case KHR_DF_CHANNEL_YUVSDA_U: + case KHR_DF_CHANNEL_YUVSDA_V: + case KHR_DF_CHANNEL_YUVSDA_A: break; - case KHR_DF_CHANNEL_RGBSDA_ALPHA: - sampleChannelPtr = A; + case KHR_DF_CHANNEL_YUVSDA_DEPTH: + case KHR_DF_CHANNEL_YUVSDA_STENCIL: + isDepthStencil = true; break; default: return i_UNSUPPORTED_CHANNEL_TYPES; } - if (sampleChannel == currentChannel) { - /* Continuation of the same channel. */ - /* Since a big (>32-bit) channel isn't "packed", */ - /* this should only happen in big-endian, or if */ - /* we have a wacky format that we won't support. */ - if (sampleByteOffset == currentByteOffset - 1U && /* One byte earlier */ - ((currentBitOffset + currentBitLength) & 7U) == 0 && /* Already at the end of a byte */ - (sampleBitOffset & 7U) == 0) { /* Start at the beginning of the byte */ - /* All is good, continue big-endian. */ - /* N.B. We shouldn't be here if we decided we were little-endian, */ - /* so we don't bother to check that disagreement. */ - result |= i_BIG_ENDIAN_FORMAT_BIT; - determinedEndianness = 1; - } else { - /* Oh dear. */ - /* We could be little-endian, but not with any standard format. */ - /* More likely we've got something weird that we can't support. */ - return i_UNSUPPORTED_NONTRIVIAL_ENDIANNESS; - } - /* Remember where we are. */ - currentBitOffset = sampleBitOffset; - currentByteOffset = sampleByteOffset; - currentBitLength = sampleBitLength; - /* Accumulate the bit length. */ - sampleChannelPtr->size += sampleBitLength; - } else { - /* Everything is new. Hopefully. */ - currentChannel = sampleChannel; - currentBitOffset = sampleBitOffset; - currentByteOffset = sampleByteOffset; - currentBitLength = sampleBitLength; - if (sampleChannelPtr->size) { - /* Uh-oh, we've seen this channel before. */ - return i_UNSUPPORTED_NONTRIVIAL_ENDIANNESS; - } - /* For now, record the bit offset in little-endian terms, */ - /* because we may not know to reverse it yet. */ - sampleChannelPtr->offset = sampleBitOffset; - sampleChannelPtr->size = sampleBitLength; - } } - if ((result & i_BIG_ENDIAN_FORMAT_BIT)) { - /* Our bit offsets to bit 0 of each channel are in little-endian terms. */ - /* We need to do a byte swap to work out where they should be. */ - /* We assume, for sanity, that byte sizes are a power of two for this. */ - uint32_t offsetMask = (*wordBytes - 1U) << 3U; - R->offset ^= offsetMask; - G->offset ^= offsetMask; - B->offset ^= offsetMask; - A->offset ^= offsetMask; + + // Determine wordBytes + uint32_t largestSampleSize = 0; + for (uint32_t i = 0; i < numSamples; ++i) { + uint32_t length = KHR_DFDSVAL(BDFDB, i, BITLENGTH) + 1; + if (largestSampleSize < length) + largestSampleSize = length; } - } else { - /* Not a packed format. */ - /* Everything is byte-aligned. */ - /* Question is whether there multiple samples per channel. */ - uint32_t currentChannel = ~0U; /* Don't start matched. */ - uint32_t currentByteOffset = 0; - uint32_t currentByteLength = 0; + *wordBytes = ((result & i_PACKED_FORMAT_BIT) ? 4 : 1) * bit_ceil(largestSampleSize) / 8; + + } else if (KHR_DFDVAL(BDFDB, MODEL) == KHR_DF_MODEL_RGBSDA) { + /* We only pay attention to sRGB. */ + if (KHR_DFDVAL(BDFDB, TRANSFER) == KHR_DF_TRANSFER_SRGB) result |= i_SRGB_FORMAT_BIT; + + /* We only support samples at coordinate 0,0,0,0. */ + /* (We could confirm this from texel_block_dimensions in 1.2, but */ + /* the interpretation might change in later versions.) */ for (sampleCounter = 0; sampleCounter < numSamples; ++sampleCounter) { - uint32_t sampleByteOffset = KHR_DFDSVAL(BDFDB, sampleCounter, BITOFFSET) >> 3U; - uint32_t sampleByteLength = (KHR_DFDSVAL(BDFDB, sampleCounter, BITLENGTH) + 1) >> 3U; - uint32_t sampleChannel = KHR_DFDSVAL(BDFDB, sampleCounter, CHANNELID); - InterpretedDFDChannel *sampleChannelPtr; - switch (sampleChannel) { - case KHR_DF_CHANNEL_RGBSDA_RED: - sampleChannelPtr = R; - break; - case KHR_DF_CHANNEL_RGBSDA_GREEN: - sampleChannelPtr = G; - break; - case KHR_DF_CHANNEL_RGBSDA_BLUE: - sampleChannelPtr = B; - break; + if (KHR_DFDSVAL(BDFDB, sampleCounter, SAMPLEPOSITION_ALL)) + return i_UNSUPPORTED_MULTIPLE_SAMPLE_LOCATIONS; + } + + /* For Depth/Stencil formats mixed channels are allowed */ + for (sampleCounter = 0; sampleCounter < numSamples; ++sampleCounter) { + switch (KHR_DFDSVAL(BDFDB, sampleCounter, CHANNELID)) { case KHR_DF_CHANNEL_RGBSDA_DEPTH: - sampleChannelPtr = R; - break; case KHR_DF_CHANNEL_RGBSDA_STENCIL: - sampleChannelPtr = G; - break; - case KHR_DF_CHANNEL_RGBSDA_ALPHA: - sampleChannelPtr = A; + isDepthStencil = true; break; default: - return i_UNSUPPORTED_CHANNEL_TYPES; + break; + } + } + + // Check for mixed channels + if (!isDepthStencil) { + for (uint32_t i = 0; i < numSamples; ++i) { + const bool isSigned = (KHR_DFDSVAL(BDFDB, i, QUALIFIERS) & KHR_DF_SAMPLE_DATATYPE_SIGNED) != 0; + const bool isFloat = (KHR_DFDSVAL(BDFDB, i, QUALIFIERS) & KHR_DF_SAMPLE_DATATYPE_FLOAT) != 0; + + if (isSigned != hasSigned) + return i_UNSUPPORTED_MIXED_CHANNELS; + if (isFloat != hasFloat) + return i_UNSUPPORTED_MIXED_CHANNELS; + + // Note: We don't check for inconsistent normalization, because + // channels composed of multiple samples will have 0 in the + // lower/upper range. Single bit channels are also ambiguous. + // This heuristic should handle 64-bit integers, too. } - if (sampleChannel == currentChannel) { - /* Continuation of the same channel. */ - /* Either big-endian, or little-endian with a very large channel. */ - if (sampleByteOffset == currentByteOffset - 1) { /* One byte earlier */ - if (determinedEndianness && !(result & i_BIG_ENDIAN_FORMAT_BIT)) { + } + + /* Remember: the canonical ordering of samples is to start with */ + /* the lowest bit of the channel/location which touches bit 0 of */ + /* the data, when the latter is concatenated in little-endian order, */ + /* and then progress until all the bits of that channel/location */ + /* have been processed. Multiple channels sharing the same source */ + /* bits are processed in channel ID order. (I should clarify this */ + /* for partially-shared data, but it doesn't really matter so long */ + /* as everything is consecutive, except to make things canonical.) */ + /* Note: For standard formats we could determine big/little-endianness */ + /* simply from whether the first sample starts in bit 0; technically */ + /* it's possible to have a format with unaligned channels wherein the */ + /* first channel starts at bit 0 and is one byte, yet other channels */ + /* take more bytes or aren't aligned (e.g. D24S8), but this should be */ + /* irrelevant for the formats that we support. */ + if ((result & i_PACKED_FORMAT_BIT)) { + /* A packed format. */ + uint32_t currentChannel = ~0U; /* Don't start matched. */ + uint32_t currentBitOffset = 0; + uint32_t currentByteOffset = 0; + uint32_t currentBitLength = 0; + *wordBytes = (BDFDB[KHR_DF_WORD_BYTESPLANE0] & 0xFFU); + for (sampleCounter = 0; sampleCounter < numSamples; ++sampleCounter) { + uint32_t sampleBitOffset = KHR_DFDSVAL(BDFDB, sampleCounter, BITOFFSET); + uint32_t sampleByteOffset = sampleBitOffset >> 3U; + /* The sample bitLength field stores the bit length - 1. */ + uint32_t sampleBitLength = KHR_DFDSVAL(BDFDB, sampleCounter, BITLENGTH) + 1; + uint32_t sampleChannel = KHR_DFDSVAL(BDFDB, sampleCounter, CHANNELID); + InterpretedDFDChannel *sampleChannelPtr; + switch (sampleChannel) { + case KHR_DF_CHANNEL_RGBSDA_RED: + sampleChannelPtr = R; + break; + case KHR_DF_CHANNEL_RGBSDA_GREEN: + sampleChannelPtr = G; + break; + case KHR_DF_CHANNEL_RGBSDA_BLUE: + sampleChannelPtr = B; + break; + case KHR_DF_CHANNEL_RGBSDA_DEPTH: + sampleChannelPtr = R; + break; + case KHR_DF_CHANNEL_RGBSDA_STENCIL: + sampleChannelPtr = G; + break; + case KHR_DF_CHANNEL_RGBSDA_ALPHA: + sampleChannelPtr = A; + break; + default: + return i_UNSUPPORTED_CHANNEL_TYPES; + } + if (sampleChannel == currentChannel) { + /* Continuation of the same channel. */ + /* Since a big (>32-bit) channel isn't "packed", */ + /* this should only happen in big-endian, or if */ + /* we have a wacky format that we won't support. */ + if (sampleByteOffset == currentByteOffset - 1U && /* One byte earlier */ + ((currentBitOffset + currentBitLength) & 7U) == 0 && /* Already at the end of a byte */ + (sampleBitOffset & 7U) == 0) { /* Start at the beginning of the byte */ + /* All is good, continue big-endian. */ + /* N.B. We shouldn't be here if we decided we were little-endian, */ + /* so we don't bother to check that disagreement. */ + result |= i_BIG_ENDIAN_FORMAT_BIT; + determinedEndianness = 1; + } else { + /* Oh dear. */ + /* We could be little-endian, but not with any standard format. */ + /* More likely we've got something weird that we can't support. */ return i_UNSUPPORTED_NONTRIVIAL_ENDIANNESS; } - /* All is good, continue big-endian. */ - result |= i_BIG_ENDIAN_FORMAT_BIT; - determinedEndianness = 1; - /* Update the start */ - sampleChannelPtr->offset = sampleByteOffset; - } else if (sampleByteOffset == currentByteOffset + currentByteLength) { - if (determinedEndianness && (result & i_BIG_ENDIAN_FORMAT_BIT)) { + /* Remember where we are. */ + currentBitOffset = sampleBitOffset; + currentByteOffset = sampleByteOffset; + currentBitLength = sampleBitLength; + /* Accumulate the bit length. */ + sampleChannelPtr->size += sampleBitLength; + } else { + /* Everything is new. Hopefully. */ + currentChannel = sampleChannel; + currentBitOffset = sampleBitOffset; + currentByteOffset = sampleByteOffset; + currentBitLength = sampleBitLength; + if (sampleChannelPtr->size) { + /* Uh-oh, we've seen this channel before. */ return i_UNSUPPORTED_NONTRIVIAL_ENDIANNESS; } - /* All is good, continue little-endian. */ - determinedEndianness = 1; - } else { - /* Oh dear. */ - /* We could be little-endian, but not with any standard format. */ - /* More likely we've got something weird that we can't support. */ - return i_UNSUPPORTED_NONTRIVIAL_ENDIANNESS; + /* For now, record the bit offset in little-endian terms, */ + /* because we may not know to reverse it yet. */ + sampleChannelPtr->offset = sampleBitOffset; + sampleChannelPtr->size = sampleBitLength; + } + } + if ((result & i_BIG_ENDIAN_FORMAT_BIT)) { + /* Our bit offsets to bit 0 of each channel are in little-endian terms. */ + /* We need to do a byte swap to work out where they should be. */ + /* We assume, for sanity, that byte sizes are a power of two for this. */ + uint32_t offsetMask = (*wordBytes - 1U) << 3U; + R->offset ^= offsetMask; + G->offset ^= offsetMask; + B->offset ^= offsetMask; + A->offset ^= offsetMask; + } + } else { + /* Not a packed format. */ + /* Everything is byte-aligned. */ + /* Question is whether there multiple samples per channel. */ + uint32_t currentChannel = ~0U; /* Don't start matched. */ + uint32_t currentByteOffset = 0; + uint32_t currentByteLength = 0; + for (sampleCounter = 0; sampleCounter < numSamples; ++sampleCounter) { + uint32_t sampleByteOffset = KHR_DFDSVAL(BDFDB, sampleCounter, BITOFFSET) >> 3U; + uint32_t sampleByteLength = (KHR_DFDSVAL(BDFDB, sampleCounter, BITLENGTH) + 1) >> 3U; + uint32_t sampleChannel = KHR_DFDSVAL(BDFDB, sampleCounter, CHANNELID); + InterpretedDFDChannel *sampleChannelPtr; + switch (sampleChannel) { + case KHR_DF_CHANNEL_RGBSDA_RED: + sampleChannelPtr = R; + break; + case KHR_DF_CHANNEL_RGBSDA_GREEN: + sampleChannelPtr = G; + break; + case KHR_DF_CHANNEL_RGBSDA_BLUE: + sampleChannelPtr = B; + break; + case KHR_DF_CHANNEL_RGBSDA_DEPTH: + sampleChannelPtr = R; + break; + case KHR_DF_CHANNEL_RGBSDA_STENCIL: + sampleChannelPtr = G; + break; + case KHR_DF_CHANNEL_RGBSDA_ALPHA: + sampleChannelPtr = A; + break; + default: + return i_UNSUPPORTED_CHANNEL_TYPES; } - /* Remember where we are. */ - currentByteOffset = sampleByteOffset; - currentByteLength = sampleByteLength; - /* Accumulate the byte length. */ - sampleChannelPtr->size += sampleByteLength; - /* Assume these are all the same. */ - *wordBytes = sampleChannelPtr->size; - } else { - /* Everything is new. Hopefully. */ - currentChannel = sampleChannel; - currentByteOffset = sampleByteOffset; - currentByteLength = sampleByteLength; - if (sampleChannelPtr->size) { - /* Uh-oh, we've seen this channel before. */ - return i_UNSUPPORTED_NONTRIVIAL_ENDIANNESS; + if (sampleChannel == currentChannel) { + /* Continuation of the same channel. */ + /* Either big-endian, or little-endian with a very large channel. */ + if (sampleByteOffset == currentByteOffset - 1) { /* One byte earlier */ + if (determinedEndianness && !(result & i_BIG_ENDIAN_FORMAT_BIT)) { + return i_UNSUPPORTED_NONTRIVIAL_ENDIANNESS; + } + /* All is good, continue big-endian. */ + result |= i_BIG_ENDIAN_FORMAT_BIT; + determinedEndianness = 1; + /* Update the start */ + sampleChannelPtr->offset = sampleByteOffset; + } else if (sampleByteOffset == currentByteOffset + currentByteLength) { + if (determinedEndianness && (result & i_BIG_ENDIAN_FORMAT_BIT)) { + return i_UNSUPPORTED_NONTRIVIAL_ENDIANNESS; + } + /* All is good, continue little-endian. */ + determinedEndianness = 1; + } else { + /* Oh dear. */ + /* We could be little-endian, but not with any standard format. */ + /* More likely we've got something weird that we can't support. */ + return i_UNSUPPORTED_NONTRIVIAL_ENDIANNESS; + } + /* Remember where we are. */ + currentByteOffset = sampleByteOffset; + currentByteLength = sampleByteLength; + /* Accumulate the byte length. */ + sampleChannelPtr->size += sampleByteLength; + /* Assume these are all the same. */ + *wordBytes = sampleChannelPtr->size; + } else { + /* Everything is new. Hopefully. */ + currentChannel = sampleChannel; + currentByteOffset = sampleByteOffset; + currentByteLength = sampleByteLength; + if (sampleChannelPtr->size) { + /* Uh-oh, we've seen this channel before. */ + return i_UNSUPPORTED_NONTRIVIAL_ENDIANNESS; + } + /* For now, record the byte offset in little-endian terms, */ + /* because we may not know to reverse it yet. */ + sampleChannelPtr->offset = sampleByteOffset; + sampleChannelPtr->size = sampleByteLength; + /* Assume these are all the same. */ + *wordBytes = sampleByteLength; } - /* For now, record the byte offset in little-endian terms, */ - /* because we may not know to reverse it yet. */ - sampleChannelPtr->offset = sampleByteOffset; - sampleChannelPtr->size = sampleByteLength; - /* Assume these are all the same. */ - *wordBytes = sampleByteLength; } } + } else { + return i_UNSUPPORTED_CHANNEL_TYPES; } + + if (isDepthStencil) { + /* For Depth/Stencil formats wordBytes is determined by the required alignment of */ + /* the larger channel. */ + uint32_t largerSize = R->size > G->size ? R->size : G->size; + *wordBytes = bit_ceil(largerSize); + } + return result; } diff --git a/lib/dfdutils/makevk2dfd.pl b/lib/dfdutils/makevk2dfd.pl index 3058be76f0..1eb881fa00 100755 --- a/lib/dfdutils/makevk2dfd.pl +++ b/lib/dfdutils/makevk2dfd.pl @@ -25,18 +25,98 @@ print "/***************************** Do not edit. *****************************\n"; print " Automatically generated by makevk2dfd.pl.\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 = <>) { - # Match any format that starts with a channel description (some number of R, G, B, A or a number) # In PERL, "=~" performs a regex operation on the left argument # m// matches the regular expression - if ($line =~ m/VK_FORMAT_[RGBAE0-9]+_/) { + # VK_FORMAT_ is a simple 422 format + if ($line =~ m/(VK_FORMAT_[RGBX0-9]+_422_UNORM(_4PACK16)?)/) { + $format = $1; # Extract the format identifier from the rest of the line + if (exists($foundFormats{$format})) { next } + $foundFormats{$format} = 1; + + # VK_FORMAT_G8B8G8R8_422_UNORM, + # VK_FORMAT_B8G8R8G8_422_UNORM, + # VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16, + # VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16, + # VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16, + # VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16, + # VK_FORMAT_G16B16G16R16_422_UNORM, + # VK_FORMAT_B16G16R16G16_422_UNORM, + + $format =~ m/VK_FORMAT_([RGBX0-9]+)_422_UNORM(_4PACK16)?/; + $formatChannels = $1; + + $channels = ""; + $bits = ""; + $paddings = ""; + $position_xs = ""; + $position_ys = ""; + $last_green = 1; + + while ($formatChannels =~ m/([RGBX0-9]*)([RGB])([0-9]+)X?([0-9]+)?/) { + # Processing from right to left for ease of regex expression + $channel = $2; + $bit = $3; + $padding = $4; + + if ($channels ne "") { + $channels = ", " . $channels; + $bits = ", " . $bits; + $paddings = ", " . $paddings; + $position_xs = ", " . $position_xs; + $position_ys = ", " . $position_ys; + } + + # The default 4:2:2 positioning is currently cosited-even. + # Block size is 2x1: Sample positions coded as 1/128 on X and 1/256 on Y + # Cosited-even: + # Position Sample + # X Y X Y + # Y0: 0.5, 0.5 -> 64, 128 + # U : 0.5, 0.5 -> 64, 128 + # Y1: 1.5, 0.5 -> 192, 128 + # V : 0.5, 0.5 -> 64, 128 + # Midpoint: + # Position Sample + # X Y X Y + # Y0: 0.5, 0.5 -> 64, 128 + # U : 1.0, 0.5 -> 128, 128 + # Y1: 1.5, 0.5 -> 192, 128 + # V : 1.0, 0.5 -> 128, 128 + + if ($channel eq 'R') { + $channels = "2" . $channels; # 2 = Cr / V + $position_xs = "64" . $position_xs; + $position_ys = "128" . $position_ys; + } elsif ($channel eq 'G') { + $channels = "0" . $channels; # 0 = Y + $position_xs = ($last_green ? "192" : "64") . $position_xs; + $position_ys = "128" . $position_ys; + $last_green = 0; + } elsif ($channel eq 'B') { + $channels = "1" . $channels; # 1 = Cb / U + $position_xs = "64" . $position_xs; + $position_ys = "128" . $position_ys; + } + + $bits = $bit . $bits; + + if ($padding ne "") { $paddings = $padding . $paddings; } + else { $paddings = "0" . $paddings; } + + $formatChannels = $1; + } + + print "case $format: {\n"; + print " int channels[] = {$channels}; int bits[] = {$bits}; int paddings[] = {$paddings};\n"; + print " int position_xs[] = {$position_xs}; int position_ys[] = {$position_ys};\n"; + print " return createDFD422($bigEndian, 4, bits, paddings, channels, position_xs, position_ys, s_UNORM);\n}\n"; + + } elsif ($line =~ m/VK_FORMAT_[RGBAE0-9]+_/) { # Set $format to the enum identifier ($line =~ m/(VK_FORMAT[A-Z0-9_]+)/); @@ -176,6 +256,62 @@ } } + # VK_FORMAT_ is a packed HDR formats with padding + # R10X6_UNORM_PACK16 + # R10X6G10X6_UNORM_2PACK16 + # R10X6G10X6B10X6A10X6_UNORM_4PACK16 + # R12X4_UNORM_PACK16 + # R12X4G12X4_UNORM_2PACK16 + # R12X4G12X4B12X4A12X4_UNORM_4PACK16 + } elsif ($line =~ m/(VK_FORMAT_R10X6_UNORM_PACK16)/) { + $format = $1; # Extract the format identifier from the rest of the line + if (!exists($foundFormats{$format})) { + $foundFormats{$format} = 1; + print "case $format: {\n"; + print " int channels[] = {0}; int bits[] = {10}; int paddings[] = {6};\n"; + print " return createDFDPackedPadded($bigEndian, 1, bits, paddings, channels, s_UNORM);\n}\n" + } + } elsif ($line =~ m/(VK_FORMAT_R10X6G10X6_UNORM_2PACK16)/) { + $format = $1; # Extract the format identifier from the rest of the line + if (!exists($foundFormats{$format})) { + $foundFormats{$format} = 1; + print "case $format: {\n"; + print " int channels[] = {0, 1}; int bits[] = {10, 10}; int paddings[] = {6, 6};\n"; + print " return createDFDPackedPadded($bigEndian, 2, bits, paddings, channels, s_UNORM);\n}\n" + } + } elsif ($line =~ m/(VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16)/) { + $format = $1; # Extract the format identifier from the rest of the line + if (!exists($foundFormats{$format})) { + $foundFormats{$format} = 1; + print "case $format: {\n"; + print " int channels[] = {0, 1, 2, 3}; int bits[] = {10, 10, 10, 10}; int paddings[] = {6, 6, 6, 6};\n"; + print " return createDFDPackedPadded($bigEndian, 4, bits, paddings, channels, s_UNORM);\n}\n" + } + } elsif ($line =~ m/(VK_FORMAT_R12X4_UNORM_PACK16)/) { + $format = $1; # Extract the format identifier from the rest of the line + if (!exists($foundFormats{$format})) { + $foundFormats{$format} = 1; + print "case $format: {\n"; + print " int channels[] = {0}; int bits[] = {12}; int paddings[] = {4};\n"; + print " return createDFDPackedPadded($bigEndian, 1, bits, paddings, channels, s_UNORM);\n}\n" + } + } elsif ($line =~ m/(VK_FORMAT_R12X4G12X4_UNORM_2PACK16)/) { + $format = $1; # Extract the format identifier from the rest of the line + if (!exists($foundFormats{$format})) { + $foundFormats{$format} = 1; + print "case $format: {\n"; + print " int channels[] = {0, 1}; int bits[] = {12, 12}; int paddings[] = {4, 4};\n"; + print " return createDFDPackedPadded($bigEndian, 2, bits, paddings, channels, s_UNORM);\n}\n" + } + } elsif ($line =~ m/(VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16)/) { + $format = $1; # Extract the format identifier from the rest of the line + if (!exists($foundFormats{$format})) { + $foundFormats{$format} = 1; + print "case $format: {\n"; + print " int channels[] = {0, 1, 2, 3}; int bits[] = {12, 12, 12, 12}; int paddings[] = {4, 4, 4, 4};\n"; + print " return createDFDPackedPadded($bigEndian, 4, bits, paddings, channels, s_UNORM);\n}\n" + } + # If we weren't VK_FORMAT_ plus a channel, we might be a compressed # format, that ends "_BLOCK" } elsif ($line =~ m/(VK_FORMAT_[A-Z0-9x_]+_BLOCK(_[A-Z]+)?)/) { @@ -285,6 +421,37 @@ $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,8);\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,4);\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"; + } + } elsif ($line =~ m/(VK_FORMAT_D32_SFLOAT)/) { # Extract the format identifier from the rest of the line diff --git a/lib/dfdutils/printdfd.c b/lib/dfdutils/printdfd.c index 0787cedd4b..bfdd33ba04 100644 --- a/lib/dfdutils/printdfd.c +++ b/lib/dfdutils/printdfd.c @@ -805,9 +805,9 @@ void printDFD(uint32_t *DFD, uint32_t dataSize) KHR_DFDSVAL(block, sample, SAMPLEUPPER)); } } else if (vendorID == KHR_DF_VENDORID_KHRONOS && descriptorType == KHR_DF_KHR_DESCRIPTORTYPE_ADDITIONAL_DIMENSIONS) { - // TODO Tools P5: Implement DFD print for ADDITIONAL_DIMENSIONS + // TODO: Implement DFD print for ADDITIONAL_DIMENSIONS } else if (vendorID == KHR_DF_VENDORID_KHRONOS && descriptorType == KHR_DF_KHR_DESCRIPTORTYPE_ADDITIONAL_PLANES) { - // TODO Tools P5: Implement DFD print for ADDITIONAL_PLANES + // TODO: Implement DFD print for ADDITIONAL_PLANES } else { printf("Unknown block\n"); } @@ -994,15 +994,15 @@ void printDFDJSON(uint32_t* DFD, uint32_t dataSize, uint32_t base_indent, uint32 } else if (vendorID == KHR_DF_VENDORID_KHRONOS && descriptorType == KHR_DF_KHR_DESCRIPTORTYPE_ADDITIONAL_DIMENSIONS) { printf("%s", nl); // printf(",%s", nl); // If there is extra member printed - // TODO Tools P5: Implement DFD print for ADDITIONAL_DIMENSIONS + // TODO: Implement DFD print for ADDITIONAL_DIMENSIONS } else if (vendorID == KHR_DF_VENDORID_KHRONOS && descriptorType == KHR_DF_KHR_DESCRIPTORTYPE_ADDITIONAL_PLANES) { printf("%s", nl); // printf(",%s", nl); // If there is extra member printed - // TODO Tools P5: Implement DFD print for ADDITIONAL_PLANES + // TODO: Implement DFD print for ADDITIONAL_PLANES } else { printf("%s", nl); // printf(",%s", nl); // If there is extra member printed - // TODO Tools P5: What to do with unknown blocks for json? + // TODO: What to do with unknown blocks for json? // Unknown block data in binary? } diff --git a/lib/dfdutils/vk2dfd.inl b/lib/dfdutils/vk2dfd.inl index 6f9ef7672b..fd59fbc8a5 100644 --- a/lib/dfdutils/vk2dfd.inl +++ b/lib/dfdutils/vk2dfd.inl @@ -5,9 +5,6 @@ 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); @@ -222,6 +219,9 @@ 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,4); +case VK_FORMAT_D24_UNORM_S8_UINT: return createDFDDepthStencil(24,8,4); +case VK_FORMAT_D32_SFLOAT_S8_UINT: return createDFDDepthStencil(32,8,8); 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); @@ -276,6 +276,70 @@ case VK_FORMAT_ASTC_12x10_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 12, 10 case VK_FORMAT_ASTC_12x10_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 12, 10, 1, s_SRGB); case VK_FORMAT_ASTC_12x12_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 12, 12, 1, s_UNORM); case VK_FORMAT_ASTC_12x12_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 12, 12, 1, s_SRGB); +case VK_FORMAT_G8B8G8R8_422_UNORM: { + int channels[] = {0, 1, 0, 2}; int bits[] = {8, 8, 8, 8}; int paddings[] = {0, 0, 0, 0}; + int position_xs[] = {64, 64, 192, 64}; int position_ys[] = {128, 128, 128, 128}; + return createDFD422(0, 4, bits, paddings, channels, position_xs, position_ys, s_UNORM); +} +case VK_FORMAT_B8G8R8G8_422_UNORM: { + int channels[] = {1, 0, 2, 0}; int bits[] = {8, 8, 8, 8}; int paddings[] = {0, 0, 0, 0}; + int position_xs[] = {64, 64, 64, 192}; int position_ys[] = {128, 128, 128, 128}; + return createDFD422(0, 4, bits, paddings, channels, position_xs, position_ys, s_UNORM); +} +case VK_FORMAT_R10X6_UNORM_PACK16: { + int channels[] = {0}; int bits[] = {10}; int paddings[] = {6}; + return createDFDPackedPadded(0, 1, bits, paddings, channels, s_UNORM); +} +case VK_FORMAT_R10X6G10X6_UNORM_2PACK16: { + int channels[] = {0, 1}; int bits[] = {10, 10}; int paddings[] = {6, 6}; + return createDFDPackedPadded(0, 2, bits, paddings, channels, s_UNORM); +} +case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16: { + int channels[] = {0, 1, 2, 3}; int bits[] = {10, 10, 10, 10}; int paddings[] = {6, 6, 6, 6}; + return createDFDPackedPadded(0, 4, bits, paddings, channels, s_UNORM); +} +case VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16: { + int channels[] = {0, 1, 0, 2}; int bits[] = {10, 10, 10, 10}; int paddings[] = {6, 6, 6, 6}; + int position_xs[] = {64, 64, 192, 64}; int position_ys[] = {128, 128, 128, 128}; + return createDFD422(0, 4, bits, paddings, channels, position_xs, position_ys, s_UNORM); +} +case VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16: { + int channels[] = {1, 0, 2, 0}; int bits[] = {10, 10, 10, 10}; int paddings[] = {6, 6, 6, 6}; + int position_xs[] = {64, 64, 64, 192}; int position_ys[] = {128, 128, 128, 128}; + return createDFD422(0, 4, bits, paddings, channels, position_xs, position_ys, s_UNORM); +} +case VK_FORMAT_R12X4_UNORM_PACK16: { + int channels[] = {0}; int bits[] = {12}; int paddings[] = {4}; + return createDFDPackedPadded(0, 1, bits, paddings, channels, s_UNORM); +} +case VK_FORMAT_R12X4G12X4_UNORM_2PACK16: { + int channels[] = {0, 1}; int bits[] = {12, 12}; int paddings[] = {4, 4}; + return createDFDPackedPadded(0, 2, bits, paddings, channels, s_UNORM); +} +case VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16: { + int channels[] = {0, 1, 2, 3}; int bits[] = {12, 12, 12, 12}; int paddings[] = {4, 4, 4, 4}; + return createDFDPackedPadded(0, 4, bits, paddings, channels, s_UNORM); +} +case VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16: { + int channels[] = {0, 1, 0, 2}; int bits[] = {12, 12, 12, 12}; int paddings[] = {4, 4, 4, 4}; + int position_xs[] = {64, 64, 192, 64}; int position_ys[] = {128, 128, 128, 128}; + return createDFD422(0, 4, bits, paddings, channels, position_xs, position_ys, s_UNORM); +} +case VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16: { + int channels[] = {1, 0, 2, 0}; int bits[] = {12, 12, 12, 12}; int paddings[] = {4, 4, 4, 4}; + int position_xs[] = {64, 64, 64, 192}; int position_ys[] = {128, 128, 128, 128}; + return createDFD422(0, 4, bits, paddings, channels, position_xs, position_ys, s_UNORM); +} +case VK_FORMAT_G16B16G16R16_422_UNORM: { + int channels[] = {0, 1, 0, 2}; int bits[] = {16, 16, 16, 16}; int paddings[] = {0, 0, 0, 0}; + int position_xs[] = {64, 64, 192, 64}; int position_ys[] = {128, 128, 128, 128}; + return createDFD422(0, 4, bits, paddings, channels, position_xs, position_ys, s_UNORM); +} +case VK_FORMAT_B16G16R16G16_422_UNORM: { + int channels[] = {1, 0, 2, 0}; int bits[] = {16, 16, 16, 16}; int paddings[] = {0, 0, 0, 0}; + int position_xs[] = {64, 64, 64, 192}; int position_ys[] = {128, 128, 128, 128}; + return createDFD422(0, 4, bits, paddings, channels, position_xs, position_ys, s_UNORM); +} case VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG: return createDFDCompressed(c_PVRTC, 8, 4, 1, s_UNORM); case VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG: return createDFDCompressed(c_PVRTC, 4, 4, 1, s_UNORM); case VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG: return createDFDCompressed(c_PVRTC2, 8, 4, 1, s_UNORM); diff --git a/lib/formatsize.h b/lib/formatsize.h index 7112a3a90d..149ff18d61 100644 --- a/lib/formatsize.h +++ b/lib/formatsize.h @@ -27,6 +27,7 @@ typedef enum ktxFormatSizeFlagBits { KTX_FORMAT_SIZE_PALETTIZED_BIT = 0x00000004, KTX_FORMAT_SIZE_DEPTH_BIT = 0x00000008, KTX_FORMAT_SIZE_STENCIL_BIT = 0x00000010, + KTX_FORMAT_SIZE_YUVSDA_BIT = 0x00000020, } ktxFormatSizeFlagBits; typedef ktx_uint32_t ktxFormatSizeFlags; diff --git a/lib/internalexport.def b/lib/internalexport.def index aef3aeca45..3e882cf67c 100644 --- a/lib/internalexport.def +++ b/lib/internalexport.def @@ -45,3 +45,4 @@ EXPORTS ktxTexture2_destruct vk2dfd vkFormatString + stringToVkFormat diff --git a/lib/internalexport_mingw.def b/lib/internalexport_mingw.def index eb21740a87..19cf39bd05 100644 --- a/lib/internalexport_mingw.def +++ b/lib/internalexport_mingw.def @@ -45,3 +45,4 @@ EXPORTS ktxTexture2_destruct vk2dfd vkFormatString + stringToVkFormat diff --git a/lib/mkvkformatfiles b/lib/mkvkformatfiles index 86b1d27c57..7d0ef1d249 100755 --- a/lib/mkvkformatfiles +++ b/lib/mkvkformatfiles @@ -98,15 +98,21 @@ $2 == "VK_HEADER_VERSION" { } # Extract valid formats with values > VK_FORMAT_END_RANGE. -/VK_FORMAT_[^F].* = 1000/ && ! /PLANE/ && ! /422/ && !/420/ { +/VK_FORMAT_[^F].* = 1000/ && ! /PLANE/ && !/420/ { valid = valid " case " $1 ":\n"; } +function removePrefix(string, prefix) { + sub("^" prefix, "", string) + return string +} + # Extract VK_FORMAT token names. [^F] avoids the VK_FORMAT_FEATURE* tokens. / VK_FORMAT_[^F]/ { # Avoid values defined as existing values and avoid the MAX_ENUM value. if ($3 !~ /VK_FORMAT_.*/ && $1 !~ /.*MAX_ENUM/) { - switch_body = switch_body " case " $1 ":\n return \"" $1 "\";\n" + switch_body_vk2str = switch_body_vk2str " case " $1 ":\n return \"" $1 "\";\n" + switch_body_str2vk = switch_body_str2vk " if (ktx_strcasecmp(str, \"" removePrefix($1, "VK_FORMAT_") "\") == 0)\n return " $1 ";\n" } } @@ -142,14 +148,54 @@ END { # vkformat_str.c prelude = "\n"; - prelude = prelude "#include \n\n"; - prelude = prelude "#include \"vkformat_enum.h\"\n\n"; + prelude = prelude "#include \n"; + prelude = prelude "#include \n"; + prelude = prelude "\n"; + prelude = prelude "#include \"vkformat_enum.h\"\n"; + prelude = prelude "\n"; prelude = prelude "const char*\nvkFormatString(VkFormat format)\n{\n"; prelude = prelude " switch (format) {\n"; postscript = " default:\n return \"VK_UNKNOWN_FORMAT\";\n"; postscript = postscript " }\n"; postscript = postscript "}\n"; - write_source_file(prelude switch_body postscript, format_strings); + begin_str2vk = "\n" + begin_str2vk = begin_str2vk "static int ktx_strcasecmp(const char* s1, const char* s2) {\n" + begin_str2vk = begin_str2vk " const unsigned char* us1 = (const unsigned char*) s1;\n" + begin_str2vk = begin_str2vk " const unsigned char* us2 = (const unsigned char*) s2;\n" + begin_str2vk = begin_str2vk "\n" + begin_str2vk = begin_str2vk " while (tolower(*us1) == tolower(*us2)) {\n" + begin_str2vk = begin_str2vk " if (*us1 == '\\0')\n" + begin_str2vk = begin_str2vk " return 0;\n" + begin_str2vk = begin_str2vk " ++us1;\n" + begin_str2vk = begin_str2vk " ++us2;\n" + begin_str2vk = begin_str2vk " }\n" + begin_str2vk = begin_str2vk " return tolower(*us1) - tolower(*us2);\n" + begin_str2vk = begin_str2vk "}\n" + begin_str2vk = begin_str2vk "\n" + begin_str2vk = begin_str2vk "static int ktx_strncasecmp(const char* s1, const char* s2, int length) {\n" + begin_str2vk = begin_str2vk " const unsigned char* us1 = (const unsigned char*) s1;\n" + begin_str2vk = begin_str2vk " const unsigned char* us2 = (const unsigned char*) s2;\n" + begin_str2vk = begin_str2vk "\n" + begin_str2vk = begin_str2vk " while (length > 0 && tolower(*us1) == tolower(*us2)) {\n" + begin_str2vk = begin_str2vk " if (*us1 == '\\0')\n" + begin_str2vk = begin_str2vk " return 0;\n" + begin_str2vk = begin_str2vk " ++us1;\n" + begin_str2vk = begin_str2vk " ++us2;\n" + begin_str2vk = begin_str2vk " --length;\n" + begin_str2vk = begin_str2vk " }\n" + begin_str2vk = begin_str2vk " return tolower(*us1) - tolower(*us2);\n" + begin_str2vk = begin_str2vk "}\n" + begin_str2vk = begin_str2vk "\n" + begin_str2vk = begin_str2vk "/// Parses a VkFormat. VK_FORMAT_ prefix is optional. Case insensitive.\n" + begin_str2vk = begin_str2vk "VkFormat\n" + begin_str2vk = begin_str2vk "stringToVkFormat(const char* str)\n" + begin_str2vk = begin_str2vk "{\n" + begin_str2vk = begin_str2vk " if (ktx_strncasecmp(str, \"VK_FORMAT_\", sizeof(\"VK_FORMAT_\") - 1) == 0)\n" + begin_str2vk = begin_str2vk " str += sizeof(\"VK_FORMAT_\") - 1;\n" + begin_str2vk = begin_str2vk "\n" + end_str2vk = " return VK_FORMAT_UNDEFINED;\n"; + end_str2vk = end_str2vk "}" + write_source_file(prelude switch_body_vk2str postscript begin_str2vk switch_body_str2vk end_str2vk, format_strings); } # vim:ai:ts=4:sts=4:sw=2:expandtab:textwidth=70 diff --git a/lib/texture.c b/lib/texture.c index 35619a3e73..5dab9945c9 100644 --- a/lib/texture.c +++ b/lib/texture.c @@ -567,7 +567,7 @@ ktxTexture_calcImageSize(ktxTexture* This, ktx_uint32_t level, blockCount.y = (ktx_uint32_t)ceilf(levelHeight / prtctd->_formatSize.blockHeight); blockCount.x = MAX(prtctd->_formatSize.minBlocksX, blockCount.x); - blockCount.y = MAX(prtctd->_formatSize.minBlocksX, blockCount.y); + blockCount.y = MAX(prtctd->_formatSize.minBlocksY, blockCount.y); blockSizeInBytes = prtctd->_formatSize.blockSizeInBits / 8; @@ -726,8 +726,10 @@ ktxTexture_layerSize(ktxTexture* This, ktx_uint32_t level, ktx_size_t imageSize, layerSize; assert (This != NULL); + assert (prtctd->_formatSize.blockDepth != 0); - blockCountZ = MAX(1, (This->baseDepth / prtctd->_formatSize.blockDepth) >> level); + blockCountZ = ((This->baseDepth >> level) + prtctd->_formatSize.blockDepth - 1) / prtctd->_formatSize.blockDepth; + blockCountZ = MAX(1, blockCountZ); imageSize = ktxTexture_calcImageSize(This, level, fv); layerSize = imageSize * blockCountZ; if (fv == KTX_FORMAT_VERSION_ONE && KTX_GL_UNPACK_ALIGNMENT != 4) { diff --git a/lib/texture2.c b/lib/texture2.c index a0c1a4146e..2e881f1194 100644 --- a/lib/texture2.c +++ b/lib/texture2.c @@ -294,6 +294,10 @@ ktxFormatSize_initFromDfd(ktxFormatSize* This, ktx_uint32_t* pDfd) return false; if (result & i_PACKED_FORMAT_BIT) This->flags |= KTX_FORMAT_SIZE_PACKED_BIT; + if (result & i_COMPRESSED_FORMAT_BIT) + This->flags |= KTX_FORMAT_SIZE_COMPRESSED_BIT; + if (result & i_YUVSDA_FORMAT_BIT) + This->flags |= KTX_FORMAT_SIZE_YUVSDA_BIT; } } if (This->blockSizeInBits == 0) { @@ -326,20 +330,7 @@ ktxFormatSize_initFromDfd(ktxFormatSize* This, ktx_uint32_t* pDfd) 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); - } + return vk2dfd(vkFormat); } /** @@ -438,7 +429,7 @@ ktxTexture2_construct(ktxTexture2* This, ktxTextureCreateInfo* createInfo, // Ideally we'd set all these things in ktxFormatSize_initFromDfd // but This->_protected is not allocated until ktxTexture_construct; - if (This->isCompressed) { + if (This->isCompressed && (formatSize.flags & KTX_FORMAT_SIZE_YUVSDA_BIT) == 0) { This->_protected->_typeSize = 1; } else if (formatSize.flags & (KTX_FORMAT_SIZE_DEPTH_BIT | KTX_FORMAT_SIZE_STENCIL_BIT)) { switch (createInfo->vkFormat) { diff --git a/lib/vkformat_check.c b/lib/vkformat_check.c index 98f0e63e16..c7f6e8d950 100644 --- a/lib/vkformat_check.c +++ b/lib/vkformat_check.c @@ -82,12 +82,20 @@ isValidFormat(VkFormat format) if ((uint32_t) format <= VK_FORMAT_MAX_STANDARD_ENUM) return true; else switch(format) { + case VK_FORMAT_G8B8G8R8_422_UNORM: + case VK_FORMAT_B8G8R8G8_422_UNORM: case VK_FORMAT_R10X6_UNORM_PACK16: case VK_FORMAT_R10X6G10X6_UNORM_2PACK16: case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16: + case VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16: + case VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16: case VK_FORMAT_R12X4_UNORM_PACK16: case VK_FORMAT_R12X4G12X4_UNORM_2PACK16: case VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16: + case VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16: + case VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16: + case VK_FORMAT_G16B16G16R16_422_UNORM: + case VK_FORMAT_B16G16R16G16_422_UNORM: case VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG: case VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG: case VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG: diff --git a/lib/vkformat_str.c b/lib/vkformat_str.c index 1d5aafa1af..7fc5e0e20b 100644 --- a/lib/vkformat_str.c +++ b/lib/vkformat_str.c @@ -11,6 +11,7 @@ #include +#include #include "vkformat_enum.h" @@ -569,3 +570,585 @@ vkFormatString(VkFormat format) } } +static int ktx_strcasecmp(const char* s1, const char* s2) { + const unsigned char* us1 = (const unsigned char*) s1; + const unsigned char* us2 = (const unsigned char*) s2; + + while (tolower(*us1) == tolower(*us2)) { + if (*us1 == '\0') + return 0; + ++us1; + ++us2; + } + return tolower(*us1) - tolower(*us2); +} + +static int ktx_strncasecmp(const char* s1, const char* s2, int length) { + const unsigned char* us1 = (const unsigned char*) s1; + const unsigned char* us2 = (const unsigned char*) s2; + + while (length > 0 && tolower(*us1) == tolower(*us2)) { + if (*us1 == '\0') + return 0; + ++us1; + ++us2; + --length; + } + return tolower(*us1) - tolower(*us2); +} + +/// Parses a VkFormat. VK_FORMAT_ prefix is optional. Case insensitive. +VkFormat +stringToVkFormat(const char* str) +{ + if (ktx_strncasecmp(str, "VK_FORMAT_", sizeof("VK_FORMAT_") - 1) == 0) + str += sizeof("VK_FORMAT_") - 1; + + if (ktx_strcasecmp(str, "UNDEFINED") == 0) + return VK_FORMAT_UNDEFINED; + if (ktx_strcasecmp(str, "R4G4_UNORM_PACK8") == 0) + return VK_FORMAT_R4G4_UNORM_PACK8; + if (ktx_strcasecmp(str, "R4G4B4A4_UNORM_PACK16") == 0) + return VK_FORMAT_R4G4B4A4_UNORM_PACK16; + if (ktx_strcasecmp(str, "B4G4R4A4_UNORM_PACK16") == 0) + return VK_FORMAT_B4G4R4A4_UNORM_PACK16; + if (ktx_strcasecmp(str, "R5G6B5_UNORM_PACK16") == 0) + return VK_FORMAT_R5G6B5_UNORM_PACK16; + if (ktx_strcasecmp(str, "B5G6R5_UNORM_PACK16") == 0) + return VK_FORMAT_B5G6R5_UNORM_PACK16; + if (ktx_strcasecmp(str, "R5G5B5A1_UNORM_PACK16") == 0) + return VK_FORMAT_R5G5B5A1_UNORM_PACK16; + if (ktx_strcasecmp(str, "B5G5R5A1_UNORM_PACK16") == 0) + return VK_FORMAT_B5G5R5A1_UNORM_PACK16; + if (ktx_strcasecmp(str, "A1R5G5B5_UNORM_PACK16") == 0) + return VK_FORMAT_A1R5G5B5_UNORM_PACK16; + if (ktx_strcasecmp(str, "R8_UNORM") == 0) + return VK_FORMAT_R8_UNORM; + if (ktx_strcasecmp(str, "R8_SNORM") == 0) + return VK_FORMAT_R8_SNORM; + if (ktx_strcasecmp(str, "R8_USCALED") == 0) + return VK_FORMAT_R8_USCALED; + if (ktx_strcasecmp(str, "R8_SSCALED") == 0) + return VK_FORMAT_R8_SSCALED; + if (ktx_strcasecmp(str, "R8_UINT") == 0) + return VK_FORMAT_R8_UINT; + if (ktx_strcasecmp(str, "R8_SINT") == 0) + return VK_FORMAT_R8_SINT; + if (ktx_strcasecmp(str, "R8_SRGB") == 0) + return VK_FORMAT_R8_SRGB; + if (ktx_strcasecmp(str, "R8G8_UNORM") == 0) + return VK_FORMAT_R8G8_UNORM; + if (ktx_strcasecmp(str, "R8G8_SNORM") == 0) + return VK_FORMAT_R8G8_SNORM; + if (ktx_strcasecmp(str, "R8G8_USCALED") == 0) + return VK_FORMAT_R8G8_USCALED; + if (ktx_strcasecmp(str, "R8G8_SSCALED") == 0) + return VK_FORMAT_R8G8_SSCALED; + if (ktx_strcasecmp(str, "R8G8_UINT") == 0) + return VK_FORMAT_R8G8_UINT; + if (ktx_strcasecmp(str, "R8G8_SINT") == 0) + return VK_FORMAT_R8G8_SINT; + if (ktx_strcasecmp(str, "R8G8_SRGB") == 0) + return VK_FORMAT_R8G8_SRGB; + if (ktx_strcasecmp(str, "R8G8B8_UNORM") == 0) + return VK_FORMAT_R8G8B8_UNORM; + if (ktx_strcasecmp(str, "R8G8B8_SNORM") == 0) + return VK_FORMAT_R8G8B8_SNORM; + if (ktx_strcasecmp(str, "R8G8B8_USCALED") == 0) + return VK_FORMAT_R8G8B8_USCALED; + if (ktx_strcasecmp(str, "R8G8B8_SSCALED") == 0) + return VK_FORMAT_R8G8B8_SSCALED; + if (ktx_strcasecmp(str, "R8G8B8_UINT") == 0) + return VK_FORMAT_R8G8B8_UINT; + if (ktx_strcasecmp(str, "R8G8B8_SINT") == 0) + return VK_FORMAT_R8G8B8_SINT; + if (ktx_strcasecmp(str, "R8G8B8_SRGB") == 0) + return VK_FORMAT_R8G8B8_SRGB; + if (ktx_strcasecmp(str, "B8G8R8_UNORM") == 0) + return VK_FORMAT_B8G8R8_UNORM; + if (ktx_strcasecmp(str, "B8G8R8_SNORM") == 0) + return VK_FORMAT_B8G8R8_SNORM; + if (ktx_strcasecmp(str, "B8G8R8_USCALED") == 0) + return VK_FORMAT_B8G8R8_USCALED; + if (ktx_strcasecmp(str, "B8G8R8_SSCALED") == 0) + return VK_FORMAT_B8G8R8_SSCALED; + if (ktx_strcasecmp(str, "B8G8R8_UINT") == 0) + return VK_FORMAT_B8G8R8_UINT; + if (ktx_strcasecmp(str, "B8G8R8_SINT") == 0) + return VK_FORMAT_B8G8R8_SINT; + if (ktx_strcasecmp(str, "B8G8R8_SRGB") == 0) + return VK_FORMAT_B8G8R8_SRGB; + if (ktx_strcasecmp(str, "R8G8B8A8_UNORM") == 0) + return VK_FORMAT_R8G8B8A8_UNORM; + if (ktx_strcasecmp(str, "R8G8B8A8_SNORM") == 0) + return VK_FORMAT_R8G8B8A8_SNORM; + if (ktx_strcasecmp(str, "R8G8B8A8_USCALED") == 0) + return VK_FORMAT_R8G8B8A8_USCALED; + if (ktx_strcasecmp(str, "R8G8B8A8_SSCALED") == 0) + return VK_FORMAT_R8G8B8A8_SSCALED; + if (ktx_strcasecmp(str, "R8G8B8A8_UINT") == 0) + return VK_FORMAT_R8G8B8A8_UINT; + if (ktx_strcasecmp(str, "R8G8B8A8_SINT") == 0) + return VK_FORMAT_R8G8B8A8_SINT; + if (ktx_strcasecmp(str, "R8G8B8A8_SRGB") == 0) + return VK_FORMAT_R8G8B8A8_SRGB; + if (ktx_strcasecmp(str, "B8G8R8A8_UNORM") == 0) + return VK_FORMAT_B8G8R8A8_UNORM; + if (ktx_strcasecmp(str, "B8G8R8A8_SNORM") == 0) + return VK_FORMAT_B8G8R8A8_SNORM; + if (ktx_strcasecmp(str, "B8G8R8A8_USCALED") == 0) + return VK_FORMAT_B8G8R8A8_USCALED; + if (ktx_strcasecmp(str, "B8G8R8A8_SSCALED") == 0) + return VK_FORMAT_B8G8R8A8_SSCALED; + if (ktx_strcasecmp(str, "B8G8R8A8_UINT") == 0) + return VK_FORMAT_B8G8R8A8_UINT; + if (ktx_strcasecmp(str, "B8G8R8A8_SINT") == 0) + return VK_FORMAT_B8G8R8A8_SINT; + if (ktx_strcasecmp(str, "B8G8R8A8_SRGB") == 0) + return VK_FORMAT_B8G8R8A8_SRGB; + if (ktx_strcasecmp(str, "A8B8G8R8_UNORM_PACK32") == 0) + return VK_FORMAT_A8B8G8R8_UNORM_PACK32; + if (ktx_strcasecmp(str, "A8B8G8R8_SNORM_PACK32") == 0) + return VK_FORMAT_A8B8G8R8_SNORM_PACK32; + if (ktx_strcasecmp(str, "A8B8G8R8_USCALED_PACK32") == 0) + return VK_FORMAT_A8B8G8R8_USCALED_PACK32; + if (ktx_strcasecmp(str, "A8B8G8R8_SSCALED_PACK32") == 0) + return VK_FORMAT_A8B8G8R8_SSCALED_PACK32; + if (ktx_strcasecmp(str, "A8B8G8R8_UINT_PACK32") == 0) + return VK_FORMAT_A8B8G8R8_UINT_PACK32; + if (ktx_strcasecmp(str, "A8B8G8R8_SINT_PACK32") == 0) + return VK_FORMAT_A8B8G8R8_SINT_PACK32; + if (ktx_strcasecmp(str, "A8B8G8R8_SRGB_PACK32") == 0) + return VK_FORMAT_A8B8G8R8_SRGB_PACK32; + if (ktx_strcasecmp(str, "A2R10G10B10_UNORM_PACK32") == 0) + return VK_FORMAT_A2R10G10B10_UNORM_PACK32; + if (ktx_strcasecmp(str, "A2R10G10B10_SNORM_PACK32") == 0) + return VK_FORMAT_A2R10G10B10_SNORM_PACK32; + if (ktx_strcasecmp(str, "A2R10G10B10_USCALED_PACK32") == 0) + return VK_FORMAT_A2R10G10B10_USCALED_PACK32; + if (ktx_strcasecmp(str, "A2R10G10B10_SSCALED_PACK32") == 0) + return VK_FORMAT_A2R10G10B10_SSCALED_PACK32; + if (ktx_strcasecmp(str, "A2R10G10B10_UINT_PACK32") == 0) + return VK_FORMAT_A2R10G10B10_UINT_PACK32; + if (ktx_strcasecmp(str, "A2R10G10B10_SINT_PACK32") == 0) + return VK_FORMAT_A2R10G10B10_SINT_PACK32; + if (ktx_strcasecmp(str, "A2B10G10R10_UNORM_PACK32") == 0) + return VK_FORMAT_A2B10G10R10_UNORM_PACK32; + if (ktx_strcasecmp(str, "A2B10G10R10_SNORM_PACK32") == 0) + return VK_FORMAT_A2B10G10R10_SNORM_PACK32; + if (ktx_strcasecmp(str, "A2B10G10R10_USCALED_PACK32") == 0) + return VK_FORMAT_A2B10G10R10_USCALED_PACK32; + if (ktx_strcasecmp(str, "A2B10G10R10_SSCALED_PACK32") == 0) + return VK_FORMAT_A2B10G10R10_SSCALED_PACK32; + if (ktx_strcasecmp(str, "A2B10G10R10_UINT_PACK32") == 0) + return VK_FORMAT_A2B10G10R10_UINT_PACK32; + if (ktx_strcasecmp(str, "A2B10G10R10_SINT_PACK32") == 0) + return VK_FORMAT_A2B10G10R10_SINT_PACK32; + if (ktx_strcasecmp(str, "R16_UNORM") == 0) + return VK_FORMAT_R16_UNORM; + if (ktx_strcasecmp(str, "R16_SNORM") == 0) + return VK_FORMAT_R16_SNORM; + if (ktx_strcasecmp(str, "R16_USCALED") == 0) + return VK_FORMAT_R16_USCALED; + if (ktx_strcasecmp(str, "R16_SSCALED") == 0) + return VK_FORMAT_R16_SSCALED; + if (ktx_strcasecmp(str, "R16_UINT") == 0) + return VK_FORMAT_R16_UINT; + if (ktx_strcasecmp(str, "R16_SINT") == 0) + return VK_FORMAT_R16_SINT; + if (ktx_strcasecmp(str, "R16_SFLOAT") == 0) + return VK_FORMAT_R16_SFLOAT; + if (ktx_strcasecmp(str, "R16G16_UNORM") == 0) + return VK_FORMAT_R16G16_UNORM; + if (ktx_strcasecmp(str, "R16G16_SNORM") == 0) + return VK_FORMAT_R16G16_SNORM; + if (ktx_strcasecmp(str, "R16G16_USCALED") == 0) + return VK_FORMAT_R16G16_USCALED; + if (ktx_strcasecmp(str, "R16G16_SSCALED") == 0) + return VK_FORMAT_R16G16_SSCALED; + if (ktx_strcasecmp(str, "R16G16_UINT") == 0) + return VK_FORMAT_R16G16_UINT; + if (ktx_strcasecmp(str, "R16G16_SINT") == 0) + return VK_FORMAT_R16G16_SINT; + if (ktx_strcasecmp(str, "R16G16_SFLOAT") == 0) + return VK_FORMAT_R16G16_SFLOAT; + if (ktx_strcasecmp(str, "R16G16B16_UNORM") == 0) + return VK_FORMAT_R16G16B16_UNORM; + if (ktx_strcasecmp(str, "R16G16B16_SNORM") == 0) + return VK_FORMAT_R16G16B16_SNORM; + if (ktx_strcasecmp(str, "R16G16B16_USCALED") == 0) + return VK_FORMAT_R16G16B16_USCALED; + if (ktx_strcasecmp(str, "R16G16B16_SSCALED") == 0) + return VK_FORMAT_R16G16B16_SSCALED; + if (ktx_strcasecmp(str, "R16G16B16_UINT") == 0) + return VK_FORMAT_R16G16B16_UINT; + if (ktx_strcasecmp(str, "R16G16B16_SINT") == 0) + return VK_FORMAT_R16G16B16_SINT; + if (ktx_strcasecmp(str, "R16G16B16_SFLOAT") == 0) + return VK_FORMAT_R16G16B16_SFLOAT; + if (ktx_strcasecmp(str, "R16G16B16A16_UNORM") == 0) + return VK_FORMAT_R16G16B16A16_UNORM; + if (ktx_strcasecmp(str, "R16G16B16A16_SNORM") == 0) + return VK_FORMAT_R16G16B16A16_SNORM; + if (ktx_strcasecmp(str, "R16G16B16A16_USCALED") == 0) + return VK_FORMAT_R16G16B16A16_USCALED; + if (ktx_strcasecmp(str, "R16G16B16A16_SSCALED") == 0) + return VK_FORMAT_R16G16B16A16_SSCALED; + if (ktx_strcasecmp(str, "R16G16B16A16_UINT") == 0) + return VK_FORMAT_R16G16B16A16_UINT; + if (ktx_strcasecmp(str, "R16G16B16A16_SINT") == 0) + return VK_FORMAT_R16G16B16A16_SINT; + if (ktx_strcasecmp(str, "R16G16B16A16_SFLOAT") == 0) + return VK_FORMAT_R16G16B16A16_SFLOAT; + if (ktx_strcasecmp(str, "R32_UINT") == 0) + return VK_FORMAT_R32_UINT; + if (ktx_strcasecmp(str, "R32_SINT") == 0) + return VK_FORMAT_R32_SINT; + if (ktx_strcasecmp(str, "R32_SFLOAT") == 0) + return VK_FORMAT_R32_SFLOAT; + if (ktx_strcasecmp(str, "R32G32_UINT") == 0) + return VK_FORMAT_R32G32_UINT; + if (ktx_strcasecmp(str, "R32G32_SINT") == 0) + return VK_FORMAT_R32G32_SINT; + if (ktx_strcasecmp(str, "R32G32_SFLOAT") == 0) + return VK_FORMAT_R32G32_SFLOAT; + if (ktx_strcasecmp(str, "R32G32B32_UINT") == 0) + return VK_FORMAT_R32G32B32_UINT; + if (ktx_strcasecmp(str, "R32G32B32_SINT") == 0) + return VK_FORMAT_R32G32B32_SINT; + if (ktx_strcasecmp(str, "R32G32B32_SFLOAT") == 0) + return VK_FORMAT_R32G32B32_SFLOAT; + if (ktx_strcasecmp(str, "R32G32B32A32_UINT") == 0) + return VK_FORMAT_R32G32B32A32_UINT; + if (ktx_strcasecmp(str, "R32G32B32A32_SINT") == 0) + return VK_FORMAT_R32G32B32A32_SINT; + if (ktx_strcasecmp(str, "R32G32B32A32_SFLOAT") == 0) + return VK_FORMAT_R32G32B32A32_SFLOAT; + if (ktx_strcasecmp(str, "R64_UINT") == 0) + return VK_FORMAT_R64_UINT; + if (ktx_strcasecmp(str, "R64_SINT") == 0) + return VK_FORMAT_R64_SINT; + if (ktx_strcasecmp(str, "R64_SFLOAT") == 0) + return VK_FORMAT_R64_SFLOAT; + if (ktx_strcasecmp(str, "R64G64_UINT") == 0) + return VK_FORMAT_R64G64_UINT; + if (ktx_strcasecmp(str, "R64G64_SINT") == 0) + return VK_FORMAT_R64G64_SINT; + if (ktx_strcasecmp(str, "R64G64_SFLOAT") == 0) + return VK_FORMAT_R64G64_SFLOAT; + if (ktx_strcasecmp(str, "R64G64B64_UINT") == 0) + return VK_FORMAT_R64G64B64_UINT; + if (ktx_strcasecmp(str, "R64G64B64_SINT") == 0) + return VK_FORMAT_R64G64B64_SINT; + if (ktx_strcasecmp(str, "R64G64B64_SFLOAT") == 0) + return VK_FORMAT_R64G64B64_SFLOAT; + if (ktx_strcasecmp(str, "R64G64B64A64_UINT") == 0) + return VK_FORMAT_R64G64B64A64_UINT; + if (ktx_strcasecmp(str, "R64G64B64A64_SINT") == 0) + return VK_FORMAT_R64G64B64A64_SINT; + if (ktx_strcasecmp(str, "R64G64B64A64_SFLOAT") == 0) + return VK_FORMAT_R64G64B64A64_SFLOAT; + if (ktx_strcasecmp(str, "B10G11R11_UFLOAT_PACK32") == 0) + return VK_FORMAT_B10G11R11_UFLOAT_PACK32; + if (ktx_strcasecmp(str, "E5B9G9R9_UFLOAT_PACK32") == 0) + return VK_FORMAT_E5B9G9R9_UFLOAT_PACK32; + if (ktx_strcasecmp(str, "D16_UNORM") == 0) + return VK_FORMAT_D16_UNORM; + if (ktx_strcasecmp(str, "X8_D24_UNORM_PACK32") == 0) + return VK_FORMAT_X8_D24_UNORM_PACK32; + if (ktx_strcasecmp(str, "D32_SFLOAT") == 0) + return VK_FORMAT_D32_SFLOAT; + if (ktx_strcasecmp(str, "S8_UINT") == 0) + return VK_FORMAT_S8_UINT; + if (ktx_strcasecmp(str, "D16_UNORM_S8_UINT") == 0) + return VK_FORMAT_D16_UNORM_S8_UINT; + if (ktx_strcasecmp(str, "D24_UNORM_S8_UINT") == 0) + return VK_FORMAT_D24_UNORM_S8_UINT; + if (ktx_strcasecmp(str, "D32_SFLOAT_S8_UINT") == 0) + return VK_FORMAT_D32_SFLOAT_S8_UINT; + if (ktx_strcasecmp(str, "BC1_RGB_UNORM_BLOCK") == 0) + return VK_FORMAT_BC1_RGB_UNORM_BLOCK; + if (ktx_strcasecmp(str, "BC1_RGB_SRGB_BLOCK") == 0) + return VK_FORMAT_BC1_RGB_SRGB_BLOCK; + if (ktx_strcasecmp(str, "BC1_RGBA_UNORM_BLOCK") == 0) + return VK_FORMAT_BC1_RGBA_UNORM_BLOCK; + if (ktx_strcasecmp(str, "BC1_RGBA_SRGB_BLOCK") == 0) + return VK_FORMAT_BC1_RGBA_SRGB_BLOCK; + if (ktx_strcasecmp(str, "BC2_UNORM_BLOCK") == 0) + return VK_FORMAT_BC2_UNORM_BLOCK; + if (ktx_strcasecmp(str, "BC2_SRGB_BLOCK") == 0) + return VK_FORMAT_BC2_SRGB_BLOCK; + if (ktx_strcasecmp(str, "BC3_UNORM_BLOCK") == 0) + return VK_FORMAT_BC3_UNORM_BLOCK; + if (ktx_strcasecmp(str, "BC3_SRGB_BLOCK") == 0) + return VK_FORMAT_BC3_SRGB_BLOCK; + if (ktx_strcasecmp(str, "BC4_UNORM_BLOCK") == 0) + return VK_FORMAT_BC4_UNORM_BLOCK; + if (ktx_strcasecmp(str, "BC4_SNORM_BLOCK") == 0) + return VK_FORMAT_BC4_SNORM_BLOCK; + if (ktx_strcasecmp(str, "BC5_UNORM_BLOCK") == 0) + return VK_FORMAT_BC5_UNORM_BLOCK; + if (ktx_strcasecmp(str, "BC5_SNORM_BLOCK") == 0) + return VK_FORMAT_BC5_SNORM_BLOCK; + if (ktx_strcasecmp(str, "BC6H_UFLOAT_BLOCK") == 0) + return VK_FORMAT_BC6H_UFLOAT_BLOCK; + if (ktx_strcasecmp(str, "BC6H_SFLOAT_BLOCK") == 0) + return VK_FORMAT_BC6H_SFLOAT_BLOCK; + if (ktx_strcasecmp(str, "BC7_UNORM_BLOCK") == 0) + return VK_FORMAT_BC7_UNORM_BLOCK; + if (ktx_strcasecmp(str, "BC7_SRGB_BLOCK") == 0) + return VK_FORMAT_BC7_SRGB_BLOCK; + if (ktx_strcasecmp(str, "ETC2_R8G8B8_UNORM_BLOCK") == 0) + return VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK; + if (ktx_strcasecmp(str, "ETC2_R8G8B8_SRGB_BLOCK") == 0) + return VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK; + if (ktx_strcasecmp(str, "ETC2_R8G8B8A1_UNORM_BLOCK") == 0) + return VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK; + if (ktx_strcasecmp(str, "ETC2_R8G8B8A1_SRGB_BLOCK") == 0) + return VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK; + if (ktx_strcasecmp(str, "ETC2_R8G8B8A8_UNORM_BLOCK") == 0) + return VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; + if (ktx_strcasecmp(str, "ETC2_R8G8B8A8_SRGB_BLOCK") == 0) + return VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK; + if (ktx_strcasecmp(str, "EAC_R11_UNORM_BLOCK") == 0) + return VK_FORMAT_EAC_R11_UNORM_BLOCK; + if (ktx_strcasecmp(str, "EAC_R11_SNORM_BLOCK") == 0) + return VK_FORMAT_EAC_R11_SNORM_BLOCK; + if (ktx_strcasecmp(str, "EAC_R11G11_UNORM_BLOCK") == 0) + return VK_FORMAT_EAC_R11G11_UNORM_BLOCK; + if (ktx_strcasecmp(str, "EAC_R11G11_SNORM_BLOCK") == 0) + return VK_FORMAT_EAC_R11G11_SNORM_BLOCK; + if (ktx_strcasecmp(str, "ASTC_4x4_UNORM_BLOCK") == 0) + return VK_FORMAT_ASTC_4x4_UNORM_BLOCK; + if (ktx_strcasecmp(str, "ASTC_4x4_SRGB_BLOCK") == 0) + return VK_FORMAT_ASTC_4x4_SRGB_BLOCK; + if (ktx_strcasecmp(str, "ASTC_5x4_UNORM_BLOCK") == 0) + return VK_FORMAT_ASTC_5x4_UNORM_BLOCK; + if (ktx_strcasecmp(str, "ASTC_5x4_SRGB_BLOCK") == 0) + return VK_FORMAT_ASTC_5x4_SRGB_BLOCK; + if (ktx_strcasecmp(str, "ASTC_5x5_UNORM_BLOCK") == 0) + return VK_FORMAT_ASTC_5x5_UNORM_BLOCK; + if (ktx_strcasecmp(str, "ASTC_5x5_SRGB_BLOCK") == 0) + return VK_FORMAT_ASTC_5x5_SRGB_BLOCK; + if (ktx_strcasecmp(str, "ASTC_6x5_UNORM_BLOCK") == 0) + return VK_FORMAT_ASTC_6x5_UNORM_BLOCK; + if (ktx_strcasecmp(str, "ASTC_6x5_SRGB_BLOCK") == 0) + return VK_FORMAT_ASTC_6x5_SRGB_BLOCK; + if (ktx_strcasecmp(str, "ASTC_6x6_UNORM_BLOCK") == 0) + return VK_FORMAT_ASTC_6x6_UNORM_BLOCK; + if (ktx_strcasecmp(str, "ASTC_6x6_SRGB_BLOCK") == 0) + return VK_FORMAT_ASTC_6x6_SRGB_BLOCK; + if (ktx_strcasecmp(str, "ASTC_8x5_UNORM_BLOCK") == 0) + return VK_FORMAT_ASTC_8x5_UNORM_BLOCK; + if (ktx_strcasecmp(str, "ASTC_8x5_SRGB_BLOCK") == 0) + return VK_FORMAT_ASTC_8x5_SRGB_BLOCK; + if (ktx_strcasecmp(str, "ASTC_8x6_UNORM_BLOCK") == 0) + return VK_FORMAT_ASTC_8x6_UNORM_BLOCK; + if (ktx_strcasecmp(str, "ASTC_8x6_SRGB_BLOCK") == 0) + return VK_FORMAT_ASTC_8x6_SRGB_BLOCK; + if (ktx_strcasecmp(str, "ASTC_8x8_UNORM_BLOCK") == 0) + return VK_FORMAT_ASTC_8x8_UNORM_BLOCK; + if (ktx_strcasecmp(str, "ASTC_8x8_SRGB_BLOCK") == 0) + return VK_FORMAT_ASTC_8x8_SRGB_BLOCK; + if (ktx_strcasecmp(str, "ASTC_10x5_UNORM_BLOCK") == 0) + return VK_FORMAT_ASTC_10x5_UNORM_BLOCK; + if (ktx_strcasecmp(str, "ASTC_10x5_SRGB_BLOCK") == 0) + return VK_FORMAT_ASTC_10x5_SRGB_BLOCK; + if (ktx_strcasecmp(str, "ASTC_10x6_UNORM_BLOCK") == 0) + return VK_FORMAT_ASTC_10x6_UNORM_BLOCK; + if (ktx_strcasecmp(str, "ASTC_10x6_SRGB_BLOCK") == 0) + return VK_FORMAT_ASTC_10x6_SRGB_BLOCK; + if (ktx_strcasecmp(str, "ASTC_10x8_UNORM_BLOCK") == 0) + return VK_FORMAT_ASTC_10x8_UNORM_BLOCK; + if (ktx_strcasecmp(str, "ASTC_10x8_SRGB_BLOCK") == 0) + return VK_FORMAT_ASTC_10x8_SRGB_BLOCK; + if (ktx_strcasecmp(str, "ASTC_10x10_UNORM_BLOCK") == 0) + return VK_FORMAT_ASTC_10x10_UNORM_BLOCK; + if (ktx_strcasecmp(str, "ASTC_10x10_SRGB_BLOCK") == 0) + return VK_FORMAT_ASTC_10x10_SRGB_BLOCK; + if (ktx_strcasecmp(str, "ASTC_12x10_UNORM_BLOCK") == 0) + return VK_FORMAT_ASTC_12x10_UNORM_BLOCK; + if (ktx_strcasecmp(str, "ASTC_12x10_SRGB_BLOCK") == 0) + return VK_FORMAT_ASTC_12x10_SRGB_BLOCK; + if (ktx_strcasecmp(str, "ASTC_12x12_UNORM_BLOCK") == 0) + return VK_FORMAT_ASTC_12x12_UNORM_BLOCK; + if (ktx_strcasecmp(str, "ASTC_12x12_SRGB_BLOCK") == 0) + return VK_FORMAT_ASTC_12x12_SRGB_BLOCK; + if (ktx_strcasecmp(str, "G8B8G8R8_422_UNORM") == 0) + return VK_FORMAT_G8B8G8R8_422_UNORM; + if (ktx_strcasecmp(str, "B8G8R8G8_422_UNORM") == 0) + return VK_FORMAT_B8G8R8G8_422_UNORM; + if (ktx_strcasecmp(str, "G8_B8_R8_3PLANE_420_UNORM") == 0) + return VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM; + if (ktx_strcasecmp(str, "G8_B8R8_2PLANE_420_UNORM") == 0) + return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM; + if (ktx_strcasecmp(str, "G8_B8_R8_3PLANE_422_UNORM") == 0) + return VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM; + if (ktx_strcasecmp(str, "G8_B8R8_2PLANE_422_UNORM") == 0) + return VK_FORMAT_G8_B8R8_2PLANE_422_UNORM; + if (ktx_strcasecmp(str, "G8_B8_R8_3PLANE_444_UNORM") == 0) + return VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM; + if (ktx_strcasecmp(str, "R10X6_UNORM_PACK16") == 0) + return VK_FORMAT_R10X6_UNORM_PACK16; + if (ktx_strcasecmp(str, "R10X6G10X6_UNORM_2PACK16") == 0) + return VK_FORMAT_R10X6G10X6_UNORM_2PACK16; + if (ktx_strcasecmp(str, "R10X6G10X6B10X6A10X6_UNORM_4PACK16") == 0) + return VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16; + if (ktx_strcasecmp(str, "G10X6B10X6G10X6R10X6_422_UNORM_4PACK16") == 0) + return VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16; + if (ktx_strcasecmp(str, "B10X6G10X6R10X6G10X6_422_UNORM_4PACK16") == 0) + return VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16; + if (ktx_strcasecmp(str, "G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16") == 0) + return VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16; + if (ktx_strcasecmp(str, "G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16") == 0) + return VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16; + if (ktx_strcasecmp(str, "G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16") == 0) + return VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16; + if (ktx_strcasecmp(str, "G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16") == 0) + return VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16; + if (ktx_strcasecmp(str, "G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16") == 0) + return VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16; + if (ktx_strcasecmp(str, "R12X4_UNORM_PACK16") == 0) + return VK_FORMAT_R12X4_UNORM_PACK16; + if (ktx_strcasecmp(str, "R12X4G12X4_UNORM_2PACK16") == 0) + return VK_FORMAT_R12X4G12X4_UNORM_2PACK16; + if (ktx_strcasecmp(str, "R12X4G12X4B12X4A12X4_UNORM_4PACK16") == 0) + return VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16; + if (ktx_strcasecmp(str, "G12X4B12X4G12X4R12X4_422_UNORM_4PACK16") == 0) + return VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16; + if (ktx_strcasecmp(str, "B12X4G12X4R12X4G12X4_422_UNORM_4PACK16") == 0) + return VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16; + if (ktx_strcasecmp(str, "G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16") == 0) + return VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16; + if (ktx_strcasecmp(str, "G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16") == 0) + return VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16; + if (ktx_strcasecmp(str, "G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16") == 0) + return VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16; + if (ktx_strcasecmp(str, "G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16") == 0) + return VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16; + if (ktx_strcasecmp(str, "G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16") == 0) + return VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16; + if (ktx_strcasecmp(str, "G16B16G16R16_422_UNORM") == 0) + return VK_FORMAT_G16B16G16R16_422_UNORM; + if (ktx_strcasecmp(str, "B16G16R16G16_422_UNORM") == 0) + return VK_FORMAT_B16G16R16G16_422_UNORM; + if (ktx_strcasecmp(str, "G16_B16_R16_3PLANE_420_UNORM") == 0) + return VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM; + if (ktx_strcasecmp(str, "G16_B16R16_2PLANE_420_UNORM") == 0) + return VK_FORMAT_G16_B16R16_2PLANE_420_UNORM; + if (ktx_strcasecmp(str, "G16_B16_R16_3PLANE_422_UNORM") == 0) + return VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM; + if (ktx_strcasecmp(str, "G16_B16R16_2PLANE_422_UNORM") == 0) + return VK_FORMAT_G16_B16R16_2PLANE_422_UNORM; + if (ktx_strcasecmp(str, "G16_B16_R16_3PLANE_444_UNORM") == 0) + return VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM; + if (ktx_strcasecmp(str, "PVRTC1_2BPP_UNORM_BLOCK_IMG") == 0) + return VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG; + if (ktx_strcasecmp(str, "PVRTC1_4BPP_UNORM_BLOCK_IMG") == 0) + return VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG; + if (ktx_strcasecmp(str, "PVRTC2_2BPP_UNORM_BLOCK_IMG") == 0) + return VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG; + if (ktx_strcasecmp(str, "PVRTC2_4BPP_UNORM_BLOCK_IMG") == 0) + return VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG; + if (ktx_strcasecmp(str, "PVRTC1_2BPP_SRGB_BLOCK_IMG") == 0) + return VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG; + if (ktx_strcasecmp(str, "PVRTC1_4BPP_SRGB_BLOCK_IMG") == 0) + return VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG; + if (ktx_strcasecmp(str, "PVRTC2_2BPP_SRGB_BLOCK_IMG") == 0) + return VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG; + if (ktx_strcasecmp(str, "PVRTC2_4BPP_SRGB_BLOCK_IMG") == 0) + return VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG; + if (ktx_strcasecmp(str, "ASTC_4x4_SFLOAT_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_5x4_SFLOAT_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_5x5_SFLOAT_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_6x5_SFLOAT_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_6x6_SFLOAT_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_8x5_SFLOAT_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_8x6_SFLOAT_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_8x8_SFLOAT_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_10x5_SFLOAT_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_10x6_SFLOAT_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_10x8_SFLOAT_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_10x10_SFLOAT_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_12x10_SFLOAT_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_12x12_SFLOAT_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_3x3x3_UNORM_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_3x3x3_UNORM_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_3x3x3_SRGB_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_3x3x3_SRGB_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_3x3x3_SFLOAT_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_3x3x3_SFLOAT_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_4x3x3_UNORM_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_4x3x3_UNORM_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_4x3x3_SRGB_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_4x3x3_SRGB_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_4x3x3_SFLOAT_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_4x3x3_SFLOAT_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_4x4x3_UNORM_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_4x4x3_UNORM_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_4x4x3_SRGB_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_4x4x3_SRGB_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_4x4x3_SFLOAT_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_4x4x3_SFLOAT_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_4x4x4_UNORM_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_4x4x4_UNORM_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_4x4x4_SRGB_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_4x4x4_SRGB_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_4x4x4_SFLOAT_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_4x4x4_SFLOAT_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_5x4x4_UNORM_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_5x4x4_UNORM_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_5x4x4_SRGB_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_5x4x4_SRGB_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_5x4x4_SFLOAT_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_5x4x4_SFLOAT_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_5x5x4_UNORM_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_5x5x4_UNORM_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_5x5x4_SRGB_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_5x5x4_SRGB_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_5x5x4_SFLOAT_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_5x5x4_SFLOAT_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_5x5x5_UNORM_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_5x5x5_UNORM_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_5x5x5_SRGB_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_5x5x5_SRGB_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_5x5x5_SFLOAT_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_5x5x5_SFLOAT_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_6x5x5_UNORM_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_6x5x5_UNORM_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_6x5x5_SRGB_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_6x5x5_SRGB_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_6x5x5_SFLOAT_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_6x5x5_SFLOAT_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_6x6x5_UNORM_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_6x6x5_UNORM_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_6x6x5_SRGB_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_6x6x5_SRGB_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_6x6x5_SFLOAT_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_6x6x5_SFLOAT_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_6x6x6_UNORM_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_6x6x6_UNORM_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_6x6x6_SRGB_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_6x6x6_SRGB_BLOCK_EXT; + if (ktx_strcasecmp(str, "ASTC_6x6x6_SFLOAT_BLOCK_EXT") == 0) + return VK_FORMAT_ASTC_6x6x6_SFLOAT_BLOCK_EXT; + if (ktx_strcasecmp(str, "A4R4G4B4_UNORM_PACK16_EXT") == 0) + return VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT; + if (ktx_strcasecmp(str, "A4B4G4R4_UNORM_PACK16_EXT") == 0) + return VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT; + return VK_FORMAT_UNDEFINED; +}