Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
2 changes: 1 addition & 1 deletion external/SPIRV-Tools
Submodule SPIRV-Tools updated 118 files
2 changes: 1 addition & 1 deletion tools/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ namespace {
result = Context->getObjCIdType();
FunctionProtoType::ExtProtoInfo fpi;
fpi.Variadic = variadic;
return Context->getFunctionType(result, args, fpi);
return Context->getFunctionType(result, args, fpi, {});
}

// Helper function: create a CStyleCastExpr with trivial type source info.
Expand Down
22 changes: 19 additions & 3 deletions tools/clang/lib/SPIRV/SpirvEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,8 @@ SpirvEmitter::SpirvEmitter(CompilerInstance &ci)
constEvaluator(astContext, spvBuilder), entryFunction(nullptr),
curFunction(nullptr), curThis(nullptr), seenPushConstantAt(),
isSpecConstantMode(false), needsLegalization(false),
needsLegalizationLoopUnroll(false),
needsLegalizationSsaRewrite(false),
beforeHlslLegalization(false), mainSourceFile(nullptr) {

// Get ShaderModel from command line hlsl profile option.
Expand Down Expand Up @@ -954,6 +956,9 @@ void SpirvEmitter::HandleTranslationUnit(ASTContext &context) {
declIdMapper.requiresFlatteningCompositeResources() ||
!dsetbindingsToCombineImageSampler.empty() ||
spirvOptions.signaturePacking;
needsLegalizationSsaRewrite =
needsLegalizationSsaRewrite ||
!dsetbindingsToCombineImageSampler.empty();

// Run legalization passes
if (spirvOptions.codeGenHighLevel) {
Expand Down Expand Up @@ -5823,8 +5828,11 @@ SpirvInstruction *SpirvEmitter::createImageSample(
SpirvInstruction *minLod, SpirvInstruction *residencyCodeId,
SourceLocation loc, SourceRange range) {

if (varOffset)
if (varOffset) {
needsLegalization = true;
needsLegalizationLoopUnroll = true;
needsLegalizationSsaRewrite = true;
}

// SampleDref* instructions in SPIR-V always return a scalar.
// They also have the correct type in HLSL.
Expand Down Expand Up @@ -8045,7 +8053,7 @@ SpirvInstruction *SpirvEmitter::createVectorSplat(const Expr *scalarExpr,
// Should find a more meaningful one.
if (auto *constVal = dyn_cast<SpirvConstant>(scalarVal)) {
llvm::SmallVector<SpirvConstant *, 4> elements(size_t(size), constVal);
const bool isSpecConst = constVal->getopcode() == spv::Op::OpSpecConstant;
const bool isSpecConst = constVal->isSpecConstant();
auto *value =
spvBuilder.getConstantComposite(vecType, elements, isSpecConst);
if (!value)
Expand Down Expand Up @@ -16665,7 +16673,15 @@ bool SpirvEmitter::spirvToolsLegalize(std::vector<uint32_t> *mod,
optimizer.RegisterPass(
spvtools::CreateInterfaceVariableScalarReplacementPass());
}
optimizer.RegisterLegalizationPasses(spirvOptions.preserveInterface);
auto legalizationSsaRewriteMode = spvtools::SSARewriteMode::None;
if (needsLegalizationLoopUnroll) {
legalizationSsaRewriteMode = spvtools::SSARewriteMode::All;
} else if (needsLegalizationSsaRewrite) {
legalizationSsaRewriteMode = spvtools::SSARewriteMode::OpaqueOnly;
}
optimizer.RegisterLegalizationPasses(
spirvOptions.preserveInterface, needsLegalizationLoopUnroll,
legalizationSsaRewriteMode);
// Add flattening of resources if needed.
if (spirvOptions.flattenResourceArrays) {
optimizer.RegisterPass(
Expand Down
2 changes: 2 additions & 0 deletions tools/clang/lib/SPIRV/SpirvEmitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -1578,6 +1578,8 @@ class SpirvEmitter : public ASTConsumer {
///
/// Note: legalization specific code
bool needsLegalization;
bool needsLegalizationLoopUnroll;
bool needsLegalizationSsaRewrite;

/// Whether the translated SPIR-V binary passes --before-hlsl-legalization
/// option to spirv-val because of illegal function parameter scope.
Expand Down
27 changes: 14 additions & 13 deletions tools/clang/test/CodeGenSPIRV/cast.flat-conversion.matrix.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,18 @@ RWStructuredBuffer<T> t_output;
// COL: OpMemberDecorate %S 0 RowMajor
// ROW: OpMemberDecorate %S 0 ColMajor

// The DXIL generated for the two cases seem to produce the same results,
// and this matches that behaviour.
// CHECK: [[array_const:%[0-9]+]] = OpConstantComposite %_arr_float_uint_6 %float_0 %float_1 %float_2 %float_3 %float_4 %float_5
// CHECK: [[t:%[0-9]+]] = OpConstantComposite %T [[array_const]]

// The DXIL that is generates different order for the values depending on
// whether the matrix is column or row major. However, for SPIR-V, the value
// stored in both cases is the same because the decoration, which is checked
// above, is what determines the layout in memory for the value.

// CHECK: [[row0:%[0-9]+]] = OpConstantComposite %v3float %float_0 %float_1 %float_2
// CHECK: [[row1:%[0-9]+]] = OpConstantComposite %v3float %float_3 %float_4 %float_5
// CHECK: [[mat:%[0-9]+]] = OpConstantComposite %mat2v3float %33 %34
// CHECK: [[s:%[0-9]+]] = OpConstantComposite %S %35
// CHECK: [[mat:%[0-9]+]] = OpLoad %mat2v3float
// CHECK: [[e00:%[0-9]+]] = OpCompositeExtract %float [[mat]] 0 0
// CHECK: [[e01:%[0-9]+]] = OpCompositeExtract %float [[mat]] 0 1
// CHECK: [[e02:%[0-9]+]] = OpCompositeExtract %float [[mat]] 0 2
// CHECK: [[e10:%[0-9]+]] = OpCompositeExtract %float [[mat]] 1 0
// CHECK: [[e11:%[0-9]+]] = OpCompositeExtract %float [[mat]] 1 1
// CHECK: [[e12:%[0-9]+]] = OpCompositeExtract %float [[mat]] 1 2

void main() {
S s;
Expand All @@ -40,13 +38,16 @@ void main() {
s.a[i][j] = i*3+j;
}
}
// CHECK: [[ac:%[0-9]+]] = OpAccessChain %_ptr_Uniform_T %t_output %int_0 %uint_0
// CHECK: OpStore [[ac]] [[t]]
// CHECK: [[tptr:%[0-9]+]] = OpAccessChain %_ptr_Uniform_T %t_output %int_0 %uint_0
// CHECK: [[tarr:%[0-9]+]] = OpCompositeConstruct %_arr_float_uint_6 [[e00]] [[e01]] [[e02]] [[e10]] [[e11]] [[e12]]
// CHECK: [[tval:%[0-9]+]] = OpCompositeConstruct %T [[tarr]]
// CHECK: OpStore [[tptr]] [[tval]]
T t = (T)(s);
t_output[0] = t;

// CHECK: [[ac:%[0-9]+]] = OpAccessChain %_ptr_Uniform_S %s_output %int_0 %uint_0
// CHECK: OpStore [[ac]] [[s]]
// CHECK: [[sptr:%[0-9]+]] = OpAccessChain %_ptr_Uniform_S %s_output %int_0 %uint_0
// CHECK: [[sval:%[0-9]+]] = OpCompositeConstruct %S [[mat]]
// CHECK: OpStore [[sptr]] [[sval]]
s = (S)t;
s_output[0] = s;
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
// RUN: %dxc -T cs_6_0 -E main -O3 -Vd %s -spirv | FileCheck %s

// CHECK: [[ptr:%[0-9]+]] = OpAccessChain %_ptr_Uniform_S %gSBuffer2
// CHECK-NEXT: [[val:%[0-9]+]] = OpLoad %S [[ptr]]
// CHECK-NEXT: [[ptr:%[0-9]+]] = OpAccessChain %_ptr_Uniform_S %gRWSBuffer
// CHECK-NEXT: OpStore [[ptr]] [[val]]

// CHECK: [[ptr:%[0-9]+]] = OpAccessChain %_ptr_Uniform_S %gSBuffer2
// CHECK-NEXT: [[val:%[0-9]+]] = OpLoad %S [[ptr]]
// CHECK-NEXT: [[ptr:%[0-9]+]] = OpAccessChain %_ptr_Uniform_S %gRWSBuffer
// CHECK-NEXT: OpStore [[ptr]] [[val]]
// CHECK: OpLoopMerge {{%[0-9]+}} {{%[0-9]+}} Unroll
// CHECK: [[which:%[0-9]+]] = OpSelect %_ptr_Uniform_type_StructuredBuffer_S {{%[0-9]+}} %gSBuffer1 %gSBuffer2

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is not legal. We have to unroll in this case.

@devshgraphicsprogramming devshgraphicsprogramming Mar 26, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

yep, it would only be legal with SPV_KHR_variable_pointers if the gSBuffer pointers were of Shader Storage Class.

However I could go out on a limb and claim that it was never supposed to be legal without [[unroll]] on the loop ( I know the example has unroll so in this case SPIR-V codegen shouldn't change)

// CHECK: [[idx:%[0-9]+]] = OpBitcast %uint {{%[0-9]+}}
// CHECK: [[src:%[0-9]+]] = OpAccessChain %_ptr_Uniform_S [[which]] %int_0 [[idx]]
// CHECK: [[val:%[0-9]+]] = OpLoad %S [[src]]
// CHECK: [[dst:%[0-9]+]] = OpAccessChain %_ptr_Uniform_S %gRWSBuffer %int_0 [[idx]]
// CHECK: OpStore [[dst]] [[val]]

struct S {
float4 f;
Expand Down
4 changes: 2 additions & 2 deletions tools/clang/test/CodeGenSPIRV/max_id.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// CHECK-30: fatal error: failed to optimize SPIR-V: ID overflow. Try running compact-ids.

// With a larger limit, the test case can compile successfully.
// CHECK-400: Bound: 204
// CHECK-400: Bound:


RWStructuredBuffer<int> data;
Expand All @@ -20,4 +20,4 @@ void main(uint3 id : SV_DispatchThreadID)
for( int i = 0; i < 64; i++ ) {
data[i] = i;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ void func(RWStructuredBuffer<uint> local) {

float4 main(PSInput input) : SV_TARGET
{
// CHECK: [[ac2:%[0-9]+]] = OpAccessChain %_ptr_Uniform_int %counter_var_g_rwbuffer {{%[0-9]+}} %uint_0
// CHECK: [[counter_struct:%[0-9]+]] = OpAccessChain %_ptr_Uniform_type_ACSBuffer_counter %counter_var_g_rwbuffer {{%[0-9]+}}
// CHECK: [[ac2:%[0-9]+]] = OpAccessChain %_ptr_Uniform_int [[counter_struct]] %uint_0
// CHECK: OpAtomicIAdd %int [[ac2]] %uint_1 %uint_0 %int_1
func(g_rwbuffer[input.idx]);

// CHECK: [[ac2_0:%[0-9]+]] = OpAccessChain %_ptr_Uniform_uint %g_rwbuffer {{%[0-9]+}} %int_0 %uint_0
// CHECK: [[rwbuffer_struct:%[0-9]+]] = OpAccessChain %_ptr_Uniform_type_RWStructuredBuffer_uint %g_rwbuffer {{%[0-9]+}}
// CHECK: [[ac2_0:%[0-9]+]] = OpAccessChain %_ptr_Uniform_uint [[rwbuffer_struct]] %int_0 %uint_0
// CHECK: OpLoad %uint [[ac2_0]]
return g_rwbuffer[input.idx][0];
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ float4 main(PSInput input) : SV_TARGET
{
RWStructuredBuffer<uint> l_rwbuffer[5] = g_rwbuffer;

// CHECK: [[ac2:%[0-9]+]] = OpAccessChain %_ptr_Uniform_int %counter_var_g_rwbuffer %int_0 %uint_0
// CHECK: [[counter_struct:%[0-9]+]] = OpAccessChain %_ptr_Uniform_type_ACSBuffer_counter %counter_var_g_rwbuffer %int_0
// CHECK: [[ac2:%[0-9]+]] = OpAccessChain %_ptr_Uniform_int [[counter_struct]] %uint_0
// CHECK: OpAtomicIAdd %int [[ac2]] %uint_1 %uint_0 %int_1
l_rwbuffer[0].IncrementCounter();

// CHECK: [[ac2_0:%[0-9]+]] = OpAccessChain %_ptr_Uniform_uint %g_rwbuffer {{%[0-9]+}} %int_0 %uint_0
// CHECK: [[rwbuffer_struct:%[0-9]+]] = OpAccessChain %_ptr_Uniform_type_RWStructuredBuffer_uint %g_rwbuffer {{%[0-9]+}}
// CHECK: [[ac2_0:%[0-9]+]] = OpAccessChain %_ptr_Uniform_uint [[rwbuffer_struct]] %int_0 %uint_0
// CHECK: OpLoad %uint [[ac2_0]]
return l_rwbuffer[input.idx][0];
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@
// Check the names
//
// CHECK: OpName %secondGlobal_t "secondGlobal.t"
// CHECK: OpName %[[fg0:firstGlobal_[0-9]+__t]] "firstGlobal{{.*}}.t"
// CHECK: OpName %[[fg1:firstGlobal_[0-9]+__t]] "firstGlobal{{.*}}.t"
// CHECK: OpName %[[fg2:firstGlobal_[0-9]+__t]] "firstGlobal{{.*}}.t"
// CHECK: OpName %[[fg3:firstGlobal_[0-9]+__t]] "firstGlobal{{.*}}.t"
// CHECK: OpName %[[fg0:[0-9A-Za-z_]+]] "firstGlobal{{.*}}.t"
// CHECK: OpName %[[fg1:[0-9A-Za-z_]+]] "firstGlobal{{.*}}.t"
// CHECK: OpName %[[fg2:[0-9A-Za-z_]+]] "firstGlobal{{.*}}.t"
// CHECK: OpName %[[fg3:[0-9A-Za-z_]+]] "firstGlobal{{.*}}.t"
// CHECK: OpName %secondGlobal_tt_0__s "secondGlobal.tt[0].s"
// CHECK: OpName %secondGlobal_tt_1__s "secondGlobal.tt[1].s"
// CHECK: OpName %[[fgtt0_0:firstGlobal_[0-9]+__tt_0__s]] "firstGlobal{{.*}}.tt[0].s"
// CHECK: OpName %[[fgtt0_1:firstGlobal_[0-9]+__tt_1__s]] "firstGlobal{{.*}}.tt[1].s"
// CHECK: OpName %[[fgtt1_0:firstGlobal_[0-9]+__tt_0__s]] "firstGlobal{{.*}}.tt[0].s"
// CHECK: OpName %[[fgtt1_1:firstGlobal_[0-9]+__tt_1__s]] "firstGlobal{{.*}}.tt[1].s"
// CHECK: OpName %[[fgtt2_0:firstGlobal_[0-9]+__tt_0__s]] "firstGlobal{{.*}}.tt[0].s"
// CHECK: OpName %[[fgtt2_1:firstGlobal_[0-9]+__tt_1__s]] "firstGlobal{{.*}}.tt[1].s"
// CHECK: OpName %[[fgtt3_0:firstGlobal_[0-9]+__tt_0__s]] "firstGlobal{{.*}}.tt[0].s"
// CHECK: OpName %[[fgtt3_1:firstGlobal_[0-9]+__tt_1__s]] "firstGlobal{{.*}}.tt[1].s"
// CHECK: OpName %[[fgtt0_0:[0-9A-Za-z_]+]] "firstGlobal{{.*}}.tt[0].s"
// CHECK: OpName %[[fgtt0_1:[0-9A-Za-z_]+]] "firstGlobal{{.*}}.tt[1].s"
// CHECK: OpName %[[fgtt1_0:[0-9A-Za-z_]+]] "firstGlobal{{.*}}.tt[0].s"
// CHECK: OpName %[[fgtt1_1:[0-9A-Za-z_]+]] "firstGlobal{{.*}}.tt[1].s"
// CHECK: OpName %[[fgtt2_0:[0-9A-Za-z_]+]] "firstGlobal{{.*}}.tt[0].s"
// CHECK: OpName %[[fgtt2_1:[0-9A-Za-z_]+]] "firstGlobal{{.*}}.tt[1].s"
// CHECK: OpName %[[fgtt3_0:[0-9A-Za-z_]+]] "firstGlobal{{.*}}.tt[0].s"
// CHECK: OpName %[[fgtt3_1:[0-9A-Za-z_]+]] "firstGlobal{{.*}}.tt[1].s"

// Check flattening of bindings
// Explanation: Only the resources that are used will have a binding assignment
Expand Down
2 changes: 1 addition & 1 deletion tools/clang/test/CodeGenSPIRV/vk.spec-constant.reuse.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@

[shader("pixel")]
float4 main(float4 position : SV_Position) : SV_Target0 {
// CHECK: OpConstantComposite %v4bool %y %y %y %y
// CHECK: OpSpecConstantComposite %v4bool %y %y %y %y
return y ? position : 1.0;
}
Loading