瀏覽代碼

Fix reflection on bitfield. (#5142)

* Fix reflection on bitfield.

This is for case where bitfield member lost when reflection.

Save bitfield information in DxilFieldAnnotation.
Then use the information in CShaderReflectionType::Initialize.

Add field for the integer and put bit fields as members of the integer field.
Xiang Li 2 年之前
父節點
當前提交
5cadb2589e

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

@@ -227,6 +227,8 @@ public:
   static const unsigned kDxilFieldAnnotationPreciseTag            = 8;
   static const unsigned kDxilFieldAnnotationCBUsedTag             = 9;
   static const unsigned kDxilFieldAnnotationResPropTag            = 10;
+  static const unsigned kDxilFieldAnnotationBitFieldsTag          = 11;
+  static const unsigned kDxilFieldAnnotationBitFieldWidthTag      = 12;
 
   // DXR Payload Annotations
   static const unsigned kDxilPayloadAnnotationStructTag           = 0;

+ 10 - 0
include/dxc/DXIL/DxilTypeSystem.h

@@ -86,6 +86,14 @@ public:
   bool IsCBVarUsed() const;
   void SetCBVarUsed(bool used);
 
+  bool HasBitFields() const;
+  const std::vector<DxilFieldAnnotation> &GetBitFields() const;
+  void SetBitFields(const std::vector<DxilFieldAnnotation> &Fields);
+
+  bool HasBitFieldWidth() const;
+  unsigned GetBitFieldWidth() const;
+  void SetBitFieldWidth(const unsigned BitWidth);
+
 private:
   bool m_bPrecise;
   CompType m_CompType;
@@ -96,6 +104,8 @@ private:
   InterpolationMode m_InterpMode;
   std::string m_FieldName;
   bool m_bCBufferVarUsed; // true if this field represents a top level variable in CB structure, and it is used.
+  std::vector<DxilFieldAnnotation> m_BitFields;
+  unsigned m_BitFieldWidth; // For bit field. 0 means not bitfield.
 };
 
 class DxilTemplateArgAnnotation {

+ 25 - 0
lib/DXIL/DxilMetadataHelper.cpp

@@ -1214,6 +1214,20 @@ Metadata *DxilMDHelper::EmitDxilFieldAnnotation(const DxilFieldAnnotation &FA) {
         m_pModule->GetDxilModule().GetOP()->GetResourcePropertiesType(),
         *m_pSM)));
   }
+  if (FA.HasBitFields()) {
+    const std::vector<DxilFieldAnnotation> &BitFields = FA.GetBitFields();
+    vector<Metadata *> MDBitFieldVals;
+    for (const DxilFieldAnnotation &BitField : BitFields) {
+      MDBitFieldVals.emplace_back(EmitDxilFieldAnnotation(BitField));
+    }
+    auto *BitFieldsMD = MDNode::get(m_Ctx, MDBitFieldVals);
+    MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationBitFieldsTag));
+    MDVals.emplace_back(BitFieldsMD);
+  }
+  if (FA.HasBitFieldWidth()) {
+    MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationBitFieldWidthTag));
+    MDVals.emplace_back(Uint32ToConstMD(FA.GetBitFieldWidth()));
+  }
 
   return MDNode::get(m_Ctx, MDVals);
 }
@@ -1267,6 +1281,17 @@ void DxilMDHelper::LoadDxilFieldAnnotation(const MDOperand &MDO, DxilFieldAnnota
               dyn_cast<ValueAsMetadata>(MDO)->getValue()))
         FA.SetResourceProperties(resource_helper::loadPropsFromConstant(*C));
       break;
+    case kDxilFieldAnnotationBitFieldsTag: {
+      const MDTuple *pBitFieldsTupleMD = dyn_cast<MDTuple>(MDO.get());
+      std::vector<DxilFieldAnnotation> BitFields(pBitFieldsTupleMD->getNumOperands());
+      for (unsigned i = 0; i < pBitFieldsTupleMD->getNumOperands(); ++i) {
+        LoadDxilFieldAnnotation(pBitFieldsTupleMD->getOperand(i), BitFields[i]);
+      }
+      FA.SetBitFields(BitFields);
+    } break;
+    case kDxilFieldAnnotationBitFieldWidthTag:
+      FA.SetBitFieldWidth(ConstMDToUint32(MDO));
+      break;
     default:
       DXASSERT(false, "Unknown extended shader properties tag");
       m_bExtraMetadata = true;

+ 15 - 0
lib/DXIL/DxilTypeSystem.cpp

@@ -45,6 +45,7 @@ DxilFieldAnnotation::DxilFieldAnnotation()
 : m_bPrecise(false)
 , m_CBufferOffset(UINT_MAX)
 , m_bCBufferVarUsed(false)
+, m_BitFieldWidth(0)
 {}
 
 bool DxilFieldAnnotation::IsPrecise() const { return m_bPrecise; }
@@ -79,6 +80,20 @@ const std::string &DxilFieldAnnotation::GetFieldName() const { return m_FieldNam
 void DxilFieldAnnotation::SetFieldName(const std::string &FieldName) { m_FieldName = FieldName; }
 bool DxilFieldAnnotation::IsCBVarUsed() const { return m_bCBufferVarUsed; }
 void DxilFieldAnnotation::SetCBVarUsed(bool used) { m_bCBufferVarUsed = used; }
+bool DxilFieldAnnotation::HasBitFields() const { return !m_BitFields.empty(); }
+const std::vector<DxilFieldAnnotation> &
+DxilFieldAnnotation::GetBitFields() const {
+  return m_BitFields;
+}
+void DxilFieldAnnotation::SetBitFields(
+    const std::vector<DxilFieldAnnotation> &Fields) {
+  m_BitFields = Fields;
+}
+bool DxilFieldAnnotation::HasBitFieldWidth() const { return m_BitFieldWidth != 0; }
+unsigned DxilFieldAnnotation::GetBitFieldWidth() const { return m_BitFieldWidth; }
+void DxilFieldAnnotation::SetBitFieldWidth(const unsigned BitWidth) {
+  m_BitFieldWidth = BitWidth;
+}
 
 //------------------------------------------------------------------------------
 //

+ 66 - 20
lib/HLSL/DxilContainerReflection.cpp

@@ -49,6 +49,7 @@ struct D3D11_SHADER_INPUT_BIND_DESC {int dummy;};
 
 // Remove this workaround once newer version of d3dcommon.h can be compiled against
 #define ADD_16_64_BIT_TYPES
+#define ADD_SVC_BIT_FIELD
 
 const GUID IID_ID3D11ShaderReflection_43 = {
     0x0a233719,
@@ -102,6 +103,14 @@ enum class PublicAPI { D3D12 = 0, D3D11_47 = 1, D3D11_43 = 2 };
 #define D3D_SVT_UINT64  ((D3D_SHADER_VARIABLE_TYPE)62)
 #endif // ADD_16_64_BIT_TYPES
 
+#ifdef ADD_SVC_BIT_FIELD
+// Disable warning about value not being valid in enum
+#pragma warning(disable : 4063)
+// FIXME: remove the define once D3D_SVC_BIT_FIELD added into
+// D3D_SHADER_VARIABLE_CLASS.
+#define D3D_SVC_BIT_FIELD ((D3D_SHADER_VARIABLE_CLASS)(D3D_SVC_INTERFACE_POINTER + 1))
+#endif
+
 class DxilModuleReflection {
 public:
   hlsl::RDAT::DxilRuntimeData m_RDAT;
@@ -1140,24 +1149,31 @@ HRESULT CShaderReflectionType::Initialize(
 
       CShaderReflectionType *fieldReflectionType = nullptr;
 
-      for(unsigned int ff = 0; ff < fieldCount; ++ff)
-      {
-        DxilFieldAnnotation& fieldAnnotation = structAnnotation->GetFieldAnnotation(ff);
-        llvm::Type* fieldType = structType->getStructElementType(ff);
+      for (unsigned int ff = 0; ff < fieldCount; ++ff) {
+        DxilFieldAnnotation &fieldAnnotation =
+            structAnnotation->GetFieldAnnotation(ff);
+        llvm::Type *fieldType = structType->getStructElementType(ff);
 
-        // Skip fields with object types, since these are not part of constant buffers,
-        // and are not allowed in other buffer types.
-        if( IsObjectType(fieldType) )
-        {
+        // Skip fields with object types, since these are not part of constant
+        // buffers, and are not allowed in other buffer types.
+        if (IsObjectType(fieldType)) {
           continue;
         }
 
         fieldReflectionType = new CShaderReflectionType();
-        allTypes.push_back(std::unique_ptr<CShaderReflectionType>(fieldReflectionType));
+        allTypes.push_back(
+            std::unique_ptr<CShaderReflectionType>(fieldReflectionType));
+
+        unsigned int elementOffset =
+            structLayout ? (unsigned int)structLayout->getElementOffset(ff) : 0;
 
-        unsigned int elementOffset = structLayout ? (unsigned int)structLayout->getElementOffset(ff) : 0;
+        fieldReflectionType->Initialize(M, fieldType, fieldAnnotation,
+                                        elementOffset, allTypes, isCBuffer);
 
-        fieldReflectionType->Initialize(M, fieldType, fieldAnnotation, elementOffset, allTypes, isCBuffer);
+        // Treat bit fields as member inside the integer.
+        if (fieldAnnotation.HasBitFields())
+          fieldReflectionType->m_Desc.Members =
+              fieldAnnotation.GetBitFields().size();
 
         m_MemberTypes.push_back(fieldReflectionType);
         m_MemberNames.push_back(fieldAnnotation.GetFieldName().c_str());
@@ -1169,15 +1185,46 @@ HRESULT CShaderReflectionType::Initialize(
           continue;
         }
 
-        // Effectively, we want to add one to `Columns` for every scalar nested recursively
-        // inside this `struct` type (ignoring objects, which we filtered above). We should
-        // be able to compute this as the product of the `Columns`, `Rows` and `Elements`
-        // of each field, with the caveat that some of these may be zero, but shoud be
-        // treated as one.
+        // Effectively, we want to add one to `Columns` for every scalar
+        // nested recursively inside this `struct` type (ignoring objects,
+        // which we filtered above). We should be able to compute this as the
+        // product of the `Columns`, `Rows` and `Elements` of each field, with
+        // the caveat that some of these may be zero, but shoud be treated as
+        // one.
         columnCounter +=
-            (fieldReflectionType->m_Desc.Columns  ? fieldReflectionType->m_Desc.Columns  : 1)
-          * (fieldReflectionType->m_Desc.Rows     ? fieldReflectionType->m_Desc.Rows     : 1)
-          * (fieldReflectionType->m_Desc.Elements ? fieldReflectionType->m_Desc.Elements : 1);
+            (fieldReflectionType->m_Desc.Columns
+                 ? fieldReflectionType->m_Desc.Columns
+                 : 1) *
+            (fieldReflectionType->m_Desc.Rows ? fieldReflectionType->m_Desc.Rows
+                                              : 1) *
+            (fieldReflectionType->m_Desc.Elements
+                 ? fieldReflectionType->m_Desc.Elements
+                 : 1);
+
+        if (fieldAnnotation.HasBitFields()) {
+          unsigned bitOffset = 0;
+          CShaderReflectionType *bitFieldReflectionType = nullptr;
+          for (auto &bitfieldAnnotation : fieldAnnotation.GetBitFields()) {
+            bitFieldReflectionType = new CShaderReflectionType();
+            allTypes.push_back(
+                std::unique_ptr<CShaderReflectionType>(bitFieldReflectionType));
+
+            bitFieldReflectionType->Initialize(M, fieldType, fieldAnnotation,
+                                            elementOffset, allTypes, isCBuffer);
+            bitFieldReflectionType->m_Desc.Class = D3D_SVC_BIT_FIELD;
+
+            // Save bit size to columns.
+            bitFieldReflectionType->m_Desc.Columns =
+                bitfieldAnnotation.GetBitFieldWidth();
+            // Save bit offset to Offset.
+            bitFieldReflectionType->m_Desc.Offset = bitOffset;
+            bitOffset += bitfieldAnnotation.GetBitFieldWidth();
+
+            fieldReflectionType->m_MemberTypes.push_back(bitFieldReflectionType);
+            fieldReflectionType->m_MemberNames.push_back(
+                bitfieldAnnotation.GetFieldName().c_str());
+          }
+        }
       }
 
       m_Desc.Columns = columnCounter;
@@ -1254,7 +1301,6 @@ HRESULT CShaderReflectionType::Initialize(
   return S_OK;
 }
 
-
 void CShaderReflectionConstantBuffer::Initialize(
   DxilModule &M,
   DxilCBuffer &CB,

+ 33 - 1
tools/clang/lib/CodeGen/CGHLSLMS.cpp

@@ -958,8 +958,11 @@ unsigned CGMSHLSLRuntime::ConstructStructAnnotation(DxilStructAnnotation *annota
       RecordDecl::field_iterator End = Field;
       for (++End; End != FieldEnd && End->isBitField(); ++End);
 
+      std::vector<DxilFieldAnnotation> BitFields;
+
       RecordDecl::field_iterator Run = End;
-      uint64_t StartBitOffset, Tail = 0;
+      uint64_t StartBitOffset = Layout.getFieldOffset(Field->getFieldIndex());
+      uint64_t Tail = 0;
       for (; Field != End; ++Field) {
         uint64_t BitOffset = Layout.getFieldOffset(Field->getFieldIndex());
         // Zero-width bitfields end runs.
@@ -967,10 +970,19 @@ unsigned CGMSHLSLRuntime::ConstructStructAnnotation(DxilStructAnnotation *annota
           Run = End;
           continue;
         }
+
         llvm::Type *Type = Types.ConvertTypeForMem(Field->getType());
         // If we don't have a run yet, or don't live within the previous run's
         // allocated storage then we allocate some storage and start a new run.
         if (Run == End || BitOffset >= Tail) {
+          // Add BitFields to current field.
+          if (BitOffset >= Tail && BitOffset > 0) {
+            DxilFieldAnnotation &curFieldAnnotation =
+                annotation->GetFieldAnnotation(fieldIdx-1);
+            curFieldAnnotation.SetBitFields(BitFields);
+            BitFields.clear();
+          }
+
           Run = Field;
           StartBitOffset = BitOffset;
           Tail = StartBitOffset + DataLayout.getTypeAllocSizeInBits(Type);
@@ -993,9 +1005,29 @@ unsigned CGMSHLSLRuntime::ConstructStructAnnotation(DxilStructAnnotation *annota
           // Update offset.
           CBufferOffset += size;
         }
+
+        DxilFieldAnnotation bitfieldAnnotation;
+
+        bitfieldAnnotation.SetBitFieldWidth(Field->getBitWidthValue(Context));
+        const BuiltinType *BTy = Field->getType()->getAs<BuiltinType>();
+        CompType::Kind kind =
+            BuiltinTyToCompTy(BTy, /*bSNorm*/ false, /*bUNorm*/ false);
+        bitfieldAnnotation.SetCompType(kind);
+        bitfieldAnnotation.SetFieldName(Field->getName());
+        bitfieldAnnotation.SetCBufferOffset(
+            (unsigned)(BitOffset - StartBitOffset));
+        BitFields.emplace_back(bitfieldAnnotation);
+      }
+
+      if (!BitFields.empty()) {
+        DxilFieldAnnotation &curFieldAnnotation =
+            annotation->GetFieldAnnotation(fieldIdx - 1);
+        curFieldAnnotation.SetBitFields(BitFields);
+        BitFields.clear();
       }
 
       CBufferSize = CBufferOffset;
+
       continue;  // Field has already been advanced past bitfields
     }
 

+ 87 - 0
tools/clang/test/HLSLFileCheck/d3dreflect/bitfield-combine-to-unsigned.hlsl

@@ -0,0 +1,87 @@
+// RUN: %dxc -E main -T ps_6_0 -HV 2021 -Vd -validator-version 0.0  %s | %D3DReflect %s | FileCheck %s
+
+// Make sure bitfiled info is saved.
+
+// CHECK:            D3D12_SHADER_TYPE_DESC: Name: BF
+// CHECK-NEXT:              Class: D3D_SVC_STRUCT
+// CHECK-NEXT:              Type: D3D_SVT_VOID
+// CHECK-NEXT:              Elements: 0
+// CHECK-NEXT:              Rows: 1
+// CHECK-NEXT:              Columns: 2
+// CHECK-NEXT:              Members: 2
+// CHECK-NEXT:              Offset: 0
+// CHECK-NEXT:            {
+// CHECK-NEXT:              ID3D12ShaderReflectionType:
+// CHECK-NEXT:                D3D12_SHADER_TYPE_DESC: Name: int
+// CHECK-NEXT:                  Class: D3D_SVC_SCALAR
+// CHECK-NEXT:                  Type: D3D_SVT_INT
+// CHECK-NEXT:                  Elements: 0
+// CHECK-NEXT:                  Rows: 1
+// CHECK-NEXT:                  Columns: 1
+// CHECK-NEXT:                  Members: 2
+// CHECK-NEXT:                  Offset: 0
+// CHECK-NEXT:                {
+// CHECK-NEXT:                  ID3D12ShaderReflectionType:
+// CHECK-NEXT:                    D3D12_SHADER_TYPE_DESC: Name: int
+// CHECK-NEXT:                      Class: D3D_SVC_BIT_FIELD
+// CHECK-NEXT:                      Type: D3D_SVT_INT
+// CHECK-NEXT:                      Elements: 0
+// CHECK-NEXT:                      Rows: 1
+// CHECK-NEXT:                      Columns: 8
+// CHECK-NEXT:                      Members: 0
+// CHECK-NEXT:                      Offset: 0
+// CHECK-NEXT:                  ID3D12ShaderReflectionType:
+// CHECK-NEXT:                    D3D12_SHADER_TYPE_DESC: Name: int
+// CHECK-NEXT:                      Class: D3D_SVC_BIT_FIELD
+// CHECK-NEXT:                      Type: D3D_SVT_INT
+// CHECK-NEXT:                      Elements: 0
+// CHECK-NEXT:                      Rows: 1
+// CHECK-NEXT:                      Columns: 8
+// CHECK-NEXT:                      Members: 0
+// CHECK-NEXT:                      Offset: 8
+// CHECK-NEXT:                }
+// CHECK-NEXT:              ID3D12ShaderReflectionType:
+// CHECK-NEXT:                D3D12_SHADER_TYPE_DESC: Name: uint64_t
+// CHECK-NEXT:                  Class: D3D_SVC_SCALAR
+// CHECK-NEXT:                  Type: D3D_SVT_UINT64
+// CHECK-NEXT:                  Elements: 0
+// CHECK-NEXT:                  Rows: 1
+// CHECK-NEXT:                  Columns: 1
+// CHECK-NEXT:                  Members: 2
+// CHECK-NEXT:                  Offset: 8
+// CHECK-NEXT:                {
+// CHECK-NEXT:                  ID3D12ShaderReflectionType:
+// CHECK-NEXT:                    D3D12_SHADER_TYPE_DESC: Name: uint64_t
+// CHECK-NEXT:                      Class: D3D_SVC_BIT_FIELD
+// CHECK-NEXT:                      Type: D3D_SVT_UINT64
+// CHECK-NEXT:                      Elements: 0
+// CHECK-NEXT:                      Rows: 1
+// CHECK-NEXT:                      Columns: 8
+// CHECK-NEXT:                      Members: 0
+// CHECK-NEXT:                      Offset: 0
+// CHECK-NEXT:                  ID3D12ShaderReflectionType:
+// CHECK-NEXT:                    D3D12_SHADER_TYPE_DESC: Name: uint64_t
+// CHECK-NEXT:                      Class: D3D_SVC_BIT_FIELD
+// CHECK-NEXT:                      Type: D3D_SVT_UINT64
+// CHECK-NEXT:                      Elements: 0
+// CHECK-NEXT:                      Rows: 1
+// CHECK-NEXT:                      Columns: 8
+// CHECK-NEXT:                      Members: 0
+// CHECK-NEXT:                      Offset: 8
+// CHECK-NEXT:                }
+// CHECK-NEXT:            }
+// CHECK-NEXT: CBuffer: B
+
+struct BF {
+   int i0 : 8;
+   uint i1 : 8;
+   uint64_t i2 : 8;
+   int64_t i3 : 8;
+};
+
+StructuredBuffer<BF> B;
+
+
+float4 main() : SV_Target {
+  return float4(B[0].i0, B[0].i1, B[0].i2, B[0].i3);
+}

+ 76 - 0
tools/clang/test/HLSLFileCheck/d3dreflect/bitfield_in-structured-buffer.hlsl

@@ -0,0 +1,76 @@
+// RUN: %dxc -E main -T ps_6_0 -HV 2021 -Vd -validator-version 0.0  %s | %D3DReflect %s | FileCheck %s
+
+// Make sure bitfiled info is saved.
+
+// CHECK: D3D12_SHADER_TYPE_DESC: Name: BF
+// CHECK-NEXT:               Class: D3D_SVC_STRUCT
+// CHECK-NEXT:               Type: D3D_SVT_VOID
+// CHECK-NEXT:               Elements: 0
+// CHECK-NEXT:               Rows: 1
+// CHECK-NEXT:               Columns: 1
+// CHECK-NEXT:               Members: 1
+// CHECK-NEXT:               Offset: 0
+// CHECK-NEXT:             {
+// CHECK-NEXT:               ID3D12ShaderReflectionType:
+// CHECK-NEXT:                 D3D12_SHADER_TYPE_DESC: Name: int
+// CHECK-NEXT:                   Class: D3D_SVC_SCALAR
+// CHECK-NEXT:                   Type: D3D_SVT_INT
+// CHECK-NEXT:                   Elements: 0
+// CHECK-NEXT:                   Rows: 1
+// CHECK-NEXT:                   Columns: 1
+// CHECK-NEXT:                   Members: 4
+// CHECK-NEXT:                   Offset: 0
+// CHECK-NEXT:                 {
+// CHECK-NEXT:                   ID3D12ShaderReflectionType:
+// CHECK-NEXT:                     D3D12_SHADER_TYPE_DESC: Name: int
+// CHECK-NEXT:                       Class: D3D_SVC_BIT_FIELD
+// CHECK-NEXT:                       Type: D3D_SVT_INT
+// CHECK-NEXT:                       Elements: 0
+// CHECK-NEXT:                       Rows: 1
+// CHECK-NEXT:                       Columns: 8
+// CHECK-NEXT:                       Members: 0
+// CHECK-NEXT:                       Offset: 0
+// CHECK-NEXT:                   ID3D12ShaderReflectionType:
+// CHECK-NEXT:                     D3D12_SHADER_TYPE_DESC: Name: int
+// CHECK-NEXT:                       Class: D3D_SVC_BIT_FIELD
+// CHECK-NEXT:                       Type: D3D_SVT_INT
+// CHECK-NEXT:                       Elements: 0
+// CHECK-NEXT:                       Rows: 1
+// CHECK-NEXT:                       Columns: 8
+// CHECK-NEXT:                       Members: 0
+// CHECK-NEXT:                       Offset: 8
+// CHECK-NEXT:                   ID3D12ShaderReflectionType:
+// CHECK-NEXT:                     D3D12_SHADER_TYPE_DESC: Name: int
+// CHECK-NEXT:                       Class: D3D_SVC_BIT_FIELD
+// CHECK-NEXT:                       Type: D3D_SVT_INT
+// CHECK-NEXT:                       Elements: 0
+// CHECK-NEXT:                       Rows: 1
+// CHECK-NEXT:                       Columns: 8
+// CHECK-NEXT:                       Members: 0
+// CHECK-NEXT:                       Offset: 16
+// CHECK-NEXT:                   ID3D12ShaderReflectionType:
+// CHECK-NEXT:                     D3D12_SHADER_TYPE_DESC: Name: int
+// CHECK-NEXT:                       Class: D3D_SVC_BIT_FIELD
+// CHECK-NEXT:                       Type: D3D_SVT_INT
+// CHECK-NEXT:                       Elements: 0
+// CHECK-NEXT:                       Rows: 1
+// CHECK-NEXT:                       Columns: 8
+// CHECK-NEXT:                       Members: 0
+// CHECK-NEXT:                       Offset: 24
+// CHECK-NEXT:                 }
+// CHECK-NEXT:             }
+// CHECK-NEXT: CBuffer: B
+
+struct BF {
+   int i0 : 8;
+   int i1 : 8;
+   int i2 : 8;
+   int i3 : 8;
+};
+
+StructuredBuffer<BF> B;
+
+
+float4 main() : SV_Target {
+  return float4(B[0].i0, B[0].i1, B[0].i2, B[0].i3);
+}

+ 46 - 0
tools/clang/test/HLSLFileCheck/d3dreflect/bitfield_single_member.hlsl

@@ -0,0 +1,46 @@
+// RUN: %dxc -E main -T ps_6_0 -HV 2021 -Vd -validator-version 0.0  %s | %D3DReflect %s | FileCheck %s
+
+// Make sure bitfiled info is saved.
+
+// CHECK: D3D12_SHADER_TYPE_DESC: Name: BF
+// CHECK-NEXT:               Class: D3D_SVC_STRUCT
+// CHECK-NEXT:               Type: D3D_SVT_VOID
+// CHECK-NEXT:               Elements: 0
+// CHECK-NEXT:               Rows: 1
+// CHECK-NEXT:               Columns: 1
+// CHECK-NEXT:               Members: 1
+// CHECK-NEXT:               Offset: 0
+// CHECK-NEXT:             {
+// CHECK-NEXT:               ID3D12ShaderReflectionType:
+// CHECK-NEXT:                 D3D12_SHADER_TYPE_DESC: Name: int
+// CHECK-NEXT:                   Class: D3D_SVC_SCALAR
+// CHECK-NEXT:                   Type: D3D_SVT_INT
+// CHECK-NEXT:                   Elements: 0
+// CHECK-NEXT:                   Rows: 1
+// CHECK-NEXT:                   Columns: 1
+// CHECK-NEXT:                   Members: 1
+// CHECK-NEXT:                   Offset: 0
+// CHECK-NEXT:                 {
+// CHECK-NEXT:                   ID3D12ShaderReflectionType:
+// CHECK-NEXT:                     D3D12_SHADER_TYPE_DESC: Name: int
+// CHECK-NEXT:                       Class: D3D_SVC_BIT_FIELD
+// CHECK-NEXT:                       Type: D3D_SVT_INT
+// CHECK-NEXT:                       Elements: 0
+// CHECK-NEXT:                       Rows: 1
+// CHECK-NEXT:                       Columns: 8
+// CHECK-NEXT:                       Members: 0
+// CHECK-NEXT:                       Offset: 0
+// CHECK-NEXT:                 }
+// CHECK-NEXT:             }
+// CHECK-NEXT: CBuffer: B
+
+struct BF {
+   int i0 : 8;
+};
+
+StructuredBuffer<BF> B;
+
+
+float main() : SV_Target {
+  return B[0].i0;
+}

+ 141 - 0
tools/clang/test/HLSLFileCheck/d3dreflect/bitfield_spill-over.hlsl

@@ -0,0 +1,141 @@
+// RUN: %dxc -E main -T ps_6_0 -HV 2021 -Vd -validator-version 0.0  %s | %D3DReflect %s | FileCheck %s
+
+// Make sure bitfiled info is saved.
+// FIXME: check half as 16bit when enable-16bit-types.
+
+// CHECK:             D3D12_SHADER_TYPE_DESC: Name: BF
+// CHECK-NEXT:               Class: D3D_SVC_STRUCT
+// CHECK-NEXT:               Type: D3D_SVT_VOID
+// CHECK-NEXT:               Elements: 0
+// CHECK-NEXT:               Rows: 1
+// CHECK-NEXT:               Columns: 3
+// CHECK-NEXT:               Members: 3
+// CHECK-NEXT:               Offset: 0
+// CHECK-NEXT:             {
+// CHECK-NEXT:               ID3D12ShaderReflectionType:
+// CHECK-NEXT:                 D3D12_SHADER_TYPE_DESC: Name: int
+// CHECK-NEXT:                   Class: D3D_SVC_SCALAR
+// CHECK-NEXT:                   Type: D3D_SVT_INT
+// CHECK-NEXT:                   Elements: 0
+// CHECK-NEXT:                   Rows: 1
+// CHECK-NEXT:                   Columns: 1
+// CHECK-NEXT:                   Members: 4
+// CHECK-NEXT:                   Offset: 0
+// CHECK-NEXT:                 {
+// CHECK-NEXT:                   ID3D12ShaderReflectionType:
+// CHECK-NEXT:                     D3D12_SHADER_TYPE_DESC: Name: int
+// CHECK-NEXT:                       Class: D3D_SVC_BIT_FIELD
+// CHECK-NEXT:                       Type: D3D_SVT_INT
+// CHECK-NEXT:                       Elements: 0
+// CHECK-NEXT:                       Rows: 1
+// CHECK-NEXT:                       Columns: 8
+// CHECK-NEXT:                       Members: 0
+// CHECK-NEXT:                       Offset: 0
+// CHECK-NEXT:                   ID3D12ShaderReflectionType:
+// CHECK-NEXT:                     D3D12_SHADER_TYPE_DESC: Name: int
+// CHECK-NEXT:                       Class: D3D_SVC_BIT_FIELD
+// CHECK-NEXT:                       Type: D3D_SVT_INT
+// CHECK-NEXT:                       Elements: 0
+// CHECK-NEXT:                       Rows: 1
+// CHECK-NEXT:                       Columns: 8
+// CHECK-NEXT:                       Members: 0
+// CHECK-NEXT:                       Offset: 8
+// CHECK-NEXT:                   ID3D12ShaderReflectionType:
+// CHECK-NEXT:                     D3D12_SHADER_TYPE_DESC: Name: int
+// CHECK-NEXT:                       Class: D3D_SVC_BIT_FIELD
+// CHECK-NEXT:                       Type: D3D_SVT_INT
+// CHECK-NEXT:                       Elements: 0
+// CHECK-NEXT:                       Rows: 1
+// CHECK-NEXT:                       Columns: 8
+// CHECK-NEXT:                       Members: 0
+// CHECK-NEXT:                       Offset: 16
+// CHECK-NEXT:                   ID3D12ShaderReflectionType:
+// CHECK-NEXT:                     D3D12_SHADER_TYPE_DESC: Name: int
+// CHECK-NEXT:                       Class: D3D_SVC_BIT_FIELD
+// CHECK-NEXT:                       Type: D3D_SVT_INT
+// CHECK-NEXT:                       Elements: 0
+// CHECK-NEXT:                       Rows: 1
+// CHECK-NEXT:                       Columns: 8
+// CHECK-NEXT:                       Members: 0
+// CHECK-NEXT:                       Offset: 24
+// CHECK-NEXT:                 }
+// CHECK-NEXT:               ID3D12ShaderReflectionType:
+// CHECK-NEXT:                 D3D12_SHADER_TYPE_DESC: Name: int
+// CHECK-NEXT:                   Class: D3D_SVC_SCALAR
+// CHECK-NEXT:                   Type: D3D_SVT_INT
+// CHECK-NEXT:                   Elements: 0
+// CHECK-NEXT:                   Rows: 1
+// CHECK-NEXT:                   Columns: 1
+// CHECK-NEXT:                   Members: 3
+// CHECK-NEXT:                   Offset: 4
+// CHECK-NEXT:                 {
+// CHECK-NEXT:                   ID3D12ShaderReflectionType:
+// CHECK-NEXT:                     D3D12_SHADER_TYPE_DESC: Name: int
+// CHECK-NEXT:                       Class: D3D_SVC_BIT_FIELD
+// CHECK-NEXT:                       Type: D3D_SVT_INT
+// CHECK-NEXT:                       Elements: 0
+// CHECK-NEXT:                       Rows: 1
+// CHECK-NEXT:                       Columns: 8
+// CHECK-NEXT:                       Members: 0
+// CHECK-NEXT:                       Offset: 0
+// CHECK-NEXT:                   ID3D12ShaderReflectionType:
+// CHECK-NEXT:                     D3D12_SHADER_TYPE_DESC: Name: int
+// CHECK-NEXT:                       Class: D3D_SVC_BIT_FIELD
+// CHECK-NEXT:                       Type: D3D_SVT_INT
+// CHECK-NEXT:                       Elements: 0
+// CHECK-NEXT:                       Rows: 1
+// CHECK-NEXT:                       Columns: 4
+// CHECK-NEXT:                       Members: 0
+// CHECK-NEXT:                       Offset: 8
+// CHECK-NEXT:                   ID3D12ShaderReflectionType:
+// CHECK-NEXT:                     D3D12_SHADER_TYPE_DESC: Name: int
+// CHECK-NEXT:                       Class: D3D_SVC_BIT_FIELD
+// CHECK-NEXT:                       Type: D3D_SVT_INT
+// CHECK-NEXT:                       Elements: 0
+// CHECK-NEXT:                       Rows: 1
+// CHECK-NEXT:                       Columns: 5
+// CHECK-NEXT:                       Members: 0
+// CHECK-NEXT:                       Offset: 12
+// CHECK-NEXT:                 }
+// CHECK-NEXT:               ID3D12ShaderReflectionType:
+// CHECK-NEXT:                 D3D12_SHADER_TYPE_DESC: Name: int
+// CHECK-NEXT:                   Class: D3D_SVC_SCALAR
+// CHECK-NEXT:                   Type: D3D_SVT_INT
+// CHECK-NEXT:                   Elements: 0
+// CHECK-NEXT:                   Rows: 1
+// CHECK-NEXT:                   Columns: 1
+// CHECK-NEXT:                   Members: 1
+// CHECK-NEXT:                   Offset: 8
+// CHECK-NEXT:                 {
+// CHECK-NEXT:                   ID3D12ShaderReflectionType:
+// CHECK-NEXT:                     D3D12_SHADER_TYPE_DESC: Name: int
+// CHECK-NEXT:                       Class: D3D_SVC_BIT_FIELD
+// CHECK-NEXT:                       Type: D3D_SVT_INT
+// CHECK-NEXT:                       Elements: 0
+// CHECK-NEXT:                       Rows: 1
+// CHECK-NEXT:                       Columns: 6
+// CHECK-NEXT:                       Members: 0
+// CHECK-NEXT:                       Offset: 0
+// CHECK-NEXT:                 }
+// CHECK-NEXT:             }
+// CHECK-NEXT: CBuffer: B
+
+struct BF {
+   int i0 : 8;
+   int i1 : 8;
+   int i2 : 8;
+   int i3 : 8;
+   int i4 : 8; // spill over, start of second primitive
+   int : 4; // what about blank field?  do we support this?
+   int i5 : 5;
+   int : 0; // force next bit field to start at next primitive
+   int i6 : 6; // start of third primitive
+};
+
+
+StructuredBuffer<BF> B;
+
+
+float main() : SV_Target {
+  return B[0].i0;
+}

+ 11 - 0
tools/clang/unittests/HLSLTestLib/D3DReflectionStrings.cpp

@@ -15,6 +15,7 @@
 
 // Remove this workaround once newer version of d3dcommon.h can be compiled against
 #define ADD_16_64_BIT_TYPES
+#define ADD_SVC_BIT_FIELD
 
 namespace hlsl {
 namespace dump {
@@ -198,6 +199,15 @@ LPCSTR ToString(D3D_TESSELLATOR_DOMAIN TessellatorDomain) {
   default: return nullptr;
   }
 }
+
+#ifdef ADD_SVC_BIT_FIELD
+// Disable warning about value not being valid in enum
+#pragma warning(disable : 4063)
+// FIXME: remove the define once D3D_SVC_BIT_FIELD added into
+// D3D_SHADER_VARIABLE_CLASS.
+#define D3D_SVC_BIT_FIELD ((D3D_SHADER_VARIABLE_CLASS)(D3D_SVC_INTERFACE_POINTER + 1))
+#endif
+
 LPCSTR ToString(D3D_SHADER_VARIABLE_CLASS Class) {
   switch (Class) {
   case D3D_SVC_SCALAR: return "D3D_SVC_SCALAR";
@@ -208,6 +218,7 @@ LPCSTR ToString(D3D_SHADER_VARIABLE_CLASS Class) {
   case D3D_SVC_STRUCT: return "D3D_SVC_STRUCT";
   case D3D_SVC_INTERFACE_CLASS: return "D3D_SVC_INTERFACE_CLASS";
   case D3D_SVC_INTERFACE_POINTER: return "D3D_SVC_INTERFACE_POINTER";
+  case D3D_SVC_BIT_FIELD: return "D3D_SVC_BIT_FIELD";
   default: return nullptr;
   }
 }