Browse Source

Allow select() to work with samplers (#5508) (#5524)

Add any_sampler builtin parameter type. This will match any sampler type
as the select() built-in added with HLSL 2021 requires.

Adds a new built-in overload that takes the any_sampler type and ensures
that the last two arguments and return type match. Many of the changes
were required because we never had to ensure object parameter types
matched nor transmit that type to the return type before. Most of the
changes to MatchArguments in SemaHLSL are addressing new issues this
revealed. Non-basic types can pass the conversion check if they outright
match.

Adds testing to select() and the ternary operator that it supplements
for these usages

Fixes #4673

(cherry picked from commit a6497c389403adf3ab76eef8f380cc749b93d818)
Greg Roth 2 years ago
parent
commit
bf7fd1a536

+ 29 - 19
include/dxc/dxcapi.internal.h

@@ -53,23 +53,32 @@ enum LEGAL_INTRINSIC_TEMPLATES {
 static const BYTE INTRIN_COMPTYPE_FROM_TYPE_ELT0 = 0xff;
 static const BYTE INTRIN_COMPTYPE_FROM_TYPE_ELT0 = 0xff;
 
 
 enum LEGAL_INTRINSIC_COMPTYPES {
 enum LEGAL_INTRINSIC_COMPTYPES {
-  LICOMPTYPE_VOID = 0,            // void, used for function returns
-  LICOMPTYPE_BOOL = 1,            // bool
-  LICOMPTYPE_INT = 2,             // i32, int-literal
-  LICOMPTYPE_UINT = 3,            // u32, int-literal
-  LICOMPTYPE_ANY_INT = 4,         // i32, u32, i64, u64, int-literal
-  LICOMPTYPE_ANY_INT32 = 5,       // i32, u32, int-literal
-  LICOMPTYPE_UINT_ONLY = 6,       // u32, u64, int-literal; no casts allowed
-  LICOMPTYPE_FLOAT = 7,           // f32, partial-precision-f32, float-literal
-  LICOMPTYPE_ANY_FLOAT = 8,       // f32, partial-precision-f32, f64, float-literal, min10-float, min16-float, half
-  LICOMPTYPE_FLOAT_LIKE = 9,      // f32, partial-precision-f32, float-literal, min10-float, min16-float, half
-  LICOMPTYPE_FLOAT_DOUBLE = 10,   // f32, partial-precision-f32, f64, float-literal
-  LICOMPTYPE_DOUBLE = 11,         // f64, float-literal
-  LICOMPTYPE_DOUBLE_ONLY = 12,    // f64; no casts allowed
-  LICOMPTYPE_NUMERIC = 13,        // float-literal, f32, partial-precision-f32, f64, min10-float, min16-float, int-literal, i32, u32, min12-int, min16-int, min16-uint, i64, u64
-  LICOMPTYPE_NUMERIC32 = 14,      // float-literal, f32, partial-precision-f32, int-literal, i32, u32
-  LICOMPTYPE_NUMERIC32_ONLY = 15, // float-literal, f32, partial-precision-f32, int-literal, i32, u32; no casts allowed
-  LICOMPTYPE_ANY = 16,            // float-literal, f32, partial-precision-f32, f64, min10-float, min16-float, int-literal, i32, u32, min12-int, min16-int, min16-uint, bool, i64, u64
+  LICOMPTYPE_VOID = 0,       // void, used for function returns
+  LICOMPTYPE_BOOL = 1,       // bool
+  LICOMPTYPE_INT = 2,        // i32, int-literal
+  LICOMPTYPE_UINT = 3,       // u32, int-literal
+  LICOMPTYPE_ANY_INT = 4,    // i32, u32, i64, u64, int-literal
+  LICOMPTYPE_ANY_INT32 = 5,  // i32, u32, int-literal
+  LICOMPTYPE_UINT_ONLY = 6,  // u32, u64, int-literal; no casts allowed
+  LICOMPTYPE_FLOAT = 7,      // f32, partial-precision-f32, float-literal
+  LICOMPTYPE_ANY_FLOAT = 8,  // f32, partial-precision-f32, f64, float-literal,
+                             // min10-float, min16-float, half
+  LICOMPTYPE_FLOAT_LIKE = 9, // f32, partial-precision-f32, float-literal,
+                             // min10-float, min16-float, half
+  LICOMPTYPE_FLOAT_DOUBLE =
+      10,                      // f32, partial-precision-f32, f64, float-literal
+  LICOMPTYPE_DOUBLE = 11,      // f64, float-literal
+  LICOMPTYPE_DOUBLE_ONLY = 12, // f64; no casts allowed
+  LICOMPTYPE_NUMERIC = 13, // float-literal, f32, partial-precision-f32, f64,
+                           // min10-float, min16-float, int-literal, i32, u32,
+                           // min12-int, min16-int, min16-uint, i64, u64
+  LICOMPTYPE_NUMERIC32 =
+      14, // float-literal, f32, partial-precision-f32, int-literal, i32, u32
+  LICOMPTYPE_NUMERIC32_ONLY = 15, // float-literal, f32, partial-precision-f32,
+                                  // int-literal, i32, u32; no casts allowed
+  LICOMPTYPE_ANY = 16, // float-literal, f32, partial-precision-f32, f64,
+                       // min10-float, min16-float, int-literal, i32, u32,
+                       // min12-int, min16-int, min16-uint, bool, i64, u64
   LICOMPTYPE_SAMPLER1D = 17,
   LICOMPTYPE_SAMPLER1D = 17,
   LICOMPTYPE_SAMPLER2D = 18,
   LICOMPTYPE_SAMPLER2D = 18,
   LICOMPTYPE_SAMPLER3D = 19,
   LICOMPTYPE_SAMPLER3D = 19,
@@ -78,7 +87,7 @@ enum LEGAL_INTRINSIC_COMPTYPES {
   LICOMPTYPE_SAMPLER = 22,
   LICOMPTYPE_SAMPLER = 22,
   LICOMPTYPE_STRING = 23,
   LICOMPTYPE_STRING = 23,
   LICOMPTYPE_WAVE = 24,
   LICOMPTYPE_WAVE = 24,
-  LICOMPTYPE_UINT64 = 25,         // u64, int-literal
+  LICOMPTYPE_UINT64 = 25, // u64, int-literal
   LICOMPTYPE_FLOAT16 = 26,
   LICOMPTYPE_FLOAT16 = 26,
   LICOMPTYPE_INT16 = 27,
   LICOMPTYPE_INT16 = 27,
   LICOMPTYPE_UINT16 = 28,
   LICOMPTYPE_UINT16 = 28,
@@ -99,7 +108,8 @@ enum LEGAL_INTRINSIC_COMPTYPES {
   LICOMPTYPE_UINT8_4PACKED = 41,
   LICOMPTYPE_UINT8_4PACKED = 41,
   LICOMPTYPE_ANY_INT16_OR_32 = 42,
   LICOMPTYPE_ANY_INT16_OR_32 = 42,
   LICOMPTYPE_SINT16_OR_32_ONLY = 43,
   LICOMPTYPE_SINT16_OR_32_ONLY = 43,
-  LICOMPTYPE_COUNT = 44
+  LICOMPTYPE_ANY_SAMPLER = 44,
+  LICOMPTYPE_COUNT = 45
 };
 };
 
 
 static const BYTE IA_SPECIAL_BASE = 0xf0;
 static const BYTE IA_SPECIAL_BASE = 0xf0;

+ 74 - 58
tools/clang/lib/Sema/SemaHLSL.cpp

@@ -900,6 +900,7 @@ static const ArTypeObjectKind g_AnyTT[] =
 static const ArTypeObjectKind g_ObjectTT[] =
 static const ArTypeObjectKind g_ObjectTT[] =
 {
 {
   AR_TOBJ_OBJECT,
   AR_TOBJ_OBJECT,
+  AR_TOBJ_STRING,
   AR_TOBJ_UNKNOWN
   AR_TOBJ_UNKNOWN
 };
 };
 
 
@@ -1099,6 +1100,13 @@ static const ArBasicKind g_AnyCT[] =
   AR_BASIC_UNKNOWN
   AR_BASIC_UNKNOWN
 };
 };
 
 
+static const ArBasicKind g_AnySamplerCT[] =
+{
+  AR_OBJECT_SAMPLER,
+  AR_OBJECT_SAMPLERCOMPARISON,
+  AR_BASIC_UNKNOWN
+};
+
 static const ArBasicKind g_Sampler1DCT[] =
 static const ArBasicKind g_Sampler1DCT[] =
 {
 {
   AR_OBJECT_SAMPLER1D,
   AR_OBJECT_SAMPLER1D,
@@ -1294,52 +1302,52 @@ static const ArBasicKind g_SInt16Or32OnlyCT[] =
 };
 };
 
 
 // Basic kinds, indexed by a LEGAL_INTRINSIC_COMPTYPES value.
 // Basic kinds, indexed by a LEGAL_INTRINSIC_COMPTYPES value.
-const ArBasicKind* g_LegalIntrinsicCompTypes[] =
-{
-  g_NullCT,             // LICOMPTYPE_VOID
-  g_BoolCT,             // LICOMPTYPE_BOOL
-  g_IntCT,              // LICOMPTYPE_INT
-  g_UIntCT,             // LICOMPTYPE_UINT
-  g_AnyIntCT,           // LICOMPTYPE_ANY_INT
-  g_AnyInt32CT,         // LICOMPTYPE_ANY_INT32
-  g_UIntOnlyCT,         // LICOMPTYPE_UINT_ONLY
-  g_FloatCT,            // LICOMPTYPE_FLOAT
-  g_AnyFloatCT,         // LICOMPTYPE_ANY_FLOAT
-  g_FloatLikeCT,        // LICOMPTYPE_FLOAT_LIKE
-  g_FloatDoubleCT,      // LICOMPTYPE_FLOAT_DOUBLE
-  g_DoubleCT,           // LICOMPTYPE_DOUBLE
-  g_DoubleOnlyCT,       // LICOMPTYPE_DOUBLE_ONLY
-  g_NumericCT,          // LICOMPTYPE_NUMERIC
-  g_Numeric32CT,        // LICOMPTYPE_NUMERIC32
-  g_Numeric32OnlyCT,    // LICOMPTYPE_NUMERIC32_ONLY
-  g_AnyCT,              // LICOMPTYPE_ANY
-  g_Sampler1DCT,        // LICOMPTYPE_SAMPLER1D
-  g_Sampler2DCT,        // LICOMPTYPE_SAMPLER2D
-  g_Sampler3DCT,        // LICOMPTYPE_SAMPLER3D
-  g_SamplerCUBECT,      // LICOMPTYPE_SAMPLERCUBE
-  g_SamplerCmpCT,       // LICOMPTYPE_SAMPLERCMP
-  g_SamplerCT,          // LICOMPTYPE_SAMPLER
-  g_StringCT,           // LICOMPTYPE_STRING
-  g_WaveCT,             // LICOMPTYPE_WAVE
-  g_UInt64CT,           // LICOMPTYPE_UINT64
-  g_Float16CT,          // LICOMPTYPE_FLOAT16
-  g_Int16CT,            // LICOMPTYPE_INT16
-  g_UInt16CT,           // LICOMPTYPE_UINT16
-  g_Numeric16OnlyCT,    // LICOMPTYPE_NUMERIC16_ONLY
-  g_RayDescCT,          // LICOMPTYPE_RAYDESC
-  g_AccelerationStructCT,   // LICOMPTYPE_ACCELERATION_STRUCT,
-  g_UDTCT,              // LICOMPTYPE_USER_DEFINED_TYPE
-  g_Texture2DCT,        // LICOMPTYPE_TEXTURE2D
-  g_Texture2DArrayCT,   // LICOMPTYPE_TEXTURE2DARRAY
-  g_ResourceCT,         // LICOMPTYPE_RESOURCE
-  g_Int32OnlyCT,        // LICOMPTYPE_INT32_ONLY
-  g_Int64OnlyCT,        // LICOMPTYPE_INT64_ONLY
-  g_AnyInt64CT,         // LICOMPTYPE_ANY_INT64
-  g_Float32OnlyCT,      // LICOMPTYPE_FLOAT32_ONLY
-  g_Int8_4PackedCT,     // LICOMPTYPE_INT8_4PACKED
-  g_UInt8_4PackedCT,    // LICOMPTYPE_UINT8_4PACKED
-  g_AnyInt16Or32CT,     // LICOMPTYPE_ANY_INT16_OR_32
-  g_SInt16Or32OnlyCT,   // LICOMPTYPE_SINT16_OR_32_ONLY
+const ArBasicKind *g_LegalIntrinsicCompTypes[] = {
+    g_NullCT,               // LICOMPTYPE_VOID
+    g_BoolCT,               // LICOMPTYPE_BOOL
+    g_IntCT,                // LICOMPTYPE_INT
+    g_UIntCT,               // LICOMPTYPE_UINT
+    g_AnyIntCT,             // LICOMPTYPE_ANY_INT
+    g_AnyInt32CT,           // LICOMPTYPE_ANY_INT32
+    g_UIntOnlyCT,           // LICOMPTYPE_UINT_ONLY
+    g_FloatCT,              // LICOMPTYPE_FLOAT
+    g_AnyFloatCT,           // LICOMPTYPE_ANY_FLOAT
+    g_FloatLikeCT,          // LICOMPTYPE_FLOAT_LIKE
+    g_FloatDoubleCT,        // LICOMPTYPE_FLOAT_DOUBLE
+    g_DoubleCT,             // LICOMPTYPE_DOUBLE
+    g_DoubleOnlyCT,         // LICOMPTYPE_DOUBLE_ONLY
+    g_NumericCT,            // LICOMPTYPE_NUMERIC
+    g_Numeric32CT,          // LICOMPTYPE_NUMERIC32
+    g_Numeric32OnlyCT,      // LICOMPTYPE_NUMERIC32_ONLY
+    g_AnyCT,                // LICOMPTYPE_ANY
+    g_Sampler1DCT,          // LICOMPTYPE_SAMPLER1D
+    g_Sampler2DCT,          // LICOMPTYPE_SAMPLER2D
+    g_Sampler3DCT,          // LICOMPTYPE_SAMPLER3D
+    g_SamplerCUBECT,        // LICOMPTYPE_SAMPLERCUBE
+    g_SamplerCmpCT,         // LICOMPTYPE_SAMPLERCMP
+    g_SamplerCT,            // LICOMPTYPE_SAMPLER
+    g_StringCT,             // LICOMPTYPE_STRING
+    g_WaveCT,               // LICOMPTYPE_WAVE
+    g_UInt64CT,             // LICOMPTYPE_UINT64
+    g_Float16CT,            // LICOMPTYPE_FLOAT16
+    g_Int16CT,              // LICOMPTYPE_INT16
+    g_UInt16CT,             // LICOMPTYPE_UINT16
+    g_Numeric16OnlyCT,      // LICOMPTYPE_NUMERIC16_ONLY
+    g_RayDescCT,            // LICOMPTYPE_RAYDESC
+    g_AccelerationStructCT, // LICOMPTYPE_ACCELERATION_STRUCT,
+    g_UDTCT,                // LICOMPTYPE_USER_DEFINED_TYPE
+    g_Texture2DCT,          // LICOMPTYPE_TEXTURE2D
+    g_Texture2DArrayCT,     // LICOMPTYPE_TEXTURE2DARRAY
+    g_ResourceCT,           // LICOMPTYPE_RESOURCE
+    g_Int32OnlyCT,          // LICOMPTYPE_INT32_ONLY
+    g_Int64OnlyCT,          // LICOMPTYPE_INT64_ONLY
+    g_AnyInt64CT,           // LICOMPTYPE_ANY_INT64
+    g_Float32OnlyCT,        // LICOMPTYPE_FLOAT32_ONLY
+    g_Int8_4PackedCT,       // LICOMPTYPE_INT8_4PACKED
+    g_UInt8_4PackedCT,      // LICOMPTYPE_UINT8_4PACKED
+    g_AnyInt16Or32CT,       // LICOMPTYPE_ANY_INT16_OR_32
+    g_SInt16Or32OnlyCT,     // LICOMPTYPE_SINT16_OR_32_ONLY
+    g_AnySamplerCT,         // LICOMPTYPE_ANY_SAMPLER
 };
 };
 static_assert(ARRAYSIZE(g_LegalIntrinsicCompTypes) == LICOMPTYPE_COUNT,
 static_assert(ARRAYSIZE(g_LegalIntrinsicCompTypes) == LICOMPTYPE_COUNT,
   "Intrinsic comp type table must be updated when new enumerants are added.");
   "Intrinsic comp type table must be updated when new enumerants are added.");
@@ -2103,16 +2111,23 @@ static bool CombineBasicTypes(ArBasicKind LeftKind,
                               ArBasicKind RightKind,
                               ArBasicKind RightKind,
                               _Out_ ArBasicKind* pOutKind)
                               _Out_ ArBasicKind* pOutKind)
 {
 {
-  if ((LeftKind < 0 || LeftKind >= AR_BASIC_COUNT) ||
-    (RightKind < 0 || RightKind >= AR_BASIC_COUNT)) {
+  // Make sure the kinds are both valid
+  if ((LeftKind < 0 || LeftKind >= AR_BASIC_MAXIMUM_COUNT) ||
+      (RightKind < 0 || RightKind >= AR_BASIC_MAXIMUM_COUNT)) {
     return false;
     return false;
   }
   }
 
 
+  // If kinds match perfectly, succeed without requiring they be basic
   if (LeftKind == RightKind) {
   if (LeftKind == RightKind) {
     *pOutKind = LeftKind;
     *pOutKind = LeftKind;
     return true;
     return true;
   }
   }
 
 
+  // More complicated combination requires that the kinds be basic
+  if (LeftKind >= AR_BASIC_COUNT || RightKind >= AR_BASIC_COUNT) {
+    return false;
+  }
+
   UINT uLeftProps = GetBasicKindProps(LeftKind);
   UINT uLeftProps = GetBasicKindProps(LeftKind);
   UINT uRightProps = GetBasicKindProps(RightKind);
   UINT uRightProps = GetBasicKindProps(RightKind);
   UINT uBits = GET_BPROP_BITS(uLeftProps) > GET_BPROP_BITS(uRightProps) ?
   UINT uBits = GET_BPROP_BITS(uLeftProps) > GET_BPROP_BITS(uRightProps) ?
@@ -6203,11 +6218,7 @@ bool HLSLExternalSource::MatchArguments(
     if (AR_TOBJ_UNKNOWN != Template[i]) {
     if (AR_TOBJ_UNKNOWN != Template[i]) {
       if ((AR_TOBJ_SCALAR == Template[i]) && (AR_TOBJ_VECTOR == *pTT || AR_TOBJ_MATRIX == *pTT)) {
       if ((AR_TOBJ_SCALAR == Template[i]) && (AR_TOBJ_VECTOR == *pTT || AR_TOBJ_MATRIX == *pTT)) {
         Template[i] = *pTT;
         Template[i] = *pTT;
-      }
-      else if(AR_TOBJ_STRING == Template[i] && *pTT == AR_TOBJ_OBJECT) {
-        Template[i] = *pTT;
-      }
-      else {
+      } else {
         while (AR_TOBJ_UNKNOWN != *pTT) {
         while (AR_TOBJ_UNKNOWN != *pTT) {
           if (Template[i] == *pTT)
           if (Template[i] == *pTT)
             break;
             break;
@@ -6370,12 +6381,11 @@ bool HLSLExternalSource::MatchArguments(
         badArgIdx = std::min(badArgIdx, i);
         badArgIdx = std::min(badArgIdx, i);
       }
       }
       pNewType = objectElement;
       pNewType = objectElement;
-    }
-    else if (pArgument->uLegalComponentTypes == LICOMPTYPE_TEXTURE2D
-      || pArgument->uLegalComponentTypes == LICOMPTYPE_TEXTURE2DARRAY) {
+    } else if (i != 0 && Template[pArgument->uTemplateId] == AR_TOBJ_OBJECT) {
+      // For object parameters, just use the argument type
+      // Return type is assigned below
       pNewType = Args[i - 1]->getType().getNonReferenceType();
       pNewType = Args[i - 1]->getType().getNonReferenceType();
-    }
-    else {
+    } else {
       ArBasicKind pEltType;
       ArBasicKind pEltType;
 
 
       // ComponentType, if the Id is special then it gets the
       // ComponentType, if the Id is special then it gets the
@@ -6449,6 +6459,12 @@ bool HLSLExternalSource::MatchArguments(
              "have as many arguments and types as the intrinsic template");
              "have as many arguments and types as the intrinsic template");
   }
   }
 
 
+  // For object return types that need to match arguments, we need to slot in
+  // the full type here Can't do it sooner because when return is encountered
+  // above, the other arg types haven't been set
+  if (Template[pIntrinsic->pArgs[0].uTemplateId] == AR_TOBJ_OBJECT)
+    argTypes[0] = argTypes[pIntrinsic->pArgs[0].uComponentTypeId];
+
   return badArgIdx == MaxIntrinsicArgs;
   return badArgIdx == MaxIntrinsicArgs;
 #undef CAB
 #undef CAB
 }
 }

+ 124 - 0
tools/clang/test/DXC/select_samplers.hlsl

@@ -0,0 +1,124 @@
+// RUN: %dxc -fcgl -HV 2018 -T ps_6_0 %s | FileCheck %s
+// RUN: %dxc -fcgl -HV 2021 -T ps_6_0 %s | FileCheck %s
+
+// Make sure the select() built-in works for sampler objects
+
+
+
+// SamplerState objects to use in selects
+SamplerState gSS1;
+SamplerState gSS2;
+SamplerComparisonState gSCS1;
+SamplerComparisonState gSCS2;
+
+Texture1D<float4> gTX1D;
+
+// A very slightly convoluted way to get a certain true result no matter the parameter
+bool getCond(int i) {
+  return i > 0 || i <= 0;
+}
+
+float4 main(int2 i : I, float4 pos : POS, float cmp :CMP) : SV_Target {
+  // Test ?: initializations
+
+  // CHECK: [[gSS1A:%[0-9]*]] = load %struct.SamplerState, %struct.SamplerState* @"\01?gSS1@@3USamplerState@@A"
+  // CHECK: store %struct.SamplerState [[gSS1A]], %struct.SamplerState* %lSS0
+  // CHECK-NEXT: br
+  // CHECK: [[gSS2A:%[0-9]*]] = load %struct.SamplerState, %struct.SamplerState* @"\01?gSS2@@3USamplerState@@A"
+  // CHECK: store %struct.SamplerState [[gSS2A]], %struct.SamplerState* %lSS0
+  // CHECK-NEXT: br
+  SamplerState lSS0 = getCond(i.x) ? gSS1 : gSS2;
+
+  // CHECK: [[gSCS1A:%[0-9]*]] = load %struct.SamplerComparisonState, %struct.SamplerComparisonState* @"\01?gSCS1@@3USamplerComparisonState@@A"
+  // CHECK: store %struct.SamplerComparisonState [[gSCS1A]], %struct.SamplerComparisonState* %lSCS0
+  // CHECK-NEXT: br
+  // CHECK: [[gSCS2A:%[0-9]*]] = load %struct.SamplerComparisonState, %struct.SamplerComparisonState* @"\01?gSCS2@@3USamplerComparisonState@@A"
+  // CHECK: store %struct.SamplerComparisonState [[gSCS2A]], %struct.SamplerComparisonState* %lSCS0
+  // CHECK-NEXT: br
+  SamplerComparisonState lSCS0 = getCond(i.x) ? gSCS1 : gSCS2;
+
+
+  // Test select() initializations
+
+  // CHECK-NOT: br
+  // CHECK: [[gSS1B:%[0-9]*]] = load %struct.SamplerState, %struct.SamplerState* @"\01?gSS1@@3USamplerState@@A"
+  // CHECK: [[gSS1CHB:%[0-9]*]] = call %dx.types.Handle @"dx.hl.createhandle..%dx.types.Handle (i32, %struct.SamplerState)"(i32 0, %struct.SamplerState [[gSS1B]])
+  // CHECK: [[gSS1CAB:%[0-9]*]] = call %dx.types.Handle @"dx.hl.annotatehandle..%dx.types.Handle (i32, %dx.types.Handle, %dx.types.ResourceProperties, %struct.SamplerState)"(i32 11, %dx.types.Handle [[gSS1CHB]]
+
+  // CHECK: [[gSS2B:%[0-9]*]] = load %struct.SamplerState, %struct.SamplerState* @"\01?gSS2@@3USamplerState@@A"
+  // CHECK: [[gSS2CHB:%[0-9]*]] = call %dx.types.Handle @"dx.hl.createhandle..%dx.types.Handle (i32, %struct.SamplerState)"(i32 0, %struct.SamplerState [[gSS2B]])
+  // CHECK: [[gSS2CAB:%[0-9]*]] = call %dx.types.Handle @"dx.hl.annotatehandle..%dx.types.Handle (i32, %dx.types.Handle, %dx.types.ResourceProperties, %struct.SamplerState)"(i32 11, %dx.types.Handle [[gSS2CHB]]
+
+  // CHECK: call %dx.types.Handle @"dx.hl.op..%dx.types.Handle (i32, i1, %dx.types.Handle, %dx.types.Handle)"(i32 {{[0-9]*}}, i1 %{{[0-9a-zA-Z_]*}}, %dx.types.Handle [[gSS1CAB]], %dx.types.Handle [[gSS2CAB]])
+
+  SamplerState lSS1 = select(getCond(i.x), gSS1, gSS2);
+
+  // CHECK: [[gSCS1B:%[0-9]*]] = load %struct.SamplerComparisonState, %struct.SamplerComparisonState* @"\01?gSCS1@@3USamplerComparisonState@@A"
+  // CHECK: [[gSCS1CHB:%[0-9]*]] = call %dx.types.Handle @"dx.hl.createhandle..%dx.types.Handle (i32, %struct.SamplerComparisonState)"(i32 0, %struct.SamplerComparisonState [[gSCS1B]])
+  // CHECK: [[gSCS1CAB:%[0-9]*]] = call %dx.types.Handle @"dx.hl.annotatehandle..%dx.types.Handle (i32, %dx.types.Handle, %dx.types.ResourceProperties, %struct.SamplerComparisonState)"(i32 11, %dx.types.Handle [[gSCS1CHB]]
+
+  // CHECK: [[gSCS2B:%[0-9]*]] = load %struct.SamplerComparisonState, %struct.SamplerComparisonState* @"\01?gSCS2@@3USamplerComparisonState@@A"
+  // CHECK: [[gSCS2CHB:%[0-9]*]] = call %dx.types.Handle @"dx.hl.createhandle..%dx.types.Handle (i32, %struct.SamplerComparisonState)"(i32 0, %struct.SamplerComparisonState [[gSCS2B]])
+  // CHECK: [[gSCS2CAB:%[0-9]*]] = call %dx.types.Handle @"dx.hl.annotatehandle..%dx.types.Handle (i32, %dx.types.Handle, %dx.types.ResourceProperties, %struct.SamplerComparisonState)"(i32 11, %dx.types.Handle [[gSCS2CHB]]
+
+  // CHECK: call %dx.types.Handle @"dx.hl.op..%dx.types.Handle (i32, i1, %dx.types.Handle, %dx.types.Handle)"(i32 {{[0-9]*}}, i1 %{{[0-9a-zA-Z_]*}}, %dx.types.Handle [[gSCS1CAB]], %dx.types.Handle [[gSCS2CAB]])
+
+  SamplerComparisonState lSCS1 = select(getCond(i.x), gSCS1, gSCS2);
+
+  // Assign post initialization, uses a slightly different code path
+
+  // Test assignment using ?:
+
+  // CHECK: br
+  // CHECK: [[gSS2C:%[0-9]*]] = load %struct.SamplerState, %struct.SamplerState* @"\01?gSS2@@3USamplerState@@A"
+  // CHECK: store %struct.SamplerState [[gSS2C]], %struct.SamplerState* %lSS0
+  // CHECK: br
+  // CHECK: [[lSS0C:%[0-9]*]] = load %struct.SamplerState, %struct.SamplerState* %lSS0
+  // CHECK: store %struct.SamplerState [[lSS0C]], %struct.SamplerState* %lSS0
+  // CHECK: br
+  lSS0 = getCond(i.y) ? gSS2 : lSS0;
+
+  // CHECK: [[gSCS2C:%[0-9]*]] = load %struct.SamplerComparisonState, %struct.SamplerComparisonState* @"\01?gSCS2@@3USamplerComparisonState@@A"
+  // CHECK: store %struct.SamplerComparisonState [[gSCS2C]], %struct.SamplerComparisonState* %lSCS0
+  // CHECK: br
+  // CHECK: [[lSCS0C:%[0-9]*]] = load %struct.SamplerComparisonState, %struct.SamplerComparisonState* %lSCS0
+  // CHECK: store %struct.SamplerComparisonState [[lSCS0C]], %struct.SamplerComparisonState* %lSCS0
+  // CHECK: br
+  lSCS0 = getCond(i.y) ? gSCS2 : lSCS0;
+
+  // Test assignment using select()
+
+  // CHECK-NOT: br
+  // CHECK: [[gSS2D:%[0-9]*]] = load %struct.SamplerState, %struct.SamplerState* @"\01?gSS2@@3USamplerState@@A"
+  // CHECK: [[gSS2CHD:%[0-9]*]] = call %dx.types.Handle @"dx.hl.createhandle..%dx.types.Handle (i32, %struct.SamplerState)"(i32 0, %struct.SamplerState [[gSS2D]])
+  // CHECK: [[gSS2CAD:%[0-9]*]] = call %dx.types.Handle @"dx.hl.annotatehandle..%dx.types.Handle (i32, %dx.types.Handle, %dx.types.ResourceProperties, %struct.SamplerState)"(i32 11, %dx.types.Handle [[gSS2CHD]]
+
+  // CHECK: [[lSS0D:%[0-9]*]] = load %struct.SamplerState, %struct.SamplerState* %lSS1
+  // CHECK: [[lSS0CHD:%[0-9]*]] = call %dx.types.Handle @"dx.hl.createhandle..%dx.types.Handle (i32, %struct.SamplerState)"(i32 0, %struct.SamplerState [[lSS0D]])
+  // CHECK: [[lSS0CAD:%[0-9]*]] = call %dx.types.Handle @"dx.hl.annotatehandle..%dx.types.Handle (i32, %dx.types.Handle, %dx.types.ResourceProperties, %struct.SamplerState)"(i32 11, %dx.types.Handle [[lSS0CHD]]
+
+  // CHECK: call %dx.types.Handle @"dx.hl.op..%dx.types.Handle (i32, i1, %dx.types.Handle, %dx.types.Handle)"(i32 {{[0-9]*}}, i1 %{{[0-9a-zA-Z_]*}}, %dx.types.Handle [[gSS2CAD]], %dx.types.Handle [[lSS0CAD]])
+
+  lSS1 = select(getCond(i.y), gSS2, lSS1);
+
+  // CHECK: [[gSCS2D:%[0-9]*]] = load %struct.SamplerComparisonState, %struct.SamplerComparisonState* @"\01?gSCS2@@3USamplerComparisonState@@A"
+  // CHECK: [[gSCS2CHD:%[0-9]*]] = call %dx.types.Handle @"dx.hl.createhandle..%dx.types.Handle (i32, %struct.SamplerComparisonState)"(i32 0, %struct.SamplerComparisonState [[gSCS2D]])
+  // CHECK: [[gSCS2CAD:%[0-9]*]] = call %dx.types.Handle @"dx.hl.annotatehandle..%dx.types.Handle (i32, %dx.types.Handle, %dx.types.ResourceProperties, %struct.SamplerComparisonState)"(i32 11, %dx.types.Handle [[gSCS2CHD]]
+
+  // CHECK: [[lSCS0D:%[0-9]*]] = load %struct.SamplerComparisonState, %struct.SamplerComparisonState* %lSCS1
+  // CHECK: [[lSCS0CHD:%[0-9]*]] = call %dx.types.Handle @"dx.hl.createhandle..%dx.types.Handle (i32, %struct.SamplerComparisonState)"(i32 0, %struct.SamplerComparisonState [[lSCS0D]])
+  // CHECK: [[lSCS0CAD:%[0-9]*]] = call %dx.types.Handle @"dx.hl.annotatehandle..%dx.types.Handle (i32, %dx.types.Handle, %dx.types.ResourceProperties, %struct.SamplerComparisonState)"(i32 11, %dx.types.Handle [[lSCS0CHD]]
+
+  // CHECK: call %dx.types.Handle @"dx.hl.op..%dx.types.Handle (i32, i1, %dx.types.Handle, %dx.types.Handle)"(i32 {{[0-9]*}}, i1 %{{[0-9a-zA-Z_]*}}, %dx.types.Handle [[gSCS2CAD]], %dx.types.Handle [[lSCS0CAD]])
+  lSCS1 = select(getCond(i.y), gSCS2, lSCS1);
+
+  // Make some trivial use of these so the shader is just slightly
+  // more representative of actual useful shaders
+  float4 l = 0;
+  l += gTX1D.Sample(lSS0, pos.x);
+  l *= gTX1D.SampleCmp(lSCS0, pos.x, cmp);
+  l += gTX1D.Sample(lSS1, pos.x);
+  l *= gTX1D.SampleCmp(lSCS1, pos.x, cmp);
+
+  return l;
+}

+ 1 - 0
utils/hct/gen_intrin_main.txt

@@ -372,6 +372,7 @@ resource [[hidden]] CreateResourceFromHeap(in uint index);
 $match<1, 0> bool<> [[rn]] and(in any<> x, in $type1 y);
 $match<1, 0> bool<> [[rn]] and(in any<> x, in $type1 y);
 $match<1, 0> bool<> [[rn]] or(in any<> x, in $type1 y);
 $match<1, 0> bool<> [[rn]] or(in any<> x, in $type1 y);
 $type2 [[rn]] select(in bool<> cond, in $match<1, 2> any<> t, in $type2 f);
 $type2 [[rn]] select(in bool<> cond, in $match<1, 2> any<> t, in $type2 f);
+$type2 [[rn]] select(in bool cond, in any_sampler t, in $type2 f);
 
 
 } namespace
 } namespace
 
 

+ 2 - 1
utils/hct/hctdb.py

@@ -2947,6 +2947,7 @@ class db_hlsl(object):
             "p32u8" : "LICOMPTYPE_UINT8_4PACKED",
             "p32u8" : "LICOMPTYPE_UINT8_4PACKED",
             "any_int16or32": "LICOMPTYPE_ANY_INT16_OR_32",
             "any_int16or32": "LICOMPTYPE_ANY_INT16_OR_32",
             "sint16or32_only": "LICOMPTYPE_SINT16_OR_32_ONLY",
             "sint16or32_only": "LICOMPTYPE_SINT16_OR_32_ONLY",
+            "any_sampler": "LICOMPTYPE_ANY_SAMPLER",
             }
             }
         self.trans_rowcol = {
         self.trans_rowcol = {
             "r": "IA_R",
             "r": "IA_R",
@@ -3076,7 +3077,7 @@ class db_hlsl(object):
                         template_list = "LITEMPLATE_ANY"
                         template_list = "LITEMPLATE_ANY"
                     else:
                     else:
                         base_type = type_name
                         base_type = type_name
-                        if base_type.startswith("sampler") or base_type.startswith("string") or base_type.startswith("Texture") or base_type.startswith("wave") or base_type.startswith("acceleration_struct") or base_type.startswith("ray_desc"):
+                        if base_type.startswith("sampler") or base_type.startswith("string") or base_type.startswith("Texture") or base_type.startswith("wave") or base_type.startswith("acceleration_struct") or base_type.startswith("ray_desc") or base_type.startswith("any_sampler"):
                             template_list = "LITEMPLATE_OBJECT"
                             template_list = "LITEMPLATE_OBJECT"
                         else:
                         else:
                             template_list = "LITEMPLATE_SCALAR"
                             template_list = "LITEMPLATE_SCALAR"