Przeglądaj źródła

Update FeedbackTexture2D types to be templated (#2347)

- Update the HLSL syntax from FeedbackTexture2DMinLod to FeedbackTexture2D<SAMPLER_FEEDBACK_MIN_MIP>
- Update DXIL to only have two UAV types for FeedbackTexture2D[Array] and use an extra metadata field to distinguish between the sampler feedback type.
Tristan Labelle 6 lat temu
rodzic
commit
0332b4bd90

+ 1 - 0
docs/DXIL.rst

@@ -3134,6 +3134,7 @@ SM.HULLPASSTHRUCONTROLPOINTCOUNTMATCH    For pass thru hull shader, input contro
 SM.INSIDETESSFACTORSIZEMATCHDOMAIN       InsideTessFactor rows, columns (%0, %1) invalid for domain %2.  Expected %3 rows and 1 column.
 SM.INVALIDRESOURCECOMPTYPE               Invalid resource return type
 SM.INVALIDRESOURCEKIND                   Invalid resources kind
+SM.INVALIDSAMPLERFEEDBACKTYPE            Invalid sampler feedback type
 SM.INVALIDTEXTUREKINDONUAV               Texture2DMS[Array] or TextureCube[Array] resources are not supported with UAVs
 SM.ISOLINEOUTPUTPRIMITIVEMISMATCH        Hull Shader declared with IsoLine Domain must specify output primitive point or line. Triangle_cw or triangle_ccw output are not compatible with the IsoLine Domain.
 SM.MAXMSSMSIZE                           Total Thread Group Shared Memory storage is %0, exceeded %1

+ 8 - 4
include/dxc/DXIL/DxilConstants.h

@@ -314,10 +314,8 @@ namespace DXIL {
     Sampler,
     TBuffer,
     RTAccelerationStructure,
-    FeedbackTexture2DMinLOD,
-    FeedbackTexture2DTiled,
-    FeedbackTexture2DArrayMinLOD,
-    FeedbackTexture2DArrayTiled,
+    FeedbackTexture2D,
+    FeedbackTexture2DArray,
     NumEntries,
   };
 
@@ -1271,6 +1269,12 @@ namespace DXIL {
     TriangleBackFace = 0xFF,
   };
 
+  enum class SamplerFeedbackType : uint8_t {
+    MinMip = 0,
+    MipRegionUsed = 1,
+    LastEntry = 2
+  };
+
   // Constant for Container.
   const uint8_t DxilProgramSigMaskX = 1;
   const uint8_t DxilProgramSigMaskY = 2;

+ 1 - 0
include/dxc/DXIL/DxilMetadataHelper.h

@@ -176,6 +176,7 @@ public:
   // Resource extended property tags.
   static const unsigned kDxilTypedBufferElementTypeTag            = 0;
   static const unsigned kDxilStructuredBufferElementStrideTag     = 1;
+  static const unsigned kDxilSamplerFeedbackKindTag               = 2;
 
   // Type system.
   static const char kDxilTypeSystemMDName[];

+ 5 - 0
include/dxc/DXIL/DxilResource.h

@@ -45,6 +45,9 @@ public:
   unsigned GetElementStride() const;
   void SetElementStride(unsigned ElemStride);
 
+  DXIL::SamplerFeedbackType GetSamplerFeedbackType() const;
+  void SetSamplerFeedbackType(DXIL::SamplerFeedbackType Value);
+
   bool IsGloballyCoherent() const;
   void SetGloballyCoherent(bool b);
   bool HasCounter() const;
@@ -61,6 +64,7 @@ public:
   bool IsTypedBuffer() const;
   bool IsRawBuffer() const;
   bool IsTBuffer() const;
+  bool IsFeedbackTexture() const;
 
   static bool classof(const DxilResourceBase *R) {
     return R->GetClass() == DXIL::ResourceClass::SRV || R->GetClass() == DXIL::ResourceClass::UAV;
@@ -70,6 +74,7 @@ private:
   unsigned m_SampleCount;
   unsigned m_ElementStride; // in bytes
   CompType m_CompType;
+  DXIL::SamplerFeedbackType m_SamplerFeedbackType;
   bool m_bGloballyCoherent;
   bool m_bHasCounter;
   bool m_bROV;

+ 1 - 0
include/dxc/HLSL/DxilValidation.h

@@ -219,6 +219,7 @@ enum class ValidationRule : unsigned {
   SmInsideTessFactorSizeMatchDomain, // InsideTessFactor rows, columns (%0, %1) invalid for domain %2.  Expected %3 rows and 1 column.
   SmInvalidResourceCompType, // Invalid resource return type
   SmInvalidResourceKind, // Invalid resources kind
+  SmInvalidSamplerFeedbackType, // Invalid sampler feedback type
   SmInvalidTextureKindOnUAV, // Texture2DMS[Array] or TextureCube[Array] resources are not supported with UAVs
   SmIsoLineOutputPrimitiveMismatch, // Hull Shader declared with IsoLine Domain must specify output primitive point or line. Triangle_cw or triangle_ccw output are not compatible with the IsoLine Domain.
   SmMaxMSSMSize, // Total Thread Group Shared Memory storage is %0, exceeded %1

+ 10 - 1
lib/DXIL/DxilMetadataHelper.cpp

@@ -2039,7 +2039,7 @@ void DxilExtraPropertyHelper::LoadSRVProperties(const MDOperand &MDO, DxilResour
 
 void DxilExtraPropertyHelper::EmitUAVProperties(const DxilResource &UAV, std::vector<Metadata *> &MDVals) {
   // Element type for typed RW resource.
-  if (!UAV.IsStructuredBuffer() && !UAV.IsRawBuffer()) {
+  if (!UAV.IsStructuredBuffer() && !UAV.IsRawBuffer() && !UAV.GetCompType().IsInvalid()) {
     MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilTypedBufferElementTypeTag, m_Ctx));
     MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD((unsigned)UAV.GetCompType().GetKind(), m_Ctx));
   }
@@ -2048,6 +2048,11 @@ void DxilExtraPropertyHelper::EmitUAVProperties(const DxilResource &UAV, std::ve
     MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilStructuredBufferElementStrideTag, m_Ctx));
     MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(UAV.GetElementStride(), m_Ctx));
   }
+  // Sampler feedback kind
+  if (UAV.IsFeedbackTexture()) {
+    MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilSamplerFeedbackKindTag, m_Ctx));
+    MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD((unsigned)UAV.GetSamplerFeedbackType(), m_Ctx));
+  }
 }
 
 void DxilExtraPropertyHelper::LoadUAVProperties(const MDOperand &MDO, DxilResource &UAV) {
@@ -2075,6 +2080,10 @@ void DxilExtraPropertyHelper::LoadUAVProperties(const MDOperand &MDO, DxilResour
       DXASSERT_NOMSG(UAV.IsStructuredBuffer());
       UAV.SetElementStride(DxilMDHelper::ConstMDToUint32(MDO));
       break;
+    case DxilMDHelper::kDxilSamplerFeedbackKindTag:
+      DXASSERT_NOMSG(UAV.IsFeedbackTexture());
+      UAV.SetSamplerFeedbackType((DXIL::SamplerFeedbackType)DxilMDHelper::ConstMDToUint32(MDO));
+      break;
     default:
       DXASSERT(false, "Unknown resource record tag");
     }

+ 21 - 16
lib/DXIL/DxilResource.cpp

@@ -25,6 +25,7 @@ DxilResource::DxilResource()
 : DxilResourceBase(DxilResourceBase::Class::Invalid)
 , m_SampleCount(0)
 , m_ElementStride(0)
+, m_SamplerFeedbackType((DXIL::SamplerFeedbackType)0)
 , m_bGloballyCoherent(false)
 , m_bHasCounter(false)
 , m_bROV(false) {
@@ -66,6 +67,14 @@ void DxilResource::SetElementStride(unsigned ElemStride) {
   m_ElementStride = ElemStride;
 }
 
+DXIL::SamplerFeedbackType DxilResource::GetSamplerFeedbackType() const {
+  return m_SamplerFeedbackType;
+}
+
+void DxilResource::SetSamplerFeedbackType(DXIL::SamplerFeedbackType Value) {
+  m_SamplerFeedbackType = Value;
+}
+
 bool DxilResource::IsGloballyCoherent() const {
   return m_bGloballyCoherent;
 }
@@ -127,6 +136,10 @@ bool DxilResource::IsTBuffer() const {
   return GetKind() == Kind::TBuffer;
 }
 
+bool DxilResource::IsFeedbackTexture() const {
+  return GetKind() == Kind::FeedbackTexture2D || GetKind() == Kind::FeedbackTexture2DArray;
+}
+
 unsigned DxilResource::GetNumCoords(Kind ResourceKind) {
   const unsigned CoordSizeTab[] = {
       0, // Invalid = 0,
@@ -146,10 +159,8 @@ unsigned DxilResource::GetNumCoords(Kind ResourceKind) {
       0, // Sampler,
       1, // TBuffer,
       0, // RaytracingAccelerationStructure,
-      2, // FeedbackTexture2DMinLOD,
-      2, // FeedbackTexture2DTiled,
-      3, // FeedbackTexture2DArrayMinLOD,
-      3, // FeedbackTexture2DArrayTiled,
+      2, // FeedbackTexture2D,
+      3, // FeedbackTexture2DArray,
   };
   static_assert(_countof(CoordSizeTab) == (unsigned)Kind::NumEntries, "check helper array size");
   DXASSERT(ResourceKind > Kind::Invalid && ResourceKind < Kind::NumEntries, "otherwise the caller passed wrong resource type");
@@ -175,10 +186,8 @@ unsigned DxilResource::GetNumDimensions(Kind ResourceKind) {
       0, // Sampler,
       1, // TBuffer,
       0, // RaytracingAccelerationStructure,
-      2, // FeedbackTexture2DMinLOD,
-      2, // FeedbackTexture2DTiled,
-      2, // FeedbackTexture2DArrayMinLOD,
-      2, // FeedbackTexture2DArrayTiled,
+      2, // FeedbackTexture2D,
+      2, // FeedbackTexture2DArray,
   };
   static_assert(_countof(NumDimTab) == (unsigned)Kind::NumEntries, "check helper array size");
   DXASSERT(ResourceKind > Kind::Invalid && ResourceKind < Kind::NumEntries, "otherwise the caller passed wrong resource type");
@@ -204,10 +213,8 @@ unsigned DxilResource::GetNumDimensionsForCalcLOD(Kind ResourceKind) {
       0, // Sampler,
       1, // TBuffer,
       0, // RaytracingAccelerationStructure,
-      2, // FeedbackTexture2DMinLOD,
-      2, // FeedbackTexture2DTiled,
-      2, // FeedbackTexture2DArrayMinLOD,
-      2, // FeedbackTexture2DArrayTiled,
+      2, // FeedbackTexture2D,
+      2, // FeedbackTexture2DArray,
   };
   static_assert(_countof(NumDimTab) == (unsigned)Kind::NumEntries, "check helper array size");
   DXASSERT(ResourceKind > Kind::Invalid && ResourceKind < Kind::NumEntries, "otherwise the caller passed wrong resource type");
@@ -233,10 +240,8 @@ unsigned DxilResource::GetNumOffsets(Kind ResourceKind) {
       0, // Sampler,
       1, // TBuffer,
       0, // RaytracingAccelerationStructure,
-      2, // FeedbackTexture2DMinLOD,
-      2, // FeedbackTexture2DTiled,
-      2, // FeedbackTexture2DArrayMinLOD,
-      2, // FeedbackTexture2DArrayTiled,
+      2, // FeedbackTexture2D,
+      2, // FeedbackTexture2DArray,
   };
   static_assert(_countof(OffsetSizeTab) == (unsigned)Kind::NumEntries, "check helper array size");
   DXASSERT(ResourceKind > Kind::Invalid && ResourceKind < Kind::NumEntries, "otherwise the caller passed wrong resource type");

+ 1 - 1
lib/DXIL/DxilResourceBase.cpp

@@ -90,7 +90,7 @@ static const char *s_ResourceDimNames[] = {
         "invalid", "1d",        "2d",      "2dMS",      "3d",
         "cube",    "1darray",   "2darray", "2darrayMS", "cubearray",
         "buf",     "rawbuf",    "structbuf", "cbuffer", "sampler",
-        "tbuffer", "ras", "fbtex2dML", "fbtex2dT", "fbtex2darrayML", "fbtex2darrayT"
+        "tbuffer", "ras", "fbtex2d", "fbtex2darray"
 };
 static_assert(_countof(s_ResourceDimNames) == (unsigned)DxilResourceBase::Kind::NumEntries,
   "Resource dim names array must be updated when new resource kind enums are added.");

+ 1 - 1
lib/DXIL/DxilUtil.cpp

@@ -497,7 +497,7 @@ bool IsHLSLResourceType(llvm::Type *Ty) {
 
     if (ConsumePrefix(name, "FeedbackTexture2D")) {
       ConsumePrefix(name, "Array");
-      return name == "MinLOD" || name == "Tiled";
+      return name.startswith("<");
     }
 
     ConsumePrefix(name, "RasterizerOrdered");

+ 1 - 0
lib/HLSL/DxilGenerationPass.cpp

@@ -88,6 +88,7 @@ void InitResourceBase(const DxilResourceBase *pSource,
 
 void InitResource(const DxilResource *pSource, DxilResource *pDest) {
   pDest->SetCompType(pSource->GetCompType());
+  pDest->SetSamplerFeedbackType(pSource->GetSamplerFeedbackType());
   pDest->SetSampleCount(pSource->GetSampleCount());
   pDest->SetElementStride(pSource->GetElementStride());
   pDest->SetGloballyCoherent(pSource->IsGloballyCoherent());

+ 6 - 5
lib/HLSL/DxilValidation.cpp

@@ -243,6 +243,7 @@ const char *hlsl::GetValidationRuleText(ValidationRule value) {
     case hlsl::ValidationRule::SmInvalidTextureKindOnUAV: return "Texture2DMS[Array] or TextureCube[Array] resources are not supported with UAVs";
     case hlsl::ValidationRule::SmInvalidResourceKind: return "Invalid resources kind";
     case hlsl::ValidationRule::SmInvalidResourceCompType: return "Invalid resource return type";
+    case hlsl::ValidationRule::SmInvalidSamplerFeedbackType: return "Invalid sampler feedback type";
     case hlsl::ValidationRule::SmSampleCountOnlyOn2DMS: return "Only Texture2DMS/2DMSArray could has sample count";
     case hlsl::ValidationRule::SmCounterOnlyOnStructBuf: return "BufferUpdateCounter valid only on structured buffers";
     case hlsl::ValidationRule::SmGSTotalOutputVertexDataRange: return "Declared output vertex count (%0) multiplied by the total number of declared scalar components of output data (%1) equals %2.  This value cannot be greater than %3";
@@ -3911,10 +3912,10 @@ static void ValidateResource(hlsl::DxilResource &res,
   case DXIL::ResourceKind::RTAccelerationStructure:
     // TODO: check profile.
     break;
-  case DXIL::ResourceKind::FeedbackTexture2DMinLOD:
-  case DXIL::ResourceKind::FeedbackTexture2DTiled:
-  case DXIL::ResourceKind::FeedbackTexture2DArrayMinLOD:
-  case DXIL::ResourceKind::FeedbackTexture2DArrayTiled:
+  case DXIL::ResourceKind::FeedbackTexture2D:
+  case DXIL::ResourceKind::FeedbackTexture2DArray:
+    if (res.GetSamplerFeedbackType() >= DXIL::SamplerFeedbackType::LastEntry)
+      ValCtx.EmitResourceError(&res, ValidationRule::SmInvalidSamplerFeedbackType);
     break;
   default:
     ValCtx.EmitResourceError(&res, ValidationRule::SmInvalidResourceKind);
@@ -3935,7 +3936,7 @@ static void ValidateResource(hlsl::DxilResource &res,
   case DXIL::ComponentType::U16:
     break;
   default:
-    if (!res.IsStructuredBuffer() && !res.IsRawBuffer())
+    if (!res.IsStructuredBuffer() && !res.IsRawBuffer() && !res.IsFeedbackTexture())
       ValCtx.EmitResourceError(&res, ValidationRule::SmInvalidResourceCompType);
     break;
   }

+ 2 - 0
tools/clang/include/clang/AST/HlslTypes.h

@@ -303,6 +303,7 @@ clang::CXXRecordDecl* DeclareRecordTypeWithHandle(
   clang::ASTContext& context, llvm::StringRef name);
 
 void AddRaytracingConstants(clang::ASTContext& context);
+void AddSamplerFeedbackConstants(clang::ASTContext& context);
 
 /// <summary>Adds the implementation for std::is_equal.</summary>
 void AddStdIsEqualImplementation(clang::ASTContext& context, clang::Sema& sema);
@@ -371,6 +372,7 @@ bool IsHLSLNumericOrAggregateOfNumericType(clang::QualType type);
 bool IsHLSLNumericUserDefinedType(clang::QualType type);
 bool IsHLSLAggregateType(clang::QualType type);
 clang::QualType GetHLSLResourceResultType(clang::QualType type);
+unsigned GetHLSLResourceTemplateUInt(clang::QualType type);
 bool IsIncompleteHLSLResourceArrayType(clang::ASTContext& context, clang::QualType type);
 clang::QualType GetHLSLInputPatchElementType(clang::QualType type);
 unsigned GetHLSLInputPatchCount(clang::QualType type);

+ 6 - 0
tools/clang/lib/AST/ASTContextHLSL.cpp

@@ -472,6 +472,12 @@ void hlsl::AddRaytracingConstants(ASTContext& context) {
   AddConstUInt(context, StringRef("RAYTRACING_PIPELINE_FLAG_SKIP_PROCEDURAL_PRIMITIVES"), (unsigned)DXIL::RaytracingPipelineFlags::SkipProceduralPrimitives);
 }
 
+/// <summary> Adds all constants and enums for sampler feedback </summary>
+void hlsl::AddSamplerFeedbackConstants(ASTContext& context) {
+  AddConstUInt(context, StringRef("SAMPLER_FEEDBACK_MIN_MIP"), (unsigned)DXIL::SamplerFeedbackType::MinMip);
+  AddConstUInt(context, StringRef("SAMPLER_FEEDBACK_MIP_REGION_USED"), (unsigned)DXIL::SamplerFeedbackType::MipRegionUsed);
+}
+
 static
 Expr* IntConstantAsBoolExpr(clang::Sema& sema, uint64_t value)
 {

+ 26 - 17
tools/clang/lib/AST/HlslTypes.cpp

@@ -511,9 +511,7 @@ bool IsHLSLResourceType(clang::QualType type) {
     if (name == "TextureCubeArray" || name == "RWTextureCubeArray")
       return true;
 
-    if (name == "FeedbackTexture2DMinLOD" || name == "FeedbackTexture2DTiled")
-      return true;
-    if (name == "FeedbackTexture2DArrayMinLOD" || name == "FeedbackTexture2DArrayTiled")
+    if (name == "FeedbackTexture2D" || name == "FeedbackTexture2DArray")
       return true;
 
     if (name == "ByteAddressBuffer" || name == "RWByteAddressBuffer")
@@ -592,29 +590,40 @@ QualType GetHLSLResourceResultType(QualType type) {
 
   if (const ClassTemplateSpecializationDecl *templateDecl =
     dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
-    // Templated resource types
+    
+    if (RD->getName().startswith("FeedbackTexture")) {
+      // Feedback textures are write-only and the data is opaque,
+      // so there is no result type per se.
+      return {};
+    }
+    
+    // Type-templated resource types
 
-    // First attempt to get the template argument from the TemplateSpecializationType sugar,
+    // Prefer getting the template argument from the TemplateSpecializationType sugar,
     // since this preserves 'snorm' from 'Buffer<snorm float>' which is lost on the
     // ClassTemplateSpecializationDecl since it's considered type sugar.
+    const TemplateArgument* templateArg = &templateDecl->getTemplateArgs()[0];
     if (const TemplateSpecializationType *specializationType = type->getAs<TemplateSpecializationType>()) {
       if (specializationType->getNumArgs() >= 1) {
-        const TemplateArgument& templateArg = specializationType->getArg(0);
-        return templateArg.getAsType();
+        templateArg = &specializationType->getArg(0);
       }
     }
 
-    const TemplateArgumentList& argList = templateDecl->getTemplateArgs();
-    DXASSERT(argList.size() >= 1, "Templated resource must have at least one argument");
-    return argList[0].getAsType();
-  }
-  else {
-    // Non-templated resource types like [RW][RasterOrder]ByteAddressBuffer
-    // Get the result type from handle field.
-    FieldDecl* HandleFieldDecl = *(RD->field_begin());
-    DXASSERT(HandleFieldDecl->getName() == "h", "Resource must have a handle field");
-    return HandleFieldDecl->getType();
+    if (templateArg->getKind() == TemplateArgument::ArgKind::Type)
+      return templateArg->getAsType();
   }
+
+  // Non-type-templated resource types like [RW][RasterOrder]ByteAddressBuffer
+  // Get the result type from handle field.
+  FieldDecl* HandleFieldDecl = *(RD->field_begin());
+  DXASSERT(HandleFieldDecl->getName() == "h", "Resource must have a handle field");
+  return HandleFieldDecl->getType();
+}
+
+unsigned GetHLSLResourceTemplateUInt(clang::QualType type) {
+  const ClassTemplateSpecializationDecl* templateDecl = cast<ClassTemplateSpecializationDecl>(
+    type->castAs<RecordType>()->getDecl());
+  return (unsigned)templateDecl->getTemplateArgs()[0].getAsIntegral().getZExtValue();
 }
 
 bool IsIncompleteHLSLResourceArrayType(clang::ASTContext &context,

+ 13 - 14
tools/clang/lib/CodeGen/CGHLSLMS.cpp

@@ -1107,10 +1107,8 @@ static DxilResource::Kind KeywordToKind(StringRef keyword) {
     return DxilResource::Kind::Texture2D;
   if (keyword == "Texture2DMS" || keyword == "RWTexture2DMS")
     return DxilResource::Kind::Texture2DMS;
-  if (keyword == "FeedbackTexture2DMinLOD")
-    return DxilResource::Kind::FeedbackTexture2DMinLOD;
-  if (keyword == "FeedbackTexture2DTiled")
-    return DxilResource::Kind::FeedbackTexture2DTiled;
+  if (keyword == "FeedbackTexture2D")
+    return DxilResource::Kind::FeedbackTexture2D;
   if (keyword == "Texture3D" || keyword == "RWTexture3D" || keyword == "RasterizerOrderedTexture3D")
     return DxilResource::Kind::Texture3D;
   if (keyword == "TextureCube" || keyword == "RWTextureCube")
@@ -1120,10 +1118,8 @@ static DxilResource::Kind KeywordToKind(StringRef keyword) {
     return DxilResource::Kind::Texture1DArray;
   if (keyword == "Texture2DArray" || keyword == "RWTexture2DArray" || keyword == "RasterizerOrderedTexture2DArray")
     return DxilResource::Kind::Texture2DArray;
-  if (keyword == "FeedbackTexture2DArrayMinLOD")
-    return DxilResource::Kind::FeedbackTexture2DArrayMinLOD;
-  if (keyword == "FeedbackTexture2DArrayTiled")
-    return DxilResource::Kind::FeedbackTexture2DArrayTiled;
+  if (keyword == "FeedbackTexture2DArray")
+    return DxilResource::Kind::FeedbackTexture2DArray;
   if (keyword == "Texture2DMSArray" || keyword == "RWTexture2DMSArray")
     return DxilResource::Kind::Texture2DMSArray;
   if (keyword == "TextureCubeArray" || keyword == "RWTextureCubeArray")
@@ -2540,10 +2536,8 @@ static DxilResourceBase::Class KeywordToClass(const std::string &keyword) {
   isUAV |= keyword == "RasterizerOrderedTexture2D";
   isUAV |= keyword == "RasterizerOrderedTexture2DArray";
   isUAV |= keyword == "RasterizerOrderedTexture3D";
-  isUAV |= keyword == "FeedbackTexture2DMinLOD";
-  isUAV |= keyword == "FeedbackTexture2DTiled";
-  isUAV |= keyword == "FeedbackTexture2DArrayMinLOD";
-  isUAV |= keyword == "FeedbackTexture2DArrayTiled";
+  isUAV |= keyword == "FeedbackTexture2D";
+  isUAV |= keyword == "FeedbackTexture2DArray";
   if (isUAV)
     return DxilResourceBase::Class::UAV;
 
@@ -2891,7 +2885,6 @@ bool CGMSHLSLRuntime::SetUAVSRV(SourceLocation loc,
 
   hlslRes->SetKind(kind);
   
-  QualType resultTy = hlsl::GetHLSLResourceResultType(QualTy);
   // Type annotation for result type of resource.
   DxilTypeSystem &dxilTypeSys = m_pHLModule->GetTypeSystem();
   unsigned arrayEltSize = 0;
@@ -2921,7 +2914,8 @@ bool CGMSHLSLRuntime::SetUAVSRV(SourceLocation loc,
     }
   }
 
-  if (kind != hlsl::DxilResource::Kind::StructuredBuffer) {
+  QualType resultTy = hlsl::GetHLSLResourceResultType(QualTy);
+  if (kind != hlsl::DxilResource::Kind::StructuredBuffer && !resultTy.isNull()) {
     QualType Ty = resultTy;
     QualType EltTy = Ty;
     if (hlsl::IsHLSLVecType(Ty)) {
@@ -2980,6 +2974,11 @@ bool CGMSHLSLRuntime::SetUAVSRV(SourceLocation loc,
     }
   }
 
+  if (hlslRes->IsFeedbackTexture()) {
+    hlslRes->SetSamplerFeedbackType(
+      static_cast<DXIL::SamplerFeedbackType>(hlsl::GetHLSLResourceTemplateUInt(QualTy)));
+  }
+
   hlslRes->SetROV(RD->getName().startswith("RasterizerOrdered"));
 
   if (kind == hlsl::DxilResource::Kind::TypedBuffer ||

+ 25 - 35
tools/clang/lib/Sema/SemaHLSL.cpp

@@ -171,10 +171,8 @@ enum ArBasicKind {
   AR_OBJECT_ROVTEXTURE2D_ARRAY,
   AR_OBJECT_ROVTEXTURE3D,
 
-  AR_OBJECT_FEEDBACKTEXTURE2D_MINLOD,
-  AR_OBJECT_FEEDBACKTEXTURE2D_TILED,
-  AR_OBJECT_FEEDBACKTEXTURE2D_ARRAY_MINLOD,
-  AR_OBJECT_FEEDBACKTEXTURE2D_ARRAY_TILED,
+  AR_OBJECT_FEEDBACKTEXTURE2D,
+  AR_OBJECT_FEEDBACKTEXTURE2D_ARRAY,
 
   // SPIRV change starts
 #ifdef ENABLE_SPIRV_CODEGEN
@@ -458,10 +456,8 @@ const UINT g_uBasicKindProps[] =
   BPROP_OBJECT | BPROP_RWBUFFER | BPROP_ROVBUFFER,    // AR_OBJECT_ROVTEXTURE2D_ARRAY
   BPROP_OBJECT | BPROP_RWBUFFER | BPROP_ROVBUFFER,    // AR_OBJECT_ROVTEXTURE3D
 
-  BPROP_OBJECT | BPROP_TEXTURE | BPROP_FEEDBACKTEXTURE, // AR_OBJECT_FEEDBACKTEXTURE2D_MINLOD
-  BPROP_OBJECT | BPROP_TEXTURE | BPROP_FEEDBACKTEXTURE, // AR_OBJECT_FEEDBACKTEXTURE2D_TILED
-  BPROP_OBJECT | BPROP_TEXTURE | BPROP_FEEDBACKTEXTURE, // AR_OBJECT_FEEDBACKTEXTURE2D_ARRAY_MINLOD
-  BPROP_OBJECT | BPROP_TEXTURE | BPROP_FEEDBACKTEXTURE, // AR_OBJECT_FEEDBACKTEXTURE2D_ARRAY_TILED
+  BPROP_OBJECT | BPROP_TEXTURE | BPROP_FEEDBACKTEXTURE, // AR_OBJECT_FEEDBACKTEXTURE2D
+  BPROP_OBJECT | BPROP_TEXTURE | BPROP_FEEDBACKTEXTURE, // AR_OBJECT_FEEDBACKTEXTURE2D_ARRAY
 
   // SPIRV change starts
 #ifdef ENABLE_SPIRV_CODEGEN
@@ -1297,10 +1293,8 @@ const ArBasicKind g_ArBasicKindsAsTypes[] =
   AR_OBJECT_ROVTEXTURE2D_ARRAY,
   AR_OBJECT_ROVTEXTURE3D,
 
-  AR_OBJECT_FEEDBACKTEXTURE2D_MINLOD,
-  AR_OBJECT_FEEDBACKTEXTURE2D_TILED,
-  AR_OBJECT_FEEDBACKTEXTURE2D_ARRAY_MINLOD,
-  AR_OBJECT_FEEDBACKTEXTURE2D_ARRAY_TILED,
+  AR_OBJECT_FEEDBACKTEXTURE2D,
+  AR_OBJECT_FEEDBACKTEXTURE2D_ARRAY,
 
   // SPIRV change starts
 #ifdef ENABLE_SPIRV_CODEGEN
@@ -1386,10 +1380,8 @@ const uint8_t g_ArBasicKindsTemplateCount[] =
   1, // AR_OBJECT_ROVTEXTURE2D_ARRAY
   1, // AR_OBJECT_ROVTEXTURE3D
 
-  0, // AR_OBJECT_FEEDBACKTEXTURE2D_MINLOD
-  0, // AR_OBJECT_FEEDBACKTEXTURE2D_TILED
-  0, // AR_OBJECT_FEEDBACKTEXTURE2D_ARRAY_MINLOD
-  0, // AR_OBJECT_FEEDBACKTEXTURE2D_ARRAY_TILED
+  1, // AR_OBJECT_FEEDBACKTEXTURE2D
+  1, // AR_OBJECT_FEEDBACKTEXTURE2D_ARRAY
 
   // SPIRV change starts
 #ifdef ENABLE_SPIRV_CODEGEN
@@ -1483,10 +1475,8 @@ const SubscriptOperatorRecord g_ArBasicKindsSubscripts[] =
   { 3, MipsFalse, SampleFalse }, // AR_OBJECT_ROVTEXTURE2D_ARRAY (ROVTexture2DArray)
   { 3, MipsFalse, SampleFalse }, // AR_OBJECT_ROVTEXTURE3D (ROVTexture3D)
 
-  { 0, MipsFalse, SampleFalse }, // AR_OBJECT_FEEDBACKTEXTURE2D_MINLOD
-  { 0, MipsFalse, SampleFalse }, // AR_OBJECT_FEEDBACKTEXTURE2D_TILED
-  { 0, MipsFalse, SampleFalse }, // AR_OBJECT_FEEDBACKTEXTURE2D_ARRAY_MINLOD
-  { 0, MipsFalse, SampleFalse }, // AR_OBJECT_FEEDBACKTEXTURE2D_ARRAY_TILED
+  { 0, MipsFalse, SampleFalse }, // AR_OBJECT_FEEDBACKTEXTURE2D
+  { 0, MipsFalse, SampleFalse }, // AR_OBJECT_FEEDBACKTEXTURE2D_ARRAY
 
   // SPIRV change starts
 #ifdef ENABLE_SPIRV_CODEGEN
@@ -1600,10 +1590,8 @@ const char* g_ArBasicTypeNames[] =
   "RasterizerOrderedTexture2DArray",
   "RasterizerOrderedTexture3D",
 
-  "FeedbackTexture2DMinLOD",
-  "FeedbackTexture2DTiled",
-  "FeedbackTexture2DArrayMinLOD",
-  "FeedbackTexture2DArrayTiled",
+  "FeedbackTexture2D",
+  "FeedbackTexture2DArray",
 
   // SPIRV change starts
 #ifdef ENABLE_SPIRV_CODEGEN
@@ -2153,13 +2141,11 @@ void GetIntrinsicMethods(ArBasicKind kind, _Outptr_result_buffer_(*intrinsicCoun
     *intrinsics = g_RWTexture3DMethods;
     *intrinsicCount = _countof(g_RWTexture3DMethods);
     break;
-  case AR_OBJECT_FEEDBACKTEXTURE2D_MINLOD:
-  case AR_OBJECT_FEEDBACKTEXTURE2D_TILED:
+  case AR_OBJECT_FEEDBACKTEXTURE2D:
     *intrinsics = g_FeedbackTexture2DMethods;
     *intrinsicCount = _countof(g_FeedbackTexture2DMethods);
     break;
-  case AR_OBJECT_FEEDBACKTEXTURE2D_ARRAY_MINLOD:
-  case AR_OBJECT_FEEDBACKTEXTURE2D_ARRAY_TILED:
+  case AR_OBJECT_FEEDBACKTEXTURE2D_ARRAY:
     *intrinsics = g_FeedbackTexture2DArrayMethods;
     *intrinsicCount = _countof(g_FeedbackTexture2DArrayMethods);
     break;
@@ -2977,7 +2963,7 @@ private:
     size_t templateParamNamedDeclsCount = 0;
     QualType argsQTs[g_MaxIntrinsicParamCount];
     StringRef argNames[g_MaxIntrinsicParamCount];
-    QualType functionResultQT;
+    QualType functionResultQT = recordDecl->getASTContext().VoidTy;
 
     DXASSERT(
       _countof(templateParamNamedDecls) >= numParams + 1,
@@ -2989,7 +2975,7 @@ private:
     // Workaround for template parameter argument count mismatch.
     // Create template parameter for return type always
     // TODO: reenable the check and skip template argument.
-    functionResultQT = AddTemplateParamToArray(
+      functionResultQT = AddTemplateParamToArray(
         "TResult", recordDecl, templateDepth, templateParamNamedDecls,
         &templateParamNamedDeclsCount);
     // }
@@ -3300,7 +3286,6 @@ private:
         case AR_OBJECT_SUBOBJECT_TO_EXPORTS_ASSOC:
           recordDecl = CreateSubobjectSubobjectToExportsAssoc(*m_context);
           break;
-          break;
         case AR_OBJECT_RAYTRACING_SHADER_CONFIG:
           recordDecl = CreateSubobjectRaytracingShaderConfig(*m_context);
           break;
@@ -3320,6 +3305,12 @@ private:
       } else if (kind == AR_OBJECT_RAY_QUERY) {
         recordDecl = DeclareUIntTemplatedTypeWithHandle(*m_context, "RayQuery", "flags");
       }
+      else if (kind == AR_OBJECT_FEEDBACKTEXTURE2D) {
+        recordDecl = DeclareUIntTemplatedTypeWithHandle(*m_context, "FeedbackTexture2D", "kind");
+      }
+      else if (kind == AR_OBJECT_FEEDBACKTEXTURE2D_ARRAY) {
+        recordDecl = DeclareUIntTemplatedTypeWithHandle(*m_context, "FeedbackTexture2DArray", "kind");
+      }
       else if (templateArgCount == 0) {
         recordDecl = DeclareRecordTypeWithHandle(*m_context, typeName);
       }
@@ -4253,6 +4244,7 @@ public:
 
     // Initializing built in integers for ray tracing
     AddRaytracingConstants(*m_context);
+    AddSamplerFeedbackConstants(*m_context);
 
     return true;
   }
@@ -9759,10 +9751,8 @@ void hlsl::DiagnoseRegisterType(
   case AR_OBJECT_ROVTEXTURE2D:
   case AR_OBJECT_ROVTEXTURE2D_ARRAY:
   case AR_OBJECT_ROVTEXTURE3D:
-  case AR_OBJECT_FEEDBACKTEXTURE2D_MINLOD:
-  case AR_OBJECT_FEEDBACKTEXTURE2D_TILED:
-  case AR_OBJECT_FEEDBACKTEXTURE2D_ARRAY_MINLOD:
-  case AR_OBJECT_FEEDBACKTEXTURE2D_ARRAY_TILED:
+  case AR_OBJECT_FEEDBACKTEXTURE2D:
+  case AR_OBJECT_FEEDBACKTEXTURE2D_ARRAY:
     expected = "'u'";
     isValid = registerType == 'u';
     break;

+ 15 - 15
tools/clang/test/CodeGenHLSL/batch/declarations/resources/textures/feedback.hlsl

@@ -2,10 +2,10 @@
 
 // Test FeedbackTexture2D*** and their WriteSamplerFeedback methods
 
-FeedbackTexture2DMinLOD feedbackMinLOD;
-FeedbackTexture2DTiled feedbackTiled;
-FeedbackTexture2DArrayMinLOD feedbackMinLODArray;
-FeedbackTexture2DArrayTiled feebackTiledArray;
+FeedbackTexture2D<SAMPLER_FEEDBACK_MIN_MIP> feedbackMinMip;
+FeedbackTexture2D<SAMPLER_FEEDBACK_MIP_REGION_USED> feedbackMipRegionUsed;
+FeedbackTexture2DArray<SAMPLER_FEEDBACK_MIN_MIP> feedbackMinMipArray;
+FeedbackTexture2DArray<SAMPLER_FEEDBACK_MIP_REGION_USED> feebackMipRegionUsedArray;
 Texture2D<float> texture2D;
 Texture2D<float4> texture2D_float4;
 Texture2DArray<float> texture2DArray;
@@ -24,43 +24,43 @@ float main() : SV_Target
     // Test every dxil intrinsic
     // CHECK: call void @dx.op.writeSamplerFeedback(
     // CHECK: float 1.000000e+00, float 2.000000e+00, float undef, float 4.000000e+00)
-    feedbackMinLOD.WriteSamplerFeedback(texture2D, samp, coords2D, clamp);
+    feedbackMinMip.WriteSamplerFeedback(texture2D, samp, coords2D, clamp);
     // CHECK: call void @dx.op.writeSamplerFeedbackBias(
     // CHECK: float 1.000000e+00, float 2.000000e+00, float undef, float 5.000000e+00, float 4.000000e+00)
-    feedbackMinLOD.WriteSamplerFeedbackBias(texture2D, samp, coords2D, bias, clamp);
+    feedbackMinMip.WriteSamplerFeedbackBias(texture2D, samp, coords2D, bias, clamp);
     // CHECK: call void @dx.op.writeSamplerFeedbackLevel(
     // CHECK: float 1.000000e+00, float 2.000000e+00, float undef, float 6.000000e+00)
-    feedbackMinLOD.WriteSamplerFeedbackLevel(texture2D, samp, coords2D, lod);
+    feedbackMinMip.WriteSamplerFeedbackLevel(texture2D, samp, coords2D, lod);
     // CHECK: call void @dx.op.writeSamplerFeedbackGrad(
     // CHECK: float 1.000000e+00, float 2.000000e+00, float undef, float 7.000000e+00, float 8.000000e+00, float 4.000000e+00)
-    feedbackMinLOD.WriteSamplerFeedbackGrad(texture2D, samp, coords2D, ddx, ddy, clamp);
+    feedbackMinMip.WriteSamplerFeedbackGrad(texture2D, samp, coords2D, ddx, ddy, clamp);
     
     // Test with undef clamp
     // CHECK: call void @dx.op.writeSamplerFeedback(
     // CHECK: float 1.000000e+00, float 2.000000e+00, float undef, float undef)
-    feedbackMinLOD.WriteSamplerFeedback(texture2D, samp, coords2D);
+    feedbackMinMip.WriteSamplerFeedback(texture2D, samp, coords2D);
     // CHECK: call void @dx.op.writeSamplerFeedbackBias(
     // CHECK: float 1.000000e+00, float 2.000000e+00, float undef, float 5.000000e+00, float undef)
-    feedbackMinLOD.WriteSamplerFeedbackBias(texture2D, samp, coords2D, bias);
+    feedbackMinMip.WriteSamplerFeedbackBias(texture2D, samp, coords2D, bias);
     // CHECK: call void @dx.op.writeSamplerFeedbackGrad(
     // CHECK: float 1.000000e+00, float 2.000000e+00, float undef, float 7.000000e+00, float 8.000000e+00, float undef)
-    feedbackMinLOD.WriteSamplerFeedbackGrad(texture2D, samp, coords2D, ddx, ddy);
+    feedbackMinMip.WriteSamplerFeedbackGrad(texture2D, samp, coords2D, ddx, ddy);
 
     // Test on every FeedbackTexture variant
     // CHECK: call void @dx.op.writeSamplerFeedback(
     // CHECK: float 1.000000e+00, float 2.000000e+00, float undef, float undef)
-    feedbackTiled.WriteSamplerFeedback(texture2D, samp, coords2D);
+    feedbackMipRegionUsed.WriteSamplerFeedback(texture2D, samp, coords2D);
     // CHECK: call void @dx.op.writeSamplerFeedback(
     // CHECK: float 1.000000e+00, float 2.000000e+00, float 3.000000e+00, float undef)
-    feedbackMinLODArray.WriteSamplerFeedback(texture2DArray, samp, coords2DArray);
+    feedbackMinMipArray.WriteSamplerFeedback(texture2DArray, samp, coords2DArray);
     // CHECK: call void @dx.op.writeSamplerFeedback(
     // CHECK: float 1.000000e+00, float 2.000000e+00, float 3.000000e+00, float undef)
-    feebackTiledArray.WriteSamplerFeedback(texture2DArray, samp, coords2DArray);
+    feebackMipRegionUsedArray.WriteSamplerFeedback(texture2DArray, samp, coords2DArray);
 
     // Test with overloaded texture type
     // CHECK: call void @dx.op.writeSamplerFeedback(
     // CHECK: float 1.000000e+00, float 2.000000e+00, float undef, float undef)
-    feedbackMinLOD.WriteSamplerFeedback(texture2D_float4, samp, coords2D);
+    feedbackMinMip.WriteSamplerFeedback(texture2D_float4, samp, coords2D);
 
     return 0;
 }

+ 20 - 0
tools/clang/test/CodeGenHLSL/batch/declarations/resources/textures/feedback_metadata.hlsl

@@ -0,0 +1,20 @@
+// RUN: %dxc -E main -T ps_6_5 %s | FileCheck %s
+
+// Test that metadata encodes the sampler feedback type.
+
+FeedbackTexture2D<SAMPLER_FEEDBACK_MIN_MIP> feedbackMinMip;
+FeedbackTexture2D<SAMPLER_FEEDBACK_MIP_REGION_USED> feedbackMipRegionUsed;
+Texture2D<float> texture2D;
+SamplerState samp;
+
+float main() : SV_Target 
+{
+    feedbackMinMip.WriteSamplerFeedback(texture2D, samp, (float2)0);
+    feedbackMipRegionUsed.WriteSamplerFeedback(texture2D, samp, (float2)0);
+    return 0;
+}
+
+// CHECK-DAG: !{i32 0, %"class.FeedbackTexture2D<0>"* undef, !"feedbackMinMip", i32 0, i32 0, i32 1, i32 17, i1 false, i1 false, i1 false, ![[minmip:.*]]}
+// CHECK-DAG: ![[minmip]] = !{i32 2, i32 0}
+// CHECK-DAG: !{i32 1, %"class.FeedbackTexture2D<1>"* undef, !"feedbackMipRegionUsed", i32 0, i32 1, i32 1, i32 17, i1 false, i1 false, i1 false, ![[mipregionused:.*]]}
+// CHECK-DAG: ![[mipregionused]] = !{i32 2, i32 1}

+ 1 - 0
utils/hct/hctdb.py

@@ -2417,6 +2417,7 @@ class db_dxil(object):
         self.add_valrule("Sm.InvalidTextureKindOnUAV", "Texture2DMS[Array] or TextureCube[Array] resources are not supported with UAVs")
         self.add_valrule("Sm.InvalidResourceKind", "Invalid resources kind")
         self.add_valrule("Sm.InvalidResourceCompType","Invalid resource return type")
+        self.add_valrule("Sm.InvalidSamplerFeedbackType","Invalid sampler feedback type")
         self.add_valrule("Sm.SampleCountOnlyOn2DMS","Only Texture2DMS/2DMSArray could has sample count")
         self.add_valrule("Sm.CounterOnlyOnStructBuf", "BufferUpdateCounter valid only on structured buffers")
         self.add_valrule("Sm.GSTotalOutputVertexDataRange", "Declared output vertex count (%0) multiplied by the total number of declared scalar components of output data (%1) equals %2.  This value cannot be greater than %3")