[clang] 14ae5d2 - [HLSL] Add SV_DispatchThreadID
Xiang Li via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 18 16:17:26 PDT 2022
Author: Xiang Li
Date: 2022-10-18T16:17:19-07:00
New Revision: 14ae5d2b745f76018a963b395fc9d7ad987f1c5c
URL: https://github.com/llvm/llvm-project/commit/14ae5d2b745f76018a963b395fc9d7ad987f1c5c
DIFF: https://github.com/llvm/llvm-project/commit/14ae5d2b745f76018a963b395fc9d7ad987f1c5c.diff
LOG: [HLSL] Add SV_DispatchThreadID
Support SV_DispatchThreadID attribute.
Translate it into dx.thread.id in clang codeGen.
Reviewed By: beanz, aaron.ballman
Differential Revision: https://reviews.llvm.org/D133983
Added:
clang/test/CodeGenHLSL/semantics/DispatchThreadID.hlsl
clang/test/CodeGenHLSL/sret_output.hlsl
clang/test/SemaHLSL/Semantics/invalid_entry_parameter.hlsl
clang/test/SemaHLSL/Semantics/valid_entry_parameter.hlsl
Modified:
clang/include/clang/Basic/Attr.td
clang/include/clang/Basic/AttrDocs.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/CodeGen/CGHLSLRuntime.cpp
clang/lib/CodeGen/CGHLSLRuntime.h
clang/lib/Parse/ParseHLSL.cpp
clang/lib/Sema/SemaDeclAttr.cpp
clang/test/SemaHLSL/Semantics/entry_parameter.hlsl
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index fddf097daaafd..58ac67e925882 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4004,6 +4004,13 @@ def HLSLResourceBinding: InheritableAttr {
let Documentation = [HLSLResourceBindingDocs];
}
+def HLSLSV_DispatchThreadID: HLSLAnnotationAttr {
+ let Spellings = [HLSLSemantic<"SV_DispatchThreadID">];
+ let Subjects = SubjectList<[ParmVar, Field]>;
+ let LangOpts = [HLSL];
+ let Documentation = [HLSLSV_DispatchThreadIDDocs];
+}
+
def HLSLShader : InheritableAttr {
let Spellings = [Microsoft<"shader">];
let Subjects = SubjectList<[HLSLEntry]>;
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 005264d4f60e4..33a18ac033252 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -6618,6 +6618,21 @@ The full documentation is available here: https://docs.microsoft.com/en-us/windo
}];
}
+def HLSLSV_DispatchThreadIDDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``SV_DispatchThreadID`` semantic, when applied to an input parameter,
+specifies a data binding to map the global thread offset within the Dispatch
+call (per dimension of the group) to the specified parameter.
+When applied to a field of a struct, the data binding is specified to the field
+when the struct is used as a parameter type.
+The semantic on the field is ignored when not used as a parameter.
+This attribute is only supported in compute shaders.
+
+The full documentation is available here: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sv-dispatchthreadid
+ }];
+}
+
def AnnotateTypeDocs : Documentation {
let Category = DocCatType;
let Heading = "annotate_type";
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 2bae254a097d9..605128ee36bc0 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11691,7 +11691,10 @@ def err_std_source_location_impl_malformed : Error<
// HLSL Diagnostics
def err_hlsl_attr_unsupported_in_stage : Error<"attribute %0 is unsupported in %select{Pixel|Vertex|Geometry|Hull|Domain|Compute|Library|RayGeneration|Intersection|AnyHit|ClosestHit|Miss|Callable|Mesh|Amplification|Invalid}1 shaders, requires %2">;
-
+def err_hlsl_attr_invalid_type : Error<
+ "attribute %0 only applies to a field or parameter of type '%1'">;
+def err_hlsl_attr_invalid_ast_node : Error<
+ "attribute %0 only applies to %1">;
def err_hlsl_numthreads_argument_oor : Error<"argument '%select{X|Y|Z}0' to numthreads attribute cannot exceed %1">;
def err_hlsl_numthreads_invalid : Error<"total number of threads cannot exceed %0">;
def err_hlsl_missing_numthreads : Error<"missing numthreads attribute for %0 shader entry">;
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index cfdc1f68a03d8..59fab7b69c20b 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -324,14 +324,31 @@ void clang::CodeGen::CGHLSLRuntime::setHLSLEntryAttributes(
}
}
+static Value *buildVectorInput(IRBuilder<> &B, Function *F, llvm::Type *Ty) {
+ if (const auto *VT = dyn_cast<FixedVectorType>(Ty)) {
+ Value *Result = PoisonValue::get(Ty);
+ for (unsigned I = 0; I < VT->getNumElements(); ++I) {
+ Value *Elt = B.CreateCall(F, {B.getInt32(I)});
+ Result = B.CreateInsertElement(Result, Elt, I);
+ }
+ return Result;
+ }
+ return B.CreateCall(F, {B.getInt32(0)});
+}
+
llvm::Value *CGHLSLRuntime::emitInputSemantic(IRBuilder<> &B,
- const ParmVarDecl &D) {
+ const ParmVarDecl &D,
+ llvm::Type *Ty) {
assert(D.hasAttrs() && "Entry parameter missing annotation attribute!");
if (D.hasAttr<HLSLSV_GroupIndexAttr>()) {
llvm::Function *DxGroupIndex =
CGM.getIntrinsic(Intrinsic::dx_flattened_thread_id_in_group);
return B.CreateCall(FunctionCallee(DxGroupIndex));
}
+ if (D.hasAttr<HLSLSV_DispatchThreadIDAttr>()) {
+ llvm::Function *DxThreadID = CGM.getIntrinsic(Intrinsic::dx_thread_id);
+ return buildVectorInput(B, DxThreadID, Ty);
+ }
assert(false && "Unhandled parameter attribute");
return nullptr;
}
@@ -359,8 +376,17 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
llvm::SmallVector<Value *> Args;
// FIXME: support struct parameters where semantics are on members.
// See: https://github.com/llvm/llvm-project/issues/57874
- for (const auto *Param : FD->parameters()) {
- Args.push_back(emitInputSemantic(B, *Param));
+ unsigned SRetOffset = 0;
+ for (const auto &Param : Fn->args()) {
+ if (Param.hasStructRetAttr()) {
+ // FIXME: support output.
+ // See: https://github.com/llvm/llvm-project/issues/57874
+ SRetOffset = 1;
+ Args.emplace_back(PoisonValue::get(Param.getType()));
+ continue;
+ }
+ const ParmVarDecl *PD = FD->getParamDecl(Param.getArgNo() - SRetOffset);
+ Args.push_back(emitInputSemantic(B, *PD, Param.getType()));
}
CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args);
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index 2bb331a78e3e5..922ef59dca37a 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -73,7 +73,8 @@ class CGHLSLRuntime {
uint32_t ResourceCounters[static_cast<uint32_t>(
hlsl::ResourceClass::NumClasses)] = {0};
- llvm::Value *emitInputSemantic(llvm::IRBuilder<> &B, const ParmVarDecl &D);
+ llvm::Value *emitInputSemantic(llvm::IRBuilder<> &B, const ParmVarDecl &D,
+ llvm::Type *Ty);
public:
CGHLSLRuntime(CodeGenModule &CGM) : CGM(CGM) {}
diff --git a/clang/lib/Parse/ParseHLSL.cpp b/clang/lib/Parse/ParseHLSL.cpp
index 6224cb1ec712e..d079c76d092a7 100644
--- a/clang/lib/Parse/ParseHLSL.cpp
+++ b/clang/lib/Parse/ParseHLSL.cpp
@@ -186,6 +186,7 @@ void Parser::ParseHLSLSemantics(ParsedAttributes &Attrs,
Diag(Loc, diag::err_unknown_hlsl_semantic) << II;
return;
case ParsedAttr::AT_HLSLSV_GroupIndex:
+ case ParsedAttr::AT_HLSLSV_DispatchThreadID:
break;
default:
llvm_unreachable("invalid HLSL Semantic");
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index d13bcf43b76c3..d8dd1ab8e1d17 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -6905,6 +6905,51 @@ static void handleHLSLSVGroupIndexAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
D->addAttr(::new (S.Context) HLSLSV_GroupIndexAttr(S.Context, AL));
}
+static bool isLegalTypeForHLSLSV_DispatchThreadID(QualType T) {
+ if (!T->hasUnsignedIntegerRepresentation())
+ return false;
+ if (const auto *VT = T->getAs<VectorType>())
+ return VT->getNumElements() <= 3;
+ return true;
+}
+
+static void handleHLSLSV_DispatchThreadIDAttr(Sema &S, Decl *D,
+ const ParsedAttr &AL) {
+ using llvm::Triple;
+ Triple Target = S.Context.getTargetInfo().getTriple();
+ // FIXME: it is OK for a compute shader entry and pixel shader entry live in
+ // same HLSL file.Issue https://github.com/llvm/llvm-project/issues/57880.
+ if (Target.getEnvironment() != Triple::Compute &&
+ Target.getEnvironment() != Triple::Library) {
+ uint32_t Pipeline =
+ (uint32_t)S.Context.getTargetInfo().getTriple().getEnvironment() -
+ (uint32_t)llvm::Triple::Pixel;
+ S.Diag(AL.getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
+ << AL << Pipeline << "Compute";
+ return;
+ }
+
+ // FIXME: report warning and ignore semantic when cannot apply on the Decl.
+ // See https://github.com/llvm/llvm-project/issues/57916.
+
+ // FIXME: support semantic on field.
+ // See https://github.com/llvm/llvm-project/issues/57889.
+ if (isa<FieldDecl>(D)) {
+ S.Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_ast_node)
+ << AL << "parameter";
+ return;
+ }
+
+ auto *VD = cast<ValueDecl>(D);
+ if (!isLegalTypeForHLSLSV_DispatchThreadID(VD->getType())) {
+ S.Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)
+ << AL << "uint/uint2/uint3";
+ return;
+ }
+
+ D->addAttr(::new (S.Context) HLSLSV_DispatchThreadIDAttr(S.Context, AL));
+}
+
static void handleHLSLShaderAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
StringRef Str;
SourceLocation ArgLoc;
@@ -8990,6 +9035,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
case ParsedAttr::AT_HLSLSV_GroupIndex:
handleHLSLSVGroupIndexAttr(S, D, AL);
break;
+ case ParsedAttr::AT_HLSLSV_DispatchThreadID:
+ handleHLSLSV_DispatchThreadIDAttr(S, D, AL);
+ break;
case ParsedAttr::AT_HLSLShader:
handleHLSLShaderAttr(S, D, AL);
break;
diff --git a/clang/test/CodeGenHLSL/semantics/DispatchThreadID.hlsl b/clang/test/CodeGenHLSL/semantics/DispatchThreadID.hlsl
new file mode 100644
index 0000000000000..e285f74a822d5
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/DispatchThreadID.hlsl
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s
+
+// Make sure SV_DispatchThreadID translated into dx.thread.id.
+
+const RWBuffer<float> In;
+RWBuffer<float> Out;
+
+// CHECK: define void @foo()
+// CHECK: %[[ID:[0-9a-zA-Z]+]] = call i32 @llvm.dx.thread.id(i32 0)
+// CHECK: call void @"?foo@@YAXH at Z"(i32 %[[ID]])
+[shader("compute")]
+[numthreads(8,8,1)]
+void foo(uint Idx : SV_DispatchThreadID) {
+ Out[Idx] = In[Idx];
+}
+
+// CHECK: define void @bar()
+// CHECK: %[[ID_X:[0-9a-zA-Z]+]] = call i32 @llvm.dx.thread.id(i32 0)
+// CHECK: %[[ID_X_:[0-9a-zA-Z]+]] = insertelement <2 x i32> poison, i32 %[[ID_X]], i64 0
+// CHECK: %[[ID_Y:[0-9a-zA-Z]+]] = call i32 @llvm.dx.thread.id(i32 1)
+// CHECK: %[[ID_XY:[0-9a-zA-Z]+]] = insertelement <2 x i32> %[[ID_X_]], i32 %[[ID_Y]], i64 1
+// CHECK: call void @"?bar@@YAXT?$__vector at H$01 at __clang@@@Z"(<2 x i32> %[[ID_XY]])
+[shader("compute")]
+[numthreads(8,8,1)]
+void bar(uint2 Idx : SV_DispatchThreadID) {
+ Out[Idx.y] = In[Idx.x];
+}
+
diff --git a/clang/test/CodeGenHLSL/sret_output.hlsl b/clang/test/CodeGenHLSL/sret_output.hlsl
new file mode 100644
index 0000000000000..6b15e017a024d
--- /dev/null
+++ b/clang/test/CodeGenHLSL/sret_output.hlsl
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
+// RUN: dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s
+
+// FIXME: add semantic to a.
+// See https://github.com/llvm/llvm-project/issues/57874
+struct S {
+ float a;
+};
+
+
+// Make sure sret parameter is generated.
+// CHECK:define internal void @"?ps_main@@YA?AUS@@XZ"(ptr noalias sret(%struct.S) align 4 %agg.result)
+// FIXME: change it to real value instead of poison value once semantic is add to a.
+// Make sure the function with sret is called.
+// CHECK:call void @"?ps_main@@YA?AUS@@XZ"(ptr poison)
+[shader("pixel")]
+S ps_main() {
+ S s;
+ s.a = 0;
+ return s;
+};
diff --git a/clang/test/SemaHLSL/Semantics/entry_parameter.hlsl b/clang/test/SemaHLSL/Semantics/entry_parameter.hlsl
index bbbd022cb5cdb..9b8f1ce7c36c4 100644
--- a/clang/test/SemaHLSL/Semantics/entry_parameter.hlsl
+++ b/clang/test/SemaHLSL/Semantics/entry_parameter.hlsl
@@ -1,10 +1,13 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-mesh -x hlsl -ast-dump -verify -o - %s
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -finclude-default-header -ast-dump -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-mesh -x hlsl -ast-dump -finclude-default-header -verify -o - %s
-[numthreads(8,8, 1)]
-// expected-error at +1 {{attribute 'SV_GroupIndex' is unsupported in Mesh shaders, requires Compute}}
-void CSMain(int GI : SV_GroupIndex) {
-// CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:6 CSMain 'void (int)'
+[numthreads(8,8,1)]
+// expected-error at +2 {{attribute 'SV_GroupIndex' is unsupported in Mesh shaders, requires Compute}}
+// expected-error at +1 {{attribute 'SV_DispatchThreadID' is unsupported in Mesh shaders, requires Compute}}
+void CSMain(int GI : SV_GroupIndex, uint ID : SV_DispatchThreadID) {
+// CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:6 CSMain 'void (int, uint)'
// CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:17 GI 'int'
// CHECK-NEXT: HLSLSV_GroupIndexAttr
+// CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:42 ID 'uint'
+// CHECK-NEXT: HLSLSV_DispatchThreadIDAttr
}
diff --git a/clang/test/SemaHLSL/Semantics/invalid_entry_parameter.hlsl b/clang/test/SemaHLSL/Semantics/invalid_entry_parameter.hlsl
new file mode 100644
index 0000000000000..bf8027d029882
--- /dev/null
+++ b/clang/test/SemaHLSL/Semantics/invalid_entry_parameter.hlsl
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -finclude-default-header -x hlsl -ast-dump -verify -o - %s
+
+[numthreads(8,8,1)]
+// expected-error at +1 {{attribute 'SV_DispatchThreadID' only applies to a field or parameter of type 'uint/uint2/uint3'}}
+void CSMain(float ID : SV_DispatchThreadID) {
+
+}
+
+struct ST {
+ int a;
+ float b;
+};
+[numthreads(8,8,1)]
+// expected-error at +1 {{attribute 'SV_DispatchThreadID' only applies to a field or parameter of type 'uint/uint2/uint3'}}
+void CSMain2(ST ID : SV_DispatchThreadID) {
+
+}
+
+void foo() {
+// expected-warning at +1 {{'SV_DispatchThreadID' attribute only applies to parameters and non-static data members}}
+ uint V : SV_DispatchThreadID;
+
+}
+
+struct ST2 {
+// expected-error at +1 {{use of undeclared identifier 'SV_DispatchThreadID'}}
+ static uint X : SV_DispatchThreadID;
+// expected-error at +1 {{use of undeclared identifier 'SV_DispatchThreadID'}}
+ uint s : SV_DispatchThreadID;
+};
diff --git a/clang/test/SemaHLSL/Semantics/valid_entry_parameter.hlsl b/clang/test/SemaHLSL/Semantics/valid_entry_parameter.hlsl
new file mode 100644
index 0000000000000..8e79fc4d85ec9
--- /dev/null
+++ b/clang/test/SemaHLSL/Semantics/valid_entry_parameter.hlsl
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -finclude-default-header -ast-dump -o - %s | FileCheck %s
+
+[numthreads(8,8,1)]
+void CSMain(uint ID : SV_DispatchThreadID) {
+// CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:6 CSMain 'void (uint)'
+// CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:18 ID 'uint'
+// CHECK-NEXT: HLSLSV_DispatchThreadIDAttr
+}
+[numthreads(8,8,1)]
+void CSMain1(uint2 ID : SV_DispatchThreadID) {
+// CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:6 CSMain1 'void (uint2)'
+// CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:20 ID 'uint2'
+// CHECK-NEXT: HLSLSV_DispatchThreadIDAttr
+}
+[numthreads(8,8,1)]
+void CSMain2(uint3 ID : SV_DispatchThreadID) {
+// CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:6 CSMain2 'void (uint3)'
+// CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:20 ID 'uint3'
+// CHECK-NEXT: HLSLSV_DispatchThreadIDAttr
+}
+[numthreads(8,8,1)]
+void CSMain3(uint3 : SV_DispatchThreadID) {
+// CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:6 CSMain3 'void (uint3)'
+// CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:20 'uint3'
+// CHECK-NEXT: HLSLSV_DispatchThreadIDAttr
+}
More information about the cfe-commits
mailing list