Skip to main content

TSMPCodec

Namespace: K13A.TSMP

Base type for codec handlers.

A codec handler tells the encoder how to write payload bytes into pixels and tells the decoder which material/options should be used to recover payload bytes.

Public fields​

FieldTypeUse
codecIdushortStable codec ID written into the frame header.
displayNamestringEditor-facing name.
codecOptionBytesbyte[]Decoder-side option bytes copied from the frame header.
selectedDecodeMaterialMaterialMaterial used for byte decode.
calibrationMaterialMaterialOptional preparation material assigned on the codec prefab; hidden in the ordinary Inspector.
payloadStartRowintFirst payload row for decode.
payloadBlockCountintNumber of payload blocks to decode.
byteCountintRequested payload byte count.

Runtime encoder query result fields are public for Udon event bridge use. They are assigned by OnTSMPEncoderQuery() and OnTSMPEncoderWritePayload().

Runtime encode methods​

MethodUse
GetEncoderSymbolMode()Return symbol mode for frame header.
GetEncoderPayloadStartRow(width, blockSize)Return first payload row.
GetEncoderPayloadCapacityBytes(width, height, blockSize)Return payload byte capacity.
GetEncoderCodecOptionByteCount()Return option byte count, max 5.
GetEncoderCodecOptionByte(index)Return one option byte.
WriteEncoderPayload(...)Write payload bytes into encoder pixels.
ApplyDecodeOptions()Apply decoder state from header/options.

These methods must be UdonSharp-compatible if the codec should run inside VRChat.

Helper methods​

MethodUse
ReadCodecOptionByte(index, fallback)Read one codec option with fallback.
ReadCodecOptionFlag(index, fallback)Read one option as a boolean.
GetEncoderActiveWidthBlocks(width, blockSize)Calculate writable block width.
GetEncoderActiveHeightBlocks(height, blockSize)Calculate writable block height.
WriteEncoderColorBlockAtIndex(...)Fill one encoded block with a color.
ReadEncoderBits(...)Read arbitrary bits from payload bytes.

Editor/native methods​

Available outside COMPILER_UDONSHARP:

MethodUse
SymbolModeNative symbol mode property.
TryWriteFrame(...)Write complete frame into a Texture2D.
TryWriteFrameBuffered(..., ref Color32[] pixels, out string error)Optional native writer that reuses an encoder-owned raster buffer. The default calls TryWriteFrame, so existing codecs remain compatible.
SupportsGpuLuma4EncodingOptional native opt-in, false by default. True lets the encoder use the standard Luma4 GPU raster writer. Only opt in when the codec uses the unchanged Luma4 palette, header layout and byte-to-nibble mapping.
GetCodecOptionBytes()Native codec option byte array.
DecodeMaterialCountNumber of decode materials.
GetDecodeMaterial(index)Decode material lookup.
DebugMaterialCountNumber of debug materials.
GetDebugMaterial(index)Debug material lookup.
ConfigureMaterials(context)Configure decode/debug materials.

Udon event bridge​

TSMPCodec exposes public event methods used by the encoder:

MethodPurpose
OnTSMPEncoderQuery()Populates encoder query result fields.
OnTSMPEncoderWritePayload()Calls WriteEncoderPayload and stores the result.

The encoder uses this bridge so optional codec packages can be called without hard-coding codec classes.

The Udon Encoder queries once per encoding attempt, so changing options on the same codec instance updates its capacity, payload row and header options together. Getters should be inexpensive and side-effect-free. A query result is reused within that attempt, not across subsequent encodes.

OnTSMPEncoderQuery() also populates encoderQueryValues, a reused int[10]: codec ID, symbol mode, payload start row, capacity in bytes, option count, then five option bytes. The bridge reads this array in one call. Treat it as a read-only result that changes on the next query, not as persistent configuration. Existing individual result fields remain available; custom codecs continue to override the same getters and need no codec-specific invalidation API.

Runtime decode preparation​

PrepareDecode(Texture source, Material material) is called immediately before each header or payload byte pass, after the decoder has assigned the source dimensions, sample size, byte count and layout. TSMPDecoder supplies its owned input snapshot to this hook and the following byte Blit, keeping header and payload on the same captured image. Do not modify or release the supplied texture. Callers outside TSMPDecoder must capture or otherwise stabilize their own input. Override the hook for optional GPU preparation, and call base.PrepareDecode(source, material) first to clear the previous LUT keyword. Existing codecs need no override.

The protected GetDecodeSampleSize(material) helper resolves automatic sampling and clamps it to the block size, matching the decode shader. PrepareCalibrationLut(source, material, width) renders the assigned calibrationMaterial into a reusable, one-row, linear ARGBFloat texture. It copies the byte material's properties to the preparation material, binds the result as _CalibrationLut, and enables the local TSMP_CALIBRATION_LUT keyword. Declare both shader variants with #pragma multi_compile_local _ TSMP_CALIBRATION_LUT so they survive Player builds.

Assign the preparation material on the codec prefab. Its shader must write every LUT texel and must not read the LUT being written. Keep an ordinary decode variant for missing resources, unsupported Float32 allocation, empty output and modes where the extra pass is slower. Do not quantize calibration values to Half or 8-bit: this can change decoded bytes. The LUT is refreshed per pass, not reused across frames.

The base class releases its LUT on disable and destruction. If a codec overrides either lifecycle method, call the base implementation. Direct callers of the preparation hook must set the same material properties as the decoder and perform the byte blit immediately afterwards.

MemberContract
public virtual void PrepareDecode(Texture source, Material material)Per-pass hook; no return value. The base disables LUT use and clears its previous material binding when the material changes.
protected int GetDecodeSampleSize(Material material)Requires a non-null material. _SampleSize > 0.5 uses its floored value; otherwise the default is 4 for blocks at least 8 pixels, or 3. The result is clamped to 1..min(blockSize, 8).
protected void PrepareCalibrationLut(Texture source, Material material, int width)Requires the base hook first. width counts LUT entries, not byte-output pixels. Allocates/reuses width x 1, copies material properties, draws the preparation shader, binds _CalibrationLut and enables the keyword only after successful texture creation.
protected virtual void OnDisable() / OnDestroy()Clear the owned LUT binding, release and destroy the generated texture. Do not destroy the assigned materials.

Missing inputs, non-positive width or _ByteCount, a non-ARGBFloat result, or failed texture creation leaves the ordinary shader path selected when the base hook was called. Native compilation additionally checks preparation shader support and SystemInfo.SupportsRenderTextureFormat; those checks are not compiled into Udon. This is not a guarantee that a shader with an implementation error will recover automatically.

The material arguments and calibrationMaterial are mutable, externally assigned references. The hook does not clone them. Setup owns its prepared material copies; independent integrations must manage material sharing and lifetime themselves. Allocation reuse does not mean reuse of calibration values across passes.

See the implementation guide for the Luma4 hook and the shader guide for preparation output, keyword variants and LUT reads.