Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions source/slang/slang-lower-to-ir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7799,12 +7799,14 @@ struct LValueExprLoweringVisitor : ExprLoweringVisitorBase<LValueExprLoweringVis
auto loweredBase = lowerLValueExpr(context, expr->base);
UInt elementCount = (UInt)expr->elementIndices.getCount();

// Assign to 'bs' the elements from 'as' according to the first 'n' indices in 'is'
auto backpermute = [](UInt n, const auto as, const auto is, auto bs)
// Assign to `resultElements` the elements from `sourceElements` according to the first `n`
// indices in `indices`
auto backpermute =
[](UInt n, const auto& sourceElements, const auto& indices, auto& resultElements)
Comment thread
jkwak-work marked this conversation as resolved.
{
for (UInt i = 0; i < n; ++i)
{
bs[i] = as[is[i]];
resultElements[i] = sourceElements[indices[i]];
}
};

Expand All @@ -7829,7 +7831,10 @@ struct LValueExprLoweringVisitor : ExprLoweringVisitorBase<LValueExprLoweringVis
RefPtr<SwizzledLValueInfo> swizzledLValue = new SwizzledLValueInfo;
swizzledLValue->type = irType;
swizzledLValue->base = baseSwizzleInfo->base;
swizzledLValue->elementIndices.add((uint32_t)elementCount);

// Set the count of indices and leave them uninitialized.
// This is safe because `backpermute` fills all `elementCount` slots below.
swizzledLValue->elementIndices.setCount((uint32_t)elementCount);
Comment thread
jkwak-work marked this conversation as resolved.
Comment thread
jkwak-work marked this conversation as resolved.
Comment thread
jkwak-work marked this conversation as resolved.
Comment thread
jkwak-work marked this conversation as resolved.
Comment thread
jkwak-work marked this conversation as resolved.
Comment thread
jkwak-work marked this conversation as resolved.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Clarity: make the "every slot is written" invariant local

The safety comment reasons in terms of elementCount, but the backpermute call below takes its loop bound from swizzledLValue->elementIndices.getCount(), not elementCount:

backpermute(
    swizzledLValue->elementIndices.getCount(),
    ...
    swizzledLValue->elementIndices);

The two are equal only because setCount(elementCount) was just called, so "backpermute fills all elementCount slots" is only obvious once the reader connects setCount here to the later getCount(). Passing elementCount directly to backpermute (or SLANG_ASSERT(swizzledLValue->elementIndices.getCount() == elementCount)) would make the write-every-slot invariant self-evident at this line.

Separately, "leave them uninitialized" is only accurate for the POD short-buffer case (setCount default-constructs elements in the overflow-buffer path). Since the load-bearing fact is that backpermute overwrites every slot before any read, consider leading with that and dropping the incidental initialization detail.

Comment thread
jkwak-work marked this conversation as resolved.

// Take the swizzle element of the "outer" swizzle, as it was
// written by the user. In our running example of `foo[i].zw.y`
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=CHECK): -compute -shaderobj -output-using-type
//TEST(compute, vulkan):COMPARE_COMPUTE(filecheck-buffer=CHECK): -vk -compute -shaderobj -output-using-type
//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=CHECK):-slang -shaderobj -mtl -output-using-type
//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=CHECK): -cpu -compute -shaderobj -output-using-type

// Test that writing to swizzles of vector swizzles works correctly

// CHECK: 2.0
// CHECK-NEXT: 1.0
// CHECK-NEXT: 0.0
// CHECK-NEXT: 9.0

//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name=outputBuffer
RWStructuredBuffer<float> outputBuffer;

[numthreads(4, 1, 1)]
void computeMain(uint tid : SV_GroupIndex)
{
float4 a = float4(0);

a.zw.y = 9.0;
a.xyzw.yx = float2(1.0, 2.0);
Comment thread
jkwak-work marked this conversation as resolved.

// a = (2.0, 1.0, 0.0, 9.0)

outputBuffer[tid] = a[tid];
}
Loading