Failed to load KTX2 texture data: Error: KTX2 container - could not transcode the data. TypeError: Cannot convert "undefined" to unsigned int

Hi, we are getting an error with our textures that we converted to KTX2.

See warnings in playground here: https://playground.babylonjs.com/#20OAV9#10002.

We are converting the KTX2 files using the khronos provided converters. Our python code looks like:

# Convert to KTX2
        tempName = os.path.splitext(filePath)[0] + '-uncompressed.ktx2'
        procresult = subprocess.run(['toktx',
                                      '--t2',
                                      tempName,
                                      filePath],
                                    stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        checkProcType(procresult, "Error converting texture (KTX2) (OUT: " + tempName + ") : (IN: " + filePath + ")")

        newName = os.path.splitext(filePath)[0] + '.ktx2'
        # Supercompress KTX2
        procresult = subprocess.run(['ktxsc',
                                      '-zcmp',
                                      '-o',
                                      newName,
                                      tempName],
                                    stdout=subprocess.PIPE, stderr=subprocess.PIPE)

Any ideas on what may be happening or what that error is telling us?

We even used the ktx2 checker provided by khronos and it reports it as a valid ktx2 file.

Side note, we’re 90% certain this worked several weeks ago, so no sure if anything has changed with the transcoder in the last few weeks.

@bghgary @Evgeni_Popov any ideas what could it be ?

Sorry to hijack your topic, but i was looking into a way to make ktx2 conversion part of the Blender exporter. All i had seen was C based code.

While i had previously made a DLL for Blender to directly connect a Kinect 2 motion capture device, that seems inferior to a Python based system. Where did you get it?

Just something we wrote. Not a blender plugin or anything, part of a larger texture conversion system that takes in pngs and spits out a variety of image formats in different LODs.

We don’t support R8G8B8 SRGB in the KTX2 decoder, try R8G8B8A8 SRGB instead.

Will give that a try monday and report back! Thank you! Is any of the ktx2 requirements for babylonjs documented anywhere?

Here are all of the supported KTX2 decoder types for Babylon.js:

Here is also a list of supported formats for KTX texture containers for WebGL:


Unrelated, for those unsure what the differences are between KTX and KTX2, here’s a good summary:

Still failing, see https://playground.babylonjs.com/#20OAV9#10015 (only the first texture was converted to R8G8B8A8 SRGB (https://storage.googleapis.com/vcassets/production/vcn/var/000006/0000786f/Texture/1025.ktx2).

New code to transform is

toktx --t2 --target_type RGBA test-uncompressed.ktx2 1024.png
ktxsc -zcmp -o 1025.ktx2 test-uncompressed.ktx2

Attached the KTX info as well:

ktxinfo 1025.ktx2
Header

identifier: «KTX 20»\r\n\x1A\n
vkFormat: VK_FORMAT_R8G8B8A8_SRGB
typeSize: 1
pixelWidth: 1024
pixelHeight: 1024
pixelDepth: 0
layerCount: 0
faceCount: 1
levelCount: 1
supercompressionScheme: KTX_SS_ZSTD
dataFormatDescriptor.byteOffset: 0x68
dataFormatDescriptor.byteLength: 92
keyValueData.byteOffset: 0xc4
keyValueData.byteLength: 108
supercompressionGlobalData.byteOffset: 0
supercompressionGlobalData.byteLength: 0

Level Index

Level0.byteOffset: 0x130
Level0.byteLength: 376387
Level0.uncompressedByteLength: 4194304

Data Format Descriptor

DFD total bytes: 92
BDB descriptor type 0x0000 vendor id = 0x00000
Descriptor block size 88 (4 samples) versionNumber = 0x0002
Flags 0x00 Xfer 02 Primaries 01 Model 001
Dimensions: 1,1,1,1
Plane bytes: 0,0,0,0,0,0,0,0
    Sample 0
Qualifiers 0 Channel 0x0 (R) Length 8 bits Offset 0
Position: 0,0,0,0
Lower 0x00000000
Upper 0x000000ff
    Sample 1
Qualifiers 0 Channel 0x1 (G) Length 8 bits Offset 8
Position: 0,0,0,0
Lower 0x00000000
Upper 0x000000ff
    Sample 2
Qualifiers 0 Channel 0x2 (B) Length 8 bits Offset 16
Position: 0,0,0,0
Lower 0x00000000
Upper 0x000000ff
    Sample 3
Qualifiers 1 Channel 0xf (A) Length 8 bits Offset 24
Position: 0,0,0,0
Lower 0x00000000
Upper 0x000000ff

Key/Value Data

KTXorientation: rd
KTXwriter: ktxsc v4.0.0-beta6~6 / libktx v4.0.0~5
KTXwriterScParams: -zcmp

The current code for the MSC transcoder module needs that supercompressionGlobalData have non empty data to work in the ETC1S case. I will have to see if we can do something about it.

It seems that not specifying an encoding scheme with ktxsc will generate a ETC1S encoded file. But Zstandard compression (--zcmp) is not supported for ETC1S. Excerpt from ktxsc -h:

  --zcmp [<compressionLevel>]
               Supercompress the data with Zstandard. Implies --t2. Can be used
               with data in any format except ETC1S / BasisLZ. Most
               effective with RDO-conditioned UASTC or uncompressed formats. The
               optional compressionLevel range is 1 - 22 and the default is 3.
               Lower values=faster but give less compression. Values above 20
               should be used with caution as they require more memory.

So, you should either use UASTC if you want to compress with Zstandard, or select the ETC1S compression scheme:

  • ktxsc --encode uastc --zcmp -o 1025.ktx2 test-uncompressed.ktx2
  • ktxsc --encode etc1s -o 1025.ktx2 test-uncompressed.ktx2

This was it!! Quick question on the compressionLevel. Is “speed” affect the speed of de-compression at runtime? or only the speed of the conversion to initially compress it. Because we dont care about the speed of compression, but we absolutely care about decompression.

Also for anyone coming along with same problem, we were able to change back to RGB instead of RGBA and have it still work. Was just the ESTC1S vs UASTC

In my understanding, the compression level affects the speed only at the compression stage.

Thanks!