Skip to content

Conversation

@inbelic
Copy link
Contributor

@inbelic inbelic commented May 16, 2025

  • defines in-memory reprsentation of comparisonFunc and borderColor
  • defines parsing of the ComparisonFunc and StaticBorderColor enum
  • integrates parsing of these number parameters with their respective parseComparisonFunc and parseStaticBorderColor
  • adds basic unit tests to demonstrate setting functionality

Part 6 of #126574

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" HLSL HLSL Language Support labels May 16, 2025
@llvmbot
Copy link
Member

llvmbot commented May 16, 2025

@llvm/pr-subscribers-hlsl

@llvm/pr-subscribers-clang

Author: Finn Plummer (inbelic)

Changes
  • defines in-memory reprsentation of comparisonFunc and borderColor
  • defines parsing of the ComparisonFunc and StaticBorderColor enum
  • integrates parsing of these number parameters with their respective parseComparisonFunc and parseStaticBorderColor
  • adds basic unit tests to demonstrate setting functionality

Part 6 of #126574


Full diff: https://github.com/llvm/llvm-project/pull/140305.diff

6 Files Affected:

  • (modified) clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def (+27)
  • (modified) clang/include/clang/Parse/ParseHLSLRootSignature.h (+5)
  • (modified) clang/lib/Parse/ParseHLSLRootSignature.cpp (+92)
  • (modified) clang/unittests/Lex/LexHLSLRootSignatureTest.cpp (+18-1)
  • (modified) clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp (+11-1)
  • (modified) llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h (+21)
diff --git a/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def b/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def
index 9515bc7d847fa..19f182d3df2c6 100644
--- a/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def
+++ b/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def
@@ -59,6 +59,12 @@
 #ifndef TEXTURE_ADDRESS_MODE_ENUM
 #define TEXTURE_ADDRESS_MODE_ENUM(NAME, LIT) ENUM(NAME, LIT)
 #endif
+#ifndef COMPARISON_FUNC_ENUM
+#define COMPARISON_FUNC_ENUM(NAME, LIT) ENUM(NAME, LIT)
+#endif
+#ifndef STATIC_BORDER_COLOR_ENUM
+#define STATIC_BORDER_COLOR_ENUM(NAME, LIT) ENUM(NAME, LIT)
+#endif
 
 // General Tokens:
 TOK(invalid, "invalid identifier")
@@ -113,6 +119,8 @@ KEYWORD(addressV)
 KEYWORD(addressW)
 KEYWORD(mipLODBias)
 KEYWORD(maxAnisotropy)
+KEYWORD(comparisonFunc)
+KEYWORD(borderColor)
 KEYWORD(minLOD)
 KEYWORD(maxLOD)
 
@@ -203,6 +211,25 @@ TEXTURE_ADDRESS_MODE_ENUM(Clamp, "TEXTURE_ADDRESS_CLAMP")
 TEXTURE_ADDRESS_MODE_ENUM(Border, "TEXTURE_ADDRESS_BORDER")
 TEXTURE_ADDRESS_MODE_ENUM(MirrorOnce, "TEXTURE_ADDRESS_MIRRORONCE")
 
+// Comparison Func Enums:
+COMPARISON_FUNC_ENUM(Never, "COMPARISON_NEVER")
+COMPARISON_FUNC_ENUM(Less, "COMPARISON_LESS")
+COMPARISON_FUNC_ENUM(Equal, "COMPARISON_EQUAL")
+COMPARISON_FUNC_ENUM(LessEqual, "COMPARISON_LESS_EQUAL")
+COMPARISON_FUNC_ENUM(Greater, "COMPARISON_GREATER")
+COMPARISON_FUNC_ENUM(NotEqual, "COMPARISON_NOT_EQUAL")
+COMPARISON_FUNC_ENUM(GreaterEqual, "COMPARISON_GREATER_EQUAL")
+COMPARISON_FUNC_ENUM(Always, "COMPARISON_ALWAYS")
+
+// Static Border Color Enums:
+STATIC_BORDER_COLOR_ENUM(TransparentBlack, "STATIC_BORDER_COLOR_TRANSPARENT_BLACK")
+STATIC_BORDER_COLOR_ENUM(OpaqueBlack, "STATIC_BORDER_COLOR_OPAQUE_BLACK")
+STATIC_BORDER_COLOR_ENUM(OpaqueWhite, "STATIC_BORDER_COLOR_OPAQUE_WHITE")
+STATIC_BORDER_COLOR_ENUM(OpaqueBlackUint, "STATIC_BORDER_COLOR_OPAQUE_BLACK_UINT")
+STATIC_BORDER_COLOR_ENUM(OpaqueWhiteUint, "STATIC_BORDER_COLOR_OPAQUE_WHITE_UINT")
+
+#undef STATIC_BORDER_COLOR_ENUM
+#undef COMPARISON_FUNC_ENUM
 #undef TEXTURE_ADDRESS_MODE_ENUM
 #undef FILTER_ENUM
 #undef SHADER_VISIBILITY_ENUM
diff --git a/clang/include/clang/Parse/ParseHLSLRootSignature.h b/clang/include/clang/Parse/ParseHLSLRootSignature.h
index c31b80ad696c3..21df9d0da4a53 100644
--- a/clang/include/clang/Parse/ParseHLSLRootSignature.h
+++ b/clang/include/clang/Parse/ParseHLSLRootSignature.h
@@ -117,6 +117,8 @@ class RootSignatureParser {
     std::optional<llvm::hlsl::rootsig::TextureAddressMode> AddressW;
     std::optional<float> MipLODBias;
     std::optional<uint32_t> MaxAnisotropy;
+    std::optional<llvm::hlsl::rootsig::ComparisonFunc> ComparisonFunc;
+    std::optional<llvm::hlsl::rootsig::StaticBorderColor> BorderColor;
     std::optional<float> MinLOD;
     std::optional<float> MaxLOD;
   };
@@ -132,6 +134,9 @@ class RootSignatureParser {
   std::optional<llvm::hlsl::rootsig::Filter> parseFilter();
   std::optional<llvm::hlsl::rootsig::TextureAddressMode>
   parseTextureAddressMode();
+  std::optional<llvm::hlsl::rootsig::ComparisonFunc> parseComparisonFunc();
+  std::optional<llvm::hlsl::rootsig::StaticBorderColor>
+  parseStaticBorderColor();
   std::optional<llvm::hlsl::rootsig::RootDescriptorFlags>
   parseRootDescriptorFlags();
   std::optional<llvm::hlsl::rootsig::DescriptorRangeFlags>
diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp
index f77e2d4ce6981..07bd10d00dfad 100644
--- a/clang/lib/Parse/ParseHLSLRootSignature.cpp
+++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp
@@ -399,6 +399,12 @@ std::optional<StaticSampler> RootSignatureParser::parseStaticSampler() {
   if (Params->MaxAnisotropy.has_value())
     Sampler.MaxAnisotropy = Params->MaxAnisotropy.value();
 
+  if (Params->ComparisonFunc.has_value())
+    Sampler.ComparisonFunc = Params->ComparisonFunc.value();
+
+  if (Params->BorderColor.has_value())
+    Sampler.BorderColor = Params->BorderColor.value();
+
   if (Params->MinLOD.has_value())
     Sampler.MinLOD = Params->MinLOD.value();
 
@@ -793,6 +799,40 @@ RootSignatureParser::parseStaticSamplerParams() {
       Params.MaxAnisotropy = MaxAnisotropy;
     }
 
+    // `comparisonFunc` `=` COMPARISON_FUNC
+    if (tryConsumeExpectedToken(TokenKind::kw_comparisonFunc)) {
+      if (Params.ComparisonFunc.has_value()) {
+        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
+            << CurToken.TokKind;
+        return std::nullopt;
+      }
+
+      if (consumeExpectedToken(TokenKind::pu_equal))
+        return std::nullopt;
+
+      auto ComparisonFunc = parseComparisonFunc();
+      if (!ComparisonFunc.has_value())
+        return std::nullopt;
+      Params.ComparisonFunc = ComparisonFunc;
+    }
+
+    // `borderColor` `=` STATIC_BORDER_COLOR
+    if (tryConsumeExpectedToken(TokenKind::kw_borderColor)) {
+      if (Params.BorderColor.has_value()) {
+        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
+            << CurToken.TokKind;
+        return std::nullopt;
+      }
+
+      if (consumeExpectedToken(TokenKind::pu_equal))
+        return std::nullopt;
+
+      auto BorderColor = parseStaticBorderColor();
+      if (!BorderColor.has_value())
+        return std::nullopt;
+      Params.BorderColor = BorderColor;
+    }
+
     // `minLOD` `=` NUMBER
     if (tryConsumeExpectedToken(TokenKind::kw_minLOD)) {
       if (Params.MinLOD.has_value()) {
@@ -980,6 +1020,58 @@ RootSignatureParser::parseTextureAddressMode() {
   return std::nullopt;
 }
 
+std::optional<llvm::hlsl::rootsig::ComparisonFunc>
+RootSignatureParser::parseComparisonFunc() {
+  assert(CurToken.TokKind == TokenKind::pu_equal &&
+         "Expects to only be invoked starting at given keyword");
+
+  TokenKind Expected[] = {
+#define COMPARISON_FUNC_ENUM(NAME, LIT) TokenKind::en_##NAME,
+#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
+  };
+
+  if (!tryConsumeExpectedToken(Expected))
+    return std::nullopt;
+
+  switch (CurToken.TokKind) {
+#define COMPARISON_FUNC_ENUM(NAME, LIT)                                        \
+  case TokenKind::en_##NAME:                                                   \
+    return ComparisonFunc::NAME;                                               \
+    break;
+#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
+  default:
+    llvm_unreachable("Switch for consumed enum token was not provided");
+  }
+
+  return std::nullopt;
+}
+
+std::optional<llvm::hlsl::rootsig::StaticBorderColor>
+RootSignatureParser::parseStaticBorderColor() {
+  assert(CurToken.TokKind == TokenKind::pu_equal &&
+         "Expects to only be invoked starting at given keyword");
+
+  TokenKind Expected[] = {
+#define STATIC_BORDER_COLOR_ENUM(NAME, LIT) TokenKind::en_##NAME,
+#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
+  };
+
+  if (!tryConsumeExpectedToken(Expected))
+    return std::nullopt;
+
+  switch (CurToken.TokKind) {
+#define STATIC_BORDER_COLOR_ENUM(NAME, LIT)                                    \
+  case TokenKind::en_##NAME:                                                   \
+    return StaticBorderColor::NAME;                                            \
+    break;
+#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
+  default:
+    llvm_unreachable("Switch for consumed enum token was not provided");
+  }
+
+  return std::nullopt;
+}
+
 std::optional<llvm::hlsl::rootsig::RootDescriptorFlags>
 RootSignatureParser::parseRootDescriptorFlags() {
   assert(CurToken.TokKind == TokenKind::pu_equal &&
diff --git a/clang/unittests/Lex/LexHLSLRootSignatureTest.cpp b/clang/unittests/Lex/LexHLSLRootSignatureTest.cpp
index 39872ea6b0a3e..3fbade375cb58 100644
--- a/clang/unittests/Lex/LexHLSLRootSignatureTest.cpp
+++ b/clang/unittests/Lex/LexHLSLRootSignatureTest.cpp
@@ -137,7 +137,9 @@ TEST_F(LexHLSLRootSignatureTest, ValidLexAllTokensTest) {
     numDescriptors offset
 
     filter addressU addressV addressW
-    mipLODBias maxAnisotropy minLOD maxLOD
+    mipLODBias maxAnisotropy
+    comparisonFunc borderColor
+    minLOD maxLOD
 
     unbounded
     DESCRIPTOR_RANGE_OFFSET_APPEND
@@ -212,6 +214,21 @@ TEST_F(LexHLSLRootSignatureTest, ValidLexAllTokensTest) {
     TEXTURE_ADDRESS_CLAMP
     TEXTURE_ADDRESS_BORDER
     TEXTURE_ADDRESS_MIRRORONCE
+
+    comparison_never
+    comparison_less
+    comparison_equal
+    comparison_less_equal
+    comparison_greater
+    comparison_not_equal
+    comparison_greater_equal
+    comparison_always
+
+    STATIC_BORDER_COLOR_TRANSPARENT_BLACK
+    STATIC_BORDER_COLOR_OPAQUE_BLACK
+    STATIC_BORDER_COLOR_OPAQUE_WHITE
+    STATIC_BORDER_COLOR_OPAQUE_BLACK_UINT
+    STATIC_BORDER_COLOR_OPAQUE_WHITE_UINT
   )cc";
   auto TokLoc = SourceLocation();
   hlsl::RootSignatureLexer Lexer(Source, TokLoc);
diff --git a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
index e40dd042dbdf5..6343d9feb4411 100644
--- a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
+++ b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
@@ -231,7 +231,9 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseStaticSamplerTest) {
       addressW = TEXTURE_ADDRESS_CLAMP,
       addressV = TEXTURE_ADDRESS_BORDER,
       filter = FILTER_MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT,
-      maxLOD = 9000, addressU = TEXTURE_ADDRESS_MIRROR
+      maxLOD = 9000, addressU = TEXTURE_ADDRESS_MIRROR,
+      comparisonFunc = COMPARISON_NOT_EQUAL,
+      borderColor = STATIC_BORDER_COLOR_OPAQUE_BLACK_UINT
     )
   )cc";
 
@@ -261,6 +263,10 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseStaticSamplerTest) {
   ASSERT_EQ(std::get<StaticSampler>(Elem).AddressW, TextureAddressMode::Wrap);
   ASSERT_EQ(std::get<StaticSampler>(Elem).MipLODBias, 0.f);
   ASSERT_EQ(std::get<StaticSampler>(Elem).MaxAnisotropy, 16u);
+  ASSERT_EQ(std::get<StaticSampler>(Elem).ComparisonFunc,
+            ComparisonFunc::LessEqual);
+  ASSERT_EQ(std::get<StaticSampler>(Elem).BorderColor,
+            StaticBorderColor::OpaqueWhite);
   ASSERT_EQ(std::get<StaticSampler>(Elem).MinLOD, 0.f);
   ASSERT_EQ(std::get<StaticSampler>(Elem).MaxLOD, 3.402823466e+38f);
 
@@ -276,6 +282,10 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseStaticSamplerTest) {
   ASSERT_EQ(std::get<StaticSampler>(Elem).AddressW, TextureAddressMode::Clamp);
   ASSERT_EQ(std::get<StaticSampler>(Elem).MipLODBias, 230.f);
   ASSERT_EQ(std::get<StaticSampler>(Elem).MaxAnisotropy, 3u);
+  ASSERT_EQ(std::get<StaticSampler>(Elem).ComparisonFunc,
+            ComparisonFunc::NotEqual);
+  ASSERT_EQ(std::get<StaticSampler>(Elem).BorderColor,
+            StaticBorderColor::OpaqueBlackUint);
   ASSERT_EQ(std::get<StaticSampler>(Elem).MinLOD, 4.2f);
   ASSERT_EQ(std::get<StaticSampler>(Elem).MaxLOD, 9000.f);
 
diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
index f5fa19a8fa6e9..025e96ec93c2a 100644
--- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
+++ b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
@@ -123,6 +123,25 @@ enum class TextureAddressMode {
   MirrorOnce = 5
 };
 
+enum class ComparisonFunc : unsigned {
+  Never = 1,
+  Less = 2,
+  Equal = 3,
+  LessEqual = 4,
+  Greater = 5,
+  NotEqual = 6,
+  GreaterEqual = 7,
+  Always = 8
+};
+
+enum class StaticBorderColor {
+  TransparentBlack = 0,
+  OpaqueBlack = 1,
+  OpaqueWhite = 2,
+  OpaqueBlackUint = 3,
+  OpaqueWhiteUint = 4
+};
+
 // Definitions of the in-memory data layout structures
 
 // Models the different registers: bReg | tReg | uReg | sReg
@@ -213,6 +232,8 @@ struct StaticSampler {
   TextureAddressMode AddressW = TextureAddressMode::Wrap;
   float MipLODBias = 0.f;
   uint32_t MaxAnisotropy = 16;
+  ComparisonFunc ComparisonFunc = ComparisonFunc::LessEqual;
+  StaticBorderColor BorderColor = StaticBorderColor::OpaqueWhite;
   float MinLOD = 0.f;
   float MaxLOD = 3.402823466e+38f; // FLT_MAX
 };

@inbelic inbelic linked an issue May 16, 2025 that may be closed by this pull request
4 tasks
@inbelic inbelic changed the base branch from users/inbelic/pr-140294 to main May 29, 2025 22:57
@inbelic inbelic force-pushed the inbelic/rs-enums-sampler branch from 845bc88 to c8e334e Compare May 29, 2025 22:58
@github-actions
Copy link

github-actions bot commented May 29, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@inbelic inbelic merged commit 9bd63b1 into llvm:main May 30, 2025
12 checks passed
@inbelic inbelic deleted the inbelic/rs-enums-sampler branch June 2, 2025 20:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category HLSL HLSL Language Support

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[HLSL] Implement Root Signature Parsing of Static Samplers

4 participants