You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Proposal: Add KHR_DF_FLAG_OPAQUE semantic flag for opaque textures #30
Currently, the Data Format Descriptor (DFD) supports the KHR_DF_FLAG_ALPHA_PREMULTIPLIED flag to indicate premultiplied alpha. However, there is no semantic flag to indicate that a texture is guaranteed to be fully opaque. This is particularly relevant for formats like ASTC, which can encode either opaque or transparent content depending on the encoder. Runtime engines and asset pipelines cannot reliably infer opacity from the format alone, which can lead to conservative rendering decisions or unnecessary blending operations.
Proposed Solution:
Introduce a new semantic flag in the Data Format Descriptor:
#define KHR_DF_FLAG_OPAQUE
Behavior:
Set when the texture is guaranteed to contain only opaque pixels (alpha = 1.0 for all pixels).
Mutually exclusive with KHR_DF_FLAG_ALPHA_PREMULTIPLIED and other alpha-related flags.
Optional and non-breaking; absence of the flag indicates no guarantee about opacity.
Rationale / Use Cases:
ASTC textures: Encoders often know that content is fully opaque but the format allows alpha. This flag communicates that guarantee.
Engine optimization: Renderers can skip alpha blending or enable more efficient paths.
Asset validation: Tools can automatically detect and enforce opaque-only usage.
Cross-API semantics: Provides a standardized way to communicate opacity regardless of runtime API.
Implementation Note:
Assign a new unique bit in the KHR_DF_FLAG enum.
Define interactions: setting both OPQUE and PREMULTIPLIED should be invalid.
No runtime decoding required; engines can rely on the flag metadata.
Absence of a sample with the channel id for alpha indicates no alpha for many formats. This is admittedly not as easy as querying a flag.
For the specific case of ASTC we are planning to introduce a new KHR_DF_CHANNEL_ASTC_RGB channel id value to identify when the texture has no alpha. Are there other formats beyond ASTC where this is an issue or will this meet your need?
@fluppeteer which way of signalling opaque do you prefer?
I prefer KHR_DF_CHANNEL_ASTC_RGB because it follows the same model we've used to indicate the type of content in the universal formats, e.g, ETC1S, to help select the best transcode target.
However, there is no semantic flag to indicate that a texture is guaranteed to be fully opaque.
That's the key point here. A texture format (raw, packed, or compressed) may contain an alpha channel but that channel may be known to be unused and/or fully opaque. Although we could have shortcuts for the most common cases (like with universal compression), such shortcuts do not solve the generic issue, so I'd say these questions are orthogonal.
For example, it's quite common to use RGBA8 even if the alpha channel is opaque because "proper" RGB8 is usually not supported in hardware. The DFD can technically represent the extra padding bytes but such layouts would be more difficult to handle in the tools (think about matching DFD to the Vulkan format enums).
I think the purpose of an image container is to carry enough semantic information that a generic engine can handle the image safely by making reasonable assumptions aligned with the common and intended use case.
From an engine’s perspective, it is important to know, for example, whether the encoder intends the image to be rendered as transparent or opaque. Relying purely on format-based assumptions is insufficient here, and you already provided a concrete example where today’s format-derived assumptions lead to non-optimal behavior for certain use cases, resulting in slower rendering (not limited to ASTC).
It is already possible to detect the presence of alpha values outside 1.0f (255) and use that information to set an explicit flag. This detection is already performed during ASTC encoding; the information is simply not preserved in the current implementation. If automatic detection is considered insufficient, this could also be exposed as an explicit encoding parameter to force the flag. Treating images as transparent is always a safe but slower default, whereas marking an image as opaque requires certainty but enables more efficient rendering paths.
As a user of KTX, I can of course embed my own metadata at encode time, but that only works for my own files and my own engine. A standardized opaque “hint” flag, on the other hand, could be used to make better decisions across engines and tools.
This would benefit both ASTC textures and the very common case of using R8G8B8A8 to encode fully opaque images (effectively R8G8B8X8). Having this intent expressed explicitly avoids format-based guesswork and enables more efficient and consistent handling across implementations.
Today, I have seen multiple KTX viewers that decompress textures to raw formats and then scan the alpha channel to make an informed decision. For GPU-optimized formats, this kind of CPU-side processing is wasteful and largely defeats the purpose of using such containers in the first place.
In the case of RGBA where the alpha channel is to be ignored and assumed to be solid, there are already separate samples for each channel and the texel block size is orthogonal; RGBX is encoded without needing to say anything about X directly. Technically you could be explicit about what a channel contains using the "constant virtual bits" in 5.17.3 of 1.4 and we should perhaps be clearer that a missing alpha channel should be interpreted as 1.0 (and maybe 0.0 for colour channels?) but I think it's convention that a missing alpha is opaque.
It's true though that this doesn't work for ASTC (or other compressed formats) which don't have the channels listed explicitly, because they're not stored independently. Some compressed formats do let this work, but I think Mark is right - ignoring the alpha channel in ASTC makes some sense, and encoding that as a separate channel type (as with BC1A) seems the better solution. Using a flag feels a little wasteful given that it won't be needed in a lot of formats.
I've forgotten, though - did we say the RGB-only version should indicate that no endpoints should be modes that include alpha, or ignore alpha even if it's there? (Not that hardware will be able to do much to make that distinction.)
Activity
MarkCallow commentedon Dec 18, 2025
Thank you for your suggestion.
Absence of a sample with the channel id for alpha indicates no alpha for many formats. This is admittedly not as easy as querying a flag.
For the specific case of ASTC we are planning to introduce a new
KHR_DF_CHANNEL_ASTC_RGBchannel id value to identify when the texture has no alpha. Are there other formats beyond ASTC where this is an issue or will this meet your need?@fluppeteer which way of signalling opaque do you prefer?
MarkCallow commentedon Dec 18, 2025
I prefer
KHR_DF_CHANNEL_ASTC_RGBbecause it follows the same model we've used to indicate the type of content in the universal formats, e.g, ETC1S, to help select the best transcode target.lexaknyazev commentedon Dec 18, 2025
That's the key point here. A texture format (raw, packed, or compressed) may contain an alpha channel but that channel may be known to be unused and/or fully opaque. Although we could have shortcuts for the most common cases (like with universal compression), such shortcuts do not solve the generic issue, so I'd say these questions are orthogonal.
lexaknyazev commentedon Dec 18, 2025
For example, it's quite common to use RGBA8 even if the alpha channel is opaque because "proper" RGB8 is usually not supported in hardware. The DFD can technically represent the extra padding bytes but such layouts would be more difficult to handle in the tools (think about matching DFD to the Vulkan format enums).
Unarmed1000 commentedon Dec 18, 2025
I think the purpose of an image container is to carry enough semantic information that a generic engine can handle the image safely by making reasonable assumptions aligned with the common and intended use case.
From an engine’s perspective, it is important to know, for example, whether the encoder intends the image to be rendered as transparent or opaque. Relying purely on format-based assumptions is insufficient here, and you already provided a concrete example where today’s format-derived assumptions lead to non-optimal behavior for certain use cases, resulting in slower rendering (not limited to ASTC).
It is already possible to detect the presence of alpha values outside 1.0f (255) and use that information to set an explicit flag. This detection is already performed during ASTC encoding; the information is simply not preserved in the current implementation. If automatic detection is considered insufficient, this could also be exposed as an explicit encoding parameter to force the flag. Treating images as transparent is always a safe but slower default, whereas marking an image as opaque requires certainty but enables more efficient rendering paths.
Unarmed1000 commentedon Dec 18, 2025
As a user of KTX, I can of course embed my own metadata at encode time, but that only works for my own files and my own engine. A standardized opaque “hint” flag, on the other hand, could be used to make better decisions across engines and tools.
This would benefit both ASTC textures and the very common case of using R8G8B8A8 to encode fully opaque images (effectively R8G8B8X8). Having this intent expressed explicitly avoids format-based guesswork and enables more efficient and consistent handling across implementations.
Today, I have seen multiple KTX viewers that decompress textures to raw formats and then scan the alpha channel to make an informed decision. For GPU-optimized formats, this kind of CPU-side processing is wasteful and largely defeats the purpose of using such containers in the first place.
fluppeteer commentedon Dec 20, 2025
In the case of RGBA where the alpha channel is to be ignored and assumed to be solid, there are already separate samples for each channel and the texel block size is orthogonal; RGBX is encoded without needing to say anything about X directly. Technically you could be explicit about what a channel contains using the "constant virtual bits" in 5.17.3 of 1.4 and we should perhaps be clearer that a missing alpha channel should be interpreted as 1.0 (and maybe 0.0 for colour channels?) but I think it's convention that a missing alpha is opaque.
It's true though that this doesn't work for ASTC (or other compressed formats) which don't have the channels listed explicitly, because they're not stored independently. Some compressed formats do let this work, but I think Mark is right - ignoring the alpha channel in ASTC makes some sense, and encoding that as a separate channel type (as with BC1A) seems the better solution. Using a flag feels a little wasteful given that it won't be needed in a lot of formats.
I've forgotten, though - did we say the RGB-only version should indicate that no endpoints should be modes that include alpha, or ignore alpha even if it's there? (Not that hardware will be able to do much to make that distinction.)