[clang] b02d88d - [HLSL] Add shader attribute

Xiang Li via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 20 23:46:51 PDT 2022


Author: Xiang Li
Date: 2022-04-20T23:46:43-07:00
New Revision: b02d88d5afb58f53b30cde31990cd2d355d6c597

URL: https://github.com/llvm/llvm-project/commit/b02d88d5afb58f53b30cde31990cd2d355d6c597
DIFF: https://github.com/llvm/llvm-project/commit/b02d88d5afb58f53b30cde31990cd2d355d6c597.diff

LOG: [HLSL] Add shader attribute

Shader attribute is for shader library identify entry functions.
Here's an example,

[shader("pixel")]
float ps_main() : SV_Target {
  return 1;
}

When compile this shader to library target like -E lib_6_3, compiler needs to know ps_main is an entry function for pixel shader. Shader attribute is to offer the information.

A new attribute HLSLShader is added to support shader attribute. It has an EnumArgument which included all possible shader stages.

Reviewed By: aaron.ballman, MaskRay

Differential Revision: https://reviews.llvm.org/D123907

Added: 
    clang/test/SemaHLSL/shader_type_attr.hlsl

Modified: 
    clang/include/clang/Basic/Attr.td
    clang/include/clang/Basic/AttrDocs.td
    clang/include/clang/Sema/Sema.h
    clang/lib/Sema/SemaDecl.cpp
    clang/lib/Sema/SemaDeclAttr.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 727e6180b41b2..eb896fe210f96 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -3968,6 +3968,23 @@ def HLSLSV_GroupIndex: InheritableAttr {
   let Documentation = [HLSLSV_GroupIndexDocs];
 }
 
+def HLSLShader : InheritableAttr {
+  let Spellings = [Microsoft<"shader">];
+  let Subjects = SubjectList<[HLSLEntry]>;
+  let LangOpts = [HLSL];
+  let Args = [EnumArgument<"Type", "ShaderType",
+                           ["pixel", "vertex", "geometry", "hull", "domain",
+                            "compute", "raygeneration", "intersection",
+                            "anyhit", "closesthit", "miss", "callable", "mesh",
+                            "amplification"],
+                           ["Pixel", "Vertex", "Geometry", "Hull", "Domain",
+                            "Compute", "RayGeneration", "Intersection",
+                            "AnyHit", "ClosestHit", "Miss", "Callable", "Mesh",
+                            "Amplification"]
+                           >];
+  let Documentation = [HLSLSV_ShaderTypeAttrDocs];
+}
+
 def RandomizeLayout : InheritableAttr {
   let Spellings = [GCC<"randomize_layout">];
   let Subjects = SubjectList<[Record]>;

diff  --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index cda143eeb1ca1..818b39933f5d0 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -6380,6 +6380,25 @@ The full documentation is available here: https://docs.microsoft.com/en-us/windo
   }];
 }
 
+def HLSLSV_ShaderTypeAttrDocs : Documentation {
+  let Category = DocCatFunction;
+  let Content = [{
+The ``shader`` type attribute applies to HLSL shader entry functions to 
+identify the shader type for the entry function.
+The syntax is:
+  ``[shader(string-literal)]``
+where the string literal is one of: "pixel", "vertex", "geometry", "hull",
+ "domain", "compute", "raygeneration", "intersection", "anyhit", "closesthit",
+ "miss", "callable", "mesh", "amplification".
+Normally the shader type is set by shader target with the ``-T`` option like
+``-Tps_6_1``.
+When compiling to a library target like ``lib_6_3``, the shader type attribute
+ can help the compiler to identify the shader type.
+It is mostly used by Raytracing shaders where shaders must be compiled into a
+library and linked at runtime.
+  }];
+}
+
 def ClangRandomizeLayoutDocs : Documentation {
   let Category = DocCatDecl;
   let Heading = "randomize_layout, no_randomize_layout";

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 74b6f21284fc6..9093bb39e9e86 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3494,6 +3494,8 @@ class Sema final {
   HLSLNumThreadsAttr *mergeHLSLNumThreadsAttr(Decl *D,
                                               const AttributeCommonInfo &AL,
                                               int X, int Y, int Z);
+  HLSLShaderAttr *mergeHLSLShaderAttr(Decl *D, const AttributeCommonInfo &AL,
+                                      HLSLShaderAttr::ShaderType ShaderType);
 
   void mergeDeclAttributes(NamedDecl *New, Decl *Old,
                            AvailabilityMergeKind AMK = AMK_Redeclaration);

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 0c8b7fcd306b6..a854de6479781 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -2810,6 +2810,8 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
   else if (const auto *NT = dyn_cast<HLSLNumThreadsAttr>(Attr))
     NewAttr =
         S.mergeHLSLNumThreadsAttr(D, *NT, NT->getX(), NT->getY(), NT->getZ());
+  else if (const auto *SA = dyn_cast<HLSLShaderAttr>(Attr))
+    NewAttr = S.mergeHLSLShaderAttr(D, *SA, SA->getType());
   else if (Attr->shouldInheritEvenIfAlreadyPresent() || !DeclHasAttr(D, Attr))
     NewAttr = cast<InheritableAttr>(Attr->clone(S.Context));
 

diff  --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 217c884f2858f..21001f8542477 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -6940,6 +6940,39 @@ static void handleHLSLSVGroupIndexAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   D->addAttr(::new (S.Context) HLSLSV_GroupIndexAttr(S.Context, AL));
 }
 
+static void handleHLSLShaderAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+  StringRef Str;
+  SourceLocation ArgLoc;
+  if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
+    return;
+
+  HLSLShaderAttr::ShaderType ShaderType;
+  if (!HLSLShaderAttr::ConvertStrToShaderType(Str, ShaderType)) {
+    S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
+        << AL << Str << ArgLoc;
+    return;
+  }
+
+  // FIXME: check function match the shader stage.
+
+  HLSLShaderAttr *NewAttr = S.mergeHLSLShaderAttr(D, AL, ShaderType);
+  if (NewAttr)
+    D->addAttr(NewAttr);
+}
+
+HLSLShaderAttr *
+Sema::mergeHLSLShaderAttr(Decl *D, const AttributeCommonInfo &AL,
+                          HLSLShaderAttr::ShaderType ShaderType) {
+  if (HLSLShaderAttr *NT = D->getAttr<HLSLShaderAttr>()) {
+    if (NT->getType() != ShaderType) {
+      Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
+      Diag(AL.getLoc(), diag::note_conflicting_attribute);
+    }
+    return nullptr;
+  }
+  return HLSLShaderAttr::Create(Context, ShaderType, AL);
+}
+
 static void handleMSInheritanceAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   if (!S.LangOpts.CPlusPlus) {
     S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang)
@@ -8815,6 +8848,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
   case ParsedAttr::AT_HLSLSV_GroupIndex:
     handleHLSLSVGroupIndexAttr(S, D, AL);
     break;
+  case ParsedAttr::AT_HLSLShader:
+    handleHLSLShaderAttr(S, D, AL);
+    break;
 
   case ParsedAttr::AT_AbiTag:
     handleAbiTagAttr(S, D, AL);

diff  --git a/clang/test/SemaHLSL/shader_type_attr.hlsl b/clang/test/SemaHLSL/shader_type_attr.hlsl
new file mode 100644
index 0000000000000..2c789271a8129
--- /dev/null
+++ b/clang/test/SemaHLSL/shader_type_attr.hlsl
@@ -0,0 +1,74 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -ast-dump -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -ast-dump -o - %s -DFAIL -verify
+
+// FileCheck test make sure HLSLShaderAttr is generated in AST.
+// verify test make sure validation on shader type attribute works as expected.
+
+#ifdef FAIL
+
+// expected-warning at +1 {{'shader' attribute only applies to global functions}}
+[shader("compute")]
+struct Fido {
+  // expected-warning at +1 {{'shader' attribute only applies to global functions}}
+  [shader("pixel")]
+  void wag() {}
+  // expected-warning at +1 {{'shader' attribute only applies to global functions}}
+  [shader("vertex")]
+  static void oops() {}
+};
+
+// expected-warning at +1 {{'shader' attribute only applies to global functions}}
+[shader("vertex")]
+static void oops() {}
+
+namespace spec {
+// expected-warning at +1 {{'shader' attribute only applies to global functions}}
+[shader("vertex")]
+static void oops() {}
+} // namespace spec
+
+// expected-error at +1 {{'shader' attribute parameters do not match the previous declaration}}
+[shader("compute")]
+// expected-note at +1 {{conflicting attribute is here}}
+[shader("vertex")]
+int doubledUp() {
+  return 1;
+}
+
+// expected-note at +1 {{conflicting attribute is here}}
+[shader("vertex")]
+int forwardDecl();
+
+// expected-error at +1 {{'shader' attribute parameters do not match the previous declaration}}
+[shader("compute")]
+int forwardDecl() {
+  return 1;
+}
+
+// expected-error at +1 {{'shader' attribute takes one argument}}
+[shader()]
+// expected-error at +1 {{'shader' attribute takes one argument}}
+[shader(1, 2)]
+// expected-error at +1 {{'shader' attribute requires a string}}
+[shader(1)]
+// expected-warning at +1 {{'shader' attribute argument not supported: cs}}
+[shader("cs")]
+
+#endif // END of FAIL
+
+// CHECK:HLSLShaderAttr 0x{{[0-9a-fA-F]+}} <line:60:2, col:18> Compute
+[shader("compute")]
+int entry() {
+  return 1;
+}
+
+// Because these two attributes match, they should both appear in the AST
+[shader("compute")]
+// CHECK:HLSLShaderAttr 0x{{[0-9a-fA-F]+}} <line:66:2, col:18> Compute
+int secondFn();
+
+[shader("compute")]
+// CHECK:HLSLShaderAttr 0x{{[0-9a-fA-F]+}} <line:70:2, col:18> Compute
+int secondFn() {
+  return 1;
+}


        


More information about the cfe-commits mailing list