Skip to content

Commit 18fbd19

Browse files
committed
[HLSL][SPIR-V] Handle SV_Postion builtin in PS
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.
1 parent 981ccf9 commit 18fbd19

File tree

10 files changed

+108
-9
lines changed

10 files changed

+108
-9
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4807,6 +4807,13 @@ def HLSLResourceBinding: InheritableAttr {
48074807
}];
48084808
}
48094809

4810+
def HLSLSV_Position : HLSLAnnotationAttr {
4811+
let Spellings = [HLSLAnnotation<"sv_position">];
4812+
let Subjects = SubjectList<[ParmVar, Field]>;
4813+
let LangOpts = [HLSL];
4814+
let Documentation = [HLSLSV_PositionDocs];
4815+
}
4816+
48104817
def HLSLPackOffset: HLSLAnnotationAttr {
48114818
let Spellings = [HLSLAnnotation<"packoffset">];
48124819
let LangOpts = [HLSL];

clang/include/clang/Basic/AttrDocs.td

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8461,6 +8461,20 @@ The full documentation is available here: https://docs.microsoft.com/en-us/windo
84618461
}];
84628462
}
84638463

8464+
def HLSLSV_PositionDocs : Documentation {
8465+
let Category = DocCatFunction;
8466+
let Content = [{
8467+
The ``SV_Position`` semantic, when applied to an input parameter in a pixel
8468+
shader, contains the location of the pixel center (x, y) in screen space.
8469+
This semantic can be applied to the parameter, or a field in a struct used
8470+
as input parameter.
8471+
This attribute is supported as input in pixel, hull, domain and mesh shaders.
8472+
This attribute is supported as output in vertex, geometry and domain shaders.
8473+
8474+
The full documentation is available here: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-semantics
8475+
}];
8476+
}
8477+
84648478
def HLSLGroupSharedAddressSpaceDocs : Documentation {
84658479
let Category = DocCatVariable;
84668480
let Content = [{

clang/include/clang/Sema/SemaHLSL.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ class SemaHLSL : public SemaBase {
124124
void handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL);
125125
void handleSV_GroupThreadIDAttr(Decl *D, const ParsedAttr &AL);
126126
void handleSV_GroupIDAttr(Decl *D, const ParsedAttr &AL);
127+
void handleSV_PositionAttr(Decl *D, const ParsedAttr &AL);
127128
void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL);
128129
void handleShaderAttr(Decl *D, const ParsedAttr &AL);
129130
void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL);
@@ -145,6 +146,7 @@ class SemaHLSL : public SemaBase {
145146

146147
// Diagnose whether the input ID is uint/unit2/uint3 type.
147148
bool diagnoseInputIDType(QualType T, const ParsedAttr &AL);
149+
bool diagnosePositionType(QualType T, const ParsedAttr &AL);
148150

149151
bool CanPerformScalarCast(QualType SrcTy, QualType DestTy);
150152
bool ContainsBitField(QualType BaseTy);

clang/lib/CodeGen/CGHLSLRuntime.cpp

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,28 @@ static Value *buildVectorInput(IRBuilder<> &B, Function *F, llvm::Type *Ty) {
345345
return B.CreateCall(F, {B.getInt32(0)});
346346
}
347347

348+
static void addBuiltinDecoration(llvm::GlobalVariable *GV, unsigned BuiltIn) {
349+
LLVMContext &Ctx = GV->getContext();
350+
IRBuilder<> B(GV->getContext());
351+
MDNode *Operands =
352+
MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32(11)),
353+
ConstantAsMetadata::get(B.getInt32(BuiltIn))});
354+
MDNode *Decoration = MDNode::get(Ctx, {Operands});
355+
GV->addMetadata("spirv.Decorations", *Decoration);
356+
}
357+
358+
static llvm::Value *createSPIRVBuiltinLoad(IRBuilder<> &B, llvm::Module &M,
359+
llvm::Type *Ty, const Twine &Name,
360+
unsigned BuiltInID) {
361+
auto *GV = new llvm::GlobalVariable(
362+
M, Ty, /* isConstant= */ true, llvm::GlobalValue::ExternalLinkage,
363+
/* Initializer= */ nullptr, Name, /* insertBefore= */ nullptr,
364+
llvm::GlobalVariable::GeneralDynamicTLSModel,
365+
/* AddressSpace */ 7, /* isExternallyInitialized= */ true);
366+
addBuiltinDecoration(GV, BuiltInID);
367+
return B.CreateLoad(Ty, GV);
368+
}
369+
348370
llvm::Value *CGHLSLRuntime::emitInputSemantic(IRBuilder<> &B,
349371
const ParmVarDecl &D,
350372
llvm::Type *Ty) {
@@ -368,6 +390,13 @@ llvm::Value *CGHLSLRuntime::emitInputSemantic(IRBuilder<> &B,
368390
llvm::Function *GroupIDIntrinsic = CGM.getIntrinsic(getGroupIdIntrinsic());
369391
return buildVectorInput(B, GroupIDIntrinsic, Ty);
370392
}
393+
if (D.hasAttr<HLSLSV_PositionAttr>()) {
394+
if (getArch() == llvm::Triple::spirv)
395+
return createSPIRVBuiltinLoad(B, CGM.getModule(), Ty, "sv_position",
396+
/* BuiltIn::Position */ 0);
397+
llvm_unreachable(
398+
"Shader signature for semantics not implemented for DXIL.");
399+
}
371400
assert(false && "Unhandled parameter attribute");
372401
return nullptr;
373402
}
@@ -556,15 +585,8 @@ static void initializeBufferFromBinding(CodeGenModule &CGM,
556585

557586
void CGHLSLRuntime::handleGlobalVarDefinition(const VarDecl *VD,
558587
llvm::GlobalVariable *GV) {
559-
if (auto Attr = VD->getAttr<HLSLVkExtBuiltinInputAttr>()) {
560-
LLVMContext &Ctx = GV->getContext();
561-
IRBuilder<> B(GV->getContext());
562-
MDNode *Operands = MDNode::get(
563-
Ctx, {ConstantAsMetadata::get(B.getInt32(11)),
564-
ConstantAsMetadata::get(B.getInt32(Attr->getBuiltIn()))});
565-
MDNode *Decoration = MDNode::get(Ctx, {Operands});
566-
GV->addMetadata("spirv.Decorations", *Decoration);
567-
}
588+
if (auto Attr = VD->getAttr<HLSLVkExtBuiltinInputAttr>())
589+
addBuiltinDecoration(GV, Attr->getBuiltIn());
568590
}
569591

570592
llvm::Instruction *CGHLSLRuntime::getConvergenceToken(BasicBlock &BB) {

clang/lib/Parse/ParseHLSL.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@ void Parser::ParseHLSLAnnotations(ParsedAttributes &Attrs,
289289
case ParsedAttr::AT_HLSLSV_GroupID:
290290
case ParsedAttr::AT_HLSLSV_GroupIndex:
291291
case ParsedAttr::AT_HLSLSV_DispatchThreadID:
292+
case ParsedAttr::AT_HLSLSV_Position:
292293
break;
293294
default:
294295
llvm_unreachable("invalid HLSL Annotation");

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7483,6 +7483,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
74837483
case ParsedAttr::AT_HLSLWaveSize:
74847484
S.HLSL().handleWaveSizeAttr(D, AL);
74857485
break;
7486+
case ParsedAttr::AT_HLSLSV_Position:
7487+
S.HLSL().handleSV_PositionAttr(D, AL);
7488+
break;
74867489
case ParsedAttr::AT_HLSLVkExtBuiltinInput:
74877490
S.HLSL().handleVkExtBuiltinInputAttr(D, AL);
74887491
break;

clang/lib/Sema/SemaHLSL.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,13 @@ void SemaHLSL::CheckSemanticAnnotation(
743743
return;
744744
DiagnoseAttrStageMismatch(AnnotationAttr, ST, {llvm::Triple::Compute});
745745
break;
746+
case attr::HLSLSV_Position:
747+
// TODO: allow use on other shader types & output once the overall semantic
748+
// logic is implemented.
749+
if (ST == llvm::Triple::Pixel)
750+
return;
751+
DiagnoseAttrStageMismatch(AnnotationAttr, ST, {llvm::Triple::Pixel});
752+
break;
746753
default:
747754
llvm_unreachable("Unknown HLSLAnnotationAttr");
748755
}
@@ -1099,6 +1106,26 @@ void SemaHLSL::handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL) {
10991106
HLSLSV_DispatchThreadIDAttr(getASTContext(), AL));
11001107
}
11011108

1109+
bool SemaHLSL::diagnosePositionType(QualType T, const ParsedAttr &AL) {
1110+
const auto *VT = T->getAs<VectorType>();
1111+
1112+
if (!T->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) {
1113+
Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)
1114+
<< AL << "float/float1/float2/float3";
1115+
return false;
1116+
}
1117+
1118+
return true;
1119+
}
1120+
1121+
void SemaHLSL::handleSV_PositionAttr(Decl *D, const ParsedAttr &AL) {
1122+
auto *VD = cast<ValueDecl>(D);
1123+
if (!diagnosePositionType(VD->getType(), AL))
1124+
return;
1125+
1126+
D->addAttr(::new (getASTContext()) HLSLSV_PositionAttr(getASTContext(), AL));
1127+
}
1128+
11021129
void SemaHLSL::handleSV_GroupThreadIDAttr(Decl *D, const ParsedAttr &AL) {
11031130
auto *VD = cast<ValueDecl>(D);
11041131
if (!diagnoseInputIDType(VD->getType(), AL))
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-pixel -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s
2+
3+
// CHECK: @sv_position = external thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations !0
4+
5+
// CHECK: define void @main() {{.*}} {
6+
float4 main(float4 p : SV_Position) {
7+
// CHECK: %[[#P:]] = load <4 x float>, ptr addrspace(7) @sv_position, align 16
8+
// CHECK: %[[#R:]] = call spir_func <4 x float> @_Z4mainDv4_f(<4 x float> %[[#P]])
9+
return p;
10+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-pixel -x hlsl -finclude-default-header -o - %s -ast-dump | FileCheck %s
2+
3+
float4 main(float4 a : SV_Position) {
4+
// CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:8 main 'float4 (float4)'
5+
// CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:20 a 'float4':'vector<float, 4>'
6+
// CHECK-NEXT: HLSLSV_PositionAttr 0x{{[0-9a-fA-F]+}} <{{.*}}>
7+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-vertex -x hlsl -finclude-default-header -o - %s -verify
2+
3+
// expected-error@+1 {{attribute 'SV_Position' is unsupported in 'vertex' shaders, requires pixel}}
4+
float4 main(float4 a : SV_Position) {
5+
return a;
6+
}

0 commit comments

Comments
 (0)