-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[HLSL][SPIR-V] Add support for SV_Target semantic #168743
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Current implementation for SV_Position was very basic to allow implementing/testing some semantics. Now that semantic support is more robust, I can move forward and implement the whole semantic logic. DX part is still a bit placeholder.
This PR adds the support for the SV_Target semantic and improved the diagnostics when the stage is correct, but the direction is disallowed.
|
@llvm/pr-subscribers-hlsl @llvm/pr-subscribers-clang-codegen Author: Nathan Gauër (Keenuts) ChangesThis PR adds the support for the SV_Target semantic and improved the diagnostics when the stage is correct, but the direction is disallowed. This PR will require #168735 to be merged first. Patch is 28.30 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/168743.diff 15 Files Affected:
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c535fe2b9f241..28ebd74547f5d 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -13213,6 +13213,8 @@ def err_hlsl_semantic_indexing_not_supported
def err_hlsl_init_priority_unsupported : Error<
"initializer priorities are not supported in HLSL">;
def err_hlsl_semantic_index_overlap : Error<"semantic index overlap %0">;
+def err_hlsl_semantic_unsupported_direction_for_stage
+ : Error<"semantic %0 is unsupported as %1 for stage %2">;
def warn_hlsl_user_defined_type_missing_member: Warning<"binding type '%select{t|u|b|s|c}0' only applies to types containing %select{SRV resources|UAV resources|constant buffer resources|sampler state|numeric types}0">, InGroup<LegacyConstantRegisterBinding>;
def err_hlsl_binding_type_mismatch: Error<"binding type '%select{t|u|b|s|c}0' only applies to %select{SRV resources|UAV resources|constant buffer resources|sampler state|numeric variables in the global scope}0">;
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index 86da323892f98..2ac88f7e82700 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -134,9 +134,6 @@ class SemaHLSL : public SemaBase {
void CheckEntryPoint(FunctionDecl *FD);
bool CheckResourceBinOp(BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr,
SourceLocation Loc);
- void DiagnoseAttrStageMismatch(
- const Attr *A, llvm::Triple::EnvironmentType Stage,
- std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages);
QualType handleVectorBinOpConversion(ExprResult &LHS, ExprResult &RHS,
QualType LHSType, QualType RHSType,
@@ -244,26 +241,50 @@ class SemaHLSL : public SemaBase {
std::optional<uint32_t> Index;
};
+ enum IOType {
+ In = 0b01,
+ Out = 0b10,
+ InOut = 0b11,
+ };
+
+ struct SemanticStageInfo {
+ llvm::Triple::EnvironmentType Stage;
+ IOType Direction;
+ };
+
private:
void collectResourceBindingsOnVarDecl(VarDecl *D);
void collectResourceBindingsOnUserRecordDecl(const VarDecl *VD,
const RecordType *RT);
void checkSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param,
- const HLSLAppliedSemanticAttr *SemanticAttr);
+ const HLSLAppliedSemanticAttr *SemanticAttr,
+ bool IsInput);
+
bool determineActiveSemanticOnScalar(FunctionDecl *FD,
DeclaratorDecl *OutputDecl,
DeclaratorDecl *D,
SemanticInfo &ActiveSemantic,
- llvm::StringSet<> &ActiveInputSemantics);
+ llvm::StringSet<> &ActiveSemantics,
+ bool IsInput);
+
bool determineActiveSemantic(FunctionDecl *FD, DeclaratorDecl *OutputDecl,
DeclaratorDecl *D, SemanticInfo &ActiveSemantic,
- llvm::StringSet<> &ActiveInputSemantics);
+ llvm::StringSet<> &ActiveSemantics,
+ bool IsInput);
void processExplicitBindingsOnDecl(VarDecl *D);
void diagnoseAvailabilityViolations(TranslationUnitDecl *TU);
+ void diagnoseAttrStageMismatch(
+ const Attr *A, llvm::Triple::EnvironmentType Stage,
+ std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages);
+
+ void diagnoseSemanticStageMismatch(
+ const Attr *A, llvm::Triple::EnvironmentType Stage, bool IsInput,
+ std::initializer_list<SemanticStageInfo> AllowedStages);
+
uint32_t getNextImplicitBindingOrderID() {
return ImplicitBindingNextOrderID++;
}
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 0371af417bdab..0a3b37052b803 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -730,10 +730,18 @@ llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad(
}
if (SemanticName == "SV_POSITION") {
- if (CGM.getTriple().getEnvironment() == Triple::EnvironmentType::Pixel)
- return createSPIRVBuiltinLoad(B, CGM.getModule(), Type,
- Semantic->getAttrName()->getName(),
- /* BuiltIn::FragCoord */ 15);
+ if (CGM.getTriple().getEnvironment() == Triple::EnvironmentType::Pixel) {
+ if (CGM.getTarget().getTriple().isSPIRV())
+ return createSPIRVBuiltinLoad(B, CGM.getModule(), Type,
+ Semantic->getAttrName()->getName(),
+ /* BuiltIn::FragCoord */ 15);
+ if (CGM.getTarget().getTriple().isDXIL())
+ return emitDXILUserSemanticLoad(B, Type, Semantic, Index);
+ }
+
+ if (CGM.getTriple().getEnvironment() == Triple::EnvironmentType::Vertex) {
+ return emitUserSemanticLoad(B, Type, Decl, Semantic, Index);
+ }
}
llvm_unreachable("non-handled system semantic. FIXME.");
@@ -759,11 +767,16 @@ void CGHLSLRuntime::emitSystemSemanticStore(IRBuilder<> &B, llvm::Value *Source,
std::optional<unsigned> Index) {
std::string SemanticName = Semantic->getAttrName()->getName().upper();
- if (SemanticName == "SV_POSITION")
- createSPIRVBuiltinStore(B, CGM.getModule(), Source,
- Semantic->getAttrName()->getName(),
- /* BuiltIn::Position */ 0);
- else
+ if (SemanticName == "SV_POSITION") {
+ if (CGM.getTarget().getTriple().isDXIL())
+ emitDXILUserSemanticStore(B, Source, Semantic, Index);
+ else if (CGM.getTarget().getTriple().isSPIRV())
+ createSPIRVBuiltinStore(B, CGM.getModule(), Source,
+ Semantic->getAttrName()->getName(),
+ /* BuiltIn::Position */ 0);
+ } else if (SemanticName == "SV_TARGET") {
+ emitUserSemanticStore(B, Source, Decl, Semantic, Index);
+ } else
llvm_unreachable("non-handled system semantic. FIXME.");
}
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index e7ee3b1adf941..f7b5de114d2c6 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -771,9 +771,12 @@ void SemaHLSL::ActOnTopLevelFunction(FunctionDecl *FD) {
}
}
-bool SemaHLSL::determineActiveSemanticOnScalar(
- FunctionDecl *FD, DeclaratorDecl *OutputDecl, DeclaratorDecl *D,
- SemanticInfo &ActiveSemantic, llvm::StringSet<> &UsedSemantics) {
+bool SemaHLSL::determineActiveSemanticOnScalar(FunctionDecl *FD,
+ DeclaratorDecl *OutputDecl,
+ DeclaratorDecl *D,
+ SemanticInfo &ActiveSemantic,
+ llvm::StringSet<> &UsedSemantics,
+ bool IsInput) {
if (ActiveSemantic.Semantic == nullptr) {
ActiveSemantic.Semantic = D->getAttr<HLSLParsedSemanticAttr>();
if (ActiveSemantic.Semantic)
@@ -792,7 +795,7 @@ bool SemaHLSL::determineActiveSemanticOnScalar(
if (!A)
return false;
- checkSemanticAnnotation(FD, D, A);
+ checkSemanticAnnotation(FD, D, A, IsInput);
OutputDecl->addAttr(A);
unsigned Location = ActiveSemantic.Index.value_or(0);
@@ -820,7 +823,8 @@ bool SemaHLSL::determineActiveSemantic(FunctionDecl *FD,
DeclaratorDecl *OutputDecl,
DeclaratorDecl *D,
SemanticInfo &ActiveSemantic,
- llvm::StringSet<> &UsedSemantics) {
+ llvm::StringSet<> &UsedSemantics,
+ bool IsInput) {
if (ActiveSemantic.Semantic == nullptr) {
ActiveSemantic.Semantic = D->getAttr<HLSLParsedSemanticAttr>();
if (ActiveSemantic.Semantic)
@@ -833,12 +837,13 @@ bool SemaHLSL::determineActiveSemantic(FunctionDecl *FD,
const RecordType *RT = dyn_cast<RecordType>(T);
if (!RT)
return determineActiveSemanticOnScalar(FD, OutputDecl, D, ActiveSemantic,
- UsedSemantics);
+ UsedSemantics, IsInput);
const RecordDecl *RD = RT->getDecl();
for (FieldDecl *Field : RD->fields()) {
SemanticInfo Info = ActiveSemantic;
- if (!determineActiveSemantic(FD, OutputDecl, Field, Info, UsedSemantics)) {
+ if (!determineActiveSemantic(FD, OutputDecl, Field, Info, UsedSemantics,
+ IsInput)) {
Diag(Field->getLocation(), diag::note_hlsl_semantic_used_here) << Field;
return false;
}
@@ -868,14 +873,14 @@ void SemaHLSL::CheckEntryPoint(FunctionDecl *FD) {
case llvm::Triple::Miss:
case llvm::Triple::Callable:
if (const auto *NT = FD->getAttr<HLSLNumThreadsAttr>()) {
- DiagnoseAttrStageMismatch(NT, ST,
+ diagnoseAttrStageMismatch(NT, ST,
{llvm::Triple::Compute,
llvm::Triple::Amplification,
llvm::Triple::Mesh});
FD->setInvalidDecl();
}
if (const auto *WS = FD->getAttr<HLSLWaveSizeAttr>()) {
- DiagnoseAttrStageMismatch(WS, ST,
+ diagnoseAttrStageMismatch(WS, ST,
{llvm::Triple::Compute,
llvm::Triple::Amplification,
llvm::Triple::Mesh});
@@ -920,7 +925,7 @@ void SemaHLSL::CheckEntryPoint(FunctionDecl *FD) {
// FIXME: Verify output semantics in parameters.
if (!determineActiveSemantic(FD, Param, Param, ActiveSemantic,
- ActiveInputSemantics)) {
+ ActiveInputSemantics, /* IsInput= */ true)) {
Diag(Param->getLocation(), diag::note_previous_decl) << Param;
FD->setInvalidDecl();
}
@@ -932,12 +937,13 @@ void SemaHLSL::CheckEntryPoint(FunctionDecl *FD) {
if (ActiveSemantic.Semantic)
ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
if (!FD->getReturnType()->isVoidType())
- determineActiveSemantic(FD, FD, FD, ActiveSemantic, ActiveOutputSemantics);
+ determineActiveSemantic(FD, FD, FD, ActiveSemantic, ActiveOutputSemantics,
+ /* IsInput= */ false);
}
void SemaHLSL::checkSemanticAnnotation(
FunctionDecl *EntryPoint, const Decl *Param,
- const HLSLAppliedSemanticAttr *SemanticAttr) {
+ const HLSLAppliedSemanticAttr *SemanticAttr, bool IsInput) {
auto *ShaderAttr = EntryPoint->getAttr<HLSLShaderAttr>();
assert(ShaderAttr && "Entry point has no shader attribute");
llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
@@ -948,7 +954,8 @@ void SemaHLSL::checkSemanticAnnotation(
SemanticName == "SV_GROUPID") {
if (ST != llvm::Triple::Compute)
- DiagnoseAttrStageMismatch(SemanticAttr, ST, {llvm::Triple::Compute});
+ diagnoseSemanticStageMismatch(SemanticAttr, ST, IsInput,
+ {{llvm::Triple::Compute, IOType::In}});
if (SemanticAttr->getSemanticIndex() != 0) {
std::string PrettyName =
@@ -961,11 +968,15 @@ void SemaHLSL::checkSemanticAnnotation(
}
if (SemanticName == "SV_POSITION") {
- // TODO(#143523): allow use on other shader types & output once the overall
- // semantic logic is implemented.
- if (ST == llvm::Triple::Pixel)
- return;
- DiagnoseAttrStageMismatch(SemanticAttr, ST, {llvm::Triple::Pixel});
+ diagnoseSemanticStageMismatch(SemanticAttr, ST, IsInput,
+ {{llvm::Triple::Vertex, IOType::InOut},
+ {llvm::Triple::Pixel, IOType::In}});
+ return;
+ }
+
+ if (SemanticName == "SV_TARGET") {
+ diagnoseSemanticStageMismatch(SemanticAttr, ST, IsInput,
+ {{llvm::Triple::Pixel, IOType::Out}});
return;
}
@@ -975,7 +986,7 @@ void SemaHLSL::checkSemanticAnnotation(
llvm_unreachable("Unknown SemanticAttr");
}
-void SemaHLSL::DiagnoseAttrStageMismatch(
+void SemaHLSL::diagnoseAttrStageMismatch(
const Attr *A, llvm::Triple::EnvironmentType Stage,
std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
SmallVector<StringRef, 8> StageStrings;
@@ -989,6 +1000,37 @@ void SemaHLSL::DiagnoseAttrStageMismatch(
<< (AllowedStages.size() != 1) << join(StageStrings, ", ");
}
+void SemaHLSL::diagnoseSemanticStageMismatch(
+ const Attr *A, llvm::Triple::EnvironmentType Stage, bool IsInput,
+ std::initializer_list<SemanticStageInfo> Allowed) {
+
+ for (auto &Case : Allowed) {
+ if (Case.Stage != Stage)
+ continue;
+
+ if (IsInput && Case.Direction & IOType::In)
+ return;
+ if (!IsInput && Case.Direction & IOType::Out)
+ return;
+
+ Diag(A->getLoc(), diag::err_hlsl_semantic_unsupported_direction_for_stage)
+ << A->getAttrName() << (IsInput ? "input" : "output")
+ << llvm::Triple::getEnvironmentTypeName(Case.Stage);
+ return;
+ }
+
+ SmallVector<StringRef, 8> StageStrings;
+ llvm::transform(
+ Allowed, std::back_inserter(StageStrings), [](SemanticStageInfo Case) {
+ return StringRef(
+ HLSLShaderAttr::ConvertEnvironmentTypeToStr(Case.Stage));
+ });
+
+ Diag(A->getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
+ << A->getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
+ << (Allowed.size() != 1) << join(StageStrings, ", ");
+}
+
template <CastKind Kind>
static void castVector(Sema &S, ExprResult &E, QualType &Ty, unsigned Sz) {
if (const auto *VTy = Ty->getAs<VectorType>())
@@ -1790,6 +1832,16 @@ void SemaHLSL::diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL,
return;
}
+ if (SemanticName == "SV_TARGET") {
+ const auto *VT = ValueType->getAs<VectorType>();
+ if (!ValueType->hasFloatingRepresentation() ||
+ (VT && VT->getNumElements() > 4))
+ Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)
+ << AL << "float/float1/float2/float3/float4";
+ D->addAttr(createSemanticAttr<HLSLParsedSemanticAttr>(AL, Index));
+ return;
+ }
+
Diag(AL.getLoc(), diag::err_hlsl_unknown_semantic) << AL;
}
diff --git a/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl b/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl
index be30e79438831..b7d2283ea7766 100644
--- a/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl
+++ b/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl
@@ -1,11 +1,21 @@
-// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-pixel -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK-SPIRV
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-pixel -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK-DXIL
-// CHECK: @SV_Position = external hidden thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations !0
+// CHECK-SPIRV: @SV_Position = external hidden thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations ![[#MD_0:]]
// CHECK: define void @main() {{.*}} {
float4 main(float4 p : SV_Position) : A {
- // CHECK: %[[#P:]] = load <4 x float>, ptr addrspace(7) @SV_Position, align 16
- // CHECK: %[[#R:]] = call spir_func <4 x float> @_Z4mainDv4_f(<4 x float> %[[#P]])
- // CHECK: store <4 x float> %[[#R]], ptr addrspace(8) @A0, align 16
+ // CHECK-SPIRV: %[[#P:]] = load <4 x float>, ptr addrspace(7) @SV_Position, align 16
+ // CHECK-SPIRV: %[[#R:]] = call spir_func <4 x float> @_Z4mainDv4_f(<4 x float> %[[#P]])
+ // CHECK-SPIRV: store <4 x float> %[[#R]], ptr addrspace(8) @A0, align 16
+
+ // CHECK-DXIL: %SV_Position0 = call <4 x float> @llvm.dx.load.input.v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison)
+ // CHECK-DXIL: %[[#TMP:]] = call <4 x float> @_Z4mainDv4_f(<4 x float> %SV_Position0)
+ // CHECK-DXIL: call void @llvm.dx.store.output.v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison, <4 x float> %[[#TMP]])
return p;
}
+
+// CHECK-SPIRV-DAG: ![[#MD_0]] = !{![[#MD_1:]]}
+// CHECK-SPIRV-DAG: ![[#MD_1]] = !{i32 11, i32 15}
+// | `-> BuiltIn Position
+// `-> SPIR-V decoration 'FragCoord'
diff --git a/clang/test/CodeGenHLSL/semantics/SV_Position.vs.hlsl b/clang/test/CodeGenHLSL/semantics/SV_Position.vs.hlsl
new file mode 100644
index 0000000000000..0156c0bb816c1
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/SV_Position.vs.hlsl
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -triple dxil-unknown-shadermodel6.8-vertex -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck --check-prefix=CHECK-DXIL %s
+// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-vertex -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck --check-prefix=CHECK-SPIRV %s
+
+// CHECK-SPIRV: @SV_Position0 = external hidden thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations ![[#MD_0:]]
+// CHECK-SPIRV: @SV_Position = external hidden thread_local addrspace(8) global <4 x float>, !spirv.Decorations ![[#MD_2:]]
+
+// CHECK: define void @main() {{.*}} {
+float4 main(float4 p : SV_Position) : SV_Position {
+ // CHECK-SPIRV: %[[#P:]] = load <4 x float>, ptr addrspace(7) @SV_Position0, align 16
+ // CHECK-SPIRV: %[[#R:]] = call spir_func <4 x float> @_Z4mainDv4_f(<4 x float> %[[#P]])
+ // CHECK-SPIRV: store <4 x float> %[[#R]], ptr addrspace(8) @SV_Position, align 16
+
+ // CHECK-DXIL: %SV_Position0 = call <4 x float> @llvm.dx.load.input.v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison)
+ // CHECK-DXIL: %[[#TMP:]] = call <4 x float> @_Z4mainDv4_f(<4 x float> %SV_Position0)
+ // CHECK-DXIL: call void @llvm.dx.store.output.v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison, <4 x float> %[[#TMP]])
+ return p;
+}
+
+// CHECK-SPIRV-DAG: ![[#MD_0]] = !{![[#MD_1:]]}
+// CHECK-SPIRV-DAG: ![[#MD_2]] = !{![[#MD_3:]]}
+// CHECK-SPIRV-DAG: ![[#MD_1]] = !{i32 30, i32 0}
+// | `-> Location 0
+// `-> SPIR-V decoration 'Location'
+// CHECK-SPIRV-DAG: ![[#MD_3]] = !{i32 11, i32 0}
+// | `-> BuiltIn Position
+// `-> SPIR-V decoration 'BuiltIn'
diff --git a/clang/test/CodeGenHLSL/semantics/SV_Target.ps.hlsl b/clang/test/CodeGenHLSL/semantics/SV_Target.ps.hlsl
new file mode 100644
index 0000000000000..4dc622a1eb6bb
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/SV_Target.ps.hlsl
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK-SPIRV
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-pixel -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK-DXIL
+
+// CHECK-SPIRV: @SV_Target0 = external hidden thread_local addrspace(8) global <4 x float>, !spirv.Decorations ![[#MD_2:]]
+
+// CHECK: define void @main() {{.*}} {
+float4 main(float4 p : SV_Position) : SV_Target {
+ // CHECK-SPIRV: %[[#R:]] = call spir_func <4 x float> @_Z4mainDv4_f(<4 x float> %[[#]])
+ // CHECK-SPIRV: store <4 x float> %[[#R]], ptr addrspace(8) @SV_Target0, align 16
+
+ // CHECK-DXIL: %[[#TMP:]] = call <4 x float> @_Z4mainDv4_f(<4 x float> %SV_Position0)
+ // CHECK-DXIL: call void @llvm.dx.store.output.v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison, <4 x float> %[[#TMP]])
+ return p;
+}
+
+// CHECK-SPIRV-DAG: ![[#MD_2]] = !{![[#MD_3:]]}
+// CHECK-SPIRV-DAG: ![[#MD_3]] = !{i32 30, i32 0}
+// ...
[truncated]
|
|
@llvm/pr-subscribers-backend-spir-v Author: Nathan Gauër (Keenuts) ChangesThis PR adds the support for the SV_Target semantic and improved the diagnostics when the stage is correct, but the direction is disallowed. This PR will require #168735 to be merged first. Patch is 28.30 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/168743.diff 15 Files Affected:
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c535fe2b9f241..28ebd74547f5d 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -13213,6 +13213,8 @@ def err_hlsl_semantic_indexing_not_supported
def err_hlsl_init_priority_unsupported : Error<
"initializer priorities are not supported in HLSL">;
def err_hlsl_semantic_index_overlap : Error<"semantic index overlap %0">;
+def err_hlsl_semantic_unsupported_direction_for_stage
+ : Error<"semantic %0 is unsupported as %1 for stage %2">;
def warn_hlsl_user_defined_type_missing_member: Warning<"binding type '%select{t|u|b|s|c}0' only applies to types containing %select{SRV resources|UAV resources|constant buffer resources|sampler state|numeric types}0">, InGroup<LegacyConstantRegisterBinding>;
def err_hlsl_binding_type_mismatch: Error<"binding type '%select{t|u|b|s|c}0' only applies to %select{SRV resources|UAV resources|constant buffer resources|sampler state|numeric variables in the global scope}0">;
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index 86da323892f98..2ac88f7e82700 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -134,9 +134,6 @@ class SemaHLSL : public SemaBase {
void CheckEntryPoint(FunctionDecl *FD);
bool CheckResourceBinOp(BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr,
SourceLocation Loc);
- void DiagnoseAttrStageMismatch(
- const Attr *A, llvm::Triple::EnvironmentType Stage,
- std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages);
QualType handleVectorBinOpConversion(ExprResult &LHS, ExprResult &RHS,
QualType LHSType, QualType RHSType,
@@ -244,26 +241,50 @@ class SemaHLSL : public SemaBase {
std::optional<uint32_t> Index;
};
+ enum IOType {
+ In = 0b01,
+ Out = 0b10,
+ InOut = 0b11,
+ };
+
+ struct SemanticStageInfo {
+ llvm::Triple::EnvironmentType Stage;
+ IOType Direction;
+ };
+
private:
void collectResourceBindingsOnVarDecl(VarDecl *D);
void collectResourceBindingsOnUserRecordDecl(const VarDecl *VD,
const RecordType *RT);
void checkSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param,
- const HLSLAppliedSemanticAttr *SemanticAttr);
+ const HLSLAppliedSemanticAttr *SemanticAttr,
+ bool IsInput);
+
bool determineActiveSemanticOnScalar(FunctionDecl *FD,
DeclaratorDecl *OutputDecl,
DeclaratorDecl *D,
SemanticInfo &ActiveSemantic,
- llvm::StringSet<> &ActiveInputSemantics);
+ llvm::StringSet<> &ActiveSemantics,
+ bool IsInput);
+
bool determineActiveSemantic(FunctionDecl *FD, DeclaratorDecl *OutputDecl,
DeclaratorDecl *D, SemanticInfo &ActiveSemantic,
- llvm::StringSet<> &ActiveInputSemantics);
+ llvm::StringSet<> &ActiveSemantics,
+ bool IsInput);
void processExplicitBindingsOnDecl(VarDecl *D);
void diagnoseAvailabilityViolations(TranslationUnitDecl *TU);
+ void diagnoseAttrStageMismatch(
+ const Attr *A, llvm::Triple::EnvironmentType Stage,
+ std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages);
+
+ void diagnoseSemanticStageMismatch(
+ const Attr *A, llvm::Triple::EnvironmentType Stage, bool IsInput,
+ std::initializer_list<SemanticStageInfo> AllowedStages);
+
uint32_t getNextImplicitBindingOrderID() {
return ImplicitBindingNextOrderID++;
}
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 0371af417bdab..0a3b37052b803 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -730,10 +730,18 @@ llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad(
}
if (SemanticName == "SV_POSITION") {
- if (CGM.getTriple().getEnvironment() == Triple::EnvironmentType::Pixel)
- return createSPIRVBuiltinLoad(B, CGM.getModule(), Type,
- Semantic->getAttrName()->getName(),
- /* BuiltIn::FragCoord */ 15);
+ if (CGM.getTriple().getEnvironment() == Triple::EnvironmentType::Pixel) {
+ if (CGM.getTarget().getTriple().isSPIRV())
+ return createSPIRVBuiltinLoad(B, CGM.getModule(), Type,
+ Semantic->getAttrName()->getName(),
+ /* BuiltIn::FragCoord */ 15);
+ if (CGM.getTarget().getTriple().isDXIL())
+ return emitDXILUserSemanticLoad(B, Type, Semantic, Index);
+ }
+
+ if (CGM.getTriple().getEnvironment() == Triple::EnvironmentType::Vertex) {
+ return emitUserSemanticLoad(B, Type, Decl, Semantic, Index);
+ }
}
llvm_unreachable("non-handled system semantic. FIXME.");
@@ -759,11 +767,16 @@ void CGHLSLRuntime::emitSystemSemanticStore(IRBuilder<> &B, llvm::Value *Source,
std::optional<unsigned> Index) {
std::string SemanticName = Semantic->getAttrName()->getName().upper();
- if (SemanticName == "SV_POSITION")
- createSPIRVBuiltinStore(B, CGM.getModule(), Source,
- Semantic->getAttrName()->getName(),
- /* BuiltIn::Position */ 0);
- else
+ if (SemanticName == "SV_POSITION") {
+ if (CGM.getTarget().getTriple().isDXIL())
+ emitDXILUserSemanticStore(B, Source, Semantic, Index);
+ else if (CGM.getTarget().getTriple().isSPIRV())
+ createSPIRVBuiltinStore(B, CGM.getModule(), Source,
+ Semantic->getAttrName()->getName(),
+ /* BuiltIn::Position */ 0);
+ } else if (SemanticName == "SV_TARGET") {
+ emitUserSemanticStore(B, Source, Decl, Semantic, Index);
+ } else
llvm_unreachable("non-handled system semantic. FIXME.");
}
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index e7ee3b1adf941..f7b5de114d2c6 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -771,9 +771,12 @@ void SemaHLSL::ActOnTopLevelFunction(FunctionDecl *FD) {
}
}
-bool SemaHLSL::determineActiveSemanticOnScalar(
- FunctionDecl *FD, DeclaratorDecl *OutputDecl, DeclaratorDecl *D,
- SemanticInfo &ActiveSemantic, llvm::StringSet<> &UsedSemantics) {
+bool SemaHLSL::determineActiveSemanticOnScalar(FunctionDecl *FD,
+ DeclaratorDecl *OutputDecl,
+ DeclaratorDecl *D,
+ SemanticInfo &ActiveSemantic,
+ llvm::StringSet<> &UsedSemantics,
+ bool IsInput) {
if (ActiveSemantic.Semantic == nullptr) {
ActiveSemantic.Semantic = D->getAttr<HLSLParsedSemanticAttr>();
if (ActiveSemantic.Semantic)
@@ -792,7 +795,7 @@ bool SemaHLSL::determineActiveSemanticOnScalar(
if (!A)
return false;
- checkSemanticAnnotation(FD, D, A);
+ checkSemanticAnnotation(FD, D, A, IsInput);
OutputDecl->addAttr(A);
unsigned Location = ActiveSemantic.Index.value_or(0);
@@ -820,7 +823,8 @@ bool SemaHLSL::determineActiveSemantic(FunctionDecl *FD,
DeclaratorDecl *OutputDecl,
DeclaratorDecl *D,
SemanticInfo &ActiveSemantic,
- llvm::StringSet<> &UsedSemantics) {
+ llvm::StringSet<> &UsedSemantics,
+ bool IsInput) {
if (ActiveSemantic.Semantic == nullptr) {
ActiveSemantic.Semantic = D->getAttr<HLSLParsedSemanticAttr>();
if (ActiveSemantic.Semantic)
@@ -833,12 +837,13 @@ bool SemaHLSL::determineActiveSemantic(FunctionDecl *FD,
const RecordType *RT = dyn_cast<RecordType>(T);
if (!RT)
return determineActiveSemanticOnScalar(FD, OutputDecl, D, ActiveSemantic,
- UsedSemantics);
+ UsedSemantics, IsInput);
const RecordDecl *RD = RT->getDecl();
for (FieldDecl *Field : RD->fields()) {
SemanticInfo Info = ActiveSemantic;
- if (!determineActiveSemantic(FD, OutputDecl, Field, Info, UsedSemantics)) {
+ if (!determineActiveSemantic(FD, OutputDecl, Field, Info, UsedSemantics,
+ IsInput)) {
Diag(Field->getLocation(), diag::note_hlsl_semantic_used_here) << Field;
return false;
}
@@ -868,14 +873,14 @@ void SemaHLSL::CheckEntryPoint(FunctionDecl *FD) {
case llvm::Triple::Miss:
case llvm::Triple::Callable:
if (const auto *NT = FD->getAttr<HLSLNumThreadsAttr>()) {
- DiagnoseAttrStageMismatch(NT, ST,
+ diagnoseAttrStageMismatch(NT, ST,
{llvm::Triple::Compute,
llvm::Triple::Amplification,
llvm::Triple::Mesh});
FD->setInvalidDecl();
}
if (const auto *WS = FD->getAttr<HLSLWaveSizeAttr>()) {
- DiagnoseAttrStageMismatch(WS, ST,
+ diagnoseAttrStageMismatch(WS, ST,
{llvm::Triple::Compute,
llvm::Triple::Amplification,
llvm::Triple::Mesh});
@@ -920,7 +925,7 @@ void SemaHLSL::CheckEntryPoint(FunctionDecl *FD) {
// FIXME: Verify output semantics in parameters.
if (!determineActiveSemantic(FD, Param, Param, ActiveSemantic,
- ActiveInputSemantics)) {
+ ActiveInputSemantics, /* IsInput= */ true)) {
Diag(Param->getLocation(), diag::note_previous_decl) << Param;
FD->setInvalidDecl();
}
@@ -932,12 +937,13 @@ void SemaHLSL::CheckEntryPoint(FunctionDecl *FD) {
if (ActiveSemantic.Semantic)
ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
if (!FD->getReturnType()->isVoidType())
- determineActiveSemantic(FD, FD, FD, ActiveSemantic, ActiveOutputSemantics);
+ determineActiveSemantic(FD, FD, FD, ActiveSemantic, ActiveOutputSemantics,
+ /* IsInput= */ false);
}
void SemaHLSL::checkSemanticAnnotation(
FunctionDecl *EntryPoint, const Decl *Param,
- const HLSLAppliedSemanticAttr *SemanticAttr) {
+ const HLSLAppliedSemanticAttr *SemanticAttr, bool IsInput) {
auto *ShaderAttr = EntryPoint->getAttr<HLSLShaderAttr>();
assert(ShaderAttr && "Entry point has no shader attribute");
llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
@@ -948,7 +954,8 @@ void SemaHLSL::checkSemanticAnnotation(
SemanticName == "SV_GROUPID") {
if (ST != llvm::Triple::Compute)
- DiagnoseAttrStageMismatch(SemanticAttr, ST, {llvm::Triple::Compute});
+ diagnoseSemanticStageMismatch(SemanticAttr, ST, IsInput,
+ {{llvm::Triple::Compute, IOType::In}});
if (SemanticAttr->getSemanticIndex() != 0) {
std::string PrettyName =
@@ -961,11 +968,15 @@ void SemaHLSL::checkSemanticAnnotation(
}
if (SemanticName == "SV_POSITION") {
- // TODO(#143523): allow use on other shader types & output once the overall
- // semantic logic is implemented.
- if (ST == llvm::Triple::Pixel)
- return;
- DiagnoseAttrStageMismatch(SemanticAttr, ST, {llvm::Triple::Pixel});
+ diagnoseSemanticStageMismatch(SemanticAttr, ST, IsInput,
+ {{llvm::Triple::Vertex, IOType::InOut},
+ {llvm::Triple::Pixel, IOType::In}});
+ return;
+ }
+
+ if (SemanticName == "SV_TARGET") {
+ diagnoseSemanticStageMismatch(SemanticAttr, ST, IsInput,
+ {{llvm::Triple::Pixel, IOType::Out}});
return;
}
@@ -975,7 +986,7 @@ void SemaHLSL::checkSemanticAnnotation(
llvm_unreachable("Unknown SemanticAttr");
}
-void SemaHLSL::DiagnoseAttrStageMismatch(
+void SemaHLSL::diagnoseAttrStageMismatch(
const Attr *A, llvm::Triple::EnvironmentType Stage,
std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
SmallVector<StringRef, 8> StageStrings;
@@ -989,6 +1000,37 @@ void SemaHLSL::DiagnoseAttrStageMismatch(
<< (AllowedStages.size() != 1) << join(StageStrings, ", ");
}
+void SemaHLSL::diagnoseSemanticStageMismatch(
+ const Attr *A, llvm::Triple::EnvironmentType Stage, bool IsInput,
+ std::initializer_list<SemanticStageInfo> Allowed) {
+
+ for (auto &Case : Allowed) {
+ if (Case.Stage != Stage)
+ continue;
+
+ if (IsInput && Case.Direction & IOType::In)
+ return;
+ if (!IsInput && Case.Direction & IOType::Out)
+ return;
+
+ Diag(A->getLoc(), diag::err_hlsl_semantic_unsupported_direction_for_stage)
+ << A->getAttrName() << (IsInput ? "input" : "output")
+ << llvm::Triple::getEnvironmentTypeName(Case.Stage);
+ return;
+ }
+
+ SmallVector<StringRef, 8> StageStrings;
+ llvm::transform(
+ Allowed, std::back_inserter(StageStrings), [](SemanticStageInfo Case) {
+ return StringRef(
+ HLSLShaderAttr::ConvertEnvironmentTypeToStr(Case.Stage));
+ });
+
+ Diag(A->getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
+ << A->getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
+ << (Allowed.size() != 1) << join(StageStrings, ", ");
+}
+
template <CastKind Kind>
static void castVector(Sema &S, ExprResult &E, QualType &Ty, unsigned Sz) {
if (const auto *VTy = Ty->getAs<VectorType>())
@@ -1790,6 +1832,16 @@ void SemaHLSL::diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL,
return;
}
+ if (SemanticName == "SV_TARGET") {
+ const auto *VT = ValueType->getAs<VectorType>();
+ if (!ValueType->hasFloatingRepresentation() ||
+ (VT && VT->getNumElements() > 4))
+ Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)
+ << AL << "float/float1/float2/float3/float4";
+ D->addAttr(createSemanticAttr<HLSLParsedSemanticAttr>(AL, Index));
+ return;
+ }
+
Diag(AL.getLoc(), diag::err_hlsl_unknown_semantic) << AL;
}
diff --git a/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl b/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl
index be30e79438831..b7d2283ea7766 100644
--- a/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl
+++ b/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl
@@ -1,11 +1,21 @@
-// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-pixel -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK-SPIRV
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-pixel -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK-DXIL
-// CHECK: @SV_Position = external hidden thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations !0
+// CHECK-SPIRV: @SV_Position = external hidden thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations ![[#MD_0:]]
// CHECK: define void @main() {{.*}} {
float4 main(float4 p : SV_Position) : A {
- // CHECK: %[[#P:]] = load <4 x float>, ptr addrspace(7) @SV_Position, align 16
- // CHECK: %[[#R:]] = call spir_func <4 x float> @_Z4mainDv4_f(<4 x float> %[[#P]])
- // CHECK: store <4 x float> %[[#R]], ptr addrspace(8) @A0, align 16
+ // CHECK-SPIRV: %[[#P:]] = load <4 x float>, ptr addrspace(7) @SV_Position, align 16
+ // CHECK-SPIRV: %[[#R:]] = call spir_func <4 x float> @_Z4mainDv4_f(<4 x float> %[[#P]])
+ // CHECK-SPIRV: store <4 x float> %[[#R]], ptr addrspace(8) @A0, align 16
+
+ // CHECK-DXIL: %SV_Position0 = call <4 x float> @llvm.dx.load.input.v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison)
+ // CHECK-DXIL: %[[#TMP:]] = call <4 x float> @_Z4mainDv4_f(<4 x float> %SV_Position0)
+ // CHECK-DXIL: call void @llvm.dx.store.output.v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison, <4 x float> %[[#TMP]])
return p;
}
+
+// CHECK-SPIRV-DAG: ![[#MD_0]] = !{![[#MD_1:]]}
+// CHECK-SPIRV-DAG: ![[#MD_1]] = !{i32 11, i32 15}
+// | `-> BuiltIn Position
+// `-> SPIR-V decoration 'FragCoord'
diff --git a/clang/test/CodeGenHLSL/semantics/SV_Position.vs.hlsl b/clang/test/CodeGenHLSL/semantics/SV_Position.vs.hlsl
new file mode 100644
index 0000000000000..0156c0bb816c1
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/SV_Position.vs.hlsl
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -triple dxil-unknown-shadermodel6.8-vertex -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck --check-prefix=CHECK-DXIL %s
+// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-vertex -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck --check-prefix=CHECK-SPIRV %s
+
+// CHECK-SPIRV: @SV_Position0 = external hidden thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations ![[#MD_0:]]
+// CHECK-SPIRV: @SV_Position = external hidden thread_local addrspace(8) global <4 x float>, !spirv.Decorations ![[#MD_2:]]
+
+// CHECK: define void @main() {{.*}} {
+float4 main(float4 p : SV_Position) : SV_Position {
+ // CHECK-SPIRV: %[[#P:]] = load <4 x float>, ptr addrspace(7) @SV_Position0, align 16
+ // CHECK-SPIRV: %[[#R:]] = call spir_func <4 x float> @_Z4mainDv4_f(<4 x float> %[[#P]])
+ // CHECK-SPIRV: store <4 x float> %[[#R]], ptr addrspace(8) @SV_Position, align 16
+
+ // CHECK-DXIL: %SV_Position0 = call <4 x float> @llvm.dx.load.input.v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison)
+ // CHECK-DXIL: %[[#TMP:]] = call <4 x float> @_Z4mainDv4_f(<4 x float> %SV_Position0)
+ // CHECK-DXIL: call void @llvm.dx.store.output.v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison, <4 x float> %[[#TMP]])
+ return p;
+}
+
+// CHECK-SPIRV-DAG: ![[#MD_0]] = !{![[#MD_1:]]}
+// CHECK-SPIRV-DAG: ![[#MD_2]] = !{![[#MD_3:]]}
+// CHECK-SPIRV-DAG: ![[#MD_1]] = !{i32 30, i32 0}
+// | `-> Location 0
+// `-> SPIR-V decoration 'Location'
+// CHECK-SPIRV-DAG: ![[#MD_3]] = !{i32 11, i32 0}
+// | `-> BuiltIn Position
+// `-> SPIR-V decoration 'BuiltIn'
diff --git a/clang/test/CodeGenHLSL/semantics/SV_Target.ps.hlsl b/clang/test/CodeGenHLSL/semantics/SV_Target.ps.hlsl
new file mode 100644
index 0000000000000..4dc622a1eb6bb
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/SV_Target.ps.hlsl
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK-SPIRV
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-pixel -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK-DXIL
+
+// CHECK-SPIRV: @SV_Target0 = external hidden thread_local addrspace(8) global <4 x float>, !spirv.Decorations ![[#MD_2:]]
+
+// CHECK: define void @main() {{.*}} {
+float4 main(float4 p : SV_Position) : SV_Target {
+ // CHECK-SPIRV: %[[#R:]] = call spir_func <4 x float> @_Z4mainDv4_f(<4 x float> %[[#]])
+ // CHECK-SPIRV: store <4 x float> %[[#R]], ptr addrspace(8) @SV_Target0, align 16
+
+ // CHECK-DXIL: %[[#TMP:]] = call <4 x float> @_Z4mainDv4_f(<4 x float> %SV_Position0)
+ // CHECK-DXIL: call void @llvm.dx.store.output.v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison, <4 x float> %[[#TMP]])
+ return p;
+}
+
+// CHECK-SPIRV-DAG: ![[#MD_2]] = !{![[#MD_3:]]}
+// CHECK-SPIRV-DAG: ![[#MD_3]] = !{i32 30, i32 0}
+// ...
[truncated]
|
🐧 Linux x64 Test Results
|
This PR adds the support for the SV_Target semantic and improved the diagnostics when the stage is correct, but the direction is disallowed.
This PR will require #168735 to be merged first.