Skip to content

Commit 4653aca

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 20d7019 commit 4653aca

File tree

10 files changed

+108
-10
lines changed

10 files changed

+108
-10
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4851,6 +4851,13 @@ def HLSLResourceBinding: InheritableAttr {
48514851
}];
48524852
}
48534853

4854+
def HLSLSV_Position : HLSLAnnotationAttr {
4855+
let Spellings = [HLSLAnnotation<"sv_position">];
4856+
let Subjects = SubjectList<[ParmVar, Field]>;
4857+
let LangOpts = [HLSL];
4858+
let Documentation = [HLSLSV_PositionDocs];
4859+
}
4860+
48544861
def HLSLPackOffset: HLSLAnnotationAttr {
48554862
let Spellings = [HLSLAnnotation<"packoffset">];
48564863
let LangOpts = [HLSL];

clang/include/clang/Basic/AttrDocs.td

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

8475+
def HLSLSV_PositionDocs : Documentation {
8476+
let Category = DocCatFunction;
8477+
let Content = [{
8478+
The ``SV_Position`` semantic, when applied to an input parameter in a pixel
8479+
shader, contains the location of the pixel center (x, y) in screen space.
8480+
This semantic can be applied to the parameter, or a field in a struct used
8481+
as input parameter.
8482+
This attribute is supported as input in pixel, hull, domain and mesh shaders.
8483+
This attribute is supported as output in vertex, geometry and domain shaders.
8484+
8485+
The full documentation is available here: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-semantics
8486+
}];
8487+
}
8488+
84758489
def HLSLGroupSharedAddressSpaceDocs : Documentation {
84768490
let Category = DocCatVariable;
84778491
let Content = [{

clang/include/clang/Sema/SemaHLSL.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ class SemaHLSL : public SemaBase {
125125
void handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL);
126126
void handleSV_GroupThreadIDAttr(Decl *D, const ParsedAttr &AL);
127127
void handleSV_GroupIDAttr(Decl *D, const ParsedAttr &AL);
128+
void handleSV_PositionAttr(Decl *D, const ParsedAttr &AL);
128129
void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL);
129130
void handleShaderAttr(Decl *D, const ParsedAttr &AL);
130131
void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL);
@@ -146,6 +147,7 @@ class SemaHLSL : public SemaBase {
146147

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

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

clang/lib/CodeGen/CGHLSLRuntime.cpp

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

387+
static void addBuiltinDecoration(llvm::GlobalVariable *GV, unsigned BuiltIn) {
388+
LLVMContext &Ctx = GV->getContext();
389+
IRBuilder<> B(GV->getContext());
390+
MDNode *Operands =
391+
MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32(11)),
392+
ConstantAsMetadata::get(B.getInt32(BuiltIn))});
393+
MDNode *Decoration = MDNode::get(Ctx, {Operands});
394+
GV->addMetadata("spirv.Decorations", *Decoration);
395+
}
396+
397+
static llvm::Value *createSPIRVBuiltinLoad(IRBuilder<> &B, llvm::Module &M,
398+
llvm::Type *Ty, const Twine &Name,
399+
unsigned BuiltInID) {
400+
auto *GV = new llvm::GlobalVariable(
401+
M, Ty, /* isConstant= */ true, llvm::GlobalValue::ExternalLinkage,
402+
/* Initializer= */ nullptr, Name, /* insertBefore= */ nullptr,
403+
llvm::GlobalVariable::GeneralDynamicTLSModel,
404+
/* AddressSpace */ 7, /* isExternallyInitialized= */ true);
405+
addBuiltinDecoration(GV, BuiltInID);
406+
return B.CreateLoad(Ty, GV);
407+
}
408+
387409
llvm::Value *CGHLSLRuntime::emitInputSemantic(IRBuilder<> &B,
388410
const ParmVarDecl &D,
389411
llvm::Type *Ty) {
@@ -407,6 +429,13 @@ llvm::Value *CGHLSLRuntime::emitInputSemantic(IRBuilder<> &B,
407429
llvm::Function *GroupIDIntrinsic = CGM.getIntrinsic(getGroupIdIntrinsic());
408430
return buildVectorInput(B, GroupIDIntrinsic, Ty);
409431
}
432+
if (D.hasAttr<HLSLSV_PositionAttr>()) {
433+
if (getArch() == llvm::Triple::spirv)
434+
return createSPIRVBuiltinLoad(B, CGM.getModule(), Ty, "sv_position",
435+
/* BuiltIn::Position */ 0);
436+
llvm_unreachable(
437+
"Shader signature for semantics not implemented for DXIL.");
438+
}
410439
assert(false && "Unhandled parameter attribute");
411440
return nullptr;
412441
}
@@ -626,16 +655,8 @@ void CGHLSLRuntime::initializeBufferFromBinding(const HLSLBufferDecl *BufDecl,
626655

627656
void CGHLSLRuntime::handleGlobalVarDefinition(const VarDecl *VD,
628657
llvm::GlobalVariable *GV) {
629-
if (auto Attr = VD->getAttr<HLSLVkExtBuiltinInputAttr>()) {
630-
LLVMContext &Ctx = GV->getContext();
631-
IRBuilder<> B(GV->getContext());
632-
MDNode *Operands = MDNode::get(
633-
Ctx, {ConstantAsMetadata::get(
634-
B.getInt32(/* Spirv::Decoration::BuiltIn */ 11)),
635-
ConstantAsMetadata::get(B.getInt32(Attr->getBuiltIn()))});
636-
MDNode *Decoration = MDNode::get(Ctx, {Operands});
637-
GV->addMetadata("spirv.Decorations", *Decoration);
638-
}
658+
if (auto Attr = VD->getAttr<HLSLVkExtBuiltinInputAttr>())
659+
addBuiltinDecoration(GV, Attr->getBuiltIn());
639660
}
640661

641662
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
@@ -7510,6 +7510,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
75107510
case ParsedAttr::AT_HLSLWaveSize:
75117511
S.HLSL().handleWaveSizeAttr(D, AL);
75127512
break;
7513+
case ParsedAttr::AT_HLSLSV_Position:
7514+
S.HLSL().handleSV_PositionAttr(D, AL);
7515+
break;
75137516
case ParsedAttr::AT_HLSLVkExtBuiltinInput:
75147517
S.HLSL().handleVkExtBuiltinInputAttr(D, AL);
75157518
break;

clang/lib/Sema/SemaHLSL.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,13 @@ void SemaHLSL::CheckSemanticAnnotation(
764764
return;
765765
DiagnoseAttrStageMismatch(AnnotationAttr, ST, {llvm::Triple::Compute});
766766
break;
767+
case attr::HLSLSV_Position:
768+
// TODO: allow use on other shader types & output once the overall semantic
769+
// logic is implemented.
770+
if (ST == llvm::Triple::Pixel)
771+
return;
772+
DiagnoseAttrStageMismatch(AnnotationAttr, ST, {llvm::Triple::Pixel});
773+
break;
767774
default:
768775
llvm_unreachable("Unknown HLSLAnnotationAttr");
769776
}
@@ -1147,6 +1154,26 @@ void SemaHLSL::handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL) {
11471154
HLSLSV_DispatchThreadIDAttr(getASTContext(), AL));
11481155
}
11491156

1157+
bool SemaHLSL::diagnosePositionType(QualType T, const ParsedAttr &AL) {
1158+
const auto *VT = T->getAs<VectorType>();
1159+
1160+
if (!T->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) {
1161+
Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)
1162+
<< AL << "float/float1/float2/float3";
1163+
return false;
1164+
}
1165+
1166+
return true;
1167+
}
1168+
1169+
void SemaHLSL::handleSV_PositionAttr(Decl *D, const ParsedAttr &AL) {
1170+
auto *VD = cast<ValueDecl>(D);
1171+
if (!diagnosePositionType(VD->getType(), AL))
1172+
return;
1173+
1174+
D->addAttr(::new (getASTContext()) HLSLSV_PositionAttr(getASTContext(), AL));
1175+
}
1176+
11501177
void SemaHLSL::handleSV_GroupThreadIDAttr(Decl *D, const ParsedAttr &AL) {
11511178
auto *VD = cast<ValueDecl>(D);
11521179
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)