Vixen
dd8b0a81
csharp
public static class Ktx2

Reads and writes the KTX2 container.

No guide page documents this yet — the page shows what the code says about itself.

Remarks

KTX2 is what a Vixen build ships textures in, and the runtime reads it with this rather than with an image codec: the bytes in the file are the bytes the GPU wants, so loading a texture is a header parse and an upload. That is also why Vixen.Core.Imaging has no PNG decoder — decoding a PNG is import-time work, and ADR-015 keeps ImageSharp out of every runtime assembly for licence reasons as well.

Level data is stored smallest first. The level index is ordered largest first, but the bytes it points at run the other way, so a streaming loader can read the small mips off the front of the file and show something before the rest has arrived. It is the one part of the format that reads like a mistake and is not, so it is the part most worth a test.

What is implemented: the identifier, the header, the level index, the data format descriptor, and level data for uncompressed and block-compressed formats. What is not: supercompression — neither Basis Universal nor Zstd — and therefore supercompression global data, which is written as absent and refused on read. A build that wants smaller bundles compresses the chunk the texture lives in, which [08](../../../docs/plan/08-asset-pipeline-and-addressables.md) already does per bundle.

Key/value data is not implemented either, and this text used to say it was. Write writes kvdByteOffset and kvdByteLength as zero and ReadLayout never looks at them, so there is no channel from an importer's settings to the runtime through this container. That is worth stating rather than leaving to be discovered: doc 08's streaming: true flag reads as though it had somewhere to go, and it has not. See [Streaming texture mip tails](../../../docs/guide/rendering/texture-streaming.md) for why nothing needs one.

What Khronos's validator says. Ktx2ConformanceTests puts a file of every format and every container shape past ktx validate --warnings-as-errors, and they pass. ⚠ All twenty-two of them failed the first time it ran — level padding, alpha's channelType, float qualifiers, BC3 and BC5's sample counts, and three VkFormat numbers, one of which named the signed BC6H block for the unsigned payload this engine writes. Every one of those had a hand-computed fixture agreeing with it, because the fixture and the code encode the same reading of the specification. "Valid KTX2" is no longer a claim about intent.

What it still is. Nothing has fed this a file written by another implementation, so Read's tolerance of layouts this would not itself choose is untested. Writing is verified; reading is not.

Fields and properties (3)

  • public static ReadOnlySpan<byte> Identifier

    The twelve bytes every KTX2 file starts with.

  • public const int HeaderLength

    How long the header is, up to and including the supercompression global data pointers.

  • public const int LevelIndexEntryLength

    How long one level index entry is.

Methods (8)

  • public static byte[] Write(TextureData texture)

    Writes a texture.

  • public static TextureData Read(ReadOnlySpan<byte> file)

    Reads a texture.

  • public static int LayoutLength(ReadOnlySpan<byte> head)

    How many bytes of the front of a file ReadLayout needs.

  • public static Ktx2Layout ReadLayout(ReadOnlySpan<byte> file)

    Reads what a file says about itself, without reading a pixel of it.

  • public static TextureData ReadTail(ReadOnlySpan<byte> file, Ktx2Layout layout, int firstLevel)

    Reads a mip tail: every level from one down to the smallest, and nothing above it.

  • public static ValueTask<Ktx2Layout> ReadLayoutAsync(Stream stream, CancellationToken cancellation = default(CancellationToken))

    Reads what a stream's file says about itself, without reading a pixel of it.

  • public static ValueTask<TextureData> ReadTailAsync(Stream stream, Ktx2Layout layout, int firstLevel, CancellationToken cancellation = default(CancellationToken))

    Reads a mip tail out of a stream, touching only the bytes it needs.

  • public static ValueTask<int> ReadLevelAsync(Stream stream, Ktx2Layout layout, int level, Memory<byte> destination, CancellationToken cancellation = default(CancellationToken))

    Reads one level out of a stream, touching only the bytes it needs.

Used by (17)

  • AssetTextureSourceVixen.Engine.Renderer
  • AssetTextureSourceTestsVixen.Engine.Renderer.Tests
  • AssetTextureStreamingTestsVixen.Engine.Renderer.Tests
  • BlockCompressorTestsVixen.Core.Imaging.Tests
  • FilesVixen.Engine.Renderer.Tests
  • Ktx2ConformanceTestsVixen.Core.Imaging.Tests
  • Ktx2TestsVixen.Core.Imaging.Tests
  • TextureDemandTestsVixen.Engine.Renderer.Tests
  • WorldRendererTestsVixen.Engine.Renderer.Tests
  • CubeLutImporterVixen.Editor.Assets
  • DdsImportTestsVixen.Editor.Assets.Tests
  • HdrImportTestsVixen.Editor.Assets.Tests
  • Ktx2DecoderVixen.Editor.Assets
  • MaterialBakeVixen.Editor.Assets
  • MaterialBakeTestsVixen.Editor.Assets.Tests
  • TextureImporterVixen.Editor.Assets
  • TextureImporterTestsVixen.Editor.Assets.Tests