Skip to content

Fix dropped alignment operand in byteAddressBufferLoad specialization#1

Open
stramit wants to merge 1 commit into
masterfrom
claude/sweet-darwin-AoOG8
Open

Fix dropped alignment operand in byteAddressBufferLoad specialization#1
stramit wants to merge 1 commit into
masterfrom
claude/sweet-darwin-AoOG8

Conversation

@stramit

@stramit stramit commented May 28, 2026

Copy link
Copy Markdown
Owner

Summary

specializeFuncsForBufferLoadArgs lumped kIROp_ByteAddressBufferLoad in with the generic two-operand "element access" instructions (GetElement, StructuredBufferLoad, etc.) in both gatherCallInfoForArg and getSpecializedValueForArg. byteAddressBufferLoad actually has three operands — (buffer, offset, alignment) — so the rewritten load inside the specialized callee was constructed with only two operands.

Downstream, legalizeByteAddressBufferOps::processLoad unconditionally reads operand index 2 to recover the alignment, hitting:

assert failure: slang-ir.h(710): index < getOperandCount()

during SPIR-V emission.

Repro

A struct large enough to trip the buffer-load specialization threshold, loaded via Buf.Load<T>() and passed by value into a helper:

struct Frame
{
    float4x4 a;
    float4x4 b;
    float3 v;
    float pad;
};

float3 makeRay(Frame f)
{
    float4 w = mul(float4(0, 0, 0, 1), f.b);
    return w.xyz + f.v;
}

uniform ByteAddressBuffer buf;
uniform RWTexture2D<float4> outTexture;
uniform uint width;
uniform uint height;

[shader("compute")]
[numthreads(8, 8, 1)]
void computeMain(uint3 dtid : SV_DispatchThreadID)
{
    if (dtid.x >= width || dtid.y >= height) return;
    Frame f = buf.Load<Frame>(0);
    outTexture[dtid.xy] = float4(makeRay(f), 1);
}

slangc repro.slang -target spirv -O0 -fvk-use-scalar-layout aborts with the assertion above.

Fix

Give byteAddressBufferLoad dedicated handling in both functions so the alignment operand survives specialization, and remove it from isElementAccessInst since it doesn't share the two-operand shape.

Test plan

  • New regression test tests/optimization/buffer-load-specialize-byte-address.slang exercises the failing pattern on SPIR-V and checks that the specialized helper takes the offset and alignment as separate uint parameters.
  • No existing tests change.

specializeFuncsForBufferLoadArgs lumped kIROp_ByteAddressBufferLoad in
with the generic two-operand "element access" instructions (GetElement,
StructuredBufferLoad, etc.) in both getCallInfoForArg and
getSpecializedValueForArg. byteAddressBufferLoad actually has three
operands -- (buffer, offset, alignment) -- so the rewritten load inside
the specialized callee was constructed with only two operands.

Downstream, legalizeByteAddressBufferOps::processLoad unconditionally
reads operand index 2 to recover the alignment, hitting

    assert failure: slang-ir.h(710): index < getOperandCount()

during SPIR-V emission. A minimal reproducer is a struct large enough
to trip the buffer-load specialization threshold (e.g. two float4x4s
plus a padded float3) loaded via Buf.Load<T>() and passed by value into
a helper function.

Give byteAddressBufferLoad dedicated handling in both functions so the
alignment operand survives specialization, and add a regression test
under tests/optimization that exercises the failing pattern on SPIR-V.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants