Skip to content

Proposal: Add KHR_DF_FLAG_OPAQUE semantic flag for opaque textures #30

Open

Description

@Unarmed1000

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.

References:

I am not sure if this repo is the best place to do the proposal or its https://github.com/KhronosGroup/KTX-Software. so I created the proposal in both places. link

Activity

  1. MarkCallow commented on Dec 18, 2025

    @MarkCallow
    Collaborator

    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_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?

  2. MarkCallow commented on Dec 18, 2025

    @MarkCallow
    Collaborator

    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.

  3. lexaknyazev commented on Dec 18, 2025

    @lexaknyazev
    Member

    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.

  4. lexaknyazev commented on Dec 18, 2025

    @lexaknyazev
    Member

    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).

  5. Unarmed1000 commented on Dec 18, 2025

    @Unarmed1000
    Author

    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.

  6. Unarmed1000 commented on Dec 18, 2025

    @Unarmed1000
    Author

    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.

  7. fluppeteer commented on Dec 20, 2025

    @fluppeteer
    Collaborator

    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.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions