MCPcopy Create free account
hub / github.com/KhronosGroup/KTX-Software / validateLevelIndex

Method validateLevelIndex

tools/ktx/validate.cpp:648–736  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

646}
647
648void ValidationContext::validateLevelIndex() {
649 levelIndices.resize(numLevels);
650
651 const auto levelIndexOffset = sizeof(KTX_header2);
652 const auto levelIndexSize = sizeof(ktxLevelIndexEntry) * numLevels;
653 read(levelIndexOffset, levelIndices.data(), levelIndexSize, "the level index");
654
655 const auto blockByteLength = (expectedBytePlanes ? expectedBytePlanes->at(0) : (parsedBlockByteLength == 0 ? uint8_t(1) : parsedBlockByteLength.value_or(0)));
656 std::size_t requiredLevelAlignment = calcLevelAlignment(ktxSupercmpScheme(header.supercompressionScheme), blockByteLength);
657
658 std::size_t expectedFirstLevelOffset = 0;
659 if (header.supercompressionGlobalData.byteLength != 0)
660 expectedFirstLevelOffset = header.supercompressionGlobalData.byteLength + header.supercompressionGlobalData.byteOffset;
661 else if (header.keyValueData.byteLength != 0)
662 expectedFirstLevelOffset = header.keyValueData.byteLength + header.keyValueData.byteOffset;
663 else if (header.dataFormatDescriptor.byteLength != 0)
664 expectedFirstLevelOffset = header.dataFormatDescriptor.byteLength + header.dataFormatDescriptor.byteOffset;
665 else
666 expectedFirstLevelOffset = levelIndexOffset + levelIndexSize;
667 expectedFirstLevelOffset = align(expectedFirstLevelOffset, requiredLevelAlignment);
668
669 // The first (largest) mip level is the first in the index and the last in the file.
670 for (std::size_t i = 1; i < levelIndices.size(); ++i) {
671 if (levelIndices[i].uncompressedByteLength > levelIndices[i - 1].uncompressedByteLength)
672 error(LevelIndex::IncorrectIndexOrder, i - 1, levelIndices[i - 1].uncompressedByteLength, i, levelIndices[i].uncompressedByteLength);
673
674 if (levelIndices[i].byteOffset > levelIndices[i - 1].byteOffset)
675 error(LevelIndex::IncorrectLevelOrder, i - 1, levelIndices[i - 1].byteOffset, i, levelIndices[i].byteOffset);
676 }
677
678 std::size_t lastByteOffset = expectedFirstLevelOffset; // Reuse lastByteOffset to inject first offset to expectedOffset
679 std::size_t lastByteLength = 0;
680
681 // Count down, so we can check the distance between levels for the UNDEFINED and SUPERCOMPRESSION cases.
682 for (auto it = static_cast<uint32_t>(levelIndices.size()); it != 0; --it) {
683 const auto index = it - 1;
684 const auto& level = levelIndices[index];
685
686 // Validate byteOffset
687 const auto knownLevelOffset = header.vkFormat != VK_FORMAT_UNDEFINED &&
688 header.supercompressionScheme == KTX_SS_NONE;
689 // If the exact level sizes are unknown we have to trust the byteLengths.
690 // In that case we know where the first level must be in the file, and we can calculate
691 // the offsets by progressively summing the lengths and paddings so far.
692 const auto expectedOffset = knownLevelOffset ?
693 calcLevelOffset(expectedFirstLevelOffset, requiredLevelAlignment, index) :
694 align(lastByteOffset + lastByteLength, requiredLevelAlignment);
695
696 if (level.byteOffset % requiredLevelAlignment != 0)
697 error(LevelIndex::IncorrectByteOffsetUnaligned, index, level.byteOffset, requiredLevelAlignment, expectedOffset);
698 else if (level.byteOffset != expectedOffset)
699 error(LevelIndex::IncorrectByteOffset, index, level.byteOffset, expectedOffset);
700
701 // Workaround: Disable ByteLength validations for the 3D ASTC encoder which currently ignores partial Z blocks in our test files
702 const auto disableByteLengthValidation = isFormat3DBlockCompressed(VkFormat(header.vkFormat))
703 && header.pixelDepth % (expectedBlockDimension2.value_or(0) + 1) != 0;
704
705 if (!disableByteLengthValidation) {

Callers

nothing calls this directly

Calls 12

calcLevelAlignmentFunction · 0.85
errorFunction · 0.85
atMethod · 0.80
alignFunction · 0.70
readFunction · 0.50
ktxSupercmpSchemeEnum · 0.50
VkFormatEnum · 0.50
maxFunction · 0.50
resizeMethod · 0.45
dataMethod · 0.45
sizeMethod · 0.45

Tested by

no test coverage detected