Skip to content

ByteAddressBuffer::Store<min16int/min16uint>() crashes for integer min precision types #8322

@alsepkow

Description

@alsepkow

Problem

ByteAddressBuffer::Store<min16int>() (and other min precision scalar/vector template stores) crashes during compilation with llvm::cast<X>() argument of incompatible type!.

The crash occurs in TranslateMinPrecisionRawBuffer (DxilGenerationPass.cpp), specifically in ReplaceMinPrecisionRawBufferStoreByType. The code does cast<StructType>(STy->getElementType(0)) to look up struct type annotations for signedness. For ByteAddressBuffer, the resource type is { i32 }, so getElementType(0) returns i32 (not a StructType), and the cast asserts.

This is a pre-existing bug — these template stores have never worked for min precision types on ByteAddressBuffer.

Why this can't be fixed in DxilGen

The TranslateMinPrecisionRawBuffer pass needs signedness information to choose between sext (signed) and zext (unsigned) when widening from 16-bit to 32-bit. For StructuredBuffers, this comes from struct type annotations. For ByteAddressBuffer, there are no struct annotations — it's a raw buffer.

An incomplete fix was attempted in PR #8274 (falling back to sext when no annotation exists), but this is wrong for min16uint and was reverted in PR #8321.

Proposed fix: widen during Clang CodeGen

At CodeGen time, signedness information is still available from the HLSL type system. For scalar/vector (non-struct) template stores on ByteAddressBuffer, the widening from 16-bit to 32-bit min precision types should be performed during CodeGen, before the information is lost.

This is simpler than the StructuredBuffer case, where embedded 16-bit types in structs would require recreating storage struct types, replacing subscript calls, and recursing through all GEP and instruction users. For scalar/vector types, the widening can be applied directly.

Open question

For templated Load/Store, is the struct type annotation captured? There has been prior work to prevent loss of type annotation information for similar cases, but it's unclear if this path is currently covered. If annotations are available, the existing TranslateMinPrecisionRawBuffer logic could potentially be extended instead.

Repro

RWByteAddressBuffer g_buf : register(u0);
[numthreads(1,1,1)]
void main() {
  min16int si = (min16int)1;
  g_buf.Store<min16int>(0, si);  // crashes
}

Compile with: dxc -E main -T cs_6_2 repro.hlsl

Related

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