-
Notifications
You must be signed in to change notification settings - Fork 13.8k
[HLSL][SPIR-V] Handle SV_Position builtin in PS #141759
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
Conversation
05cd38a
to
18fbd19
Compare
18fbd19
to
4653aca
Compare
@llvm/pr-subscribers-hlsl @llvm/pr-subscribers-clang-codegen Author: Nathan Gauër (Keenuts) ChangesThis commit is using the same mechanism as vk::ext_builtin_input to This is incomplete as it doesn't allow the semantic on hull/domain and Full diff: https://github.com/llvm/llvm-project/pull/141759.diff 10 Files Affected:
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 7c63279f156a9..ae363a780a674 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4851,6 +4851,13 @@ def HLSLResourceBinding: InheritableAttr {
}];
}
+def HLSLSV_Position : HLSLAnnotationAttr {
+ let Spellings = [HLSLAnnotation<"sv_position">];
+ let Subjects = SubjectList<[ParmVar, Field]>;
+ let LangOpts = [HLSL];
+ let Documentation = [HLSLSV_PositionDocs];
+}
+
def HLSLPackOffset: HLSLAnnotationAttr {
let Spellings = [HLSLAnnotation<"packoffset">];
let LangOpts = [HLSL];
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 5b58bbb510c54..a09de9220608d 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8472,6 +8472,20 @@ The full documentation is available here: https://docs.microsoft.com/en-us/windo
}];
}
+def HLSLSV_PositionDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``SV_Position`` semantic, when applied to an input parameter in a pixel
+shader, contains the location of the pixel center (x, y) in screen space.
+This semantic can be applied to the parameter, or a field in a struct used
+as input parameter.
+This attribute is supported as input in pixel, hull, domain and mesh shaders.
+This attribute is supported as output in vertex, geometry and domain shaders.
+
+The full documentation is available here: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-semantics
+ }];
+}
+
def HLSLGroupSharedAddressSpaceDocs : Documentation {
let Category = DocCatVariable;
let Content = [{
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index 66d09f49680be..ba5f06f93dc30 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -125,6 +125,7 @@ class SemaHLSL : public SemaBase {
void handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL);
void handleSV_GroupThreadIDAttr(Decl *D, const ParsedAttr &AL);
void handleSV_GroupIDAttr(Decl *D, const ParsedAttr &AL);
+ void handleSV_PositionAttr(Decl *D, const ParsedAttr &AL);
void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL);
void handleShaderAttr(Decl *D, const ParsedAttr &AL);
void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL);
@@ -146,6 +147,7 @@ class SemaHLSL : public SemaBase {
// Diagnose whether the input ID is uint/unit2/uint3 type.
bool diagnoseInputIDType(QualType T, const ParsedAttr &AL);
+ bool diagnosePositionType(QualType T, const ParsedAttr &AL);
bool CanPerformScalarCast(QualType SrcTy, QualType DestTy);
bool ContainsBitField(QualType BaseTy);
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 6d267e6164845..9115492d1b1dd 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -384,6 +384,28 @@ static Value *buildVectorInput(IRBuilder<> &B, Function *F, llvm::Type *Ty) {
return B.CreateCall(F, {B.getInt32(0)});
}
+static void addBuiltinDecoration(llvm::GlobalVariable *GV, unsigned BuiltIn) {
+ LLVMContext &Ctx = GV->getContext();
+ IRBuilder<> B(GV->getContext());
+ MDNode *Operands =
+ MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32(11)),
+ ConstantAsMetadata::get(B.getInt32(BuiltIn))});
+ MDNode *Decoration = MDNode::get(Ctx, {Operands});
+ GV->addMetadata("spirv.Decorations", *Decoration);
+}
+
+static llvm::Value *createSPIRVBuiltinLoad(IRBuilder<> &B, llvm::Module &M,
+ llvm::Type *Ty, const Twine &Name,
+ unsigned BuiltInID) {
+ auto *GV = new llvm::GlobalVariable(
+ M, Ty, /* isConstant= */ true, llvm::GlobalValue::ExternalLinkage,
+ /* Initializer= */ nullptr, Name, /* insertBefore= */ nullptr,
+ llvm::GlobalVariable::GeneralDynamicTLSModel,
+ /* AddressSpace */ 7, /* isExternallyInitialized= */ true);
+ addBuiltinDecoration(GV, BuiltInID);
+ return B.CreateLoad(Ty, GV);
+}
+
llvm::Value *CGHLSLRuntime::emitInputSemantic(IRBuilder<> &B,
const ParmVarDecl &D,
llvm::Type *Ty) {
@@ -407,6 +429,13 @@ llvm::Value *CGHLSLRuntime::emitInputSemantic(IRBuilder<> &B,
llvm::Function *GroupIDIntrinsic = CGM.getIntrinsic(getGroupIdIntrinsic());
return buildVectorInput(B, GroupIDIntrinsic, Ty);
}
+ if (D.hasAttr<HLSLSV_PositionAttr>()) {
+ if (getArch() == llvm::Triple::spirv)
+ return createSPIRVBuiltinLoad(B, CGM.getModule(), Ty, "sv_position",
+ /* BuiltIn::Position */ 0);
+ llvm_unreachable(
+ "Shader signature for semantics not implemented for DXIL.");
+ }
assert(false && "Unhandled parameter attribute");
return nullptr;
}
@@ -626,16 +655,8 @@ void CGHLSLRuntime::initializeBufferFromBinding(const HLSLBufferDecl *BufDecl,
void CGHLSLRuntime::handleGlobalVarDefinition(const VarDecl *VD,
llvm::GlobalVariable *GV) {
- if (auto Attr = VD->getAttr<HLSLVkExtBuiltinInputAttr>()) {
- LLVMContext &Ctx = GV->getContext();
- IRBuilder<> B(GV->getContext());
- MDNode *Operands = MDNode::get(
- Ctx, {ConstantAsMetadata::get(
- B.getInt32(/* Spirv::Decoration::BuiltIn */ 11)),
- ConstantAsMetadata::get(B.getInt32(Attr->getBuiltIn()))});
- MDNode *Decoration = MDNode::get(Ctx, {Operands});
- GV->addMetadata("spirv.Decorations", *Decoration);
- }
+ if (auto Attr = VD->getAttr<HLSLVkExtBuiltinInputAttr>())
+ addBuiltinDecoration(GV, Attr->getBuiltIn());
}
llvm::Instruction *CGHLSLRuntime::getConvergenceToken(BasicBlock &BB) {
diff --git a/clang/lib/Parse/ParseHLSL.cpp b/clang/lib/Parse/ParseHLSL.cpp
index 5569605c287b1..53d46465e3362 100644
--- a/clang/lib/Parse/ParseHLSL.cpp
+++ b/clang/lib/Parse/ParseHLSL.cpp
@@ -289,6 +289,7 @@ void Parser::ParseHLSLAnnotations(ParsedAttributes &Attrs,
case ParsedAttr::AT_HLSLSV_GroupID:
case ParsedAttr::AT_HLSLSV_GroupIndex:
case ParsedAttr::AT_HLSLSV_DispatchThreadID:
+ case ParsedAttr::AT_HLSLSV_Position:
break;
default:
llvm_unreachable("invalid HLSL Annotation");
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index c829a4426b9f7..e721db5cfb890 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -7510,6 +7510,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
case ParsedAttr::AT_HLSLWaveSize:
S.HLSL().handleWaveSizeAttr(D, AL);
break;
+ case ParsedAttr::AT_HLSLSV_Position:
+ S.HLSL().handleSV_PositionAttr(D, AL);
+ break;
case ParsedAttr::AT_HLSLVkExtBuiltinInput:
S.HLSL().handleVkExtBuiltinInputAttr(D, AL);
break;
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 9065cc5a1d4a5..bcc7f7b40715e 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -764,6 +764,13 @@ void SemaHLSL::CheckSemanticAnnotation(
return;
DiagnoseAttrStageMismatch(AnnotationAttr, ST, {llvm::Triple::Compute});
break;
+ case attr::HLSLSV_Position:
+ // TODO: allow use on other shader types & output once the overall semantic
+ // logic is implemented.
+ if (ST == llvm::Triple::Pixel)
+ return;
+ DiagnoseAttrStageMismatch(AnnotationAttr, ST, {llvm::Triple::Pixel});
+ break;
default:
llvm_unreachable("Unknown HLSLAnnotationAttr");
}
@@ -1147,6 +1154,26 @@ void SemaHLSL::handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL) {
HLSLSV_DispatchThreadIDAttr(getASTContext(), AL));
}
+bool SemaHLSL::diagnosePositionType(QualType T, const ParsedAttr &AL) {
+ const auto *VT = T->getAs<VectorType>();
+
+ if (!T->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) {
+ Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)
+ << AL << "float/float1/float2/float3";
+ return false;
+ }
+
+ return true;
+}
+
+void SemaHLSL::handleSV_PositionAttr(Decl *D, const ParsedAttr &AL) {
+ auto *VD = cast<ValueDecl>(D);
+ if (!diagnosePositionType(VD->getType(), AL))
+ return;
+
+ D->addAttr(::new (getASTContext()) HLSLSV_PositionAttr(getASTContext(), AL));
+}
+
void SemaHLSL::handleSV_GroupThreadIDAttr(Decl *D, const ParsedAttr &AL) {
auto *VD = cast<ValueDecl>(D);
if (!diagnoseInputIDType(VD->getType(), AL))
diff --git a/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl b/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl
new file mode 100644
index 0000000000000..58b91fc9264dd
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-pixel -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s
+
+// CHECK: @sv_position = external thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations !0
+
+// CHECK: define void @main() {{.*}} {
+float4 main(float4 p : SV_Position) {
+ // 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]])
+ return p;
+}
diff --git a/clang/test/SemaHLSL/Semantics/position.ps.hlsl b/clang/test/SemaHLSL/Semantics/position.ps.hlsl
new file mode 100644
index 0000000000000..32bc5f55b2abd
--- /dev/null
+++ b/clang/test/SemaHLSL/Semantics/position.ps.hlsl
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-pixel -x hlsl -finclude-default-header -o - %s -ast-dump | FileCheck %s
+
+float4 main(float4 a : SV_Position) {
+// CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:8 main 'float4 (float4)'
+// CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:20 a 'float4':'vector<float, 4>'
+// CHECK-NEXT: HLSLSV_PositionAttr 0x{{[0-9a-fA-F]+}} <{{.*}}>
+}
diff --git a/clang/test/SemaHLSL/Semantics/position.vs.hlsl b/clang/test/SemaHLSL/Semantics/position.vs.hlsl
new file mode 100644
index 0000000000000..19f781fa3757c
--- /dev/null
+++ b/clang/test/SemaHLSL/Semantics/position.vs.hlsl
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-vertex -x hlsl -finclude-default-header -o - %s -verify
+
+// expected-error@+1 {{attribute 'SV_Position' is unsupported in 'vertex' shaders, requires pixel}}
+float4 main(float4 a : SV_Position) {
+ return a;
+}
|
@llvm/pr-subscribers-clang Author: Nathan Gauër (Keenuts) ChangesThis commit is using the same mechanism as vk::ext_builtin_input to This is incomplete as it doesn't allow the semantic on hull/domain and Full diff: https://github.com/llvm/llvm-project/pull/141759.diff 10 Files Affected:
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 7c63279f156a9..ae363a780a674 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4851,6 +4851,13 @@ def HLSLResourceBinding: InheritableAttr {
}];
}
+def HLSLSV_Position : HLSLAnnotationAttr {
+ let Spellings = [HLSLAnnotation<"sv_position">];
+ let Subjects = SubjectList<[ParmVar, Field]>;
+ let LangOpts = [HLSL];
+ let Documentation = [HLSLSV_PositionDocs];
+}
+
def HLSLPackOffset: HLSLAnnotationAttr {
let Spellings = [HLSLAnnotation<"packoffset">];
let LangOpts = [HLSL];
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 5b58bbb510c54..a09de9220608d 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8472,6 +8472,20 @@ The full documentation is available here: https://docs.microsoft.com/en-us/windo
}];
}
+def HLSLSV_PositionDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``SV_Position`` semantic, when applied to an input parameter in a pixel
+shader, contains the location of the pixel center (x, y) in screen space.
+This semantic can be applied to the parameter, or a field in a struct used
+as input parameter.
+This attribute is supported as input in pixel, hull, domain and mesh shaders.
+This attribute is supported as output in vertex, geometry and domain shaders.
+
+The full documentation is available here: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-semantics
+ }];
+}
+
def HLSLGroupSharedAddressSpaceDocs : Documentation {
let Category = DocCatVariable;
let Content = [{
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index 66d09f49680be..ba5f06f93dc30 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -125,6 +125,7 @@ class SemaHLSL : public SemaBase {
void handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL);
void handleSV_GroupThreadIDAttr(Decl *D, const ParsedAttr &AL);
void handleSV_GroupIDAttr(Decl *D, const ParsedAttr &AL);
+ void handleSV_PositionAttr(Decl *D, const ParsedAttr &AL);
void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL);
void handleShaderAttr(Decl *D, const ParsedAttr &AL);
void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL);
@@ -146,6 +147,7 @@ class SemaHLSL : public SemaBase {
// Diagnose whether the input ID is uint/unit2/uint3 type.
bool diagnoseInputIDType(QualType T, const ParsedAttr &AL);
+ bool diagnosePositionType(QualType T, const ParsedAttr &AL);
bool CanPerformScalarCast(QualType SrcTy, QualType DestTy);
bool ContainsBitField(QualType BaseTy);
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 6d267e6164845..9115492d1b1dd 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -384,6 +384,28 @@ static Value *buildVectorInput(IRBuilder<> &B, Function *F, llvm::Type *Ty) {
return B.CreateCall(F, {B.getInt32(0)});
}
+static void addBuiltinDecoration(llvm::GlobalVariable *GV, unsigned BuiltIn) {
+ LLVMContext &Ctx = GV->getContext();
+ IRBuilder<> B(GV->getContext());
+ MDNode *Operands =
+ MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32(11)),
+ ConstantAsMetadata::get(B.getInt32(BuiltIn))});
+ MDNode *Decoration = MDNode::get(Ctx, {Operands});
+ GV->addMetadata("spirv.Decorations", *Decoration);
+}
+
+static llvm::Value *createSPIRVBuiltinLoad(IRBuilder<> &B, llvm::Module &M,
+ llvm::Type *Ty, const Twine &Name,
+ unsigned BuiltInID) {
+ auto *GV = new llvm::GlobalVariable(
+ M, Ty, /* isConstant= */ true, llvm::GlobalValue::ExternalLinkage,
+ /* Initializer= */ nullptr, Name, /* insertBefore= */ nullptr,
+ llvm::GlobalVariable::GeneralDynamicTLSModel,
+ /* AddressSpace */ 7, /* isExternallyInitialized= */ true);
+ addBuiltinDecoration(GV, BuiltInID);
+ return B.CreateLoad(Ty, GV);
+}
+
llvm::Value *CGHLSLRuntime::emitInputSemantic(IRBuilder<> &B,
const ParmVarDecl &D,
llvm::Type *Ty) {
@@ -407,6 +429,13 @@ llvm::Value *CGHLSLRuntime::emitInputSemantic(IRBuilder<> &B,
llvm::Function *GroupIDIntrinsic = CGM.getIntrinsic(getGroupIdIntrinsic());
return buildVectorInput(B, GroupIDIntrinsic, Ty);
}
+ if (D.hasAttr<HLSLSV_PositionAttr>()) {
+ if (getArch() == llvm::Triple::spirv)
+ return createSPIRVBuiltinLoad(B, CGM.getModule(), Ty, "sv_position",
+ /* BuiltIn::Position */ 0);
+ llvm_unreachable(
+ "Shader signature for semantics not implemented for DXIL.");
+ }
assert(false && "Unhandled parameter attribute");
return nullptr;
}
@@ -626,16 +655,8 @@ void CGHLSLRuntime::initializeBufferFromBinding(const HLSLBufferDecl *BufDecl,
void CGHLSLRuntime::handleGlobalVarDefinition(const VarDecl *VD,
llvm::GlobalVariable *GV) {
- if (auto Attr = VD->getAttr<HLSLVkExtBuiltinInputAttr>()) {
- LLVMContext &Ctx = GV->getContext();
- IRBuilder<> B(GV->getContext());
- MDNode *Operands = MDNode::get(
- Ctx, {ConstantAsMetadata::get(
- B.getInt32(/* Spirv::Decoration::BuiltIn */ 11)),
- ConstantAsMetadata::get(B.getInt32(Attr->getBuiltIn()))});
- MDNode *Decoration = MDNode::get(Ctx, {Operands});
- GV->addMetadata("spirv.Decorations", *Decoration);
- }
+ if (auto Attr = VD->getAttr<HLSLVkExtBuiltinInputAttr>())
+ addBuiltinDecoration(GV, Attr->getBuiltIn());
}
llvm::Instruction *CGHLSLRuntime::getConvergenceToken(BasicBlock &BB) {
diff --git a/clang/lib/Parse/ParseHLSL.cpp b/clang/lib/Parse/ParseHLSL.cpp
index 5569605c287b1..53d46465e3362 100644
--- a/clang/lib/Parse/ParseHLSL.cpp
+++ b/clang/lib/Parse/ParseHLSL.cpp
@@ -289,6 +289,7 @@ void Parser::ParseHLSLAnnotations(ParsedAttributes &Attrs,
case ParsedAttr::AT_HLSLSV_GroupID:
case ParsedAttr::AT_HLSLSV_GroupIndex:
case ParsedAttr::AT_HLSLSV_DispatchThreadID:
+ case ParsedAttr::AT_HLSLSV_Position:
break;
default:
llvm_unreachable("invalid HLSL Annotation");
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index c829a4426b9f7..e721db5cfb890 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -7510,6 +7510,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
case ParsedAttr::AT_HLSLWaveSize:
S.HLSL().handleWaveSizeAttr(D, AL);
break;
+ case ParsedAttr::AT_HLSLSV_Position:
+ S.HLSL().handleSV_PositionAttr(D, AL);
+ break;
case ParsedAttr::AT_HLSLVkExtBuiltinInput:
S.HLSL().handleVkExtBuiltinInputAttr(D, AL);
break;
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 9065cc5a1d4a5..bcc7f7b40715e 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -764,6 +764,13 @@ void SemaHLSL::CheckSemanticAnnotation(
return;
DiagnoseAttrStageMismatch(AnnotationAttr, ST, {llvm::Triple::Compute});
break;
+ case attr::HLSLSV_Position:
+ // TODO: allow use on other shader types & output once the overall semantic
+ // logic is implemented.
+ if (ST == llvm::Triple::Pixel)
+ return;
+ DiagnoseAttrStageMismatch(AnnotationAttr, ST, {llvm::Triple::Pixel});
+ break;
default:
llvm_unreachable("Unknown HLSLAnnotationAttr");
}
@@ -1147,6 +1154,26 @@ void SemaHLSL::handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL) {
HLSLSV_DispatchThreadIDAttr(getASTContext(), AL));
}
+bool SemaHLSL::diagnosePositionType(QualType T, const ParsedAttr &AL) {
+ const auto *VT = T->getAs<VectorType>();
+
+ if (!T->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) {
+ Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)
+ << AL << "float/float1/float2/float3";
+ return false;
+ }
+
+ return true;
+}
+
+void SemaHLSL::handleSV_PositionAttr(Decl *D, const ParsedAttr &AL) {
+ auto *VD = cast<ValueDecl>(D);
+ if (!diagnosePositionType(VD->getType(), AL))
+ return;
+
+ D->addAttr(::new (getASTContext()) HLSLSV_PositionAttr(getASTContext(), AL));
+}
+
void SemaHLSL::handleSV_GroupThreadIDAttr(Decl *D, const ParsedAttr &AL) {
auto *VD = cast<ValueDecl>(D);
if (!diagnoseInputIDType(VD->getType(), AL))
diff --git a/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl b/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl
new file mode 100644
index 0000000000000..58b91fc9264dd
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-pixel -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s
+
+// CHECK: @sv_position = external thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations !0
+
+// CHECK: define void @main() {{.*}} {
+float4 main(float4 p : SV_Position) {
+ // 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]])
+ return p;
+}
diff --git a/clang/test/SemaHLSL/Semantics/position.ps.hlsl b/clang/test/SemaHLSL/Semantics/position.ps.hlsl
new file mode 100644
index 0000000000000..32bc5f55b2abd
--- /dev/null
+++ b/clang/test/SemaHLSL/Semantics/position.ps.hlsl
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-pixel -x hlsl -finclude-default-header -o - %s -ast-dump | FileCheck %s
+
+float4 main(float4 a : SV_Position) {
+// CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:8 main 'float4 (float4)'
+// CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:20 a 'float4':'vector<float, 4>'
+// CHECK-NEXT: HLSLSV_PositionAttr 0x{{[0-9a-fA-F]+}} <{{.*}}>
+}
diff --git a/clang/test/SemaHLSL/Semantics/position.vs.hlsl b/clang/test/SemaHLSL/Semantics/position.vs.hlsl
new file mode 100644
index 0000000000000..19f781fa3757c
--- /dev/null
+++ b/clang/test/SemaHLSL/Semantics/position.vs.hlsl
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-vertex -x hlsl -finclude-default-header -o - %s -verify
+
+// expected-error@+1 {{attribute 'SV_Position' is unsupported in 'vertex' shaders, requires pixel}}
+float4 main(float4 a : SV_Position) {
+ return a;
+}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
clang/lib/Sema/SemaHLSL.cpp
Outdated
|
||
if (!T->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) { | ||
Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type) | ||
<< AL << "float/float1/float2/float3"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we use VT->getNumElements()
as an argument so we don't have to define each float vector and instead use language to indicate the range.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what you mean by 'use language to indicate the range'.
The message says which type is expected, if I used VT->getNumElements()
it would say what type has been given, not what's expected.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean some thing like float vector between 1 and VT->getNumElements()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I still don't get it, you mean passing VT->getNumElements()
in the argument list for the Diag
call right?
Right now the error message is:
attribute 'SV_Position' only applies to a field or parameter of type 'float/float1/float2/float3/float4'
If we used VT->getNumElements()
as argument, it would only be used to say what we got, so we'd still enumerate the 5 allowed floatN forms.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was just thinking with shader model 6.9 allowing n dimensional vectors should we be future proof this so we don’t have to iterate all the float vectors. That said the coop vectors stuff is more for compute shaders so what you have is probably fine.
This commit is using the same mechanism as vk::ext_builtin_input to implement the SV_Position semantic input. The HLSL signature is not yet ready for DXIL, hence this commit only implements the SPIR-V side. This is incomplete as it doesn't allow the semantic on hull/domain and other shaders, but it's a first step to validate the overall input/output semantic logic.
4653aca
to
ce43937
Compare
This commit is using the same mechanism as vk::ext_builtin_input to implement the SV_Position semantic input. The HLSL signature is not yet ready for DXIL, hence this commit only implements the SPIR-V side. This is incomplete as it doesn't allow the semantic on hull/domain and other shaders, but it's a first step to validate the overall input/output semantic logic. Fixes llvm#136969
This commit is using the same mechanism as vk::ext_builtin_input to
implement the SV_Position semantic input.
The HLSL signature is not yet ready for DXIL, hence this commit only
implements the SPIR-V side.
This is incomplete as it doesn't allow the semantic on hull/domain and
other shaders, but it's a first step to validate the overall input/output
semantic logic.
Fixes #136969