Browse Source

Merge pull request #2416 from tex3d/sep-reflect

Merge separate refleciton and validator 1.4 compatibility fixes
Tex Riddell 6 years ago
parent
commit
114080aaec
68 changed files with 1587 additions and 492 deletions
  1. 0 1
      docs/DXIL.rst
  2. 12 0
      include/dxc/DXIL/DxilConstants.h
  3. 8 0
      include/dxc/DXIL/DxilMetadataHelper.h
  4. 1 1
      include/dxc/DXIL/DxilModule.h
  5. 1 0
      include/dxc/DXIL/DxilOperations.h
  6. 6 0
      include/dxc/DXIL/DxilSignatureElement.h
  7. 4 0
      include/dxc/DXIL/DxilTypeSystem.h
  8. 6 5
      include/dxc/DxilContainer/DxilContainer.h
  9. 2 1
      include/dxc/DxilContainer/DxilContainerAssembler.h
  10. 0 2
      include/dxc/DxilContainer/DxilRuntimeReflection.h
  11. 1 63
      include/dxc/DxilContainer/DxilRuntimeReflection.inl
  12. 1 0
      include/dxc/HLSL/DxilLinker.h
  13. 0 1
      include/dxc/HLSL/DxilValidation.h
  14. 3 0
      include/dxc/Support/HLSLOptions.h
  15. 17 7
      include/dxc/Support/HLSLOptions.td
  16. 1 1
      lib/Analysis/IPA/CallGraph.cpp
  17. 47 13
      lib/DXIL/DxilMetadataHelper.cpp
  18. 82 16
      lib/DXIL/DxilModule.cpp
  19. 9 0
      lib/DXIL/DxilOperations.cpp
  20. 22 0
      lib/DXIL/DxilShaderFlags.cpp
  21. 11 1
      lib/DXIL/DxilSignatureElement.cpp
  22. 6 2
      lib/DXIL/DxilTypeSystem.cpp
  23. 50 0
      lib/DxcSupport/HLSLOptions.cpp
  24. 147 31
      lib/DxilContainer/DxilContainerAssembler.cpp
  25. 154 1
      lib/HLSL/DxilCondenseResources.cpp
  26. 212 132
      lib/HLSL/DxilContainerReflection.cpp
  27. 112 3
      lib/HLSL/DxilPreparePasses.cpp
  28. 4 9
      lib/HLSL/DxilValidation.cpp
  29. 2 8
      lib/Transforms/IPO/GlobalDCE.cpp
  30. 16 9
      tools/clang/lib/CodeGen/CGHLSLMS.cpp
  31. 3 4
      tools/clang/test/CodeGenHLSL/batch/compiler_options/Qstrip_reflect.hlsl
  32. 3 4
      tools/clang/test/CodeGenHLSL/batch/compiler_options/Qstrip_reflect_struct_buf.hlsl
  33. 1 1
      tools/clang/test/CodeGenHLSL/batch/compiler_options/pack_clip_cull/optimized2.hlsl
  34. 1 1
      tools/clang/test/CodeGenHLSL/batch/compiler_options/pack_clip_cull/optimized3.hlsl
  35. 1 1
      tools/clang/test/CodeGenHLSL/batch/compiler_options/pack_clip_cull/prefix_stable2.hlsl
  36. 1 1
      tools/clang/test/CodeGenHLSL/batch/compiler_options/pack_clip_cull/prefix_stable3.hlsl
  37. 2 2
      tools/clang/test/CodeGenHLSL/batch/debug/locals/scalarized_vector.hlsl
  38. 2 2
      tools/clang/test/CodeGenHLSL/batch/debug/misc/share_mem_dbg.hlsl
  39. 2 2
      tools/clang/test/CodeGenHLSL/batch/debug/types/struct_resource_numerical.hlsl
  40. 1 1
      tools/clang/test/CodeGenHLSL/batch/declarations/resources/constant_buffers/array1.hlsl
  41. 1 1
      tools/clang/test/CodeGenHLSL/batch/misc/d3dreflect/cb_sizes.hlsl
  42. 1 1
      tools/clang/test/CodeGenHLSL/batch/misc/d3dreflect/cbuf-usage-lib.hlsl
  43. 1 1
      tools/clang/test/CodeGenHLSL/batch/misc/d3dreflect/empty_struct2.hlsl
  44. 125 0
      tools/clang/test/CodeGenHLSL/batch/misc/d3dreflect/lib_global.hlsl
  45. 1 1
      tools/clang/test/CodeGenHLSL/batch/misc/d3dreflect/reflect-lib-1.hlsl
  46. 1 1
      tools/clang/test/CodeGenHLSL/batch/misc/d3dreflect/structured_buffer_layout.hlsl
  47. 1 1
      tools/clang/test/CodeGenHLSL/batch/misc/sig-bool-as-uint.hlsl
  48. 1 1
      tools/clang/test/CodeGenHLSL/batch/misc/static_const_global.hlsl
  49. 1 1
      tools/clang/test/CodeGenHLSL/batch/shader_stages/raytracing/subobjects_raytracingPipelineConfig1.hlsl
  50. 1 1
      tools/clang/test/CodeGenHLSL/batch/validation/rawbufferstore_uav.hlsl
  51. 4 1
      tools/clang/test/CodeGenHLSL/lib_global.hlsl
  52. 1 1
      tools/clang/tools/dxcompiler/dxcassembler.cpp
  53. 33 3
      tools/clang/tools/dxcompiler/dxcdisassembler.cpp
  54. 8 0
      tools/clang/tools/dxcompiler/dxclinker.cpp
  55. 20 11
      tools/clang/tools/dxcompiler/dxcompilerobj.cpp
  56. 2 1
      tools/clang/tools/dxcompiler/dxcontainerbuilder.cpp
  57. 19 0
      tools/clang/tools/dxcompiler/dxcutil.cpp
  58. 1 0
      tools/clang/unittests/HLSL/CMakeLists.txt
  59. 9 1
      tools/clang/unittests/HLSL/CompilerTest.cpp
  60. 30 0
      tools/clang/unittests/HLSL/DxcTestUtils.cpp
  61. 4 0
      tools/clang/unittests/HLSL/DxcTestUtils.h
  62. 73 12
      tools/clang/unittests/HLSL/DxilContainerTest.cpp
  63. 92 1
      tools/clang/unittests/HLSL/DxilModuleTest.cpp
  64. 55 31
      tools/clang/unittests/HLSL/FileCheckerTest.cpp
  65. 30 4
      tools/clang/unittests/HLSL/LinkerTest.cpp
  66. 2 0
      tools/clang/unittests/HLSL/OptimizerTest.cpp
  67. 116 90
      tools/clang/unittests/HLSL/ValidationTest.cpp
  68. 0 1
      utils/hct/hctdb.py

+ 0 - 1
docs/DXIL.rst

@@ -3075,7 +3075,6 @@ META.DUPLICATESYSVALUE                    System value may only appear once in s
 META.ENTRYFUNCTION                        entrypoint not found
 META.ENTRYFUNCTION                        entrypoint not found
 META.FLAGSUSAGE                           Flags must match usage
 META.FLAGSUSAGE                           Flags must match usage
 META.FORCECASEONSWITCH                    Attribute forcecase only works for switch
 META.FORCECASEONSWITCH                    Attribute forcecase only works for switch
-META.FUNCTIONANNOTATION                   Cannot find function annotation for %0
 META.GLCNOTONAPPENDCONSUME                globallycoherent cannot be used with append/consume buffers
 META.GLCNOTONAPPENDCONSUME                globallycoherent cannot be used with append/consume buffers
 META.INTEGERINTERPMODE                    Interpolation mode on integer must be Constant
 META.INTEGERINTERPMODE                    Interpolation mode on integer must be Constant
 META.INTERPMODEINONEROW                   Interpolation mode must be identical for all elements packed into the same row.
 META.INTERPMODEINONEROW                   Interpolation mode must be identical for all elements packed into the same row.

+ 12 - 0
include/dxc/DXIL/DxilConstants.h

@@ -35,6 +35,17 @@ namespace DXIL {
   inline unsigned GetCurrentDxilVersion() { return MakeDxilVersion(kDxilMajor, kDxilMinor); }
   inline unsigned GetCurrentDxilVersion() { return MakeDxilVersion(kDxilMajor, kDxilMinor); }
   inline unsigned GetDxilVersionMajor(unsigned DxilVersion) { return (DxilVersion >> 8) & 0xFF; }
   inline unsigned GetDxilVersionMajor(unsigned DxilVersion) { return (DxilVersion >> 8) & 0xFF; }
   inline unsigned GetDxilVersionMinor(unsigned DxilVersion) { return DxilVersion & 0xFF; }
   inline unsigned GetDxilVersionMinor(unsigned DxilVersion) { return DxilVersion & 0xFF; }
+  // Return positive if v1 > v2, negative if v1 < v2, zero if equal
+  inline int CompareVersions(unsigned Major1, unsigned Minor1, unsigned Major2, unsigned Minor2) {
+    if (Major1 != Major2) {
+      // Special case for Major == 0 (latest/unbound)
+      if (Major1 == 0 || Major2 == 0) return Major1 > 0 ? -1 : 1;
+      return Major1 < Major2 ? -1 : 1;
+    }
+    if (Minor1 < Minor2) return -1;
+    if (Minor1 > Minor2) return 1;
+    return 0;
+  }
 
 
   // Shader flags.
   // Shader flags.
   const unsigned kDisableOptimizations          = 0x00000001; // D3D11_1_SB_GLOBAL_FLAG_SKIP_OPTIMIZATION
   const unsigned kDisableOptimizations          = 0x00000001; // D3D11_1_SB_GLOBAL_FLAG_SKIP_OPTIMIZATION
@@ -1340,6 +1351,7 @@ namespace DXIL {
     AllowLocalDependenciesOnExternalDefinitions = 0x1,
     AllowLocalDependenciesOnExternalDefinitions = 0x1,
     AllowExternalDependenciesOnLocalDefinitions = 0x2,
     AllowExternalDependenciesOnLocalDefinitions = 0x2,
     AllowStateObjectAdditions                   = 0x4,
     AllowStateObjectAdditions                   = 0x4,
+    ValidMask_1_4                               = 0x3,
     ValidMask                                   = 0x7,
     ValidMask                                   = 0x7,
   };
   };
 
 

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

@@ -128,6 +128,7 @@ public:
   static const unsigned kDxilSignatureElementOutputStreamTag    = 0;
   static const unsigned kDxilSignatureElementOutputStreamTag    = 0;
   static const unsigned kHLSignatureElementGlobalSymbolTag      = 1;
   static const unsigned kHLSignatureElementGlobalSymbolTag      = 1;
   static const unsigned kDxilSignatureElementDynIdxCompMaskTag  = 2;
   static const unsigned kDxilSignatureElementDynIdxCompMaskTag  = 2;
+  static const unsigned kDxilSignatureElementUsageCompMaskTag   = 3;
 
 
   // Resources.
   // Resources.
   static const char kDxilResourcesMDName[];
   static const char kDxilResourcesMDName[];
@@ -192,6 +193,7 @@ public:
   static const unsigned kDxilFieldAnnotationFieldNameTag          = 6;
   static const unsigned kDxilFieldAnnotationFieldNameTag          = 6;
   static const unsigned kDxilFieldAnnotationCompTypeTag           = 7;
   static const unsigned kDxilFieldAnnotationCompTypeTag           = 7;
   static const unsigned kDxilFieldAnnotationPreciseTag            = 8;
   static const unsigned kDxilFieldAnnotationPreciseTag            = 8;
+  static const unsigned kDxilFieldAnnotationCBUsedTag             = 9;
 
 
   // StructAnnotation extended property tags (DXIL 1.5+ only, appended)
   // StructAnnotation extended property tags (DXIL 1.5+ only, appended)
   static const unsigned kDxilTemplateArgumentsTag                 = 0;  // Name for name-value list of extended struct properties
   static const unsigned kDxilTemplateArgumentsTag                 = 0;  // Name for name-value list of extended struct properties
@@ -293,6 +295,10 @@ public:
   protected:
   protected:
     llvm::LLVMContext &m_Ctx;
     llvm::LLVMContext &m_Ctx;
     llvm::Module *m_pModule;
     llvm::Module *m_pModule;
+
+  public:
+    unsigned m_ValMajor, m_ValMinor;        // Reported validation version in DXIL
+    unsigned m_MinValMajor, m_MinValMinor;  // Minimum validation version dictated by shader model
   };
   };
 
 
 public:
 public:
@@ -484,6 +490,8 @@ private:
   llvm::Module *m_pModule;
   llvm::Module *m_pModule;
   const ShaderModel *m_pSM;
   const ShaderModel *m_pSM;
   std::unique_ptr<ExtraPropertyHelper> m_ExtraPropertyHelper;
   std::unique_ptr<ExtraPropertyHelper> m_ExtraPropertyHelper;
+  unsigned m_ValMajor, m_ValMinor;        // Reported validation version in DXIL
+  unsigned m_MinValMajor, m_MinValMinor;  // Minimum validation version dictated by shader model
 };
 };
 
 
 
 

+ 1 - 1
include/dxc/DXIL/DxilModule.h

@@ -189,7 +189,7 @@ public:
   void ResetOP(hlsl::OP *hlslOP);
   void ResetOP(hlsl::OP *hlslOP);
   void ResetEntryPropsMap(DxilEntryPropsMap &&PropMap);
   void ResetEntryPropsMap(DxilEntryPropsMap &&PropMap);
 
 
-  void StripReflection();
+  bool StripReflection();
   void StripDebugRelatedCode();
   void StripDebugRelatedCode();
   llvm::DebugInfoFinder &GetOrCreateDebugInfoFinder();
   llvm::DebugInfoFinder &GetOrCreateDebugInfoFinder();
 
 

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

@@ -109,6 +109,7 @@ public:
                                        unsigned &major, unsigned &minor,
                                        unsigned &major, unsigned &minor,
                                        unsigned &mask);
                                        unsigned &mask);
   static void GetMinShaderModelAndMask(const llvm::CallInst *CI, bool bWithTranslation,
   static void GetMinShaderModelAndMask(const llvm::CallInst *CI, bool bWithTranslation,
+                                       unsigned valMajor, unsigned valMinor,
                                        unsigned &major, unsigned &minor,
                                        unsigned &major, unsigned &minor,
                                        unsigned &mask);
                                        unsigned &mask);
 
 

+ 6 - 0
include/dxc/DXIL/DxilSignatureElement.h

@@ -89,6 +89,9 @@ public:
   unsigned GetDynIdxCompMask() const;
   unsigned GetDynIdxCompMask() const;
   void SetDynIdxCompMask(unsigned DynIdxCompMask);
   void SetDynIdxCompMask(unsigned DynIdxCompMask);
 
 
+  uint8_t GetUsageMask() const;
+  void SetUsageMask(unsigned UsageMask);
+
 protected:
 protected:
   DXIL::SigPointKind m_sigPointKind;
   DXIL::SigPointKind m_sigPointKind;
   const Semantic *m_pSemantic;
   const Semantic *m_pSemantic;
@@ -105,6 +108,9 @@ protected:
   int m_StartCol;
   int m_StartCol;
   unsigned m_OutputStream;
   unsigned m_OutputStream;
   unsigned m_DynIdxCompMask;
   unsigned m_DynIdxCompMask;
+  // UsageMask is meant to match the signature usage mask, used for validation:
+  // for output: may-write, for input: always-reads
+  unsigned m_UsageMask;
 };
 };
 
 
 } // namespace hlsl
 } // namespace hlsl

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

@@ -79,6 +79,9 @@ public:
   const std::string &GetFieldName() const;
   const std::string &GetFieldName() const;
   void SetFieldName(const std::string &FieldName);
   void SetFieldName(const std::string &FieldName);
 
 
+  bool IsCBVarUsed() const;
+  void SetCBVarUsed(bool used);
+
 private:
 private:
   bool m_bPrecise;
   bool m_bPrecise;
   CompType m_CompType;
   CompType m_CompType;
@@ -88,6 +91,7 @@ private:
   std::string m_Semantic;
   std::string m_Semantic;
   InterpolationMode m_InterpMode;
   InterpolationMode m_InterpMode;
   std::string m_FieldName;
   std::string m_FieldName;
+  bool m_bCBufferVarUsed; // true if this field represents a top level variable in CB structure, and it is used.
 };
 };
 
 
 class DxilTemplateArgAnnotation : DxilFieldAnnotation {
 class DxilTemplateArgAnnotation : DxilFieldAnnotation {

+ 6 - 5
include/dxc/DxilContainer/DxilContainer.h

@@ -404,11 +404,12 @@ inline bool GetDxilShaderDebugName(const DxilPartHeader *pDebugNamePart,
 }
 }
 
 
 enum class SerializeDxilFlags : uint32_t {
 enum class SerializeDxilFlags : uint32_t {
-  None = 0,                         // No flags defined.
-  IncludeDebugInfoPart = 1,         // Include the debug info part in the container.
-  IncludeDebugNamePart = 2,         // Include the debug name part in the container.
-  DebugNameDependOnSource = 4,      // Make the debug name depend on source (and not just final module).
-  StripReflectionFromDxilPart = 8,  // Strip Reflection info from DXIL part.
+  None                        = 0,      // No flags defined.
+  IncludeDebugInfoPart        = 1 << 0, // Include the debug info part in the container.
+  IncludeDebugNamePart        = 1 << 1, // Include the debug name part in the container.
+  DebugNameDependOnSource     = 1 << 2, // Make the debug name depend on source (and not just final module).
+  StripReflectionFromDxilPart = 1 << 3, // Strip Reflection info from DXIL part.
+  IncludeReflectionPart       = 1 << 4, // Include reflection in STAT part.
 };
 };
 inline SerializeDxilFlags& operator |=(SerializeDxilFlags& l, const SerializeDxilFlags& r) {
 inline SerializeDxilFlags& operator |=(SerializeDxilFlags& l, const SerializeDxilFlags& r) {
   l = static_cast<SerializeDxilFlags>(static_cast<int>(l) | static_cast<int>(r));
   l = static_cast<SerializeDxilFlags>(static_cast<int>(l) | static_cast<int>(r));

+ 2 - 1
include/dxc/DxilContainer/DxilContainerAssembler.h

@@ -51,7 +51,8 @@ void SerializeDxilContainerForModule(hlsl::DxilModule *pModule,
                                      AbstractMemoryStream *pStream,
                                      AbstractMemoryStream *pStream,
                                      llvm::StringRef DebugName,
                                      llvm::StringRef DebugName,
                                      SerializeDxilFlags Flags,
                                      SerializeDxilFlags Flags,
-                                     DxilShaderHash *pShaderHashOut = nullptr);
+                                     DxilShaderHash *pShaderHashOut = nullptr,
+                                     AbstractMemoryStream *pReflectionStreamOut = nullptr);
 void SerializeDxilContainerForRootSignature(hlsl::RootSignatureHandle *pRootSigHandle,
 void SerializeDxilContainerForRootSignature(hlsl::RootSignatureHandle *pRootSigHandle,
                                      AbstractMemoryStream *pStream);
                                      AbstractMemoryStream *pStream);
 
 

+ 0 - 2
include/dxc/DxilContainer/DxilRuntimeReflection.h

@@ -601,8 +601,6 @@ public:
   DxilRuntimeData(const void *ptr, size_t size);
   DxilRuntimeData(const void *ptr, size_t size);
   // initializing reader from RDAT. return true if no error has occured.
   // initializing reader from RDAT. return true if no error has occured.
   bool InitFromRDAT(const void *pRDAT, size_t size);
   bool InitFromRDAT(const void *pRDAT, size_t size);
-  // read prerelease data:
-  bool InitFromRDAT_Prerelease(const void *pRDAT, size_t size);
   FunctionTableReader *GetFunctionTableReader();
   FunctionTableReader *GetFunctionTableReader();
   ResourceTableReader *GetResourceTableReader();
   ResourceTableReader *GetResourceTableReader();
   SubobjectTableReader *GetSubobjectTableReader();
   SubobjectTableReader *GetSubobjectTableReader();

+ 1 - 63
include/dxc/DxilContainer/DxilRuntimeReflection.inl

@@ -112,8 +112,7 @@ bool DxilRuntimeData::InitFromRDAT(const void *pRDAT, size_t size) {
       CheckedReader Reader(pRDAT, size);
       CheckedReader Reader(pRDAT, size);
       RuntimeDataHeader RDATHeader = Reader.Read<RuntimeDataHeader>();
       RuntimeDataHeader RDATHeader = Reader.Read<RuntimeDataHeader>();
       if (RDATHeader.Version < RDAT_Version_10) {
       if (RDATHeader.Version < RDAT_Version_10) {
-        // Prerelease version, fallback to that Init
-        return InitFromRDAT_Prerelease(pRDAT, size);
+        return false;
       }
       }
       const uint32_t *offsets = Reader.ReadArray<uint32_t>(RDATHeader.PartCount);
       const uint32_t *offsets = Reader.ReadArray<uint32_t>(RDATHeader.PartCount);
       for (uint32_t i = 0; i < RDATHeader.PartCount; ++i) {
       for (uint32_t i = 0; i < RDATHeader.PartCount; ++i) {
@@ -172,67 +171,6 @@ bool DxilRuntimeData::InitFromRDAT(const void *pRDAT, size_t size) {
   return false;
   return false;
 }
 }
 
 
-bool DxilRuntimeData::InitFromRDAT_Prerelease(const void *pRDAT, size_t size) {
-  enum class RuntimeDataPartType_Prerelease : uint32_t {
-    Invalid = 0,
-    String,
-    Function,
-    Resource,
-    Index
-  };
-  struct RuntimeDataTableHeader_Prerelease {
-    uint32_t tableType; // RuntimeDataPartType
-    uint32_t size;
-    uint32_t offset;
-  };
-  if (pRDAT) {
-    try {
-      CheckedReader Reader(pRDAT, size);
-      uint32_t partCount = Reader.Read<uint32_t>();
-      const RuntimeDataTableHeader_Prerelease *tableHeaders =
-        Reader.ReadArray<RuntimeDataTableHeader_Prerelease>(partCount);
-      for (uint32_t i = 0; i < partCount; ++i) {
-        uint32_t partSize = tableHeaders[i].size;
-        Reader.Advance(tableHeaders[i].offset);
-        CheckedReader PR(Reader.ReadArray<char>(partSize), partSize);
-        switch ((RuntimeDataPartType_Prerelease)(tableHeaders[i].tableType)) {
-        case RuntimeDataPartType_Prerelease::String: {
-          m_StringReader = StringTableReader(
-            PR.ReadArray<char>(partSize), partSize);
-          break;
-        }
-        case RuntimeDataPartType_Prerelease::Index: {
-          uint32_t count = partSize / sizeof(uint32_t);
-          m_IndexTableReader = IndexTableReader(
-            PR.ReadArray<uint32_t>(count), count);
-          break;
-        }
-        case RuntimeDataPartType_Prerelease::Resource: {
-          uint32_t count = partSize / sizeof(RuntimeDataResourceInfo);
-          m_ResourceTableReader.SetResourceInfo(PR.ReadArray<char>(partSize),
-            count, sizeof(RuntimeDataResourceInfo));
-          break;
-        }
-        case RuntimeDataPartType_Prerelease::Function: {
-          uint32_t count = partSize / sizeof(RuntimeDataFunctionInfo);
-          m_FunctionTableReader.SetFunctionInfo(PR.ReadArray<char>(partSize),
-            count, sizeof(RuntimeDataFunctionInfo));
-          break;
-        }
-        default:
-          return false; // There should be no unrecognized parts
-        }
-      }
-      return true;
-    } catch(CheckedReader::exception e) {
-      // TODO: error handling
-      //throw hlsl::Exception(DXC_E_MALFORMED_CONTAINER, e.what());
-      return false;
-    }
-  }
-  return false;
-}
-
 FunctionTableReader *DxilRuntimeData::GetFunctionTableReader() {
 FunctionTableReader *DxilRuntimeData::GetFunctionTableReader() {
   return &m_FunctionTableReader;
   return &m_FunctionTableReader;
 }
 }

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

@@ -37,6 +37,7 @@ public:
   virtual ~DxilLinker() {}
   virtual ~DxilLinker() {}
   static DxilLinker *CreateLinker(llvm::LLVMContext &Ctx, unsigned valMajor, unsigned valMinor);
   static DxilLinker *CreateLinker(llvm::LLVMContext &Ctx, unsigned valMajor, unsigned valMinor);
 
 
+  void SetValidatorVersion(unsigned valMajor, unsigned valMinor) { m_valMajor = valMajor, m_valMinor = valMinor; }
   virtual bool HasLibNameRegistered(llvm::StringRef name) = 0;
   virtual bool HasLibNameRegistered(llvm::StringRef name) = 0;
   virtual bool RegisterLib(llvm::StringRef name,
   virtual bool RegisterLib(llvm::StringRef name,
                            std::unique_ptr<llvm::Module> pModule,
                            std::unique_ptr<llvm::Module> pModule,

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

@@ -152,7 +152,6 @@ enum class ValidationRule : unsigned {
   MetaEntryFunction, // entrypoint not found
   MetaEntryFunction, // entrypoint not found
   MetaFlagsUsage, // Flags must match usage
   MetaFlagsUsage, // Flags must match usage
   MetaForceCaseOnSwitch, // Attribute forcecase only works for switch
   MetaForceCaseOnSwitch, // Attribute forcecase only works for switch
-  MetaFunctionAnnotation, // Cannot find function annotation for %0
   MetaGlcNotOnAppendConsume, // globallycoherent cannot be used with append/consume buffers
   MetaGlcNotOnAppendConsume, // globallycoherent cannot be used with append/consume buffers
   MetaIntegerInterpMode, // Interpolation mode on integer must be Constant
   MetaIntegerInterpMode, // Interpolation mode on integer must be Constant
   MetaInterpModeInOneRow, // Interpolation mode must be identical for all elements packed into the same row.
   MetaInterpModeInOneRow, // Interpolation mode must be identical for all elements packed into the same row.

+ 3 - 0
include/dxc/Support/HLSLOptions.h

@@ -154,6 +154,8 @@ public:
   bool StripRootSignature = false; // OPT_Qstrip_rootsignature
   bool StripRootSignature = false; // OPT_Qstrip_rootsignature
   bool StripPrivate = false; // OPT_Qstrip_priv
   bool StripPrivate = false; // OPT_Qstrip_priv
   bool StripReflection = false; // OPT_Qstrip_reflect
   bool StripReflection = false; // OPT_Qstrip_reflect
+  bool KeepReflectionInDxil = false; // OPT_Qkeep_reflect_in_dxil
+  bool StripReflectionFromDxil = false; // OPT_Qstrip_reflect_from_dxil
   bool ExtractRootSignature = false; // OPT_extractrootsignature
   bool ExtractRootSignature = false; // OPT_extractrootsignature
   bool DisassembleColorCoded = false; // OPT_Cc
   bool DisassembleColorCoded = false; // OPT_Cc
   bool DisassembleInstNumbers = false; //OPT_Ni
   bool DisassembleInstNumbers = false; //OPT_Ni
@@ -164,6 +166,7 @@ public:
   unsigned long AutoBindingSpace = UINT_MAX; // OPT_auto_binding_space
   unsigned long AutoBindingSpace = UINT_MAX; // OPT_auto_binding_space
   bool ExportShadersOnly = false; // OPT_export_shaders_only
   bool ExportShadersOnly = false; // OPT_export_shaders_only
   bool ResMayAlias = false; // OPT_res_may_alias
   bool ResMayAlias = false; // OPT_res_may_alias
+  unsigned long ValVerMajor = UINT_MAX, ValVerMinor = UINT_MAX; // OPT_validator_version
 
 
   bool IsRootSignatureProfile();
   bool IsRootSignatureProfile();
   bool IsLibraryProfile();
   bool IsLibraryProfile();

+ 17 - 7
include/dxc/Support/HLSLOptions.td

@@ -242,6 +242,8 @@ def export_shaders_only : Flag<["-", "/"], "export-shaders-only">, Group<hlslcom
   HelpText<"Only export shaders when compiling a library">;
   HelpText<"Only export shaders when compiling a library">;
 def default_linkage : Separate<["-", "/"], "default-linkage">, Group<hlslcomp_Group>, Flags<[CoreOption]>,
 def default_linkage : Separate<["-", "/"], "default-linkage">, Group<hlslcomp_Group>, Flags<[CoreOption]>,
   HelpText<"Set default linkage for non-shader functions when compiling or linking to a library target (internal, external)">;
   HelpText<"Set default linkage for non-shader functions when compiling or linking to a library target (internal, external)">;
+def validator_version : Separate<["-", "/"], "validator-version">, Group<hlslcomp_Group>, Flags<[CoreOption, HelpHidden]>,
+  HelpText<"Override validator version for module.  Format: <major.minor> ; Default: DXIL.dll version or current internal version.">;
 
 
 // SPIRV Change Starts
 // SPIRV Change Starts
 def spirv : Flag<["-"], "spirv">, Group<spirv_Group>, Flags<[CoreOption, DriverOption]>,
 def spirv : Flag<["-"], "spirv">, Group<spirv_Group>, Flags<[CoreOption, DriverOption]>,
@@ -328,12 +330,12 @@ def Gis : Flag<["-", "/"], "Gis">, HelpText<"Force IEEE strictness">, Flags<[Cor
 
 
 def denorm : JoinedOrSeparate<["-", "/"], "denorm">, HelpText<"select denormal value options (any, preserve, ftz). any is the default.">, Flags<[CoreOption]>, Group<hlslcomp_Group>;
 def denorm : JoinedOrSeparate<["-", "/"], "denorm">, HelpText<"select denormal value options (any, preserve, ftz). any is the default.">, Flags<[CoreOption]>, Group<hlslcomp_Group>;
 
 
-def Fo : JoinedOrSeparate<["-", "/"], "Fo">, MetaVarName<"<file>">, HelpText<"Output object file">, Flags<[DriverOption]>, Group<hlslcomp_Group>;
+def Fo : JoinedOrSeparate<["-", "/"], "Fo">, MetaVarName<"<file>">, HelpText<"Output object file">, Flags<[CoreOption, DriverOption]>, Group<hlslcomp_Group>;
 // def Fl : JoinedOrSeparate<["-", "/"], "Fl">, MetaVarName<"<file>">, HelpText<"Output a library">;
 // def Fl : JoinedOrSeparate<["-", "/"], "Fl">, MetaVarName<"<file>">, HelpText<"Output a library">;
 def Fc : JoinedOrSeparate<["-", "/"], "Fc">, MetaVarName<"<file>">, HelpText<"Output assembly code listing file">, Flags<[DriverOption]>, Group<hlslcomp_Group>;
 def Fc : JoinedOrSeparate<["-", "/"], "Fc">, MetaVarName<"<file>">, HelpText<"Output assembly code listing file">, Flags<[DriverOption]>, Group<hlslcomp_Group>;
 //def Fx : JoinedOrSeparate<["-", "/"], "Fx">, MetaVarName<"<file>">, HelpText<"Output assembly code and hex listing file">;
 //def Fx : JoinedOrSeparate<["-", "/"], "Fx">, MetaVarName<"<file>">, HelpText<"Output assembly code and hex listing file">;
 def Fh : JoinedOrSeparate<["-", "/"], "Fh">, MetaVarName<"<file>">, HelpText<"Output header file containing object code">, Flags<[DriverOption]>, Group<hlslcomp_Group>;
 def Fh : JoinedOrSeparate<["-", "/"], "Fh">, MetaVarName<"<file>">, HelpText<"Output header file containing object code">, Flags<[DriverOption]>, Group<hlslcomp_Group>;
-def Fe : JoinedOrSeparate<["-", "/"], "Fe">, MetaVarName<"<file>">, HelpText<"Output warnings and errors to the given file">, Flags<[DriverOption]>, Group<hlslcomp_Group>;
+def Fe : JoinedOrSeparate<["-", "/"], "Fe">, MetaVarName<"<file>">, HelpText<"Output warnings and errors to the given file">, Flags<[CoreOption, DriverOption]>, Group<hlslcomp_Group>;
 def Fd : JoinedOrSeparate<["-", "/"], "Fd">, MetaVarName<"<file>">,
 def Fd : JoinedOrSeparate<["-", "/"], "Fd">, MetaVarName<"<file>">,
   HelpText<"Write debug information to the given file, or automatically named file in directory when ending in '\\'">,
   HelpText<"Write debug information to the given file, or automatically named file in directory when ending in '\\'">,
   Flags<[CoreOption, DriverOption]>, Group<hlslcomp_Group>;
   Flags<[CoreOption, DriverOption]>, Group<hlslcomp_Group>;
@@ -344,28 +346,36 @@ def No : Flag<["-", "/"], "No">, HelpText<"Output instruction byte offsets in as
 def Lx : Flag<["-", "/"], "Lx">, HelpText<"Output hexadecimal literals">, Group<hlslcomp_Group>, Flags<[DriverOption]>;
 def Lx : Flag<["-", "/"], "Lx">, HelpText<"Output hexadecimal literals">, Group<hlslcomp_Group>, Flags<[DriverOption]>;
 
 
 // In place of 'E' for clang; fxc uses 'E' for entry point.
 // In place of 'E' for clang; fxc uses 'E' for entry point.
-def P : Separate<["-", "/"], "P">, Flags<[DriverOption]>, Group<hlslutil_Group>,
+def P : Separate<["-", "/"], "P">, Flags<[CoreOption, DriverOption]>, Group<hlslutil_Group>,
   HelpText<"Preprocess to file (must be used alone)">;
   HelpText<"Preprocess to file (must be used alone)">;
 
 
 // @<file> - options response file
 // @<file> - options response file
 
 
 def dumpbin : Flag<["-", "/"], "dumpbin">, Flags<[DriverOption]>, Group<hlslutil_Group>,
 def dumpbin : Flag<["-", "/"], "dumpbin">, Flags<[DriverOption]>, Group<hlslutil_Group>,
   HelpText<"Load a binary file rather than compiling">;
   HelpText<"Load a binary file rather than compiling">;
-def Qstrip_reflect : Flag<["-", "/"], "Qstrip_reflect">, Flags<[CoreOption]>, Group<hlslutil_Group>,
+def Qstrip_reflect : Flag<["-", "/"], "Qstrip_reflect">, Flags<[CoreOption, DriverOption]>, Group<hlslutil_Group>,
   HelpText<"Strip reflection data from shader bytecode  (must be used with /Fo <file>)">;
   HelpText<"Strip reflection data from shader bytecode  (must be used with /Fo <file>)">;
-def Qstrip_debug : Flag<["-", "/"], "Qstrip_debug">, Flags<[CoreOption]>, Group<hlslutil_Group>,
+def Qstrip_debug : Flag<["-", "/"], "Qstrip_debug">, Flags<[CoreOption, DriverOption]>, Group<hlslutil_Group>,
   HelpText<"Strip debug information from 4_0+ shader bytecode  (must be used with /Fo <file>)">;
   HelpText<"Strip debug information from 4_0+ shader bytecode  (must be used with /Fo <file>)">;
 def Qembed_debug : Flag<["-", "/"], "Qembed_debug">, Flags<[CoreOption]>, Group<hlslutil_Group>,
 def Qembed_debug : Flag<["-", "/"], "Qembed_debug">, Flags<[CoreOption]>, Group<hlslutil_Group>,
   HelpText<"Embed PDB in shader container (must be used with /Zi)">;
   HelpText<"Embed PDB in shader container (must be used with /Zi)">;
 def Qstrip_priv : Flag<["-", "/"], "Qstrip_priv">, Flags<[DriverOption]>, Group<hlslutil_Group>,
 def Qstrip_priv : Flag<["-", "/"], "Qstrip_priv">, Flags<[DriverOption]>, Group<hlslutil_Group>,
   HelpText<"Strip private data from shader bytecode  (must be used with /Fo <file>)">;
   HelpText<"Strip private data from shader bytecode  (must be used with /Fo <file>)">;
 
 
-def Qstrip_rootsignature : Flag<["-", "/"], "Qstrip_rootsignature">, Flags<[DriverOption]>, Group<hlslutil_Group>, HelpText<"Strip root signature data from shader bytecode  (must be used with /Fo <file>)">;
-def setrootsignature     : JoinedOrSeparate<["-", "/"], "setrootsignature">,     MetaVarName<"<file>">, Flags<[DriverOption]>, Group<hlslutil_Group>, HelpText<"Attach root signature to shader bytecode">;
+def Qstrip_rootsignature : Flag<["-", "/"], "Qstrip_rootsignature">, Flags<[CoreOption, DriverOption]>, Group<hlslutil_Group>, HelpText<"Strip root signature data from shader bytecode  (must be used with /Fo <file>)">;
+def setrootsignature     : JoinedOrSeparate<["-", "/"], "setrootsignature">,     MetaVarName<"<file>">, Flags<[CoreOption, DriverOption]>, Group<hlslutil_Group>, HelpText<"Attach root signature to shader bytecode">;
 def extractrootsignature : Flag<["-", "/"], "extractrootsignature">, Flags<[DriverOption]>, Group<hlslutil_Group>, HelpText<"Extract root signature from shader bytecode (must be used with /Fo <file>)">;
 def extractrootsignature : Flag<["-", "/"], "extractrootsignature">, Flags<[DriverOption]>, Group<hlslutil_Group>, HelpText<"Extract root signature from shader bytecode (must be used with /Fo <file>)">;
 def verifyrootsignature  : JoinedOrSeparate<["-", "/"], "verifyrootsignature">,  MetaVarName<"<file>">, Flags<[DriverOption]>, Group<hlslutil_Group>, HelpText<"Verify shader bytecode with root signature">;
 def verifyrootsignature  : JoinedOrSeparate<["-", "/"], "verifyrootsignature">,  MetaVarName<"<file>">, Flags<[DriverOption]>, Group<hlslutil_Group>, HelpText<"Verify shader bytecode with root signature">;
 def force_rootsig_ver    : JoinedOrSeparate<["-", "/"], "force_rootsig_ver">,    Flags<[CoreOption]>, MetaVarName<"<profile>">, Group<hlslcomp_Group>, HelpText<"force root signature version (rootsig_1_1 if omitted)">;
 def force_rootsig_ver    : JoinedOrSeparate<["-", "/"], "force_rootsig_ver">,    Flags<[CoreOption]>, MetaVarName<"<profile>">, Group<hlslcomp_Group>, HelpText<"force root signature version (rootsig_1_1 if omitted)">;
 
 
+// Temporary TEST options, until reflection inside DXIL part can always be stripped
+def Qkeep_reflect_in_dxil : Flag<["-", "/"], "Qkeep_reflect_in_dxil">,
+  Flags<[CoreOption, HelpHidden]>, Group<hlslutil_Group>,
+  HelpText<"Keep reflection data in shader bytecode">;
+def Qstrip_reflect_from_dxil : Flag<["-", "/"], "Qstrip_reflect_from_dxil">,
+  Flags<[CoreOption, HelpHidden]>, Group<hlslutil_Group>,
+  HelpText<"Strip reflection data from shader bytecode  (must be used with /Fo <file>)">;
+
 /*
 /*
 def shtemplate : JoinedOrSeparate<["-", "/"], "shtemplate">, MetaVarName<"<file>">, Group<hlslcomp_Group>,
 def shtemplate : JoinedOrSeparate<["-", "/"], "shtemplate">, MetaVarName<"<file>">, Group<hlslcomp_Group>,
   HelpText<"Template shader file for merging/matching resources">;
   HelpText<"Template shader file for merging/matching resources">;

+ 1 - 1
lib/Analysis/IPA/CallGraph.cpp

@@ -159,7 +159,7 @@ Function *CallGraph::removeFunctionFromModule(CallGraphNode *CGN) {
   delete CGN;                       // Delete the call graph node for this func
   delete CGN;                       // Delete the call graph node for this func
   FunctionMap.erase(F);             // Remove the call graph node from the map
   FunctionMap.erase(F);             // Remove the call graph node from the map
 
 
-  if (M.HasHLModule()) M.GetHLModule().RemoveFunction(F); // HLSL Change
+  M.CallRemoveGlobalHook(F); // HLSL Change
 
 
   M.getFunctionList().remove(F);
   M.getFunctionList().remove(F);
   return F;
   return F;

+ 47 - 13
lib/DXIL/DxilMetadataHelper.cpp

@@ -77,7 +77,12 @@ DxilMDHelper::DxilMDHelper(Module *pModule, std::unique_ptr<ExtraPropertyHelper>
 : m_Ctx(pModule->getContext())
 : m_Ctx(pModule->getContext())
 , m_pModule(pModule)
 , m_pModule(pModule)
 , m_pSM(nullptr)
 , m_pSM(nullptr)
-, m_ExtraPropertyHelper(std::move(EPH)) {
+, m_ExtraPropertyHelper(std::move(EPH))
+, m_ValMajor(1)
+, m_ValMinor(0)
+, m_MinValMajor(1)
+, m_MinValMinor(0)
+{
 }
 }
 
 
 DxilMDHelper::~DxilMDHelper() {
 DxilMDHelper::~DxilMDHelper() {
@@ -85,6 +90,17 @@ DxilMDHelper::~DxilMDHelper() {
 
 
 void DxilMDHelper::SetShaderModel(const ShaderModel *pSM) {
 void DxilMDHelper::SetShaderModel(const ShaderModel *pSM) {
   m_pSM = pSM;
   m_pSM = pSM;
+  m_pSM->GetMinValidatorVersion(m_MinValMajor, m_MinValMinor);
+  if (DXIL::CompareVersions(m_ValMajor, m_ValMinor, m_MinValMajor, m_MinValMinor) < 0) {
+    m_ValMajor = m_MinValMajor;
+    m_ValMinor = m_MinValMinor;
+  }
+  if (m_ExtraPropertyHelper) {
+    m_ExtraPropertyHelper->m_ValMajor = m_ValMajor;
+    m_ExtraPropertyHelper->m_ValMinor = m_ValMinor;
+    m_ExtraPropertyHelper->m_MinValMajor = m_MinValMajor;
+    m_ExtraPropertyHelper->m_MinValMinor = m_MinValMinor;
+  }
 }
 }
 
 
 const ShaderModel *DxilMDHelper::GetShaderModel() const {
 const ShaderModel *DxilMDHelper::GetShaderModel() const {
@@ -135,6 +151,8 @@ void DxilMDHelper::EmitValidatorVersion(unsigned Major, unsigned Minor) {
   MDVals[kDxilVersionMinorIdx] = Uint32ToConstMD(Minor);
   MDVals[kDxilVersionMinorIdx] = Uint32ToConstMD(Minor);
 
 
   pDxilValidatorVersionMD->addOperand(MDNode::get(m_Ctx, MDVals));
   pDxilValidatorVersionMD->addOperand(MDNode::get(m_Ctx, MDVals));
+
+  m_ValMajor = Major; m_ValMinor = Minor; // Keep these for later use
 }
 }
 
 
 void DxilMDHelper::LoadValidatorVersion(unsigned &Major, unsigned &Minor) {
 void DxilMDHelper::LoadValidatorVersion(unsigned &Major, unsigned &Minor) {
@@ -144,6 +162,7 @@ void DxilMDHelper::LoadValidatorVersion(unsigned &Major, unsigned &Minor) {
     // If no validator version metadata, assume 1.0
     // If no validator version metadata, assume 1.0
     Major = 1;
     Major = 1;
     Minor = 0;
     Minor = 0;
+    m_ValMajor = Major; m_ValMinor = Minor; // Keep these for later use
     return;
     return;
   }
   }
 
 
@@ -154,6 +173,7 @@ void DxilMDHelper::LoadValidatorVersion(unsigned &Major, unsigned &Minor) {
 
 
   Major = ConstMDToUint32(pVersionMD->getOperand(kDxilVersionMajorIdx));
   Major = ConstMDToUint32(pVersionMD->getOperand(kDxilVersionMajorIdx));
   Minor = ConstMDToUint32(pVersionMD->getOperand(kDxilVersionMinorIdx));
   Minor = ConstMDToUint32(pVersionMD->getOperand(kDxilVersionMinorIdx));
+  m_ValMajor = Major; m_ValMinor = Minor; // Keep these for later use
 }
 }
 
 
 //
 //
@@ -170,6 +190,8 @@ void DxilMDHelper::EmitDxilShaderModel(const ShaderModel *pSM) {
   MDVals[kDxilShaderModelMinorIdx] = Uint32ToConstMD(pSM->GetMinor());
   MDVals[kDxilShaderModelMinorIdx] = Uint32ToConstMD(pSM->GetMinor());
 
 
   pShaderModelNamedMD->addOperand(MDNode::get(m_Ctx, MDVals));
   pShaderModelNamedMD->addOperand(MDNode::get(m_Ctx, MDVals));
+
+  SetShaderModel(pSM);
 }
 }
 
 
 void DxilMDHelper::LoadDxilShaderModel(const ShaderModel *&pSM) {
 void DxilMDHelper::LoadDxilShaderModel(const ShaderModel *&pSM) {
@@ -792,11 +814,12 @@ void DxilMDHelper::LoadDxilTemplateArgAnnotation(const llvm::MDOperand &MDO, Dxi
   IFTBOOL(pTupleMD->getNumOperands() >= 1, DXC_E_INCORRECT_DXIL_METADATA);
   IFTBOOL(pTupleMD->getNumOperands() >= 1, DXC_E_INCORRECT_DXIL_METADATA);
   unsigned Tag = ConstMDToUint32(pTupleMD->getOperand(0));
   unsigned Tag = ConstMDToUint32(pTupleMD->getOperand(0));
   switch (Tag) {
   switch (Tag) {
-  case kDxilTemplateArgTypeTag:
+  case kDxilTemplateArgTypeTag: {
     IFTBOOL(pTupleMD->getNumOperands() == 2, DXC_E_INCORRECT_DXIL_METADATA);
     IFTBOOL(pTupleMD->getNumOperands() == 2, DXC_E_INCORRECT_DXIL_METADATA);
-    annotation.SetType(MetadataAsValue::get(m_Ctx,
-      pTupleMD->getOperand(kDxilTemplateArgValue))->getType());
-    break;
+    Constant *C = dyn_cast<Constant>(ValueMDToValue(pTupleMD->getOperand(kDxilTemplateArgValue)));
+    IFTBOOL(C != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
+    annotation.SetType(C->getType());
+  } break;
   case kDxilTemplateArgIntegralTag:
   case kDxilTemplateArgIntegralTag:
     IFTBOOL(pTupleMD->getNumOperands() == 2, DXC_E_INCORRECT_DXIL_METADATA);
     IFTBOOL(pTupleMD->getNumOperands() == 2, DXC_E_INCORRECT_DXIL_METADATA);
     annotation.SetIntegral((int64_t)ConstMDToUint64(pTupleMD->getOperand(kDxilTemplateArgValue)));
     annotation.SetIntegral((int64_t)ConstMDToUint64(pTupleMD->getOperand(kDxilTemplateArgValue)));
@@ -805,10 +828,7 @@ void DxilMDHelper::LoadDxilTemplateArgAnnotation(const llvm::MDOperand &MDO, Dxi
 }
 }
 
 
 Metadata *DxilMDHelper::EmitDxilStructAnnotation(const DxilStructAnnotation &SA) {
 Metadata *DxilMDHelper::EmitDxilStructAnnotation(const DxilStructAnnotation &SA) {
-  unsigned valMajor = 0, valMinor = 0;
-  if (m_pSM)
-    m_pSM->GetMinValidatorVersion(valMajor, valMinor);
-  bool bSupportExtended = !(valMajor == 1 && valMinor < 5);
+  bool bSupportExtended = DXIL::CompareVersions(m_ValMajor, m_ValMinor, 1, 5) >= 0;
 
 
   vector<Metadata *> MDVals;
   vector<Metadata *> MDVals;
   MDVals.reserve(SA.GetNumFields() + 2);  // In case of extended 1.5 property list
   MDVals.reserve(SA.GetNumFields() + 2);  // In case of extended 1.5 property list
@@ -841,10 +861,7 @@ void DxilMDHelper::LoadDxilStructAnnotation(const MDOperand &MDO, DxilStructAnno
   if (pTupleMD->getNumOperands() == 1) {
   if (pTupleMD->getNumOperands() == 1) {
     SA.MarkEmptyStruct();
     SA.MarkEmptyStruct();
   }
   }
-  unsigned valMajor = 0, valMinor = 0;
-  if (m_pSM)
-    m_pSM->GetMinValidatorVersion(valMajor, valMinor);
-  if (!(valMajor == 1 && valMinor < 5) &&
+  if (DXIL::CompareVersions(m_ValMajor, m_ValMinor, 1, 5) >= 0 &&
       (pTupleMD->getNumOperands() == SA.GetNumFields()+2)) {
       (pTupleMD->getNumOperands() == SA.GetNumFields()+2)) {
     // Load template args from extended operand
     // Load template args from extended operand
     const MDOperand &MDOExtra = pTupleMD->getOperand(SA.GetNumFields()+1);
     const MDOperand &MDOExtra = pTupleMD->getOperand(SA.GetNumFields()+1);
@@ -969,6 +986,11 @@ Metadata *DxilMDHelper::EmitDxilFieldAnnotation(const DxilFieldAnnotation &FA) {
     MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationCompTypeTag));
     MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationCompTypeTag));
     MDVals.emplace_back(Uint32ToConstMD((unsigned)FA.GetCompType().GetKind()));
     MDVals.emplace_back(Uint32ToConstMD((unsigned)FA.GetCompType().GetKind()));
   }
   }
+  if (FA.IsCBVarUsed() &&
+      DXIL::CompareVersions(m_ValMajor, m_ValMinor, 1, 5) >= 0) {
+    MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationCBUsedTag));
+    MDVals.emplace_back(BoolToConstMD(true));
+  }
 
 
   return MDNode::get(m_Ctx, MDVals);
   return MDNode::get(m_Ctx, MDVals);
 }
 }
@@ -1013,6 +1035,9 @@ void DxilMDHelper::LoadDxilFieldAnnotation(const MDOperand &MDO, DxilFieldAnnota
     case kDxilFieldAnnotationCompTypeTag:
     case kDxilFieldAnnotationCompTypeTag:
       FA.SetCompType((CompType::Kind)ConstMDToUint32(MDO));
       FA.SetCompType((CompType::Kind)ConstMDToUint32(MDO));
       break;
       break;
+    case kDxilFieldAnnotationCBUsedTag:
+      FA.SetCBVarUsed(ConstMDToBool(MDO));
+      break;
     default:
     default:
       // TODO:  I don't think we should be failing unrecognized extended tags.
       // TODO:  I don't think we should be failing unrecognized extended tags.
       //        Perhaps we can flag this case in the module and fail validation
       //        Perhaps we can flag this case in the module and fail validation
@@ -2158,6 +2183,12 @@ void DxilExtraPropertyHelper::EmitSignatureElementProperties(const DxilSignature
     MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilSignatureElementDynIdxCompMaskTag, m_Ctx));
     MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilSignatureElementDynIdxCompMaskTag, m_Ctx));
     MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(SE.GetDynIdxCompMask(), m_Ctx));
     MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(SE.GetDynIdxCompMask(), m_Ctx));
   }
   }
+
+  if (SE.GetUsageMask() != 0 &&
+      DXIL::CompareVersions(m_ValMajor, m_ValMinor, 1, 5) >= 0) {
+    MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilSignatureElementUsageCompMaskTag, m_Ctx));
+    MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(SE.GetUsageMask(), m_Ctx));
+  }
 }
 }
 
 
 void DxilExtraPropertyHelper::LoadSignatureElementProperties(const MDOperand &MDO, DxilSignatureElement &SE) {
 void DxilExtraPropertyHelper::LoadSignatureElementProperties(const MDOperand &MDO, DxilSignatureElement &SE) {
@@ -2182,6 +2213,9 @@ void DxilExtraPropertyHelper::LoadSignatureElementProperties(const MDOperand &MD
     case DxilMDHelper::kDxilSignatureElementDynIdxCompMaskTag:
     case DxilMDHelper::kDxilSignatureElementDynIdxCompMaskTag:
       SE.SetDynIdxCompMask(DxilMDHelper::ConstMDToUint32(MDO));
       SE.SetDynIdxCompMask(DxilMDHelper::ConstMDToUint32(MDO));
       break;
       break;
+    case DxilMDHelper::kDxilSignatureElementUsageCompMaskTag:
+      SE.SetUsageMask(DxilMDHelper::ConstMDToUint32(MDO));
+      break;
     default:
     default:
       DXASSERT(false, "Unknown signature element tag");
       DXASSERT(false, "Unknown signature element tag");
     }
     }

+ 82 - 16
lib/DXIL/DxilModule.cpp

@@ -197,7 +197,13 @@ bool DxilModule::GetMinValidatorVersion(unsigned &ValMajor, unsigned &ValMinor)
   if (!m_pSM)
   if (!m_pSM)
     return false;
     return false;
   m_pSM->GetMinValidatorVersion(ValMajor, ValMinor);
   m_pSM->GetMinValidatorVersion(ValMajor, ValMinor);
-  if (ValMajor == 1 && ValMinor == 0 &&
+  if (DXIL::CompareVersions(ValMajor, ValMinor, 1, 5) < 0 &&
+      m_ShaderFlags.GetRaytracingTier1_1())
+    ValMinor = 5;
+  else if (DXIL::CompareVersions(ValMajor, ValMinor, 1, 4) < 0 &&
+           GetSubobjects() && !GetSubobjects()->GetSubobjects().empty())
+    ValMinor = 4;
+  else if (DXIL::CompareVersions(ValMajor, ValMinor, 1, 1) < 0 &&
       (m_ShaderFlags.GetFeatureInfo() & hlsl::DXIL::ShaderFeatureInfo_ViewID))
       (m_ShaderFlags.GetFeatureInfo() & hlsl::DXIL::ShaderFeatureInfo_ViewID))
     ValMinor = 1;
     ValMinor = 1;
   return true;
   return true;
@@ -1531,52 +1537,112 @@ void DxilModule::ReEmitDxilResources() {
 }
 }
 
 
 template <typename TResource>
 template <typename TResource>
-static void
+static bool
 StripResourcesReflection(std::vector<std::unique_ptr<TResource>> &vec) {
 StripResourcesReflection(std::vector<std::unique_ptr<TResource>> &vec) {
+  bool bChanged = false;
   for (auto &p : vec) {
   for (auto &p : vec) {
     p->SetGlobalName("");
     p->SetGlobalName("");
     // Cannot remove global symbol which used by validation.
     // Cannot remove global symbol which used by validation.
+    bChanged = true;
   }
   }
+  return bChanged;
 }
 }
 
 
-void DxilModule::StripReflection() {
+static bool ResourceTypeRequiresTranslation(const StructType* Ty) {
+  if (Ty->getName().startswith("class.matrix."))
+    return true;
+  for (auto eTy : Ty->elements()) {
+    if (StructType *structTy = dyn_cast<StructType>(eTy)) {
+      if (ResourceTypeRequiresTranslation(structTy))
+        return true;
+    }
+    SequentialType *seqTy;
+    while (seqTy = dyn_cast<SequentialType>(eTy)) {
+      eTy = seqTy->getElementType();
+    }
+    if (eTy->getScalarSizeInBits() < 32) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool DxilModule::StripReflection() {
+  bool bChanged = false;
+  bool bIsLib = GetShaderModel()->IsLib();
+
   // Remove names.
   // Remove names.
   for (Function &F : m_pModule->functions()) {
   for (Function &F : m_pModule->functions()) {
     for (BasicBlock &BB : F) {
     for (BasicBlock &BB : F) {
-      if (BB.hasName())
+      if (BB.hasName()) {
         BB.setName("");
         BB.setName("");
+        bChanged = true;
+      }
       for (Instruction &I : BB) {
       for (Instruction &I : BB) {
-        if (I.hasName())
+        if (I.hasName()) {
           I.setName("");
           I.setName("");
+          bChanged = true;
+        }
       }
       }
     }
     }
   }
   }
-  // Remove struct annotation.
-  // FunctionAnnotation is used later, so keep it.
-  m_pTypeSystem->GetStructAnnotationMap().clear();
 
 
+  if (bIsLib && GetUseMinPrecision())
+  {
+    // We must preserve struct annotations for resources containing min-precision types,
+    // since they have not yet been converted for legacy layout.
+    SmallVector<const StructType*, 4> structsToRemove;
+    for (auto &item : m_pTypeSystem->GetStructAnnotationMap()) {
+      if (!ResourceTypeRequiresTranslation(item.first))
+        structsToRemove.emplace_back(item.first);
+    }
+    for (auto Ty : structsToRemove) {
+      m_pTypeSystem->GetStructAnnotationMap().erase(Ty);
+    }
+  } else {
+    // Remove struct annotations.
+    if (!m_pTypeSystem->GetStructAnnotationMap().empty()) {
+      m_pTypeSystem->GetStructAnnotationMap().clear();
+      bChanged = true;
+    }
+    if (DXIL::CompareVersions(m_ValMajor, m_ValMinor, 1, 5) >= 0) {
+      // Remove function annotations.
+      if (!m_pTypeSystem->GetFunctionAnnotationMap().empty()) {
+        m_pTypeSystem->GetFunctionAnnotationMap().clear();
+        bChanged = true;
+      }
+    }
+  }
 
 
   // Resource
   // Resource
-  if (!GetShaderModel()->IsLib()) {
-    StripResourcesReflection(m_CBuffers);
-    StripResourcesReflection(m_UAVs);
-    StripResourcesReflection(m_SRVs);
-    StripResourcesReflection(m_Samplers);
+  if (!bIsLib) {
+    bChanged |= StripResourcesReflection(m_CBuffers);
+    bChanged |= StripResourcesReflection(m_UAVs);
+    bChanged |= StripResourcesReflection(m_SRVs);
+    bChanged |= StripResourcesReflection(m_Samplers);
   }
   }
 
 
   // Unused global.
   // Unused global.
   SmallVector<GlobalVariable *,2> UnusedGlobals;
   SmallVector<GlobalVariable *,2> UnusedGlobals;
   for (GlobalVariable &GV : m_pModule->globals()) {
   for (GlobalVariable &GV : m_pModule->globals()) {
-    if (GV.use_empty())
-      UnusedGlobals.emplace_back(&GV);
+    if (GV.use_empty()) {
+      // Need to preserve this global, otherwise we drop constructors
+      // for static globals.
+      if (!bIsLib || GV.getName().compare("llvm.global_ctors") != 0)
+        UnusedGlobals.emplace_back(&GV);
+    }
   }
   }
+  bChanged |= !UnusedGlobals.empty();
 
 
   for (GlobalVariable *GV : UnusedGlobals) {
   for (GlobalVariable *GV : UnusedGlobals) {
     GV->eraseFromParent();
     GV->eraseFromParent();
   }
   }
 
 
   // ReEmit meta.
   // ReEmit meta.
-  ReEmitDxilResources();
+  if (bChanged)
+    ReEmitDxilResources();
+
+  return bChanged;
 }
 }
 
 
 void DxilModule::LoadDxilResources(const llvm::MDOperand &MDO) {
 void DxilModule::LoadDxilResources(const llvm::MDOperand &MDO) {

+ 9 - 0
lib/DXIL/DxilOperations.cpp

@@ -807,11 +807,20 @@ void OP::GetMinShaderModelAndMask(OpCode C, bool bWithTranslation,
 }
 }
 
 
 void OP::GetMinShaderModelAndMask(const llvm::CallInst *CI, bool bWithTranslation,
 void OP::GetMinShaderModelAndMask(const llvm::CallInst *CI, bool bWithTranslation,
+                                  unsigned valMajor, unsigned valMinor,
                                   unsigned &major, unsigned &minor,
                                   unsigned &major, unsigned &minor,
                                   unsigned &mask) {
                                   unsigned &mask) {
   OpCode opcode = OP::GetDxilOpFuncCallInst(CI);
   OpCode opcode = OP::GetDxilOpFuncCallInst(CI);
   GetMinShaderModelAndMask(opcode, bWithTranslation, major, minor, mask);
   GetMinShaderModelAndMask(opcode, bWithTranslation, major, minor, mask);
 
 
+  if (DXIL::CompareVersions(valMajor, valMinor, 1, 5) < 0) {
+    // validator 1.4 didn't exclude wave ops in mask
+    if (IsDxilOpWave(opcode))
+      mask = ((unsigned)1 << (unsigned)DXIL::ShaderKind::Invalid) - 1;
+    // validator 1.4 didn't have any additional rules applied:
+    return;
+  }
+
   // Additional rules are applied manually here.
   // Additional rules are applied manually here.
 
 
   // Barrier with mode != UAVFenceGlobal requires compute, amplification, or mesh
   // Barrier with mode != UAVFenceGlobal requires compute, amplification, or mesh

+ 22 - 0
lib/DXIL/DxilShaderFlags.cpp

@@ -459,6 +459,28 @@ ShaderFlags ShaderFlags::CollectShaderFlags(const Function *F,
     }
     }
   }
   }
 
 
+  if (!hasRaytracingTier1_1) {
+    if (const DxilSubobjects *pSubobjects = M->GetSubobjects()) {
+      for (const auto &it : pSubobjects->GetSubobjects()) {
+        switch (it.second->GetKind()) {
+        case DXIL::SubobjectKind::RaytracingPipelineConfig1:
+          hasRaytracingTier1_1 = true;
+          break;
+        case DXIL::SubobjectKind::StateObjectConfig: {
+          uint32_t Flags;
+          if (it.second->GetStateObjectConfig(Flags) &&
+              ((Flags & ~(unsigned)DXIL::StateObjectFlags::ValidMask_1_4) != 0))
+            hasRaytracingTier1_1 = true;
+        } break;
+        default:
+          break;
+        }
+        if (hasRaytracingTier1_1)
+          break;
+      }
+    }
+  }
+
   flag.SetEnableDoublePrecision(hasDouble);
   flag.SetEnableDoublePrecision(hasDouble);
   flag.SetStencilRef(hasStencilRef);
   flag.SetStencilRef(hasStencilRef);
   flag.SetInnerCoverage(hasInnerCoverage);
   flag.SetInnerCoverage(hasInnerCoverage);

+ 11 - 1
lib/DXIL/DxilSignatureElement.cpp

@@ -37,7 +37,8 @@ DxilSignatureElement::DxilSignatureElement(DXIL::SigPointKind sigPointKind)
 , m_Cols(0)
 , m_Cols(0)
 , m_StartRow(Semantic::kUndefinedRow)
 , m_StartRow(Semantic::kUndefinedRow)
 , m_StartCol(Semantic::kUndefinedCol)
 , m_StartCol(Semantic::kUndefinedCol)
-, m_DynIdxCompMask(0) {
+, m_DynIdxCompMask(0)
+, m_UsageMask(0) {
 }
 }
 
 
 DxilSignatureElement::~DxilSignatureElement() {
 DxilSignatureElement::~DxilSignatureElement() {
@@ -277,4 +278,13 @@ void DxilSignatureElement::SetDynIdxCompMask(unsigned DynIdxCompMask) {
   m_DynIdxCompMask = DynIdxCompMask;
   m_DynIdxCompMask = DynIdxCompMask;
 }
 }
 
 
+uint8_t DxilSignatureElement::GetUsageMask() const {
+  DXASSERT_NOMSG(m_UsageMask <= 0xF);
+  return (uint8_t)m_UsageMask;
+}
+void DxilSignatureElement::SetUsageMask(unsigned UsageMask) {
+  DXASSERT_NOMSG(UsageMask <= 0xF);
+  m_UsageMask = UsageMask;
+}
+
 } // namespace hlsl
 } // namespace hlsl

+ 6 - 2
lib/DXIL/DxilTypeSystem.cpp

@@ -43,8 +43,9 @@ DxilMatrixAnnotation::DxilMatrixAnnotation()
 DxilFieldAnnotation::DxilFieldAnnotation()
 DxilFieldAnnotation::DxilFieldAnnotation()
 : m_bPrecise(false)
 : m_bPrecise(false)
 , m_ResourceAttribute(nullptr)
 , m_ResourceAttribute(nullptr)
-, m_CBufferOffset(UINT_MAX) {
-}
+, m_CBufferOffset(UINT_MAX)
+, m_bCBufferVarUsed(false)
+{}
 
 
 bool DxilFieldAnnotation::IsPrecise() const { return m_bPrecise; }
 bool DxilFieldAnnotation::IsPrecise() const { return m_bPrecise; }
 void DxilFieldAnnotation::SetPrecise(bool b) { m_bPrecise = b; }
 void DxilFieldAnnotation::SetPrecise(bool b) { m_bPrecise = b; }
@@ -76,6 +77,9 @@ void DxilFieldAnnotation::SetInterpolationMode(const InterpolationMode &IM) { m_
 bool DxilFieldAnnotation::HasFieldName() const { return !m_FieldName.empty(); }
 bool DxilFieldAnnotation::HasFieldName() const { return !m_FieldName.empty(); }
 const std::string &DxilFieldAnnotation::GetFieldName() const { return m_FieldName; }
 const std::string &DxilFieldAnnotation::GetFieldName() const { return m_FieldName; }
 void DxilFieldAnnotation::SetFieldName(const std::string &FieldName) { m_FieldName = FieldName; }
 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; }
+
 
 
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------

+ 50 - 0
lib/DxcSupport/HLSLOptions.cpp

@@ -13,6 +13,7 @@
 #include "llvm/Option/Option.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Path.h"
+#include "llvm/ADT/APInt.h"
 #include "dxc/Support/Global.h"
 #include "dxc/Support/Global.h"
 #include "dxc/Support/WinIncludes.h"
 #include "dxc/Support/WinIncludes.h"
 #include "dxc/Support/HLSLOptions.h"
 #include "dxc/Support/HLSLOptions.h"
@@ -552,6 +553,8 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
   opts.StripRootSignature = Args.hasFlag(OPT_Qstrip_rootsignature, OPT_INVALID, false);
   opts.StripRootSignature = Args.hasFlag(OPT_Qstrip_rootsignature, OPT_INVALID, false);
   opts.StripPrivate = Args.hasFlag(OPT_Qstrip_priv, OPT_INVALID, false);
   opts.StripPrivate = Args.hasFlag(OPT_Qstrip_priv, OPT_INVALID, false);
   opts.StripReflection = Args.hasFlag(OPT_Qstrip_reflect, OPT_INVALID, false);
   opts.StripReflection = Args.hasFlag(OPT_Qstrip_reflect, OPT_INVALID, false);
+  opts.KeepReflectionInDxil = Args.hasFlag(OPT_Qkeep_reflect_in_dxil, OPT_INVALID, false);
+  opts.StripReflectionFromDxil = Args.hasFlag(OPT_Qstrip_reflect_from_dxil, OPT_INVALID, false);
   opts.ExtractRootSignature = Args.hasFlag(OPT_extractrootsignature, OPT_INVALID, false);
   opts.ExtractRootSignature = Args.hasFlag(OPT_extractrootsignature, OPT_INVALID, false);
   opts.DisassembleColorCoded = Args.hasFlag(OPT_Cc, OPT_INVALID, false);
   opts.DisassembleColorCoded = Args.hasFlag(OPT_Cc, OPT_INVALID, false);
   opts.DisassembleInstNumbers = Args.hasFlag(OPT_Ni, OPT_INVALID, false);
   opts.DisassembleInstNumbers = Args.hasFlag(OPT_Ni, OPT_INVALID, false);
@@ -642,11 +645,45 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
     return 1;
     return 1;
   }
   }
 
 
+  llvm::StringRef valVersionStr = Args.getLastArgValue(OPT_validator_version);
+  if (!valVersionStr.empty()) {
+    // Parse "major.minor" version string
+    auto verPair = valVersionStr.split(".");
+    llvm::APInt major, minor;
+    if (verPair.first.getAsInteger(0, major) || verPair.second.getAsInteger(0, minor)) {
+      errors << "Format of validator version is \"<major>.<minor>\" (ex: \"1.4\").";
+      return 1;
+    }
+    uint64_t major64 = major.getLimitedValue();
+    uint64_t minor64 = minor.getLimitedValue();
+    if (major64 > DXIL::kDxilMajor ||
+        (major64 == DXIL::kDxilMajor && minor64 > DXIL::kDxilMinor)) {
+      errors << "Validator version must be less than or equal to current internal version.";
+      return 1;
+    }
+    if (major64 == 0 && minor64 != 0) {
+      errors << "If validator major version is 0, minor version must also be 0.";
+      return 1;
+    }
+    opts.ValVerMajor = (unsigned long)major64;
+    opts.ValVerMinor = (unsigned long)minor64;
+  }
+
   if (opts.IsLibraryProfile() && Minor == 0xF) {
   if (opts.IsLibraryProfile() && Minor == 0xF) {
+    if (opts.ValVerMajor != UINT_MAX && opts.ValVerMajor != 0) {
+      errors << "Offline library profile cannot be used with non-zero -validator-version.";
+      return 1;
+    }
     // Disable validation for offline link only target
     // Disable validation for offline link only target
     opts.DisableValidation = true;
     opts.DisableValidation = true;
+
+    // ValVerMajor == 0 means that the module is not meant to ever be validated.
+    opts.ValVerMajor = 0;
+    opts.ValVerMinor = 0;
   }
   }
 
 
+  // These targets are only useful as an intermediate step towards linking to matching
+  // shader targets without going through target downgrading at link time.
   // Disable lib_6_1 and lib_6_2 if /Vd is not present
   // Disable lib_6_1 and lib_6_2 if /Vd is not present
   if (opts.IsLibraryProfile() && (Major < 6 || (Major == 6 && Minor < 3))) {
   if (opts.IsLibraryProfile() && (Major < 6 || (Major == 6 && Minor < 3))) {
     if (!opts.DisableValidation) {
     if (!opts.DisableValidation) {
@@ -654,6 +691,19 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
                 "targets.";
                 "targets.";
       return 1;
       return 1;
     }
     }
+    if (opts.ValVerMajor != UINT_MAX && opts.ValVerMajor != 0) {
+      errors << "non-zero -validator-version cannot be used with library profiles lib_6_1 or lib_6_2.";
+      return 1;
+    }
+
+    // ValVerMajor == 0 means that the module is not meant to ever be validated.
+    opts.ValVerMajor = 0;
+    opts.ValVerMinor = 0;
+  }
+
+  if (opts.KeepReflectionInDxil && opts.StripReflectionFromDxil) {
+    errors << "-Qstrip_reflect_from_dxil mutually exclusive with -Qkeep_reflect_in_dxil.";
+    return 1;
   }
   }
 
 
     // SPIRV Change Starts
     // SPIRV Change Starts

+ 147 - 31
lib/DxilContainer/DxilContainerAssembler.cpp

@@ -17,6 +17,7 @@
 #include "llvm/Bitcode/ReaderWriter.h"
 #include "llvm/Bitcode/ReaderWriter.h"
 #include "llvm/Support/MD5.h"
 #include "llvm/Support/MD5.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/Transforms/Utils/Cloning.h"
 #include "dxc/DxilContainer/DxilContainer.h"
 #include "dxc/DxilContainer/DxilContainer.h"
 #include "dxc/DXIL/DxilModule.h"
 #include "dxc/DXIL/DxilModule.h"
 #include "dxc/DXIL/DxilShaderModel.h"
 #include "dxc/DXIL/DxilShaderModel.h"
@@ -101,10 +102,15 @@ static DxilProgramSigSemantic KindToSystemValue(Semantic::Kind kind, DXIL::Tesse
   // TODO: Final_* values need mappings
   // TODO: Final_* values need mappings
 }
 }
 
 
-static DxilProgramSigCompType CompTypeToSigCompType(hlsl::CompType value) {
+static DxilProgramSigCompType CompTypeToSigCompType(hlsl::CompType value, bool i1ToUnknownCompat) {
   switch (value.GetKind()) {
   switch (value.GetKind()) {
   case CompType::Kind::I32: return DxilProgramSigCompType::SInt32;
   case CompType::Kind::I32: return DxilProgramSigCompType::SInt32;
-  case CompType::Kind::I1: __fallthrough;
+
+  case CompType::Kind::I1:
+    // Validator 1.4 and below returned Unknown for i1
+    if (i1ToUnknownCompat)  return DxilProgramSigCompType::Unknown;
+    else                    return DxilProgramSigCompType::UInt32;
+
   case CompType::Kind::U32: return DxilProgramSigCompType::UInt32;
   case CompType::Kind::U32: return DxilProgramSigCompType::UInt32;
   case CompType::Kind::F32: return DxilProgramSigCompType::Float32;
   case CompType::Kind::F32: return DxilProgramSigCompType::Float32;
   case CompType::Kind::I16: return DxilProgramSigCompType::SInt16;
   case CompType::Kind::I16: return DxilProgramSigCompType::SInt16;
@@ -154,6 +160,10 @@ struct sort_sig {
   }
   }
 };
 };
 
 
+static uint8_t NegMask(uint8_t V) {
+  V ^= 0xF;
+  return V & 0xF;
+}
 
 
 class DxilProgramSignatureWriter : public DxilPartWriter {
 class DxilProgramSignatureWriter : public DxilPartWriter {
 private:
 private:
@@ -161,6 +171,7 @@ private:
   DXIL::TessellatorDomain m_domain;
   DXIL::TessellatorDomain m_domain;
   bool   m_isInput;
   bool   m_isInput;
   bool   m_useMinPrecision;
   bool   m_useMinPrecision;
+  bool m_bCompat_1_4;
   size_t m_fixedSize;
   size_t m_fixedSize;
   typedef std::pair<const char *, uint32_t> NameOffsetPair;
   typedef std::pair<const char *, uint32_t> NameOffsetPair;
   typedef llvm::SmallMapVector<const char *, uint32_t, 8> NameOffsetMap;
   typedef llvm::SmallMapVector<const char *, uint32_t, 8> NameOffsetMap;
@@ -203,16 +214,27 @@ private:
     sig.Stream = pElement->GetOutputStream();
     sig.Stream = pElement->GetOutputStream();
     sig.SemanticName = GetSemanticOffset(pElement);
     sig.SemanticName = GetSemanticOffset(pElement);
     sig.SystemValue = KindToSystemValue(pElement->GetKind(), m_domain);
     sig.SystemValue = KindToSystemValue(pElement->GetKind(), m_domain);
-    sig.CompType = CompTypeToSigCompType(pElement->GetCompType());
+    sig.CompType = CompTypeToSigCompType(pElement->GetCompType(), m_bCompat_1_4);
     sig.Register = pElement->GetStartRow();
     sig.Register = pElement->GetStartRow();
 
 
     sig.Mask = pElement->GetColsAsMask();
     sig.Mask = pElement->GetColsAsMask();
-    // Only mark exist channel write for output.
-    // All channel not used for input.
-    if (!m_isInput)
-      sig.NeverWrites_Mask = ~(sig.Mask);
-    else
-      sig.AlwaysReads_Mask = 0;
+    if (m_bCompat_1_4) {
+      // Match what validator 1.4 and below expects
+      // Only mark exist channel write for output.
+      // All channel not used for input.
+      if (!m_isInput)
+        sig.NeverWrites_Mask = ~sig.Mask;
+      else
+        sig.AlwaysReads_Mask = 0;
+    } else {
+      unsigned UsageMask = pElement->GetUsageMask();
+      if (pElement->IsAllocated())
+        UsageMask <<= pElement->GetStartCol();
+      if (!m_isInput)
+        sig.NeverWrites_Mask = NegMask(UsageMask);
+      else
+        sig.AlwaysReads_Mask = UsageMask;
+    }
 
 
     sig.MinPrecision = m_useMinPrecision
     sig.MinPrecision = m_useMinPrecision
                            ? CompTypeToSigMinPrecision(pElement->GetCompType())
                            ? CompTypeToSigMinPrecision(pElement->GetCompType())
@@ -252,8 +274,12 @@ private:
 
 
 public:
 public:
   DxilProgramSignatureWriter(const DxilSignature &signature,
   DxilProgramSignatureWriter(const DxilSignature &signature,
-                             DXIL::TessellatorDomain domain, bool isInput, bool UseMinPrecision)
-      : m_signature(signature), m_domain(domain), m_isInput(isInput), m_useMinPrecision(UseMinPrecision) {
+                             DXIL::TessellatorDomain domain,
+                             bool isInput, bool UseMinPrecision,
+                             bool bCompat_1_4)
+      : m_signature(signature), m_domain(domain),
+        m_isInput(isInput), m_useMinPrecision(UseMinPrecision),
+        m_bCompat_1_4(bCompat_1_4) {
     calcSizes();
     calcSizes();
   }
   }
 
 
@@ -306,20 +332,26 @@ DxilPartWriter *hlsl::NewProgramSignatureWriter(const DxilModule &M, DXIL::Signa
   DXIL::TessellatorDomain domain = DXIL::TessellatorDomain::Undefined;
   DXIL::TessellatorDomain domain = DXIL::TessellatorDomain::Undefined;
   if (M.GetShaderModel()->IsHS() || M.GetShaderModel()->IsDS())
   if (M.GetShaderModel()->IsHS() || M.GetShaderModel()->IsDS())
     domain = M.GetTessellatorDomain();
     domain = M.GetTessellatorDomain();
+  unsigned ValMajor, ValMinor;
+  M.GetValidatorVersion(ValMajor, ValMinor);
+  bool bCompat_1_4 = DXIL::CompareVersions(ValMajor, ValMinor, 1, 5) < 0;
   switch (Kind) {
   switch (Kind) {
   case DXIL::SignatureKind::Input:
   case DXIL::SignatureKind::Input:
     return new DxilProgramSignatureWriter(
     return new DxilProgramSignatureWriter(
         M.GetInputSignature(), domain, true,
         M.GetInputSignature(), domain, true,
-        M.GetUseMinPrecision());
+        M.GetUseMinPrecision(),
+        bCompat_1_4);
   case DXIL::SignatureKind::Output:
   case DXIL::SignatureKind::Output:
     return new DxilProgramSignatureWriter(
     return new DxilProgramSignatureWriter(
         M.GetOutputSignature(), domain, false,
         M.GetOutputSignature(), domain, false,
-        M.GetUseMinPrecision());
+        M.GetUseMinPrecision(),
+        bCompat_1_4);
   case DXIL::SignatureKind::PatchConstOrPrim:
   case DXIL::SignatureKind::PatchConstOrPrim:
     return new DxilProgramSignatureWriter(
     return new DxilProgramSignatureWriter(
         M.GetPatchConstOrPrimSignature(), domain,
         M.GetPatchConstOrPrimSignature(), domain,
         /*IsInput*/ M.GetShaderModel()->IsDS(),
         /*IsInput*/ M.GetShaderModel()->IsDS(),
-        /*UseMinPrecision*/M.GetUseMinPrecision());
+        /*UseMinPrecision*/M.GetUseMinPrecision(),
+        bCompat_1_4);
   case DXIL::SignatureKind::Invalid:
   case DXIL::SignatureKind::Invalid:
     return nullptr;
     return nullptr;
   }
   }
@@ -367,6 +399,7 @@ DxilPartWriter *hlsl::NewFeatureInfoWriter(const DxilModule &M) {
 class DxilPSVWriter : public DxilPartWriter  {
 class DxilPSVWriter : public DxilPartWriter  {
 private:
 private:
   const DxilModule &m_Module;
   const DxilModule &m_Module;
+  unsigned m_ValMajor, m_ValMinor;
   PSVInitInfo m_PSVInitInfo;
   PSVInitInfo m_PSVInitInfo;
   DxilPipelineStateValidation m_PSV;
   DxilPipelineStateValidation m_PSV;
   uint32_t m_PSVBufferSize;
   uint32_t m_PSVBufferSize;
@@ -422,7 +455,8 @@ private:
       E.StartRow = (uint8_t)SE.GetStartRow();
       E.StartRow = (uint8_t)SE.GetStartRow();
     }
     }
     E.SemanticKind = (uint8_t)SE.GetKind();
     E.SemanticKind = (uint8_t)SE.GetKind();
-    E.ComponentType = (uint8_t)CompTypeToSigCompType(SE.GetCompType());
+    E.ComponentType = (uint8_t)CompTypeToSigCompType(SE.GetCompType(),
+      /*i1ToUnknownCompat*/DXIL::CompareVersions(m_ValMajor, m_ValMinor, 1, 5) < 0);
     E.InterpolationMode = (uint8_t)SE.GetInterpolationMode()->GetKind();
     E.InterpolationMode = (uint8_t)SE.GetInterpolationMode()->GetKind();
     DXASSERT_NOMSG(SE.GetOutputStream() < 4);
     DXASSERT_NOMSG(SE.GetOutputStream() < 4);
     E.DynamicMaskAndStream = (uint8_t)((SE.GetOutputStream() & 0x3) << 4);
     E.DynamicMaskAndStream = (uint8_t)((SE.GetOutputStream() & 0x3) << 4);
@@ -450,13 +484,12 @@ public:
   : m_Module(module),
   : m_Module(module),
     m_PSVInitInfo(PSVVersion)
     m_PSVInitInfo(PSVVersion)
   {
   {
-    unsigned ValMajor, ValMinor;
-    m_Module.GetValidatorVersion(ValMajor, ValMinor);
+    m_Module.GetValidatorVersion(m_ValMajor, m_ValMinor);
     // Allow PSVVersion to be upgraded
     // Allow PSVVersion to be upgraded
-    if (ValMajor == 0 && ValMinor == 0) {
+    if (m_ValMajor == 0 && m_ValMinor == 0) {
       // Validation disabled upgrades to maximum PSVVersion
       // Validation disabled upgrades to maximum PSVVersion
       m_PSVInitInfo.PSVVersion = MAX_PSV_VERSION;
       m_PSVInitInfo.PSVVersion = MAX_PSV_VERSION;
-    } else if (m_PSVInitInfo.PSVVersion < 1 && (ValMajor > 1 || (ValMajor == 1 && ValMinor >= 1))) {
+    } else if (m_PSVInitInfo.PSVVersion < 1 && (m_ValMajor > 1 || (m_ValMajor == 1 && m_ValMinor >= 1))) {
       m_PSVInitInfo.PSVVersion = 1;
       m_PSVInitInfo.PSVVersion = 1;
     }
     }
 
 
@@ -1006,6 +1039,8 @@ private:
   FunctionIndexMap m_FuncToResNameOffset; // list of resources used
   FunctionIndexMap m_FuncToResNameOffset; // list of resources used
   FunctionIndexMap m_FuncToDependencies;  // list of unresolved functions used
   FunctionIndexMap m_FuncToDependencies;  // list of unresolved functions used
 
 
+  unsigned m_ValMajor, m_ValMinor;
+
   struct ShaderCompatInfo {
   struct ShaderCompatInfo {
     ShaderCompatInfo()
     ShaderCompatInfo()
       : minMajor(6), minMinor(0),
       : minMajor(6), minMinor(0),
@@ -1025,7 +1060,9 @@ private:
         ShaderCompatInfo &info = m_FuncToShaderCompat[F];
         ShaderCompatInfo &info = m_FuncToShaderCompat[F];
         unsigned major, minor, mask;
         unsigned major, minor, mask;
         // bWithTranslation = true for library modules
         // bWithTranslation = true for library modules
-        OP::GetMinShaderModelAndMask(CI, /*bWithTranslation*/true, major, minor, mask);
+        OP::GetMinShaderModelAndMask(CI, /*bWithTranslation*/true,
+                                     m_ValMajor, m_ValMinor,
+                                     major, minor, mask);
         if (major > info.minMajor) {
         if (major > info.minMajor) {
           info.minMajor = major;
           info.minMajor = major;
           info.minMinor = minor;
           info.minMinor = minor;
@@ -1128,6 +1165,12 @@ private:
   }
   }
 
 
   void UpdateFunctionInfo(const DxilModule &DM) {
   void UpdateFunctionInfo(const DxilModule &DM) {
+    // We must select the appropriate shader mask for the validator version,
+    // so we don't set any bits the validator doesn't recognize.
+    unsigned ValidShaderMask = (1 << ((unsigned)DXIL::ShaderKind::Amplification + 1)) - 1;
+    if (DXIL::CompareVersions(m_ValMajor, m_ValMinor, 1, 5) < 0) {
+      ValidShaderMask = (1 << ((unsigned)DXIL::ShaderKind::Callable + 1)) - 1;
+    }
     for (auto &function : DM.GetModule()->getFunctionList()) {
     for (auto &function : DM.GetModule()->getFunctionList()) {
       if (function.isDeclaration() && !function.isIntrinsic()) {
       if (function.isDeclaration() && !function.isIntrinsic()) {
         if (OP::IsDxilOpFunc(&function)) {
         if (OP::IsDxilOpFunc(&function)) {
@@ -1196,7 +1239,7 @@ private:
         }
         }
         if ((DXIL::ShaderKind)shaderKind == DXIL::ShaderKind::Library) {
         if ((DXIL::ShaderKind)shaderKind == DXIL::ShaderKind::Library) {
           // Init mask to all kinds for library functions
           // Init mask to all kinds for library functions
-          info.ShaderStageFlag = ((unsigned)1 << (unsigned)DXIL::ShaderKind::Invalid) - 1;
+          info.ShaderStageFlag = ValidShaderMask;
         } else {
         } else {
           // Init mask to current kind for shader functions
           // Init mask to current kind for shader functions
           info.ShaderStageFlag = (unsigned)1 << shaderKind;
           info.ShaderStageFlag = (unsigned)1 << shaderKind;
@@ -1313,6 +1356,9 @@ private:
 public:
 public:
   DxilRDATWriter(const DxilModule &module, uint32_t InfoVersion = 0)
   DxilRDATWriter(const DxilModule &module, uint32_t InfoVersion = 0)
       : m_RDATBuffer(), m_Parts(), m_FuncToResNameOffset() {
       : m_RDATBuffer(), m_Parts(), m_FuncToResNameOffset() {
+    // Keep track of validator version so we can make a compatible RDAT
+    module.GetValidatorVersion(m_ValMajor, m_ValMinor);
+
     CreateParts();
     CreateParts();
     UpdateResourceInfo(module);
     UpdateResourceInfo(module);
     UpdateFunctionInfo(module);
     UpdateFunctionInfo(module);
@@ -1498,7 +1544,8 @@ void hlsl::SerializeDxilContainerForModule(DxilModule *pModule,
                                            AbstractMemoryStream *pFinalStream,
                                            AbstractMemoryStream *pFinalStream,
                                            llvm::StringRef DebugName,
                                            llvm::StringRef DebugName,
                                            SerializeDxilFlags Flags,
                                            SerializeDxilFlags Flags,
-                                           DxilShaderHash *pShaderHashOut) {
+                                           DxilShaderHash *pShaderHashOut,
+                                           AbstractMemoryStream *pReflectionStreamOut) {
   // TODO: add a flag to update the module and remove information that is not part
   // TODO: add a flag to update the module and remove information that is not part
   // of DXIL proper and is used only to assemble the container.
   // of DXIL proper and is used only to assemble the container.
 
 
@@ -1508,11 +1555,12 @@ void hlsl::SerializeDxilContainerForModule(DxilModule *pModule,
 
 
   unsigned ValMajor, ValMinor;
   unsigned ValMajor, ValMinor;
   pModule->GetValidatorVersion(ValMajor, ValMinor);
   pModule->GetValidatorVersion(ValMajor, ValMinor);
-  if (ValMajor == 1 && ValMinor == 0)
+  if (DXIL::CompareVersions(ValMajor, ValMinor, 1, 1) < 0)
     Flags &= ~SerializeDxilFlags::IncludeDebugNamePart;
     Flags &= ~SerializeDxilFlags::IncludeDebugNamePart;
-  bool bSupportsShaderHash = true;
-  if (ValMajor == 1 && ValMinor < 5)
-    bSupportsShaderHash = false;
+  bool bSupportsShaderHash = DXIL::CompareVersions(ValMajor, ValMinor, 1, 5) >= 0;
+  bool bCompat_1_4 = DXIL::CompareVersions(ValMajor, ValMinor, 1, 5) < 0;
+  bool bEmitReflection = Flags & SerializeDxilFlags::IncludeReflectionPart ||
+                         pReflectionStreamOut;
 
 
   DxilContainerWriter_impl writer;
   DxilContainerWriter_impl writer;
 
 
@@ -1532,11 +1580,13 @@ void hlsl::SerializeDxilContainerForModule(DxilModule *pModule,
     pInputSigWriter = llvm::make_unique<DxilProgramSignatureWriter>(
     pInputSigWriter = llvm::make_unique<DxilProgramSignatureWriter>(
         pModule->GetInputSignature(), domain,
         pModule->GetInputSignature(), domain,
         /*IsInput*/ true,
         /*IsInput*/ true,
-        /*UseMinPrecision*/ pModule->GetUseMinPrecision());
+        /*UseMinPrecision*/ pModule->GetUseMinPrecision(),
+        bCompat_1_4);
     pOutputSigWriter = llvm::make_unique<DxilProgramSignatureWriter>(
     pOutputSigWriter = llvm::make_unique<DxilProgramSignatureWriter>(
         pModule->GetOutputSignature(), domain,
         pModule->GetOutputSignature(), domain,
         /*IsInput*/ false,
         /*IsInput*/ false,
-        /*UseMinPrecision*/ pModule->GetUseMinPrecision());
+        /*UseMinPrecision*/ pModule->GetUseMinPrecision(),
+        bCompat_1_4);
     // Write the input and output signature parts.
     // Write the input and output signature parts.
     writer.AddPart(DFCC_InputSignature, pInputSigWriter->size(),
     writer.AddPart(DFCC_InputSignature, pInputSigWriter->size(),
                    [&](AbstractMemoryStream *pStream) {
                    [&](AbstractMemoryStream *pStream) {
@@ -1550,7 +1600,8 @@ void hlsl::SerializeDxilContainerForModule(DxilModule *pModule,
     pPatchConstOrPrimSigWriter = llvm::make_unique<DxilProgramSignatureWriter>(
     pPatchConstOrPrimSigWriter = llvm::make_unique<DxilProgramSignatureWriter>(
         pModule->GetPatchConstOrPrimSignature(), domain,
         pModule->GetPatchConstOrPrimSignature(), domain,
         /*IsInput*/ pModule->GetShaderModel()->IsDS(),
         /*IsInput*/ pModule->GetShaderModel()->IsDS(),
-        /*UseMinPrecision*/ pModule->GetUseMinPrecision());
+        /*UseMinPrecision*/ pModule->GetUseMinPrecision(),
+        bCompat_1_4);
     if (pModule->GetPatchConstOrPrimSignature().GetElements().size()) {
     if (pModule->GetPatchConstOrPrimSignature().GetElements().size()) {
       writer.AddPart(DFCC_PatchConstantSignature,
       writer.AddPart(DFCC_PatchConstantSignature,
                      pPatchConstOrPrimSigWriter->size(),
                      pPatchConstOrPrimSigWriter->size(),
@@ -1623,9 +1674,74 @@ void hlsl::SerializeDxilContainerForModule(DxilModule *pModule,
     Flags &= ~SerializeDxilFlags::DebugNameDependOnSource;
     Flags &= ~SerializeDxilFlags::DebugNameDependOnSource;
   }
   }
 
 
+  // Clone module for reflection, strip function defs
+  std::unique_ptr<Module> reflectionModule;
+  if (bEmitReflection) {
+    if (DXIL::CompareVersions(ValMajor, ValMinor, 1, 5) < 0) {
+      // Retain usage information in metadata for reflection by:
+      // Upgrade validator version, re-emit metadata, then clone module for reflection.
+      // 0,0 = Not meant to be validated, support latest
+      pModule->SetValidatorVersion(0, 0);
+      pModule->ReEmitDxilResources();
+    }
+
+    reflectionModule.reset(llvm::CloneModule(pModule->GetModule()));
+
+    if (DXIL::CompareVersions(ValMajor, ValMinor, 1, 5) < 0) {
+      // Now restore validator version on main module and re-emit metadata.
+      pModule->SetValidatorVersion(ValMajor, ValMinor);
+      pModule->ReEmitDxilResources();
+    }
+
+    for (Function &F : reflectionModule->functions()) {
+      if (!F.isDeclaration()) {
+        F.deleteBody();
+      }
+    }
+    // Just make sure this doesn't crash/assert on debug build:
+    DXASSERT_NOMSG(&reflectionModule->GetOrCreateDxilModule());
+  }
+
+  CComPtr<AbstractMemoryStream> pReflectionBitcodeStream;
+
+  uint32_t reflectPartSizeInBytes = 0;
+  if (bEmitReflection)
+  {
+    IFT(CreateMemoryStream(DxcGetThreadMallocNoRef(), &pReflectionBitcodeStream));
+    raw_stream_ostream outStream(pReflectionBitcodeStream.p);
+    WriteBitcodeToFile(reflectionModule.get(), outStream, false);
+    outStream.flush();
+    uint32_t reflectInUInt32 = 0, reflectPaddingBytes = 0;
+    GetPaddedProgramPartSize(pReflectionBitcodeStream, reflectInUInt32, reflectPaddingBytes);
+    reflectPartSizeInBytes = reflectInUInt32 * sizeof(uint32_t) + sizeof(DxilProgramHeader);
+  }
+
+  if (pReflectionStreamOut) {
+    DxilPartHeader partSTAT;
+    partSTAT.PartFourCC = DFCC_ShaderStatistics;
+    partSTAT.PartSize = reflectPartSizeInBytes;
+    IFT(WriteStreamValue(pReflectionStreamOut, partSTAT));
+    WriteProgramPart(pModule->GetShaderModel(), pReflectionBitcodeStream, pReflectionStreamOut);
+
+    // If library, we need RDAT part as well.  For now, we just append it
+    if (pModule->GetShaderModel()->IsLib()) {
+      DxilPartHeader partRDAT;
+      partRDAT.PartFourCC = DFCC_RuntimeData;
+      partRDAT.PartSize = pRDATWriter->size();
+      IFT(WriteStreamValue(pReflectionStreamOut, partRDAT));
+      pRDATWriter->write(pReflectionStreamOut);
+    }
+  }
+
+  if (Flags & SerializeDxilFlags::IncludeReflectionPart) {
+    writer.AddPart(DFCC_ShaderStatistics, reflectPartSizeInBytes,
+      [pModule, pReflectionBitcodeStream](AbstractMemoryStream *pStream) {
+        WriteProgramPart(pModule->GetShaderModel(), pReflectionBitcodeStream, pStream);
+      });
+  }
+
   if (Flags & SerializeDxilFlags::StripReflectionFromDxilPart) {
   if (Flags & SerializeDxilFlags::StripReflectionFromDxilPart) {
-    pModule->StripReflection();
-    bModuleStripped = true;
+    bModuleStripped |= pModule->StripReflection();
   }
   }
 
 
   // If debug info or reflection was stripped, re-serialize the module.
   // If debug info or reflection was stripped, re-serialize the module.

+ 154 - 1
lib/HLSL/DxilCondenseResources.cpp

@@ -477,6 +477,9 @@ public:
 
 
     bChanged |= ResourceRegisterAllocator.AllocateRegisters(DM);
     bChanged |= ResourceRegisterAllocator.AllocateRegisters(DM);
 
 
+    // Fill in top-level CBuffer variable usage bit
+    UpdateCBufferUsage();
+
     if (m_bIsLib && DM.GetShaderModel()->GetMinor() == ShaderModel::kOfflineMinor)
     if (m_bIsLib && DM.GetShaderModel()->GetMinor() == ShaderModel::kOfflineMinor)
       return bChanged;
       return bChanged;
 
 
@@ -494,8 +497,14 @@ public:
 
 
     GenerateDxilResourceHandles();
     GenerateDxilResourceHandles();
 
 
+    // TODO: Update types earlier for libraries and replace users, to
+    //       avoid having to preserve HL struct annotation.
+    // Note 1: Needs to happen after legalize
+    // Note 2: Cannot do this easily/trivially if any functions have
+    //         resource arguments (in offline linking target).
     if (DM.GetOP()->UseMinPrecision())
     if (DM.GetOP()->UseMinPrecision())
       UpdateStructTypeForLegacyLayout();
       UpdateStructTypeForLegacyLayout();
+
     // Change resource symbol into undef.
     // Change resource symbol into undef.
     UpdateResourceSymbols();
     UpdateResourceSymbols();
 
 
@@ -516,6 +525,7 @@ private:
   // Switch CBuffer for SRV for TBuffers.
   // Switch CBuffer for SRV for TBuffers.
   bool PatchTBuffers(DxilModule &DM);
   bool PatchTBuffers(DxilModule &DM);
   void PatchTBufferUse(Value *V, DxilModule &DM);
   void PatchTBufferUse(Value *V, DxilModule &DM);
+  void UpdateCBufferUsage();
 };
 };
 
 
 } // namespace
 } // namespace
@@ -1597,7 +1607,11 @@ StructType *UpdateStructTypeForLegacyLayout(StructType *ST,
   unsigned fieldsCount = ST->getNumElements();
   unsigned fieldsCount = ST->getNumElements();
   std::vector<Type *> fieldTypes(fieldsCount);
   std::vector<Type *> fieldTypes(fieldsCount);
   DxilStructAnnotation *SA = TypeSys.GetStructAnnotation(ST);
   DxilStructAnnotation *SA = TypeSys.GetStructAnnotation(ST);
-  DXASSERT(SA, "must have annotation for struct type");
+
+  // After reflection is stripped from library, this will be null if no update is required.
+  if (!SA) {
+    return ST;
+  }
 
 
   if (SA->IsEmptyStruct()) {
   if (SA->IsEmptyStruct()) {
     return ST;
     return ST;
@@ -2093,6 +2107,145 @@ bool DxilLowerCreateHandleForLib::PatchTBuffers(DxilModule &DM) {
   return bChanged;
   return bChanged;
 }
 }
 
 
+// Find the imm offset part from a value.
+// It must exist unless offset is 0.
+static unsigned GetCBOffset(Value *V) {
+  if (ConstantInt *Imm = dyn_cast<ConstantInt>(V))
+    return Imm->getLimitedValue();
+  else if (UnaryInstruction *UI = dyn_cast<UnaryInstruction>(V)) {
+    return 0;
+  } else if (BinaryOperator *BO = dyn_cast<BinaryOperator>(V)) {
+    switch (BO->getOpcode()) {
+    case Instruction::Add: {
+      unsigned left = GetCBOffset(BO->getOperand(0));
+      unsigned right = GetCBOffset(BO->getOperand(1));
+      return left + right;
+    } break;
+    case Instruction::Or: {
+      unsigned left = GetCBOffset(BO->getOperand(0));
+      unsigned right = GetCBOffset(BO->getOperand(1));
+      return left | right;
+    } break;
+    default:
+      return 0;
+    }
+  } else {
+    return 0;
+  }
+}
+
+typedef std::map<unsigned, DxilFieldAnnotation*> FieldAnnotationByOffsetMap;
+
+static void MarkCBUse(unsigned offset, FieldAnnotationByOffsetMap &fieldMap) {
+  auto it = fieldMap.upper_bound(offset);
+  it--;
+  if (it != fieldMap.end())
+    it->second->SetCBVarUsed(true);
+}
+
+static unsigned GetOffsetForCBExtractValue(ExtractValueInst *EV, bool bMinPrecision) {
+  DXASSERT(EV->getNumIndices() == 1, "otherwise, unexpected indices/type for extractvalue");
+  unsigned typeSize = 4;
+  unsigned bits = EV->getType()->getScalarSizeInBits();
+  if (bits == 64)
+    typeSize = 8;
+  else if (bits == 16 && !bMinPrecision)
+    typeSize = 2;
+  return (EV->getIndices().front() * typeSize);
+}
+
+static void CollectInPhiChain(PHINode *cbUser, unsigned offset,
+                              std::unordered_set<Value *> &userSet,
+                              FieldAnnotationByOffsetMap &fieldMap,
+                              bool bMinPrecision) {
+  if (userSet.count(cbUser) > 0)
+    return;
+
+  userSet.insert(cbUser);
+  for (User *cbU : cbUser->users()) {
+    if (ExtractValueInst *EV = dyn_cast<ExtractValueInst>(cbU)) {
+      MarkCBUse(offset + GetOffsetForCBExtractValue(EV, bMinPrecision), fieldMap);
+    } else {
+      PHINode *phi = cast<PHINode>(cbU);
+      CollectInPhiChain(phi, offset, userSet, fieldMap, bMinPrecision);
+    }
+  }
+}
+
+static void CollectCBufferMemberUsage(Value *V,
+                                      FieldAnnotationByOffsetMap &legacyFieldMap,
+                                      FieldAnnotationByOffsetMap &newFieldMap,
+                                      hlsl::OP *hlslOP, bool bMinPrecision) {
+  for (auto U : V->users()) {
+    if (Constant *C = dyn_cast<Constant>(U)) {
+      CollectCBufferMemberUsage(C, legacyFieldMap, newFieldMap, hlslOP, bMinPrecision);
+    } else if (LoadInst *LI = dyn_cast<LoadInst>(U)) {
+      CollectCBufferMemberUsage(U, legacyFieldMap, newFieldMap, hlslOP, bMinPrecision);
+    } else if (CallInst *CI = dyn_cast<CallInst>(U)) {
+      if (hlslOP->IsDxilOpFuncCallInst(CI)) {
+        hlsl::OP::OpCode op = hlslOP->GetDxilOpFuncCallInst(CI);
+        if (op == DXIL::OpCode::CreateHandleForLib) {
+          CollectCBufferMemberUsage(U, legacyFieldMap, newFieldMap, hlslOP, bMinPrecision);
+        } else if (op == DXIL::OpCode::CBufferLoadLegacy) {
+          DxilInst_CBufferLoadLegacy cbload(CI);
+          Value *resIndex = cbload.get_regIndex();
+          unsigned offset = GetCBOffset(resIndex);
+          offset <<= 4; // translate 16-byte vector index to byte offset
+          for (User *cbU : U->users()) {
+            if (ExtractValueInst *EV = dyn_cast<ExtractValueInst>(cbU)) {
+              MarkCBUse(offset + GetOffsetForCBExtractValue(EV, bMinPrecision), legacyFieldMap);
+            } else {
+              PHINode *phi = cast<PHINode>(cbU);
+              std::unordered_set<Value *> userSet;
+              CollectInPhiChain(phi, offset, userSet, legacyFieldMap, bMinPrecision);
+            }
+          }
+        } else if (op == DXIL::OpCode::CBufferLoad) {
+          DxilInst_CBufferLoad cbload(CI);
+          Value *byteOffset = cbload.get_byteOffset();
+          unsigned offset = GetCBOffset(byteOffset);
+          MarkCBUse(offset, newFieldMap);
+        }
+      }
+    }
+  }
+}
+
+void DxilLowerCreateHandleForLib::UpdateCBufferUsage() {
+  DxilTypeSystem &TypeSys = m_DM->GetTypeSystem();
+  hlsl::OP *hlslOP = m_DM->GetOP();
+  const DataLayout &DL = m_DM->GetModule()->getDataLayout();
+  const auto &CBuffers = m_DM->GetCBuffers();
+  for (auto it = CBuffers.begin(); it != CBuffers.end(); it++) {
+    DxilCBuffer *CB = it->get();
+    GlobalVariable *GV = dyn_cast<GlobalVariable>(CB->GetGlobalSymbol());
+    if (GV == nullptr)
+      continue;
+    Type *ElemTy = GV->getType()->getPointerElementType();
+    ElemTy = dxilutil::StripArrayTypes(ElemTy, nullptr);
+    StructType *ST = cast<StructType>(ElemTy);
+    DxilStructAnnotation *SA = TypeSys.GetStructAnnotation(ST);
+    if (SA == nullptr)
+      continue;
+    // If elements < 2, it's used if it exists.
+    // Only old-style cbuffer { ... } will have more than one member, and
+    // old-style cbuffers are the only ones that report usage per member.
+    if (ST->getStructNumElements() < 2) {
+      continue;
+    }
+
+    // Create offset maps for legacy layout and new compact layout, while resetting usage flags
+    const StructLayout *SL = DL.getStructLayout(ST);
+    FieldAnnotationByOffsetMap legacyFieldMap, newFieldMap;
+    for (unsigned i = 0; i < SA->GetNumFields(); ++i) {
+      DxilFieldAnnotation &FA = SA->GetFieldAnnotation(i);
+      FA.SetCBVarUsed(false);
+      legacyFieldMap[FA.GetCBufferOffset()] = &FA;
+      newFieldMap[(unsigned)SL->getElementOffset(i)] = &FA;
+    }
+    CollectCBufferMemberUsage(GV, legacyFieldMap, newFieldMap, hlslOP, m_DM->GetUseMinPrecision());
+ }
+}
 
 
 
 
 char DxilLowerCreateHandleForLib::ID = 0;
 char DxilLowerCreateHandleForLib::ID = 0;

+ 212 - 132
lib/HLSL/DxilContainerReflection.cpp

@@ -38,6 +38,8 @@
 #include "d3d12shader.h" // for compatibility
 #include "d3d12shader.h" // for compatibility
 #include "d3d11shader.h" // for compatibility
 #include "d3d11shader.h" // for compatibility
 
 
+#include "dxc/DxilContainer/DxilRuntimeReflection.h"
+
 const GUID IID_ID3D11ShaderReflection_43 = {
 const GUID IID_ID3D11ShaderReflection_43 = {
     0x0a233719,
     0x0a233719,
     0x3960,
     0x3960,
@@ -82,17 +84,19 @@ enum class PublicAPI { D3D12 = 0, D3D11_47 = 1, D3D11_43 = 2 };
 
 
 class DxilModuleReflection {
 class DxilModuleReflection {
 public:
 public:
-  CComPtr<IDxcBlob> m_pContainer;
+  hlsl::RDAT::DxilRuntimeData m_RDAT;
   LLVMContext Context;
   LLVMContext Context;
   std::unique_ptr<Module> m_pModule; // Must come after LLVMContext, otherwise unique_ptr will over-delete.
   std::unique_ptr<Module> m_pModule; // Must come after LLVMContext, otherwise unique_ptr will over-delete.
   DxilModule *m_pDxilModule = nullptr;
   DxilModule *m_pDxilModule = nullptr;
+  bool m_bUsageInMetadata = false;
   std::vector<std::unique_ptr<CShaderReflectionConstantBuffer>>    m_CBs;
   std::vector<std::unique_ptr<CShaderReflectionConstantBuffer>>    m_CBs;
   std::vector<D3D12_SHADER_INPUT_BIND_DESC>       m_Resources;
   std::vector<D3D12_SHADER_INPUT_BIND_DESC>       m_Resources;
   std::vector<std::unique_ptr<CShaderReflectionType>> m_Types;
   std::vector<std::unique_ptr<CShaderReflectionType>> m_Types;
   void CreateReflectionObjects();
   void CreateReflectionObjects();
   void CreateReflectionObjectForResource(DxilResourceBase *R);
   void CreateReflectionObjectForResource(DxilResourceBase *R);
 
 
-  HRESULT LoadModule(IDxcBlob *pBlob, const DxilPartHeader *pPart);
+  HRESULT LoadRDAT(const DxilPartHeader *pPart);
+  HRESULT LoadModule(const DxilPartHeader *pPart);
 
 
   // Common code
   // Common code
   ID3D12ShaderReflectionConstantBuffer* _GetConstantBufferByIndex(UINT Index);
   ID3D12ShaderReflectionConstantBuffer* _GetConstantBufferByIndex(UINT Index);
@@ -150,7 +154,7 @@ public:
     return hr;
     return hr;
   }
   }
 
 
-  HRESULT Load(IDxcBlob *pBlob, const DxilPartHeader *pPart);
+  HRESULT Load(const DxilPartHeader *pModulePart, const DxilPartHeader *pRDATPart);
 
 
   // ID3D12ShaderReflection
   // ID3D12ShaderReflection
   STDMETHODIMP GetDesc(THIS_ _Out_ D3D12_SHADER_DESC *pDesc);
   STDMETHODIMP GetDesc(THIS_ _Out_ D3D12_SHADER_DESC *pDesc);
@@ -205,7 +209,6 @@ private:
   // Enable indexing into functions in deterministic order:
   // Enable indexing into functions in deterministic order:
   std::vector<CFunctionReflection*> m_FunctionVector;
   std::vector<CFunctionReflection*> m_FunctionVector;
 
 
-  void AddResourceUseToFunctions(DxilResourceBase &resource, unsigned resIndex);
   void AddResourceDependencies();
   void AddResourceDependencies();
   void SetCBufferUsage();
   void SetCBufferUsage();
 
 
@@ -216,7 +219,7 @@ public:
     return DoBasicQueryInterface<ID3D12LibraryReflection>(this, iid, ppvObject);
     return DoBasicQueryInterface<ID3D12LibraryReflection>(this, iid, ppvObject);
   }
   }
 
 
-  HRESULT Load(IDxcBlob *pBlob, const DxilPartHeader *pPart);
+  HRESULT Load(const DxilPartHeader *pModulePart, const DxilPartHeader *pDXILPart);
 
 
   // ID3D12LibraryReflection
   // ID3D12LibraryReflection
   STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_LIBRARY_DESC * pDesc);
   STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_LIBRARY_DESC * pDesc);
@@ -224,6 +227,31 @@ public:
   STDMETHOD_(ID3D12FunctionReflection *, GetFunctionByIndex)(THIS_ _In_ INT FunctionIndex);
   STDMETHOD_(ID3D12FunctionReflection *, GetFunctionByIndex)(THIS_ _In_ INT FunctionIndex);
 };
 };
 
 
+namespace hlsl {
+HRESULT CreateDxilShaderReflection(const DxilPartHeader *pModulePart, const DxilPartHeader *pRDATPart, REFIID iid, void **ppvObject) {
+  if (!ppvObject)
+    return E_INVALIDARG;
+  CComPtr<DxilShaderReflection> pReflection = DxilShaderReflection::Alloc(DxcGetThreadMallocNoRef());
+  IFROOM(pReflection.p);
+  PublicAPI api = DxilShaderReflection::IIDToAPI(iid);
+  pReflection->SetPublicAPI(api);
+  // pRDATPart to be used for transition.
+  IFR(pReflection->Load(pModulePart, pRDATPart));
+  IFR(pReflection.p->QueryInterface(iid, ppvObject));
+  return S_OK;
+}
+HRESULT CreateDxilLibraryReflection(const DxilPartHeader *pModulePart, const DxilPartHeader *pRDATPart, REFIID iid, void **ppvObject) {
+  if (!ppvObject)
+    return E_INVALIDARG;
+  CComPtr<DxilLibraryReflection> pReflection = DxilLibraryReflection::Alloc(DxcGetThreadMallocNoRef());
+  IFROOM(pReflection.p);
+  // pRDATPart used for resource usage per-function.
+  IFR(pReflection->Load(pModulePart, pRDATPart));
+  IFR(pReflection.p->QueryInterface(iid, ppvObject));
+  return S_OK;
+}
+}
+
 _Use_decl_annotations_
 _Use_decl_annotations_
 HRESULT DxilContainerReflection::Load(IDxcBlob *pContainer) {
 HRESULT DxilContainerReflection::Load(IDxcBlob *pContainer) {
 
 
@@ -311,32 +339,45 @@ HRESULT DxilContainerReflection::GetPartReflection(UINT32 idx, REFIID iid, void
   if (!IsLoaded()) return E_NOT_VALID_STATE;
   if (!IsLoaded()) return E_NOT_VALID_STATE;
   if (idx >= m_pHeader->PartCount) return E_BOUNDS;
   if (idx >= m_pHeader->PartCount) return E_BOUNDS;
   const DxilPartHeader *pPart = GetDxilContainerPart(m_pHeader, idx);
   const DxilPartHeader *pPart = GetDxilContainerPart(m_pHeader, idx);
-  if (pPart->PartFourCC != DFCC_DXIL && pPart->PartFourCC != DFCC_ShaderDebugInfoDXIL) {
+  if (pPart->PartFourCC != DFCC_DXIL && pPart->PartFourCC != DFCC_ShaderDebugInfoDXIL &&
+      pPart->PartFourCC != DFCC_ShaderStatistics) {
     return E_NOTIMPL;
     return E_NOTIMPL;
   }
   }
+
+  // Use DFCC_ShaderStatistics for reflection instead of DXIL part, until switch
+  // to using RDAT for reflection instead of module.
+  const DxilPartHeader *pRDATPart = nullptr;
+  for (idx = 0; idx < m_pHeader->PartCount; ++idx) {
+    const DxilPartHeader *pPartTest = GetDxilContainerPart(m_pHeader, idx);
+    if (pPartTest->PartFourCC == DFCC_RuntimeData) {
+      pRDATPart = pPartTest;
+    }
+    if (pPart->PartFourCC != DFCC_ShaderStatistics) {
+      if (pPartTest->PartFourCC == DFCC_ShaderStatistics) {
+        const DxilProgramHeader *pProgramHeaderTest =
+          reinterpret_cast<const DxilProgramHeader*>(GetDxilPartData(pPartTest));
+        if (IsValidDxilProgramHeader(pProgramHeaderTest, pPartTest->PartSize)) {
+          pPart = pPartTest;
+          continue;
+        }
+      }
+    }
+  }
   
   
-  DxcThreadMalloc TM(m_pMalloc);
-  HRESULT hr = S_OK;
   const DxilProgramHeader *pProgramHeader =
   const DxilProgramHeader *pProgramHeader =
     reinterpret_cast<const DxilProgramHeader*>(GetDxilPartData(pPart));
     reinterpret_cast<const DxilProgramHeader*>(GetDxilPartData(pPart));
   if (!IsValidDxilProgramHeader(pProgramHeader, pPart->PartSize)) {
   if (!IsValidDxilProgramHeader(pProgramHeader, pPart->PartSize)) {
     return E_INVALIDARG;
     return E_INVALIDARG;
   }
   }
 
 
+  DxcThreadMalloc TM(m_pMalloc);
+  HRESULT hr = S_OK;
+
   DXIL::ShaderKind SK = GetVersionShaderType(pProgramHeader->ProgramVersion);
   DXIL::ShaderKind SK = GetVersionShaderType(pProgramHeader->ProgramVersion);
   if (SK == DXIL::ShaderKind::Library) {
   if (SK == DXIL::ShaderKind::Library) {
-    CComPtr<DxilLibraryReflection> pReflection = DxilLibraryReflection::Alloc(m_pMalloc);
-    IFCOOM(pReflection.p);
-    IFC(pReflection->Load(m_container, pPart));
-    IFC(pReflection.p->QueryInterface(iid, ppvObject));
+    IFC(hlsl::CreateDxilLibraryReflection(pPart, pRDATPart, iid, ppvObject));
   } else {
   } else {
-    CComPtr<DxilShaderReflection> pReflection = DxilShaderReflection::Alloc(m_pMalloc);
-    IFCOOM(pReflection.p);
-    PublicAPI api = DxilShaderReflection::IIDToAPI(iid);
-    pReflection->SetPublicAPI(api);
-
-    IFC(pReflection->Load(m_container, pPart));
-    IFC(pReflection.p->QueryInterface(iid, ppvObject));
+    IFC(hlsl::CreateDxilShaderReflection(pPart, pRDATPart, iid, ppvObject));
   }
   }
 
 
 Cleanup:
 Cleanup:
@@ -444,7 +485,8 @@ public:
 
 
   void Initialize(DxilModule &M,
   void Initialize(DxilModule &M,
                   DxilCBuffer &CB,
                   DxilCBuffer &CB,
-                  std::vector<std::unique_ptr<CShaderReflectionType>>& allTypes);
+                  std::vector<std::unique_ptr<CShaderReflectionType>>& allTypes,
+                  bool bUsageInMetadata);
   void InitializeStructuredBuffer(DxilModule &M,
   void InitializeStructuredBuffer(DxilModule &M,
                                   DxilResource &R,
                                   DxilResource &R,
                                   std::vector<std::unique_ptr<CShaderReflectionType>>& allTypes);
                                   std::vector<std::unique_ptr<CShaderReflectionType>>& allTypes);
@@ -829,6 +871,7 @@ HRESULT CShaderReflectionType::Initialize(
   //
   //
   // Note that DXIL supports some types that don't currently have equivalents
   // Note that DXIL supports some types that don't currently have equivalents
   // in the reflection interface, so we try to muddle through here.
   // in the reflection interface, so we try to muddle through here.
+  bool bMinPrec = M.GetUseMinPrecision();
   D3D_SHADER_VARIABLE_TYPE componentType = D3D_SVT_VOID;
   D3D_SHADER_VARIABLE_TYPE componentType = D3D_SVT_VOID;
   switch(typeAnnotation.GetCompType().GetKind())
   switch(typeAnnotation.GetCompType().GetKind())
   {
   {
@@ -842,12 +885,22 @@ HRESULT CShaderReflectionType::Initialize(
 
 
   case hlsl::DXIL::ComponentType::I16:
   case hlsl::DXIL::ComponentType::I16:
     componentType = D3D_SVT_MIN16INT;
     componentType = D3D_SVT_MIN16INT;
-    m_Name = "min16int";
+    if (bMinPrec) {
+      m_Name = "min16int";
+    } else {
+      m_Name = "int16_t";
+      cbCompSize = 2;
+    }
     break;
     break;
 
 
   case hlsl::DXIL::ComponentType::U16:
   case hlsl::DXIL::ComponentType::U16:
     componentType = D3D_SVT_MIN16UINT;
     componentType = D3D_SVT_MIN16UINT;
-    m_Name = "min16uint";
+    if (bMinPrec) {
+      m_Name = "min16uint";
+    } else {
+      m_Name = "uint16_t";
+      cbCompSize = 2;
+    }
     break;
     break;
 
 
   case hlsl::DXIL::ComponentType::I64:
   case hlsl::DXIL::ComponentType::I64:
@@ -874,7 +927,12 @@ HRESULT CShaderReflectionType::Initialize(
   case hlsl::DXIL::ComponentType::SNormF16:
   case hlsl::DXIL::ComponentType::SNormF16:
   case hlsl::DXIL::ComponentType::UNormF16:
   case hlsl::DXIL::ComponentType::UNormF16:
     componentType = D3D_SVT_MIN16FLOAT;
     componentType = D3D_SVT_MIN16FLOAT;
-    m_Name = "min16float";
+    if (bMinPrec) {
+      m_Name = "min16float";
+    } else {
+      m_Name = "float16_t";
+      cbCompSize = 2;
+    }
     break;
     break;
 
 
   case hlsl::DXIL::ComponentType::F32:
   case hlsl::DXIL::ComponentType::F32:
@@ -1103,7 +1161,8 @@ HRESULT CShaderReflectionType::Initialize(
 void CShaderReflectionConstantBuffer::Initialize(
 void CShaderReflectionConstantBuffer::Initialize(
   DxilModule &M,
   DxilModule &M,
   DxilCBuffer &CB,
   DxilCBuffer &CB,
-  std::vector<std::unique_ptr<CShaderReflectionType>>& allTypes) {
+  std::vector<std::unique_ptr<CShaderReflectionType>>& allTypes,
+  bool bUsageInMetadata) {
   ZeroMemory(&m_Desc, sizeof(m_Desc));
   ZeroMemory(&m_Desc, sizeof(m_Desc));
   m_Desc.Name = CB.GetGlobalName().c_str();
   m_Desc.Name = CB.GetGlobalName().c_str();
   m_Desc.Size = CB.GetSize();
   m_Desc.Size = CB.GetSize();
@@ -1129,12 +1188,16 @@ void CShaderReflectionConstantBuffer::Initialize(
     DXASSERT(m_Desc.Variables == 1, "otherwise, assumption is wrong");
     DXASSERT(m_Desc.Variables == 1, "otherwise, assumption is wrong");
   }
   }
 
 
+  // If only one member, it's used if it's here.
+  bool bAllUsed = ST->getNumContainedTypes() < 2;
+  bAllUsed |= !bUsageInMetadata;  // Will update in SetCBufferUsage.
+
   for (unsigned i = 0; i < ST->getNumContainedTypes(); ++i) {
   for (unsigned i = 0; i < ST->getNumContainedTypes(); ++i) {
     DxilFieldAnnotation &fieldAnnotation = annotation->GetFieldAnnotation(i);
     DxilFieldAnnotation &fieldAnnotation = annotation->GetFieldAnnotation(i);
 
 
     D3D12_SHADER_VARIABLE_DESC VarDesc;
     D3D12_SHADER_VARIABLE_DESC VarDesc;
     ZeroMemory(&VarDesc, sizeof(VarDesc));
     ZeroMemory(&VarDesc, sizeof(VarDesc));
-    VarDesc.uFlags |= D3D_SVF_USED; // Will update in SetCBufferUsage.
+    VarDesc.uFlags = (bAllUsed || fieldAnnotation.IsCBVarUsed()) ? D3D_SVF_USED : 0;
     CShaderReflectionVariable Var;
     CShaderReflectionVariable Var;
     //Create reflection type.
     //Create reflection type.
     CShaderReflectionType *pVarType = new CShaderReflectionType();
     CShaderReflectionType *pVarType = new CShaderReflectionType();
@@ -1211,7 +1274,7 @@ void CShaderReflectionConstantBuffer::InitializeStructuredBuffer(
   VarDesc.Size = CalcResTypeSize(M, R);
   VarDesc.Size = CalcResTypeSize(M, R);
   VarDesc.StartTexture = UINT_MAX;
   VarDesc.StartTexture = UINT_MAX;
   VarDesc.StartSampler = UINT_MAX;
   VarDesc.StartSampler = UINT_MAX;
-  VarDesc.uFlags |= D3D_SVF_USED; // TODO: not necessarily true
+  VarDesc.uFlags |= D3D_SVF_USED;
   CShaderReflectionVariable Var;
   CShaderReflectionVariable Var;
   CShaderReflectionType *pVarType = nullptr;
   CShaderReflectionType *pVarType = nullptr;
 
 
@@ -1476,26 +1539,37 @@ static unsigned GetCBOffset(Value *V) {
   }
   }
 }
 }
 
 
-void CollectInPhiChain(PHINode *cbUser, std::vector<unsigned> &cbufUsage,
-                  unsigned offset, std::unordered_set<Value *> &userSet) {
+static unsigned GetOffsetForCBExtractValue(ExtractValueInst *EV, bool bMinPrecision) {
+  DXASSERT(EV->getNumIndices() == 1, "otherwise, unexpected indices/type for extractvalue");
+  unsigned typeSize = 4;
+  unsigned bits = EV->getType()->getScalarSizeInBits();
+  if (bits == 64)
+    typeSize = 8;
+  else if (bits == 16 && !bMinPrecision)
+    typeSize = 2;
+  return (EV->getIndices().front() * typeSize);
+}
+
+static void CollectInPhiChain(PHINode *cbUser, std::vector<unsigned> &cbufUsage,
+                              unsigned offset, std::unordered_set<Value *> &userSet,
+                              bool bMinPrecision) {
   if (userSet.count(cbUser) > 0)
   if (userSet.count(cbUser) > 0)
     return;
     return;
 
 
   userSet.insert(cbUser);
   userSet.insert(cbUser);
   for (User *cbU : cbUser->users()) {
   for (User *cbU : cbUser->users()) {
     if (ExtractValueInst *EV = dyn_cast<ExtractValueInst>(cbU)) {
     if (ExtractValueInst *EV = dyn_cast<ExtractValueInst>(cbU)) {
-      for (unsigned idx : EV->getIndices()) {
-        cbufUsage.emplace_back(offset + idx * 4);
-      }
+      cbufUsage.emplace_back(offset + GetOffsetForCBExtractValue(EV, bMinPrecision));
     } else {
     } else {
       PHINode *phi = cast<PHINode>(cbU);
       PHINode *phi = cast<PHINode>(cbU);
-      CollectInPhiChain(phi, cbufUsage, offset, userSet);
+      CollectInPhiChain(phi, cbufUsage, offset, userSet, bMinPrecision);
     }
     }
   }
   }
 }
 }
 
 
 static void CollectCBufUsage(Value *cbHandle,
 static void CollectCBufUsage(Value *cbHandle,
-                             std::vector<unsigned> &cbufUsage) {
+                             std::vector<unsigned> &cbufUsage,
+                             bool bMinPrecision) {
   for (User *U : cbHandle->users()) {
   for (User *U : cbHandle->users()) {
     CallInst *CI = cast<CallInst>(U);
     CallInst *CI = cast<CallInst>(U);
     ConstantInt *opcodeV =
     ConstantInt *opcodeV =
@@ -1509,13 +1583,11 @@ static void CollectCBufUsage(Value *cbHandle,
       offset <<= 4;
       offset <<= 4;
       for (User *cbU : U->users()) {
       for (User *cbU : U->users()) {
         if (ExtractValueInst *EV = dyn_cast<ExtractValueInst>(cbU)) {
         if (ExtractValueInst *EV = dyn_cast<ExtractValueInst>(cbU)) {
-          for (unsigned idx : EV->getIndices()) {
-            cbufUsage.emplace_back(offset + idx * 4);
-          }
+          cbufUsage.emplace_back(offset + GetOffsetForCBExtractValue(EV, bMinPrecision));
         } else {
         } else {
           PHINode *phi = cast<PHINode>(cbU);
           PHINode *phi = cast<PHINode>(cbU);
           std::unordered_set<Value *> userSet;
           std::unordered_set<Value *> userSet;
-          CollectInPhiChain(phi, cbufUsage, offset, userSet);
+          CollectInPhiChain(phi, cbufUsage, offset, userSet, bMinPrecision);
         }
         }
       }
       }
     } else if (opcode == DXIL::OpCode::CBufferLoad) {
     } else if (opcode == DXIL::OpCode::CBufferLoad) {
@@ -1531,7 +1603,7 @@ static void CollectCBufUsage(Value *cbHandle,
 }
 }
 
 
 static void SetCBufVarUsage(CShaderReflectionConstantBuffer &cb,
 static void SetCBufVarUsage(CShaderReflectionConstantBuffer &cb,
-                            std::vector<unsigned> usage) {
+                            std::vector<unsigned> &usage) {
   D3D12_SHADER_BUFFER_DESC Desc;
   D3D12_SHADER_BUFFER_DESC Desc;
   if (FAILED(cb.GetDesc(&Desc)))
   if (FAILED(cb.GetDesc(&Desc)))
     return;
     return;
@@ -1590,7 +1662,7 @@ void DxilShaderReflection::SetCBufferUsage() {
     ConstantInt *immResClass = cast<ConstantInt>(resClass);
     ConstantInt *immResClass = cast<ConstantInt>(resClass);
     if (immResClass->getLimitedValue() == (unsigned)DXIL::ResourceClass::CBuffer) {
     if (immResClass->getLimitedValue() == (unsigned)DXIL::ResourceClass::CBuffer) {
       ConstantInt *cbID = cast<ConstantInt>(handle.get_rangeId());
       ConstantInt *cbID = cast<ConstantInt>(handle.get_rangeId());
-      CollectCBufUsage(U, cbufUsage[cbID->getLimitedValue()]);
+      CollectCBufUsage(U, cbufUsage[cbID->getLimitedValue()], m_pDxilModule->GetUseMinPrecision());
     }
     }
   }
   }
 
 
@@ -1605,7 +1677,7 @@ void DxilModuleReflection::CreateReflectionObjects() {
   // Create constant buffers, resources and signatures.
   // Create constant buffers, resources and signatures.
   for (auto && cb : m_pDxilModule->GetCBuffers()) {
   for (auto && cb : m_pDxilModule->GetCBuffers()) {
     std::unique_ptr<CShaderReflectionConstantBuffer> rcb(new CShaderReflectionConstantBuffer());
     std::unique_ptr<CShaderReflectionConstantBuffer> rcb(new CShaderReflectionConstantBuffer());
-    rcb->Initialize(*m_pDxilModule, *(cb.get()), m_Types);
+    rcb->Initialize(*m_pDxilModule, *(cb.get()), m_Types, m_bUsageInMetadata);
     m_CBs.emplace_back(std::move(rcb));
     m_CBs.emplace_back(std::move(rcb));
   }
   }
 
 
@@ -1771,7 +1843,14 @@ void DxilShaderReflection::CreateReflectionObjectsForSignature(
     // D3D11_43 does not have MinPrecison.
     // D3D11_43 does not have MinPrecison.
     if (m_PublicAPI != PublicAPI::D3D11_43)
     if (m_PublicAPI != PublicAPI::D3D11_43)
       Desc.MinPrecision = CompTypeToMinPrecision(SigElem->GetCompType());
       Desc.MinPrecision = CompTypeToMinPrecision(SigElem->GetCompType());
-    Desc.ReadWriteMask = Sig.IsInput() ? 0 : Desc.Mask; // Start with output-never-written/input-never-read.
+    if (m_bUsageInMetadata) {
+      unsigned UsageMask = SigElem->GetUsageMask();
+      if (SigElem->IsAllocated())
+        UsageMask <<= SigElem->GetStartCol();
+      Desc.ReadWriteMask = Sig.IsInput() ? UsageMask : NegMask(UsageMask);
+    } else {
+      Desc.ReadWriteMask = Sig.IsInput() ? 0 : Desc.Mask; // Start with output-never-written/input-never-read.
+    }
     Desc.Register = SigElem->GetStartRow();
     Desc.Register = SigElem->GetStartRow();
     Desc.Stream = SigElem->GetOutputStream();
     Desc.Stream = SigElem->GetOutputStream();
     Desc.SystemValueType = SemanticToSystemValueType(SigElem->GetSemantic(), m_pDxilModule->GetTessellatorDomain());
     Desc.SystemValueType = SemanticToSystemValueType(SigElem->GetSemantic(), m_pDxilModule->GetTessellatorDomain());
@@ -1818,12 +1897,16 @@ LPCSTR DxilShaderReflection::CreateUpperCase(LPCSTR pValue) {
   return m_UpperCaseNames.back().get();
   return m_UpperCaseNames.back().get();
 }
 }
 
 
-HRESULT DxilModuleReflection::LoadModule(IDxcBlob *pBlob,
-                                         const DxilPartHeader *pPart) {
-  DXASSERT_NOMSG(pBlob != nullptr);
-  DXASSERT_NOMSG(pPart != nullptr);
-  m_pContainer = pBlob;
-  const char *pData = GetDxilPartData(pPart);
+HRESULT DxilModuleReflection::LoadRDAT(const DxilPartHeader *pPart) {
+  if (pPart) {
+    IFRBOOL(m_RDAT.InitFromRDAT(GetDxilPartData(pPart), pPart->PartSize), DXC_E_CONTAINER_INVALID);
+  }
+  return S_OK;
+}
+
+HRESULT DxilModuleReflection::LoadModule(const DxilPartHeader *pShaderPart) {
+  DXASSERT_NOMSG(pShaderPart != nullptr);
+  const char *pData = GetDxilPartData(pShaderPart);
   try {
   try {
     const char *pBitcode;
     const char *pBitcode;
     uint32_t bitcodeLength;
     uint32_t bitcodeLength;
@@ -1842,25 +1925,33 @@ HRESULT DxilModuleReflection::LoadModule(IDxcBlob *pBlob,
     }
     }
     std::swap(m_pModule, module.get());
     std::swap(m_pModule, module.get());
     m_pDxilModule = &m_pModule->GetOrCreateDxilModule();
     m_pDxilModule = &m_pModule->GetOrCreateDxilModule();
+
+    unsigned ValMajor, ValMinor;
+    m_pDxilModule->GetValidatorVersion(ValMajor, ValMinor);
+    m_bUsageInMetadata = hlsl::DXIL::CompareVersions(ValMajor, ValMinor, 1, 5) >= 0;
+
     CreateReflectionObjects();
     CreateReflectionObjects();
     return S_OK;
     return S_OK;
   }
   }
   CATCH_CPP_RETURN_HRESULT();
   CATCH_CPP_RETURN_HRESULT();
 };
 };
 
 
-HRESULT DxilShaderReflection::Load(IDxcBlob *pBlob,
-                                   const DxilPartHeader *pPart) {
-  IFR(LoadModule(pBlob, pPart));
+HRESULT DxilShaderReflection::Load(const DxilPartHeader *pModulePart,
+                                   const DxilPartHeader *pRDATPart) {
+  IFR(LoadRDAT(pRDATPart));
+  IFR(LoadModule(pModulePart));
 
 
   try {
   try {
     // Set cbuf usage.
     // Set cbuf usage.
-    SetCBufferUsage();
+    if (!m_bUsageInMetadata)
+      SetCBufferUsage();
 
 
     // Populate input/output/patch constant signatures.
     // Populate input/output/patch constant signatures.
     CreateReflectionObjectsForSignature(m_pDxilModule->GetInputSignature(), m_InputSignature);
     CreateReflectionObjectsForSignature(m_pDxilModule->GetInputSignature(), m_InputSignature);
     CreateReflectionObjectsForSignature(m_pDxilModule->GetOutputSignature(), m_OutputSignature);
     CreateReflectionObjectsForSignature(m_pDxilModule->GetOutputSignature(), m_OutputSignature);
     CreateReflectionObjectsForSignature(m_pDxilModule->GetPatchConstOrPrimSignature(), m_PatchConstantSignature);
     CreateReflectionObjectsForSignature(m_pDxilModule->GetPatchConstOrPrimSignature(), m_PatchConstantSignature);
-    MarkUsedSignatureElements();
+    if (!m_bUsageInMetadata)
+      MarkUsedSignatureElements();
     return S_OK;
     return S_OK;
   }
   }
   CATCH_CPP_RETURN_HRESULT();
   CATCH_CPP_RETURN_HRESULT();
@@ -1952,37 +2043,51 @@ void DxilShaderReflection::MarkUsedSignatureElements() {
     DxilInst_StoreOutput SO(&*I);
     DxilInst_StoreOutput SO(&*I);
     DxilInst_LoadPatchConstant LPC(&*I);
     DxilInst_LoadPatchConstant LPC(&*I);
     DxilInst_StorePatchConstant SPC(&*I);
     DxilInst_StorePatchConstant SPC(&*I);
+    DxilInst_StoreVertexOutput SVO(&*I);
+    DxilInst_StorePrimitiveOutput SPO(&*I);
     std::vector<D3D12_SIGNATURE_PARAMETER_DESC> *pDescs;
     std::vector<D3D12_SIGNATURE_PARAMETER_DESC> *pDescs;
     const DxilSignature *pSig;
     const DxilSignature *pSig;
     uint32_t col, row, sigId;
     uint32_t col, row, sigId;
     if (LI) {
     if (LI) {
       if (!GetUnsignedVal(LI.get_inputSigId(), &sigId)) continue;
       if (!GetUnsignedVal(LI.get_inputSigId(), &sigId)) continue;
       if (!GetUnsignedVal(LI.get_colIndex(), &col)) continue;
       if (!GetUnsignedVal(LI.get_colIndex(), &col)) continue;
-      if (!GetUnsignedVal(LI.get_rowIndex(), &row)) continue;
+      GetUnsignedVal(LI.get_rowIndex(), &row);
       pDescs = &m_InputSignature;
       pDescs = &m_InputSignature;
       pSig = &m_pDxilModule->GetInputSignature();
       pSig = &m_pDxilModule->GetInputSignature();
     }
     }
     else if (SO) {
     else if (SO) {
       if (!GetUnsignedVal(SO.get_outputSigId(), &sigId)) continue;
       if (!GetUnsignedVal(SO.get_outputSigId(), &sigId)) continue;
       if (!GetUnsignedVal(SO.get_colIndex(), &col)) continue;
       if (!GetUnsignedVal(SO.get_colIndex(), &col)) continue;
-      if (!GetUnsignedVal(SO.get_rowIndex(), &row)) continue;
+      GetUnsignedVal(SO.get_rowIndex(), &row);
       pDescs = &m_OutputSignature;
       pDescs = &m_OutputSignature;
       pSig = &m_pDxilModule->GetOutputSignature();
       pSig = &m_pDxilModule->GetOutputSignature();
     }
     }
     else if (SPC) {
     else if (SPC) {
       if (!GetUnsignedVal(SPC.get_outputSigID(), &sigId)) continue;
       if (!GetUnsignedVal(SPC.get_outputSigID(), &sigId)) continue;
       if (!GetUnsignedVal(SPC.get_col(), &col)) continue;
       if (!GetUnsignedVal(SPC.get_col(), &col)) continue;
-      if (!GetUnsignedVal(SPC.get_row(), &row)) continue;
+      GetUnsignedVal(SPC.get_row(), &row);
       pDescs = &m_PatchConstantSignature;
       pDescs = &m_PatchConstantSignature;
       pSig = &m_pDxilModule->GetPatchConstOrPrimSignature();
       pSig = &m_pDxilModule->GetPatchConstOrPrimSignature();
     }
     }
     else if (LPC) {
     else if (LPC) {
       if (!GetUnsignedVal(LPC.get_inputSigId(), &sigId)) continue;
       if (!GetUnsignedVal(LPC.get_inputSigId(), &sigId)) continue;
       if (!GetUnsignedVal(LPC.get_col(), &col)) continue;
       if (!GetUnsignedVal(LPC.get_col(), &col)) continue;
-      if (!GetUnsignedVal(LPC.get_row(), &row)) continue;
+      GetUnsignedVal(LPC.get_row(), &row);
       pDescs = &m_PatchConstantSignature;
       pDescs = &m_PatchConstantSignature;
       pSig = &m_pDxilModule->GetPatchConstOrPrimSignature();
       pSig = &m_pDxilModule->GetPatchConstOrPrimSignature();
     }
     }
+    else if (SVO) {
+      if (!GetUnsignedVal(SVO.get_outputSigId(), &sigId)) continue;
+      if (!GetUnsignedVal(SVO.get_colIndex(), &col)) continue;
+      GetUnsignedVal(SVO.get_rowIndex(), &row);
+      pSig = &m_pDxilModule->GetOutputSignature();
+    }
+    else if (SPO) {
+      if (!GetUnsignedVal(SPO.get_outputSigId(), &sigId)) continue;
+      if (!GetUnsignedVal(SPO.get_colIndex(), &col)) continue;
+      GetUnsignedVal(SPO.get_rowIndex(), &row);
+      pSig = &m_pDxilModule->GetPatchConstOrPrimSignature();
+    }
     else {
     else {
       continue;
       continue;
     }
     }
@@ -2328,94 +2433,67 @@ HRESULT CFunctionReflection::GetResourceBindingDescByName(LPCSTR Name,
 
 
 // DxilLibraryReflection
 // DxilLibraryReflection
 
 
-// From DxilContainerAssembler:
-static llvm::Function *FindUsingFunction(llvm::Value *User) {
-  if (llvm::Instruction *I = dyn_cast<llvm::Instruction>(User)) {
-    // Instruction should be inside a basic block, which is in a function
-    return cast<llvm::Function>(I->getParent()->getParent());
-  }
-  // User can be either instruction, constant, or operator. But User is an
-  // operator only if constant is a scalar value, not resource pointer.
-  llvm::Constant *CU = cast<llvm::Constant>(User);
-  if (!CU->user_empty())
-    return FindUsingFunction(*CU->user_begin());
-  else
-    return nullptr;
-}
-
-void DxilLibraryReflection::AddResourceUseToFunctions(DxilResourceBase &resource, unsigned resIndex) {
-  Constant *var = resource.GetGlobalSymbol();
-  if (var) {
-    for (auto user : var->users()) {
-      // Find the function.
-      if (llvm::Function *F = FindUsingFunction(user)) {
-        auto funcReflector = m_FunctionsByPtr[F];
-        funcReflector->AddResourceReference(resIndex);
-        if (resource.GetClass() == DXIL::ResourceClass::CBuffer) {
-          funcReflector->AddCBReference(resource.GetID());
-        }
-      }
-    }
-  }
-}
-
 void DxilLibraryReflection::AddResourceDependencies() {
 void DxilLibraryReflection::AddResourceDependencies() {
+  RDAT::FunctionTableReader *functionTable = m_RDAT.GetFunctionTableReader();
+  m_FunctionVector.clear();
+  m_FunctionVector.reserve(functionTable->GetNumFunctions());
   std::map<StringRef, CFunctionReflection*> orderedMap;
   std::map<StringRef, CFunctionReflection*> orderedMap;
-  for (auto &F : m_pModule->functions()) {
-    if (F.isDeclaration())
-      continue;
-    auto &func = m_FunctionMap[F.getName()];
+
+  RDAT::ResourceTableReader *resourceTable = m_RDAT.GetResourceTableReader();
+  unsigned SamplersStart = resourceTable->GetNumCBuffers();
+  unsigned SRVsStart = SamplersStart + resourceTable->GetNumSamplers();
+  unsigned UAVsStart = SRVsStart + resourceTable->GetNumSRVs();
+  IFTBOOL(resourceTable->GetNumResources() == m_Resources.size(),
+          DXC_E_INCORRECT_DXIL_METADATA);
+
+  for (unsigned iFunc = 0; iFunc < functionTable->GetNumFunctions(); ++iFunc) {
+    RDAT::FunctionReader FR = functionTable->GetItem(iFunc);
+    auto &func = m_FunctionMap[FR.GetName()];
     DXASSERT(!func.get(), "otherwise duplicate named functions");
     DXASSERT(!func.get(), "otherwise duplicate named functions");
+    Function *F = m_pModule->getFunction(FR.GetName());
     func.reset(new CFunctionReflection());
     func.reset(new CFunctionReflection());
-    func->Initialize(this, &F);
-    m_FunctionsByPtr[&F] = func.get();
-    orderedMap[F.getName()] = func.get();
+    func->Initialize(this, F);
+    m_FunctionsByPtr[F] = func.get();
+    orderedMap[FR.GetName()] = func.get();
+
+    for (unsigned iRes = 0; iRes < FR.GetNumResources(); ++iRes) {
+      RDAT::ResourceReader RR = FR.GetResource(iRes);
+      unsigned id = RR.GetID();
+      switch (RR.GetResourceClass()) {
+      case DXIL::ResourceClass::CBuffer:
+        func->AddResourceReference(id);
+        func->AddCBReference(id);
+        break;
+      case DXIL::ResourceClass::Sampler:
+        func->AddResourceReference(SamplersStart + id);
+        break;
+      case DXIL::ResourceClass::SRV:
+        func->AddResourceReference(SRVsStart + id);
+        break;
+      case DXIL::ResourceClass::UAV:
+        func->AddResourceReference(UAVsStart + id);
+        break;
+      default:
+        DXASSERT(false, "Unrecognized ResourceClass in RDAT");
+      }
+    }
   }
   }
-  // Fill in function vector sorted by name
-  m_FunctionVector.clear();
-  m_FunctionVector.reserve(orderedMap.size());
+
   for (auto &it : orderedMap) {
   for (auto &it : orderedMap) {
     m_FunctionVector.push_back(it.second);
     m_FunctionVector.push_back(it.second);
   }
   }
-  UINT resIndex = 0;
-  for (auto &resource : m_Resources) {
-    switch ((UINT32)resource.Type) {
-    case D3D_SIT_CBUFFER:
-      AddResourceUseToFunctions(m_pDxilModule->GetCBuffer(resource.uID), resIndex);
-      break;
-    case D3D_SIT_TBUFFER:   // TODO: Handle when TBuffers are added to CB list
-    case D3D_SIT_TEXTURE:
-    case D3D_SIT_STRUCTURED:
-    case D3D_SIT_BYTEADDRESS:
-    case D3D_SIT_RTACCELERATIONSTRUCTURE:
-      AddResourceUseToFunctions(m_pDxilModule->GetSRV(resource.uID), resIndex);
-      break;
-    case D3D_SIT_UAV_RWTYPED:
-    case D3D_SIT_UAV_RWSTRUCTURED:
-    case D3D_SIT_UAV_RWBYTEADDRESS:
-    case D3D_SIT_UAV_APPEND_STRUCTURED:
-    case D3D_SIT_UAV_CONSUME_STRUCTURED:
-    case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER:
-      AddResourceUseToFunctions(m_pDxilModule->GetUAV(resource.uID), resIndex);
-      break;
-    case D3D_SIT_SAMPLER:
-      AddResourceUseToFunctions(m_pDxilModule->GetSampler(resource.uID), resIndex);
-      break;
-    }
-    resIndex++;
-  }
 }
 }
 
 
-static void CollectCBufUsageForLib(Value *V, std::vector<unsigned> &cbufUsage) {
+static void CollectCBufUsageForLib(Value *V, std::vector<unsigned> &cbufUsage, bool bMinPrecision) {
   for (auto user : V->users()) {
   for (auto user : V->users()) {
     Value *V = user;
     Value *V = user;
     if (auto *CI = dyn_cast<CallInst>(V)) {
     if (auto *CI = dyn_cast<CallInst>(V)) {
       if (hlsl::OP::IsDxilOpFuncCallInst(CI, hlsl::OP::OpCode::CreateHandleForLib)) {
       if (hlsl::OP::IsDxilOpFuncCallInst(CI, hlsl::OP::OpCode::CreateHandleForLib)) {
-        CollectCBufUsage(CI, cbufUsage);
+        CollectCBufUsage(CI, cbufUsage, bMinPrecision);
       }
       }
     } else if (isa<GEPOperator>(V) ||
     } else if (isa<GEPOperator>(V) ||
                isa<LoadInst>(V)) {
                isa<LoadInst>(V)) {
-      CollectCBufUsageForLib(user, cbufUsage);
+      CollectCBufUsageForLib(user, cbufUsage, bMinPrecision);
     }
     }
   }
   }
 }
 }
@@ -2425,7 +2503,7 @@ void DxilLibraryReflection::SetCBufferUsage() {
 
 
   for (unsigned i=0;i<cbSize;i++) {
   for (unsigned i=0;i<cbSize;i++) {
     std::vector<unsigned> cbufUsage;
     std::vector<unsigned> cbufUsage;
-    CollectCBufUsageForLib(m_pDxilModule->GetCBuffer(i).GetGlobalSymbol(), cbufUsage);
+    CollectCBufUsageForLib(m_pDxilModule->GetCBuffer(i).GetGlobalSymbol(), cbufUsage, m_pDxilModule->GetUseMinPrecision());
     SetCBufVarUsage(*m_CBs[i], cbufUsage);
     SetCBufVarUsage(*m_CBs[i], cbufUsage);
   }
   }
 }
 }
@@ -2433,13 +2511,15 @@ void DxilLibraryReflection::SetCBufferUsage() {
 
 
 // ID3D12LibraryReflection
 // ID3D12LibraryReflection
 
 
-HRESULT DxilLibraryReflection::Load(IDxcBlob *pBlob,
-  const DxilPartHeader *pPart) {
-  IFR(LoadModule(pBlob, pPart));
+HRESULT DxilLibraryReflection::Load(const DxilPartHeader *pModulePart,
+                                    const DxilPartHeader *pRDATPart) {
+  IFR(LoadRDAT(pRDATPart));
+  IFR(LoadModule(pModulePart));
 
 
   try {
   try {
     AddResourceDependencies();
     AddResourceDependencies();
-    SetCBufferUsage();
+    if (!m_bUsageInMetadata)
+      SetCBufferUsage();
     return S_OK;
     return S_OK;
   }
   }
   CATCH_CPP_RETURN_HRESULT();
   CATCH_CPP_RETURN_HRESULT();

+ 112 - 3
lib/HLSL/DxilPreparePasses.cpp

@@ -17,6 +17,7 @@
 #include "dxc/DXIL/DxilTypeSystem.h"
 #include "dxc/DXIL/DxilTypeSystem.h"
 #include "dxc/DXIL/DxilUtil.h"
 #include "dxc/DXIL/DxilUtil.h"
 #include "dxc/DXIL/DxilFunctionProps.h"
 #include "dxc/DXIL/DxilFunctionProps.h"
+#include "dxc/DXIL/DxilInstructions.h"
 #include "llvm/IR/GetElementPtrTypeIterator.h"
 #include "llvm/IR/GetElementPtrTypeIterator.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/Instructions.h"
@@ -246,6 +247,88 @@ void CheckInBoundForTGSM(GlobalVariable &GV, const DataLayout &DL) {
   }
   }
 }
 }
 
 
+static bool GetUnsignedVal(Value *V, uint32_t *pValue) {
+  ConstantInt *CI = dyn_cast<ConstantInt>(V);
+  if (!CI) return false;
+  uint64_t u = CI->getZExtValue();
+  if (u > UINT32_MAX) return false;
+  *pValue = (uint32_t)u;
+  return true;
+}
+
+static uint8_t NegMask(uint8_t V) {
+  V ^= 0xF;
+  return V & 0xF;
+}
+
+static void MarkUsedSignatureElements(Function *F, DxilModule &DM) {
+  DXASSERT_NOMSG(F != nullptr);
+  // For every loadInput/storeOutput, update the corresponding ReadWriteMask.
+  // F is a pointer to a Function instance
+  for (llvm::inst_iterator I = llvm::inst_begin(F), E = llvm::inst_end(F); I != E; ++I) {
+    DxilInst_LoadInput LI(&*I);
+    DxilInst_StoreOutput SO(&*I);
+    DxilInst_LoadPatchConstant LPC(&*I);
+    DxilInst_StorePatchConstant SPC(&*I);
+    DxilInst_StoreVertexOutput SVO(&*I);
+    DxilInst_StorePrimitiveOutput SPO(&*I);
+    DxilSignature *pSig;
+    uint32_t col, row, sigId;
+    bool bDynIdx = false;
+    if (LI) {
+      if (!GetUnsignedVal(LI.get_inputSigId(), &sigId)) continue;
+      if (!GetUnsignedVal(LI.get_colIndex(), &col)) continue;
+      if (!GetUnsignedVal(LI.get_rowIndex(), &row)) bDynIdx = true;
+      pSig = &DM.GetInputSignature();
+    }
+    else if (SO) {
+      if (!GetUnsignedVal(SO.get_outputSigId(), &sigId)) continue;
+      if (!GetUnsignedVal(SO.get_colIndex(), &col)) continue;
+      if (!GetUnsignedVal(SO.get_rowIndex(), &row)) bDynIdx = true;
+      pSig = &DM.GetOutputSignature();
+    }
+    else if (SPC) {
+      if (!GetUnsignedVal(SPC.get_outputSigID(), &sigId)) continue;
+      if (!GetUnsignedVal(SPC.get_col(), &col)) continue;
+      if (!GetUnsignedVal(SPC.get_row(), &row)) bDynIdx = true;
+      pSig = &DM.GetPatchConstOrPrimSignature();
+    }
+    else if (LPC) {
+      if (!GetUnsignedVal(LPC.get_inputSigId(), &sigId)) continue;
+      if (!GetUnsignedVal(LPC.get_col(), &col)) continue;
+      if (!GetUnsignedVal(LPC.get_row(), &row)) bDynIdx = true;
+      pSig = &DM.GetPatchConstOrPrimSignature();
+    }
+    else if (SVO) {
+      if (!GetUnsignedVal(SVO.get_outputSigId(), &sigId)) continue;
+      if (!GetUnsignedVal(SVO.get_colIndex(), &col)) continue;
+      if (!GetUnsignedVal(SVO.get_rowIndex(), &row)) bDynIdx = true;
+      pSig = &DM.GetOutputSignature();
+    }
+    else if (SPO) {
+      if (!GetUnsignedVal(SPO.get_outputSigId(), &sigId)) continue;
+      if (!GetUnsignedVal(SPO.get_colIndex(), &col)) continue;
+      if (!GetUnsignedVal(SPO.get_rowIndex(), &row)) bDynIdx = true;
+      pSig = &DM.GetPatchConstOrPrimSignature();
+    }
+    else {
+      continue;
+    }
+
+    // Consider being more fine-grained about masks.
+    // We report sometimes-read on input as always-read.
+    auto &El = pSig->GetElement(sigId);
+    unsigned UsageMask = El.GetUsageMask();
+    unsigned colBit = 1 << col;
+    if (!(colBit & UsageMask)) {
+      El.SetUsageMask(UsageMask | colBit);
+    }
+    if (bDynIdx && (El.GetDynIdxCompMask() & colBit) == 0) {
+      El.SetDynIdxCompMask(El.GetDynIdxCompMask() | colBit);
+    }
+  }
+}
+
 class DxilFinalizeModule : public ModulePass {
 class DxilFinalizeModule : public ModulePass {
 public:
 public:
   static char ID; // Pass identification, replacement for typeid
   static char ID; // Pass identification, replacement for typeid
@@ -283,16 +366,21 @@ public:
   bool runOnModule(Module &M) override {
   bool runOnModule(Module &M) override {
     if (M.HasDxilModule()) {
     if (M.HasDxilModule()) {
       DxilModule &DM = M.GetDxilModule();
       DxilModule &DM = M.GetDxilModule();
+      unsigned ValMajor = 0;
+      unsigned ValMinor = 0;
+      M.GetDxilModule().GetValidatorVersion(ValMajor, ValMinor);
 
 
       bool IsLib = DM.GetShaderModel()->IsLib();
       bool IsLib = DM.GetShaderModel()->IsLib();
       // Skip validation patch for lib.
       // Skip validation patch for lib.
       if (!IsLib) {
       if (!IsLib) {
-        unsigned ValMajor = 0;
-        unsigned ValMinor = 0;
-        M.GetDxilModule().GetValidatorVersion(ValMajor, ValMinor);
         if (ValMajor == 1 && ValMinor <= 1) {
         if (ValMajor == 1 && ValMinor <= 1) {
           patchValidation_1_1(M);
           patchValidation_1_1(M);
         }
         }
+
+        // Set used masks for signature elements
+        MarkUsedSignatureElements(DM.GetEntryFunction(), DM);
+        if (DM.GetShaderModel()->IsHS())
+          MarkUsedSignatureElements(DM.GetPatchConstantFunction(), DM);
       }
       }
 
 
       // Remove store undef output.
       // Remove store undef output.
@@ -319,6 +407,11 @@ public:
       // Clear intermediate options that shouldn't be in the final DXIL
       // Clear intermediate options that shouldn't be in the final DXIL
       DM.ClearIntermediateOptions();
       DM.ClearIntermediateOptions();
 
 
+      if (IsLib && DXIL::CompareVersions(ValMajor, ValMinor, 1, 4) <= 0) {
+        // 1.4 validator requires function annotations for all functions
+        AddFunctionAnnotationForInitializers(M, DM);
+      }
+
       return true;
       return true;
     }
     }
 
 
@@ -468,6 +561,22 @@ private:
       }
       }
     }
     }
   }
   }
+
+  void AddFunctionAnnotationForInitializers(Module &M, DxilModule &DM) {
+    if (GlobalVariable *GV = M.getGlobalVariable("llvm.global_ctors")) {
+      ConstantArray *init = cast<ConstantArray>(GV->getInitializer());
+      for (auto V : init->operand_values()) {
+        if (isa<ConstantAggregateZero>(V))
+          continue;
+        ConstantStruct *CS = cast<ConstantStruct>(V);
+        if (isa<ConstantPointerNull>(CS->getOperand(1)))
+          continue;
+        Function *F = cast<Function>(CS->getOperand(1));
+        if (DM.GetTypeSystem().GetFunctionAnnotation(F) == nullptr)
+          DM.GetTypeSystem().AddFunctionAnnotation(F);
+      }
+    }
+  }
 };
 };
 }
 }
 
 

+ 4 - 9
lib/HLSL/DxilValidation.cpp

@@ -104,7 +104,6 @@ const char *hlsl::GetValidationRuleText(ValidationRule value) {
     case hlsl::ValidationRule::MetaTessellatorOutputPrimitive: return "Invalid Tessellator Output Primitive specified. Must be point, line, triangleCW or triangleCCW.";
     case hlsl::ValidationRule::MetaTessellatorOutputPrimitive: return "Invalid Tessellator Output Primitive specified. Must be point, line, triangleCW or triangleCCW.";
     case hlsl::ValidationRule::MetaMaxTessFactor: return "Hull Shader MaxTessFactor must be [%0..%1].  %2 specified";
     case hlsl::ValidationRule::MetaMaxTessFactor: return "Hull Shader MaxTessFactor must be [%0..%1].  %2 specified";
     case hlsl::ValidationRule::MetaValidSamplerMode: return "Invalid sampler mode on sampler ";
     case hlsl::ValidationRule::MetaValidSamplerMode: return "Invalid sampler mode on sampler ";
-    case hlsl::ValidationRule::MetaFunctionAnnotation: return "Cannot find function annotation for %0";
     case hlsl::ValidationRule::MetaGlcNotOnAppendConsume: return "globallycoherent cannot be used with append/consume buffers";
     case hlsl::ValidationRule::MetaGlcNotOnAppendConsume: return "globallycoherent cannot be used with append/consume buffers";
     case hlsl::ValidationRule::MetaStructBufAlignment: return "structured buffer element size must be a multiple of %0 bytes (actual size %1 bytes)";
     case hlsl::ValidationRule::MetaStructBufAlignment: return "structured buffer element size must be a multiple of %0 bytes (actual size %1 bytes)";
     case hlsl::ValidationRule::MetaStructBufAlignmentOutOfBound: return "structured buffer elements cannot be larger than %0 bytes (actual size %1 bytes)";
     case hlsl::ValidationRule::MetaStructBufAlignmentOutOfBound: return "structured buffer elements cannot be larger than %0 bytes (actual size %1 bytes)";
@@ -3593,13 +3592,6 @@ static void ValidateFunction(Function &F, ValidationContext &ValCtx) {
     if (isShader && !F.getReturnType()->isVoidTy())
     if (isShader && !F.getReturnType()->isVoidTy())
       ValCtx.EmitFormatError(ValidationRule::DeclShaderReturnVoid, { F.getName() });
       ValCtx.EmitFormatError(ValidationRule::DeclShaderReturnVoid, { F.getName() });
 
 
-    DxilFunctionAnnotation *funcAnnotation =
-        ValCtx.DxilMod.GetTypeSystem().GetFunctionAnnotation(&F);
-    if (!funcAnnotation) {
-      ValCtx.EmitFormatError(ValidationRule::MetaFunctionAnnotation, { F.getName() });
-      return;
-    }
-
     auto ArgFormatError = [&](Argument &arg, ValidationRule rule) {
     auto ArgFormatError = [&](Argument &arg, ValidationRule rule) {
       if (arg.hasName())
       if (arg.hasName())
         ValCtx.EmitFormatError(rule, { arg.getName().str(), F.getName() });
         ValCtx.EmitFormatError(rule, { arg.getName().str(), F.getName() });
@@ -5727,7 +5719,10 @@ static void VerifySignatureMatches(_In_ ValidationContext &ValCtx,
     pName = "Program Output Signature";
     pName = "Program Output Signature";
     break;
     break;
   case hlsl::DXIL::SignatureKind::PatchConstOrPrim:
   case hlsl::DXIL::SignatureKind::PatchConstOrPrim:
-    pName = "Program Patch Constant or Primitive Signature";
+    if (ValCtx.DxilMod.GetShaderModel()->GetKind() == DXIL::ShaderKind::Mesh)
+      pName = "Program Primitive Signature";
+    else
+      pName = "Program Patch Constant Signature";
     break;
     break;
   default:
   default:
     break;
     break;

+ 2 - 8
lib/Transforms/IPO/GlobalDCE.cpp

@@ -25,10 +25,6 @@
 #include "llvm/Transforms/Utils/GlobalStatus.h"
 #include "llvm/Transforms/Utils/GlobalStatus.h"
 #include "llvm/Pass.h"
 #include "llvm/Pass.h"
 #include <unordered_map>
 #include <unordered_map>
-#include "dxc/HLSL/HLModule.h" // HLSL Change
-#include "dxc/DXIL/DxilModule.h" // HLSL Change
-#include "dxc/DXIL/DxilOperations.h" // HLSL Change
-#include "dxc/DXIL/DxilInstructions.h" // HLSL Change
 using namespace llvm;
 using namespace llvm;
 
 
 #define DEBUG_TYPE "globaldce"
 #define DEBUG_TYPE "globaldce"
@@ -166,14 +162,12 @@ bool GlobalDCE::runOnModule(Module &M) {
       I->setAliasee(nullptr);
       I->setAliasee(nullptr);
     } 
     } 
 
 
-  hlsl::HLModule *HLM = M.HasHLModule() ? &M.GetHLModule() : nullptr; // HLSL Change
-
   if (!DeadFunctions.empty()) {
   if (!DeadFunctions.empty()) {
     // Now that all interferences have been dropped, delete the actual objects
     // Now that all interferences have been dropped, delete the actual objects
     // themselves.
     // themselves.
     for (unsigned i = 0, e = DeadFunctions.size(); i != e; ++i) {
     for (unsigned i = 0, e = DeadFunctions.size(); i != e; ++i) {
       RemoveUnusedGlobalValue(*DeadFunctions[i]);
       RemoveUnusedGlobalValue(*DeadFunctions[i]);
-      if (HLM != nullptr) HLM->RemoveFunction(DeadFunctions[i]); // HLSL Change
+      M.CallRemoveGlobalHook(DeadFunctions[i]); // HLSL Change
       M.getFunctionList().erase(DeadFunctions[i]);
       M.getFunctionList().erase(DeadFunctions[i]);
     }
     }
     NumFunctions += DeadFunctions.size();
     NumFunctions += DeadFunctions.size();
@@ -183,7 +177,7 @@ bool GlobalDCE::runOnModule(Module &M) {
   if (!DeadGlobalVars.empty()) {
   if (!DeadGlobalVars.empty()) {
     for (unsigned i = 0, e = DeadGlobalVars.size(); i != e; ++i) {
     for (unsigned i = 0, e = DeadGlobalVars.size(); i != e; ++i) {
       RemoveUnusedGlobalValue(*DeadGlobalVars[i]);
       RemoveUnusedGlobalValue(*DeadGlobalVars[i]);
-      if (HLM != nullptr) HLM->RemoveGlobal(DeadGlobalVars[i]); // HLSL Change
+      M.CallRemoveGlobalHook(DeadGlobalVars[i]); // HLSL Change
       M.getGlobalList().erase(DeadGlobalVars[i]);
       M.getGlobalList().erase(DeadGlobalVars[i]);
     }
     }
     NumVariables += DeadGlobalVars.size();
     NumVariables += DeadGlobalVars.size();

+ 16 - 9
tools/clang/lib/CodeGen/CGHLSLMS.cpp

@@ -366,6 +366,22 @@ CGMSHLSLRuntime::CGMSHLSLRuntime(CodeGenModule &CGM)
     Diags.Report(DiagID) << CGM.getCodeGenOpts().HLSLProfile;
     Diags.Report(DiagID) << CGM.getCodeGenOpts().HLSLProfile;
     return;
     return;
   }
   }
+  if (CGM.getCodeGenOpts().HLSLValidatorMajorVer != 0) {
+    // Check validator version against minimum for target profile:
+    unsigned MinMajor, MinMinor;
+    SM->GetMinValidatorVersion(MinMajor, MinMinor);
+    if (DXIL::CompareVersions(CGM.getCodeGenOpts().HLSLValidatorMajorVer,
+                              CGM.getCodeGenOpts().HLSLValidatorMinorVer,
+                              MinMajor, MinMinor) < 0) {
+      DiagnosticsEngine &Diags = CGM.getDiags();
+      unsigned DiagID =
+          Diags.getCustomDiagID(DiagnosticsEngine::Error,
+            "validator version %0,%1 does not support target profile.");
+      Diags.Report(DiagID) << CGM.getCodeGenOpts().HLSLValidatorMajorVer
+                           << CGM.getCodeGenOpts().HLSLValidatorMinorVer;
+      return;
+    }
+  }
   m_bIsLib = SM->IsLib();
   m_bIsLib = SM->IsLib();
   // TODO: add AllResourceBound.
   // TODO: add AllResourceBound.
   if (CGM.getCodeGenOpts().HLSLAvoidControlFlow && !CGM.getCodeGenOpts().HLSLAllResourcesBound) {
   if (CGM.getCodeGenOpts().HLSLAvoidControlFlow && !CGM.getCodeGenOpts().HLSLAllResourcesBound) {
@@ -2443,15 +2459,6 @@ void CGMSHLSLRuntime::addSubobject(Decl *D) {
   VarDecl *VD = dyn_cast<VarDecl>(D);
   VarDecl *VD = dyn_cast<VarDecl>(D);
   DXASSERT(VD != nullptr, "must be a global variable");
   DXASSERT(VD != nullptr, "must be a global variable");
 
 
-  if (CGM.getCodeGenOpts().HLSLValidatorMajorVer == 1 &&
-      CGM.getCodeGenOpts().HLSLValidatorMinorVer < 4) {
-    // subobjects unsupported with this validator
-    DiagnosticsEngine &Diags = CGM.getDiags();
-    unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, "subobjects are not supported by current validator version");
-    Diags.Report(D->getLocStart(), DiagID);
-    return;
-  }
- 
   DXIL::SubobjectKind subobjKind;
   DXIL::SubobjectKind subobjKind;
   DXIL::HitGroupType hgType;
   DXIL::HitGroupType hgType;
   if (!hlsl::GetHLSLSubobjectKind(VD->getType(), subobjKind, hgType)) {
   if (!hlsl::GetHLSLSubobjectKind(VD->getType(), subobjKind, hgType)) {

+ 3 - 4
tools/clang/test/CodeGenHLSL/batch/compiler_options/Qstrip_reflect.hlsl

@@ -1,8 +1,7 @@
-// RUN: %dxc -E main -T ps_6_0 %s -Qstrip_reflect | FileCheck %s
+// RUN: %dxilver 1.5 | %dxc -E main -T ps_6_0 %s -Qstrip_reflect | FileCheck %s
 
 
-// Make sure only function annotation, no struct annotation.
-// CHECK:!dx.typeAnnotations = !{[[FuncAnnot:[^,]+]]}
-// CHECK:[[FuncAnnot]] = !{i32 1, void ()* @main,
+// Make sure there are no type annotations
+// CHECK-NOT: !dx.typeAnnotations
 
 
 //--------------------------------------------------------------------------------------
 //--------------------------------------------------------------------------------------
 // File: BasicHLSL11_PS.hlsl
 // File: BasicHLSL11_PS.hlsl

+ 3 - 4
tools/clang/test/CodeGenHLSL/batch/compiler_options/Qstrip_reflect_struct_buf.hlsl

@@ -1,4 +1,4 @@
-// RUN: %dxc -E main -T ps_6_2 -enable-16bit-types -HV 2018 -Qstrip_reflect %s  | FileCheck %s
+// RUN: %dxilver 1.5 | %dxc -E main -T ps_6_2 -enable-16bit-types -HV 2018 -Qstrip_reflect %s  | FileCheck %s
 
 
 
 
 struct MyStruct1
 struct MyStruct1
@@ -76,6 +76,5 @@ float4 main() : SV_Target {
     return 1;
     return 1;
 }
 }
 
 
-// Make sure only function annotation, no struct annotation.
-// CHECK:!dx.typeAnnotations = !{[[FuncAnnot:[^,]+]]}
-// CHECK:[[FuncAnnot]] = !{i32 1, void ()* @main,
+// Make sure there are no type annotations
+// CHECK-NOT: !dx.typeAnnotations

+ 1 - 1
tools/clang/test/CodeGenHLSL/batch/compiler_options/pack_clip_cull/optimized2.hlsl

@@ -1,4 +1,4 @@
-// RUN: %dxc -E main -T vs_6_0 -pack_optimized %s | FileCheck %s
+// RUN: %dxilver 1.5 | %dxc -E main -T vs_6_0 -pack_optimized %s | FileCheck %s
 
 
 // CHECK:      ; Output signature:
 // CHECK:      ; Output signature:
 // CHECK:      ; Name                 Index   Mask Register SysValue  Format   Used
 // CHECK:      ; Name                 Index   Mask Register SysValue  Format   Used

+ 1 - 1
tools/clang/test/CodeGenHLSL/batch/compiler_options/pack_clip_cull/optimized3.hlsl

@@ -1,4 +1,4 @@
-// RUN: %dxc -E main -T vs_6_0 -pack_optimized %s | FileCheck %s
+// RUN: %dxilver 1.5 | %dxc -E main -T vs_6_0 -pack_optimized %s | FileCheck %s
 
 
 // CHECK:      ; Output signature:
 // CHECK:      ; Output signature:
 // CHECK:      ; Name                 Index   Mask Register SysValue  Format   Used
 // CHECK:      ; Name                 Index   Mask Register SysValue  Format   Used

+ 1 - 1
tools/clang/test/CodeGenHLSL/batch/compiler_options/pack_clip_cull/prefix_stable2.hlsl

@@ -1,4 +1,4 @@
-// RUN: %dxc -E main -T vs_6_0 -pack_prefix_stable %s | FileCheck %s
+// RUN: %dxilver 1.5 | %dxc -E main -T vs_6_0 -pack_prefix_stable %s | FileCheck %s
 
 
 // CHECK:      ; Output signature:
 // CHECK:      ; Output signature:
 // CHECK:      ; Name                 Index   Mask Register SysValue  Format   Used
 // CHECK:      ; Name                 Index   Mask Register SysValue  Format   Used

+ 1 - 1
tools/clang/test/CodeGenHLSL/batch/compiler_options/pack_clip_cull/prefix_stable3.hlsl

@@ -1,4 +1,4 @@
-// RUN: %dxc -E main -T vs_6_0 -pack_prefix_stable %s | FileCheck %s
+// RUN: %dxilver 1.5 | %dxc -E main -T vs_6_0 -pack_prefix_stable %s | FileCheck %s
 
 
 // CHECK:      ; Output signature:
 // CHECK:      ; Output signature:
 // CHECK:      ; Name                 Index   Mask Register SysValue  Format   Used
 // CHECK:      ; Name                 Index   Mask Register SysValue  Format   Used

+ 2 - 2
tools/clang/test/CodeGenHLSL/batch/debug/locals/scalarized_vector.hlsl

@@ -4,8 +4,8 @@
 
 
 // CHECK: %[[x:.*]] = add i32
 // CHECK: %[[x:.*]] = add i32
 // CHECK: %[[y:.*]] = add i32
 // CHECK: %[[y:.*]] = add i32
-// CHECK-DAG: call void @llvm.dbg.value(metadata i32 %[[x]], i64 0, metadata ![[vec:.*]], metadata ![[xexp:.*]]), !dbg !46
-// CHECK-DAG: call void @llvm.dbg.value(metadata i32 %[[y]], i64 0, metadata ![[vec]], metadata ![[yexp:.*]]), !dbg !46
+// CHECK-DAG: call void @llvm.dbg.value(metadata i32 %[[x]], i64 0, metadata ![[vec:.*]], metadata ![[xexp:.*]])
+// CHECK-DAG: call void @llvm.dbg.value(metadata i32 %[[y]], i64 0, metadata ![[vec]], metadata ![[yexp:.*]])
 
 
 // Exclude quoted source file (see readme)
 // Exclude quoted source file (see readme)
 // CHECK-LABEL: {{!"[^"]*\\0A[^"]*"}}
 // CHECK-LABEL: {{!"[^"]*\\0A[^"]*"}}

+ 2 - 2
tools/clang/test/CodeGenHLSL/batch/debug/misc/share_mem_dbg.hlsl

@@ -1,4 +1,4 @@
-// RUN: %dxc -E main -T cs_6_0 -Zi -Od -DDefineA -DDefineB=0 %s | FileCheck %s
+// RUN: %dxc -E main -T cs_6_0 -Zi -Od -DDefineA -DDefineB=0 %s -Qstrip_reflect | FileCheck %s
 
 
 // CHECK: threadId
 // CHECK: threadId
 // CHECK: groupId
 // CHECK: groupId
@@ -22,7 +22,7 @@
 // Make sure source info contents exist.
 // Make sure source info contents exist.
 // CHECK: !{!"DefineA=1", !"DefineB=0"}
 // CHECK: !{!"DefineA=1", !"DefineB=0"}
 // CHECK: share_mem_dbg.hlsl"}
 // CHECK: share_mem_dbg.hlsl"}
-// CHECK: !{!"-E", !"main", !"-T", !"cs_6_0", !"-Zi", !"-Od", !"-D", !"DefineA", !"-D", !"DefineB=0"}
+// CHECK: !{!"-E", !"main", !"-T", !"cs_6_0", !"-Zi", !"-Od", !"-D", !"DefineA", !"-D", !"DefineB=0", !"-Qstrip_reflect"}
 
 
 
 
 struct S {
 struct S {

+ 2 - 2
tools/clang/test/CodeGenHLSL/batch/debug/types/struct_resource_numerical.hlsl

@@ -10,8 +10,8 @@
 // Texture types are currently 64 bits due to an implementation detail.
 // Texture types are currently 64 bits due to an implementation detail.
 // If this changes, this test can be safely updated.
 // If this changes, this test can be safely updated.
 // CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "TexAndCoord", {{.*}}, size: 96, align: 32
 // CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "TexAndCoord", {{.*}}, size: 96, align: 32
-// CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "tex", scope: !53, {{.*}}, size: 64, align: 32
-// CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "u", scope: !53, {{.*}}, size: 32, align: 32, offset: 64
+// CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "tex", scope: {{.*}}, size: 64, align: 32
+// CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "u", scope: {{.*}}, size: 32, align: 32, offset: 64
 
 
 // The bit_piece for 'tc.u' should be right after the texture.
 // The bit_piece for 'tc.u' should be right after the texture.
 // CHECK-DAG: !DIExpression(DW_OP_bit_piece, 64, 32)
 // CHECK-DAG: !DIExpression(DW_OP_bit_piece, 64, 32)

+ 1 - 1
tools/clang/test/CodeGenHLSL/batch/declarations/resources/constant_buffers/array1.hlsl

@@ -1,4 +1,4 @@
-// RUN: %dxc -E main -T ps_6_0 %s | FileCheck %s
+// RUN: %dxilver 1.5 | %dxc -E main -T ps_6_0 %s | FileCheck %s
 
 
 
 
 // CHECK: cbuffer $Globals
 // CHECK: cbuffer $Globals

+ 1 - 1
tools/clang/test/CodeGenHLSL/batch/misc/d3dreflect/cb_sizes.hlsl

@@ -1,4 +1,4 @@
-// RUN: %dxc -E main -T vs_6_0 %s | %D3DReflect %s | FileCheck %s
+// RUN: %dxilver 1.5 | %dxc -E main -T vs_6_0 %s | %D3DReflect %s | FileCheck %s
 
 
 // Verify CB variable sizes align with expectations.
 // Verify CB variable sizes align with expectations.
 // This also tests some matrix, struct, and array cases that may
 // This also tests some matrix, struct, and array cases that may

+ 1 - 1
tools/clang/test/CodeGenHLSL/batch/misc/d3dreflect/cbuf-usage-lib.hlsl

@@ -1,4 +1,4 @@
-// RUN: %dxc -auto-binding-space 13 -T lib_6_3 %s | %D3DReflect %s | FileCheck %s
+// RUN: %dxilver 1.5 | %dxc -auto-binding-space 13 -T lib_6_3 %s | %D3DReflect %s | FileCheck %s
 
 
 // Make sure usage flag is set properly for cbuffers used in libraries
 // Make sure usage flag is set properly for cbuffers used in libraries
 
 

+ 1 - 1
tools/clang/test/CodeGenHLSL/batch/misc/d3dreflect/empty_struct2.hlsl

@@ -1,4 +1,4 @@
-// RUN: %dxc -E main -T vs_6_0 %s | %D3DReflect %s | FileCheck %s
+// RUN: %dxilver 1.5 | %dxc -E main -T vs_6_0 %s | %D3DReflect %s | FileCheck %s
 
 
 // Make sure nest empty struct works.
 // Make sure nest empty struct works.
 
 

+ 125 - 0
tools/clang/test/CodeGenHLSL/batch/misc/d3dreflect/lib_global.hlsl

@@ -0,0 +1,125 @@
+// RUN: %dxilver 1.5 | %dxc -T lib_6_3 -enable-16bit-types %s | %D3DReflect %s | FileCheck %s
+
+// Note: validator version 1.5 is required because these tests use
+// module disassembly -> reassembly between steps, and type annotations
+// compatible with the 1.4 validator does not have usage metadata, so it's lost.
+
+// Make sure CB usage is correct.
+#if 0
+// CHECK: ID3D12LibraryReflection:
+// CHECK-NEXT:   D3D12_LIBRARY_DESC:
+// CHECK-NEXT:     Creator: <nullptr>
+// CHECK-NEXT:     Flags: 0
+// CHECK-NEXT:     FunctionCount: 2
+// CHECK-NEXT:   ID3D12FunctionReflection:
+// CHECK-NEXT:     D3D12_FUNCTION_DESC: Name: _GLOBAL__sub_I_lib_global.hlsl
+// CHECK-NEXT:       Shader Version: Library 6.3
+// CHECK-NEXT:       Creator: <nullptr>
+// CHECK-NEXT:       Flags: 0
+// CHECK-NEXT:       ConstantBuffers: 1
+// CHECK-NEXT:       BoundResources: 1
+// CHECK-NEXT:       FunctionParameterCount: 0
+// CHECK-NEXT:       HasReturn: FALSE
+// CHECK-NEXT:     Constant Buffers:
+// CHECK-NEXT:       ID3D12ShaderReflectionConstantBuffer:
+// CHECK-NEXT:         D3D12_SHADER_BUFFER_DESC: Name: X
+// CHECK-NEXT:           Type: D3D_CT_CBUFFER
+// CHECK-NEXT:           Size: 16
+// CHECK-NEXT:           uFlags: 0
+// CHECK-NEXT:           Num Variables: 2
+// CHECK-NEXT:         {
+// CHECK-NEXT:           ID3D12ShaderReflectionVariable:
+// CHECK-NEXT:             D3D12_SHADER_VARIABLE_DESC: Name: e
+// CHECK-NEXT:               Size: 2
+// CHECK-NEXT:               StartOffset: 0
+// CHECK-NEXT:               uFlags: 0
+// CHECK-NEXT:               DefaultValue: <nullptr>
+// CHECK-NEXT:             ID3D12ShaderReflectionType:
+// CHECK-NEXT:               D3D12_SHADER_TYPE_DESC: Name: float16_t
+// CHECK-NEXT:                 Class: D3D_SVC_SCALAR
+// CHECK-NEXT:                 Type: D3D_SVT_MIN16FLOAT
+// CHECK-NEXT:                 Elements: 0
+// CHECK-NEXT:                 Rows: 1
+// CHECK-NEXT:                 Columns: 1
+// CHECK-NEXT:                 Members: 0
+// CHECK-NEXT:                 Offset: 0
+// CHECK-NEXT:             CBuffer: X
+// CHECK-NEXT:           ID3D12ShaderReflectionVariable:
+// CHECK-NEXT:             D3D12_SHADER_VARIABLE_DESC: Name: f
+// CHECK-NEXT:               Size: 2
+// CHECK-NEXT:               StartOffset: 2
+// CHECK-NEXT:               uFlags: 0x2
+// CHECK-NEXT:               DefaultValue: <nullptr>
+// CHECK-NEXT:             ID3D12ShaderReflectionType:
+// CHECK-NEXT:               D3D12_SHADER_TYPE_DESC: Name: float16_t
+// CHECK-NEXT:                 Class: D3D_SVC_SCALAR
+// CHECK-NEXT:                 Type: D3D_SVT_MIN16FLOAT
+// CHECK-NEXT:                 Elements: 0
+// CHECK-NEXT:                 Rows: 1
+// CHECK-NEXT:                 Columns: 1
+// CHECK-NEXT:                 Members: 0
+// CHECK-NEXT:                 Offset: 0
+// CHECK-NEXT:             CBuffer: X
+// CHECK-NEXT:         }
+// CHECK-NEXT:     Bound Resources:
+// CHECK-NEXT:       D3D12_SHADER_BUFFER_DESC: Name: X
+// CHECK-NEXT:         Type: D3D_SIT_CBUFFER
+// CHECK-NEXT:         uID: 0
+// CHECK-NEXT:         BindCount: 1
+// CHECK-NEXT:         BindPoint: 4294967295
+// CHECK-NEXT:         Space: 4294967295
+// CHECK-NEXT:         ReturnType: <unknown: 0>
+// CHECK-NEXT:         Dimension: D3D_SRV_DIMENSION_UNKNOWN
+// CHECK-NEXT:         NumSamples (or stride): 0
+// CHECK-NEXT:         uFlags: 0
+// CHECK-NEXT:   ID3D12FunctionReflection:
+// CHECK-NEXT:     D3D12_FUNCTION_DESC: Name: test
+// CHECK-NEXT:       Shader Version: Pixel 6.3
+// CHECK-NEXT:       Creator: <nullptr>
+// CHECK-NEXT:       Flags: 0
+// CHECK-NEXT:       ConstantBuffers: 0
+// CHECK-NEXT:       BoundResources: 2
+// CHECK-NEXT:       FunctionParameterCount: 0
+// CHECK-NEXT:       HasReturn: FALSE
+// CHECK-NEXT:     Bound Resources:
+// CHECK-NEXT:       D3D12_SHADER_BUFFER_DESC: Name: g_samLinear
+// CHECK-NEXT:         Type: D3D_SIT_SAMPLER
+// CHECK-NEXT:         uID: 0
+// CHECK-NEXT:         BindCount: 1
+// CHECK-NEXT:         BindPoint: 4294967295
+// CHECK-NEXT:         Space: 4294967295
+// CHECK-NEXT:         ReturnType: <unknown: 0>
+// CHECK-NEXT:         Dimension: D3D_SRV_DIMENSION_UNKNOWN
+// CHECK-NEXT:         NumSamples (or stride): 0
+// CHECK-NEXT:         uFlags: 0
+// CHECK-NEXT:       D3D12_SHADER_BUFFER_DESC: Name: g_txDiffuse
+// CHECK-NEXT:         Type: D3D_SIT_TEXTURE
+// CHECK-NEXT:         uID: 0
+// CHECK-NEXT:         BindCount: 1
+// CHECK-NEXT:         BindPoint: 4294967295
+// CHECK-NEXT:         Space: 4294967295
+// CHECK-NEXT:         ReturnType: D3D_RETURN_TYPE_FLOAT
+// CHECK-NEXT:         Dimension: D3D_SRV_DIMENSION_TEXTURE2D
+// CHECK-NEXT:         NumSamples (or stride): 4294967295
+// CHECK-NEXT:         uFlags: 0xc
+#endif
+
+Texture2D    g_txDiffuse;
+SamplerState    g_samLinear;
+
+cbuffer X {
+  half e, f;
+}
+
+static float g[2] = { 1, f };
+
+[shader("pixel")]
+float4 test(float2 c : C) : SV_TARGET
+{
+  float4 x = g_txDiffuse.Sample( g_samLinear, c );
+  return x + g[1];
+}
+
+void update() {
+  g[1]++;
+}

+ 1 - 1
tools/clang/test/CodeGenHLSL/batch/misc/d3dreflect/reflect-lib-1.hlsl

@@ -1,4 +1,4 @@
-// RUN: %dxc -T lib_6_3 -auto-binding-space 11 -default-linkage external %s | %D3DReflect %s | FileCheck %s
+// RUN: %dxilver 1.5 | %dxc -T lib_6_3 -auto-binding-space 11 -default-linkage external %s | %D3DReflect %s | FileCheck %s
 
 
 float cbval1;
 float cbval1;
 cbuffer MyCB : register(b11, space2) { int4 cbval2, cbval3; }
 cbuffer MyCB : register(b11, space2) { int4 cbval2, cbval3; }

+ 1 - 1
tools/clang/test/CodeGenHLSL/batch/misc/d3dreflect/structured_buffer_layout.hlsl

@@ -1,4 +1,4 @@
-// RUN: %dxc -E main -T vs_6_0 %s | %D3DReflect %s | FileCheck %s
+// RUN: %dxilver 1.5 | %dxc -E main -T vs_6_0 %s | %D3DReflect %s | FileCheck %s
 
 
 // Verify SB type description does not follow the CB offseting alignment
 // Verify SB type description does not follow the CB offseting alignment
 // even when structure is shared with a ConstantBuffer.
 // even when structure is shared with a ConstantBuffer.

+ 1 - 1
tools/clang/test/CodeGenHLSL/batch/misc/sig-bool-as-uint.hlsl

@@ -1,4 +1,4 @@
-// RUN: %dxc -E main -T ps_6_0 %s | FileCheck %s
+// RUN: %dxilver 1.5 | %dxc -E main -T ps_6_0 %s | FileCheck %s
 
 
 // make sure bool maps to uint in signature
 // make sure bool maps to uint in signature
 // CHECK: ; BOOL                     0   x           0     NONE    uint
 // CHECK: ; BOOL                     0   x           0     NONE    uint

+ 1 - 1
tools/clang/test/CodeGenHLSL/batch/misc/static_const_global.hlsl

@@ -1,4 +1,4 @@
-// RUN: %dxc -T lib_6_3 -auto-binding-space 11 %s | FileCheck %s
+// RUN: %dxilver 1.5 | %dxc -T lib_6_3 -auto-binding-space 11 %s | FileCheck %s
 
 
 // Make sure ST is removed
 // Make sure ST is removed
 // CHECK-NOT: @ST
 // CHECK-NOT: @ST

+ 1 - 1
tools/clang/test/CodeGenHLSL/batch/shader_stages/raytracing/subobjects_raytracingPipelineConfig1.hlsl

@@ -1,4 +1,4 @@
-// RUN: %dxc -T lib_6_3 %s | FileCheck %s
+// RUN: %dxilver 1.5 | %dxc -T lib_6_3 %s | FileCheck %s
 
 
 // CHECK: ; GlobalRootSignature grs = { <48 bytes> };
 // CHECK: ; GlobalRootSignature grs = { <48 bytes> };
 // CHECK: ; StateObjectConfig soc = { STATE_OBJECT_FLAG_ALLOW_LOCAL_DEPENDENCIES_ON_EXTERNAL_DEFINITIONS | STATE_OBJECT_FLAG_ALLOW_STATE_OBJECT_ADDITIONS };
 // CHECK: ; StateObjectConfig soc = { STATE_OBJECT_FLAG_ALLOW_LOCAL_DEPENDENCIES_ON_EXTERNAL_DEFINITIONS | STATE_OBJECT_FLAG_ALLOW_STATE_OBJECT_ADDITIONS };

+ 1 - 1
tools/clang/test/CodeGenHLSL/batch/validation/rawbufferstore_uav.hlsl

@@ -1,4 +1,4 @@
-// RUN: %dxc -T vs_6_2 -E main %s | FileCheck %s
+// RUN: %dxilver 1.5 | %dxc -T vs_6_2 -E main %s | FileCheck %s
 
 
 // CHECK: store should be on uav resource
 // CHECK: store should be on uav resource
 
 

+ 4 - 1
tools/clang/test/CodeGenHLSL/lib_global.hlsl

@@ -4,7 +4,10 @@ Texture2D    g_txDiffuse;
 SamplerState    g_samLinear;
 SamplerState    g_samLinear;
 
 
 cbuffer X {
 cbuffer X {
-float f;
+  // Use min-precision type to force conversion of constant buffer type for legacy.
+  // This has to happen at link time at the moment, so this will break unless type
+  // annotations are retained for library.
+  min16float f;
 }
 }
 
 
 static float g[2] = { 1, f };
 static float g[2] = { 1, f };

+ 1 - 1
tools/clang/tools/dxcompiler/dxcassembler.cpp

@@ -141,7 +141,7 @@ HRESULT STDMETHODCALLTYPE DxcAssembler::AssembleToContainer(
     outStream.flush();
     outStream.flush();
 
 
     CComPtr<IDxcBlob> pResultBlob;
     CComPtr<IDxcBlob> pResultBlob;
-    hlsl::SerializeDxilFlags flags = hlsl::SerializeDxilFlags::None;
+    hlsl::SerializeDxilFlags flags = hlsl::SerializeDxilFlags::IncludeReflectionPart;
     if (HasDebugInfo(*M)) {
     if (HasDebugInfo(*M)) {
       flags |= SerializeDxilFlags::IncludeDebugInfoPart;
       flags |= SerializeDxilFlags::IncludeDebugInfoPart;
       flags |= SerializeDxilFlags::IncludeDebugNamePart;
       flags |= SerializeDxilFlags::IncludeDebugNamePart;

+ 33 - 3
tools/clang/tools/dxcompiler/dxcdisassembler.cpp

@@ -1549,6 +1549,8 @@ namespace dxcutil {
 HRESULT Disassemble(IDxcBlob *pProgram, raw_string_ostream &Stream) {
 HRESULT Disassemble(IDxcBlob *pProgram, raw_string_ostream &Stream) {
   const char *pIL = (const char *)pProgram->GetBufferPointer();
   const char *pIL = (const char *)pProgram->GetBufferPointer();
   uint32_t pILLength = pProgram->GetBufferSize();
   uint32_t pILLength = pProgram->GetBufferSize();
+  const char *pReflectionIL = nullptr;
+  uint32_t pReflectionILLength = 0;
   const DxilPartHeader *pRDATPart = nullptr;
   const DxilPartHeader *pRDATPart = nullptr;
   if (const DxilContainerHeader *pContainer =
   if (const DxilContainerHeader *pContainer =
           IsDxilContainerLike(pIL, pILLength)) {
           IsDxilContainerLike(pIL, pILLength)) {
@@ -1649,6 +1651,18 @@ HRESULT Disassemble(IDxcBlob *pProgram, raw_string_ostream &Stream) {
     }
     }
 
 
     GetDxilProgramBitcode(pProgramHeader, &pIL, &pILLength);
     GetDxilProgramBitcode(pProgramHeader, &pIL, &pILLength);
+
+    it = std::find_if(begin(pContainer), end(pContainer),
+                      DxilPartIsType(DFCC_ShaderStatistics));
+    if (it != end(pContainer)) {
+      // If this part exists, use it for reflection data, probably stripped from DXIL part.
+      const DxilProgramHeader *pReflectionProgramHeader =
+          reinterpret_cast<const DxilProgramHeader *>(GetDxilPartData(*it));
+      if (IsValidDxilProgramHeader(pReflectionProgramHeader, (*it)->PartSize)) {
+        GetDxilProgramBitcode(pReflectionProgramHeader, &pReflectionIL, &pReflectionILLength);
+      }
+    }
+
   } else {
   } else {
     const DxilProgramHeader *pProgramHeader =
     const DxilProgramHeader *pProgramHeader =
         reinterpret_cast<const DxilProgramHeader *>(pIL);
         reinterpret_cast<const DxilProgramHeader *>(pIL);
@@ -1665,8 +1679,20 @@ HRESULT Disassemble(IDxcBlob *pProgram, raw_string_ostream &Stream) {
     return DXC_E_IR_VERIFICATION_FAILED;
     return DXC_E_IR_VERIFICATION_FAILED;
   }
   }
 
 
+  std::unique_ptr<llvm::Module> pReflectionModule;
+  if (pReflectionIL && pReflectionILLength) {
+    pReflectionModule = dxilutil::LoadModuleFromBitcode(
+      llvm::StringRef(pReflectionIL, pReflectionILLength), llvmContext, DiagStr);
+    if (pReflectionModule.get() == nullptr) {
+      return DXC_E_IR_VERIFICATION_FAILED;
+    }
+  }
+
   if (pModule->getNamedMetadata("dx.version")) {
   if (pModule->getNamedMetadata("dx.version")) {
     DxilModule &dxilModule = pModule->GetOrCreateDxilModule();
     DxilModule &dxilModule = pModule->GetOrCreateDxilModule();
+    DxilModule &dxilReflectionModule = pReflectionModule.get()
+      ? pReflectionModule->GetOrCreateDxilModule()
+      : dxilModule;
 
 
     if (!dxilModule.GetShaderModel()->IsLib()) {
     if (!dxilModule.GetShaderModel()->IsLib()) {
       PrintDxilSignature("Input", dxilModule.GetInputSignature(), Stream,
       PrintDxilSignature("Input", dxilModule.GetInputSignature(), Stream,
@@ -1685,9 +1711,9 @@ HRESULT Disassemble(IDxcBlob *pProgram, raw_string_ostream &Stream) {
                            /*comment*/ ";");
                            /*comment*/ ";");
       }
       }
     }
     }
-    PrintBufferDefinitions(dxilModule, Stream, /*comment*/ ";");
-    PrintResourceBindings(dxilModule, Stream, /*comment*/ ";");
-    PrintViewIdState(dxilModule, Stream, /*comment*/ ";");
+    PrintBufferDefinitions(dxilReflectionModule, Stream, /*comment*/ ";");
+    PrintResourceBindings(dxilReflectionModule, Stream, /*comment*/ ";");
+    PrintViewIdState(dxilReflectionModule, Stream, /*comment*/ ";");
 
 
     if (pRDATPart) {
     if (pRDATPart) {
       RDAT::DxilRuntimeData runtimeData(GetDxilPartData(pRDATPart), pRDATPart->PartSize);
       RDAT::DxilRuntimeData runtimeData(GetDxilPartData(pRDATPart), pRDATPart->PartSize);
@@ -1706,6 +1732,10 @@ HRESULT Disassemble(IDxcBlob *pProgram, raw_string_ostream &Stream) {
   }
   }
   DxcAssemblyAnnotationWriter w;
   DxcAssemblyAnnotationWriter w;
   pModule->print(Stream, &w);
   pModule->print(Stream, &w);
+  //if (pReflectionModule) {
+  //  Stream << "\n========== Reflection Module from STAT part ==========\n";
+  //  pReflectionModule->print(Stream, &w);
+  //}
   Stream.flush();
   Stream.flush();
   return S_OK;
   return S_OK;
 }
 }

+ 8 - 0
tools/clang/tools/dxcompiler/dxclinker.cpp

@@ -114,6 +114,8 @@ HRESULT
 DxcLinker::RegisterLibrary(_In_opt_ LPCWSTR pLibName, // Name of the library.
 DxcLinker::RegisterLibrary(_In_opt_ LPCWSTR pLibName, // Name of the library.
                            _In_ IDxcBlob *pBlob       // Library to add.
                            _In_ IDxcBlob *pBlob       // Library to add.
 ) {
 ) {
+  if (!pLibName || !pBlob)
+    return E_INVALIDARG;
   DXASSERT(m_pLinker.get(), "else Initialize() not called or failed silently");
   DXASSERT(m_pLinker.get(), "else Initialize() not called or failed silently");
   DxcThreadMalloc TM(m_pMalloc);
   DxcThreadMalloc TM(m_pMalloc);
   // Prepare UTF8-encoded versions of API values.
   // Prepare UTF8-encoded versions of API values.
@@ -163,6 +165,8 @@ HRESULT STDMETHODCALLTYPE DxcLinker::Link(
     _COM_Outptr_ IDxcOperationResult *
     _COM_Outptr_ IDxcOperationResult *
         *ppResult // Linker output status, buffer, and errors
         *ppResult // Linker output status, buffer, and errors
 ) {
 ) {
+  if (!pTargetProfile || !pLibNames || libCount == 0 || !ppResult)
+    return E_INVALIDARG;
   DxcThreadMalloc TM(m_pMalloc);
   DxcThreadMalloc TM(m_pMalloc);
   // Prepare UTF8-encoded versions of API values.
   // Prepare UTF8-encoded versions of API values.
   CW2A pUtf8TargetProfile(pTargetProfile, CP_UTF8);
   CW2A pUtf8TargetProfile(pTargetProfile, CP_UTF8);
@@ -209,6 +213,10 @@ HRESULT STDMETHODCALLTYPE DxcLinker::Link(
     m_Ctx.setDiagnosticHandler(PrintDiagnosticContext::PrintDiagnosticHandler,
     m_Ctx.setDiagnosticHandler(PrintDiagnosticContext::PrintDiagnosticHandler,
                                &DiagContext, true);
                                &DiagContext, true);
 
 
+    if (opts.ValVerMajor != UINT32_MAX) {
+      m_pLinker->SetValidatorVersion(opts.ValVerMajor, opts.ValVerMinor);
+    }
+
     // Attach libraries.
     // Attach libraries.
     bool bSuccess = true;
     bool bSuccess = true;
     for (unsigned i = 0; i < libCount; i++) {
     for (unsigned i = 0; i < libCount; i++) {

+ 20 - 11
tools/clang/tools/dxcompiler/dxcompilerobj.cpp

@@ -561,8 +561,6 @@ public:
 
 
       StringRef Data((LPSTR)utf8Source->GetBufferPointer(),
       StringRef Data((LPSTR)utf8Source->GetBufferPointer(),
                      utf8Source->GetBufferSize());
                      utf8Source->GetBufferSize());
-      std::unique_ptr<llvm::MemoryBuffer> pBuffer(
-          llvm::MemoryBuffer::getMemBufferCopy(Data, pUtf8SourceName));
 
 
       // Not very efficient but also not very important.
       // Not very efficient but also not very important.
       std::vector<std::string> defines;
       std::vector<std::string> defines;
@@ -616,19 +614,29 @@ public:
       // NOTE: this calls the validation component from dxil.dll; the built-in
       // NOTE: this calls the validation component from dxil.dll; the built-in
       // validator can be used as a fallback.
       // validator can be used as a fallback.
       bool produceFullContainer = !opts.CodeGenHighLevel && !opts.AstDump && !opts.OptDump && rootSigMajor == 0;
       bool produceFullContainer = !opts.CodeGenHighLevel && !opts.AstDump && !opts.OptDump && rootSigMajor == 0;
-
       bool needsValidation = produceFullContainer && !opts.DisableValidation;
       bool needsValidation = produceFullContainer && !opts.DisableValidation;
+
       // Disable validation for lib_6_1 and lib_6_2.
       // Disable validation for lib_6_1 and lib_6_2.
+      // This is needed for this API because the profile is provided separately,
+      // so the option parsing will not have verified that /Vd was provided.
       if (compiler.getCodeGenOpts().HLSLProfile == "lib_6_1" ||
       if (compiler.getCodeGenOpts().HLSLProfile == "lib_6_1" ||
           compiler.getCodeGenOpts().HLSLProfile == "lib_6_2") {
           compiler.getCodeGenOpts().HLSLProfile == "lib_6_2") {
         needsValidation = false;
         needsValidation = false;
       }
       }
 
 
-      if (needsValidation || (opts.CodeGenHighLevel && !opts.DisableValidation)) {
-        UINT32 majorVer, minorVer;
-        dxcutil::GetValidatorVersion(&majorVer, &minorVer);
-        compiler.getCodeGenOpts().HLSLValidatorMajorVer = majorVer;
-        compiler.getCodeGenOpts().HLSLValidatorMinorVer = minorVer;
+      if (compiler.getCodeGenOpts().HLSLProfile == "lib_6_x") {
+        // Currently do not support stripping reflection from offline linking target.
+        opts.KeepReflectionInDxil = true;
+      }
+
+      if (opts.ValVerMajor != UINT_MAX) {
+        // user-specified validator version override
+        compiler.getCodeGenOpts().HLSLValidatorMajorVer = opts.ValVerMajor;
+        compiler.getCodeGenOpts().HLSLValidatorMinorVer = opts.ValVerMinor;
+      } else {
+        // Version from dxil.dll, or internal validator if unavailable
+        dxcutil::GetValidatorVersion(&compiler.getCodeGenOpts().HLSLValidatorMajorVer,
+                                     &compiler.getCodeGenOpts().HLSLValidatorMinorVer);
       }
       }
 
 
       if (opts.AstDump) {
       if (opts.AstDump) {
@@ -732,9 +740,12 @@ public:
           // Implies name part
           // Implies name part
           SerializeFlags |= SerializeDxilFlags::IncludeDebugNamePart;
           SerializeFlags |= SerializeDxilFlags::IncludeDebugNamePart;
         }
         }
-        if (opts.StripReflection) {
+        if (!opts.KeepReflectionInDxil) {
           SerializeFlags |= SerializeDxilFlags::StripReflectionFromDxilPart;
           SerializeFlags |= SerializeDxilFlags::StripReflectionFromDxilPart;
         }
         }
+        if (!opts.StripReflection) {
+          SerializeFlags |= SerializeDxilFlags::IncludeReflectionPart;
+        }
 
 
         // Don't do work to put in a container if an error has occurred
         // Don't do work to put in a container if an error has occurred
         // Do not create a container when there is only a a high-level representation in the module.
         // Do not create a container when there is only a a high-level representation in the module.
@@ -886,8 +897,6 @@ public:
 
 
       StringRef Data((LPSTR)utf8Source->GetBufferPointer(),
       StringRef Data((LPSTR)utf8Source->GetBufferPointer(),
         utf8Source->GetBufferSize());
         utf8Source->GetBufferSize());
-      std::unique_ptr<llvm::MemoryBuffer> pBuffer(
-        llvm::MemoryBuffer::getMemBufferCopy(Data, pUtf8SourceName));
 
 
       // Not very efficient but also not very important.
       // Not very efficient but also not very important.
       std::vector<std::string> defines;
       std::vector<std::string> defines;

+ 2 - 1
tools/clang/tools/dxcompiler/dxcontainerbuilder.cpp

@@ -123,7 +123,8 @@ HRESULT STDMETHODCALLTYPE DxcContainerBuilder::RemovePart(_In_ UINT32 fourCC) {
     IFTBOOL(fourCC == DxilFourCC::DFCC_ShaderDebugInfoDXIL ||
     IFTBOOL(fourCC == DxilFourCC::DFCC_ShaderDebugInfoDXIL ||
                 fourCC == DxilFourCC::DFCC_ShaderDebugName ||
                 fourCC == DxilFourCC::DFCC_ShaderDebugName ||
                 fourCC == DxilFourCC::DFCC_RootSignature ||
                 fourCC == DxilFourCC::DFCC_RootSignature ||
-                fourCC == DxilFourCC::DFCC_PrivateData,
+                fourCC == DxilFourCC::DFCC_PrivateData ||
+                fourCC == DxilFourCC::DFCC_ShaderStatistics,
             E_INVALIDARG); // You can only remove debug info, debug info name, rootsignature, or private data blob
             E_INVALIDARG); // You can only remove debug info, debug info name, rootsignature, or private data blob
     PartList::iterator it =
     PartList::iterator it =
       std::find_if(m_parts.begin(), m_parts.end(),
       std::find_if(m_parts.begin(), m_parts.end(),

+ 19 - 0
tools/clang/tools/dxcompiler/dxcutil.cpp

@@ -27,6 +27,7 @@
 #include "llvm/Transforms/Utils/Cloning.h"
 #include "llvm/Transforms/Utils/Cloning.h"
 #include "dxc/Support/dxcapi.impl.h"
 #include "dxc/Support/dxcapi.impl.h"
 #include "dxc/Support/HLSLOptions.h"
 #include "dxc/Support/HLSLOptions.h"
+#include "dxc/DXIL/DxilModule.h"
 
 
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Path.h"
 
 
@@ -190,6 +191,24 @@ HRESULT ValidateAndAssembleToContainer(
     llvmModule.SetDebugName(DebugName);
     llvmModule.SetDebugName(DebugName);
   }
   }
 
 
+  // Verify validator version can validate this module
+  CComPtr<IDxcVersionInfo> pValidatorVersion;
+  IFT(pValidator->QueryInterface(&pValidatorVersion));
+  UINT32 ValMajor, ValMinor;
+  IFT(pValidatorVersion->GetVersion(&ValMajor, &ValMinor));
+  DxilModule &DM = llvmModule.get()->GetDxilModule();
+  unsigned ReqValMajor, ReqValMinor;
+  DM.GetValidatorVersion(ReqValMajor, ReqValMinor);
+  if (DXIL::CompareVersions(ValMajor, ValMinor, ReqValMajor, ReqValMinor) < 0) {
+    // Module is expecting to be validated by a newer validator.
+    unsigned diagID =
+      Diag.getCustomDiagID(clang::DiagnosticsEngine::Level::Error,
+        "The module cannot be validated by the version of the validator "
+        "currently attached.");
+    Diag.Report(diagID);
+    return E_FAIL;
+  }
+
   llvmModule.WrapModuleInDxilContainer(pMalloc, pOutputStream, pOutputBlob,
   llvmModule.WrapModuleInDxilContainer(pMalloc, pOutputStream, pOutputBlob,
                                        SerializeFlags, pShaderHashOut);
                                        SerializeFlags, pShaderHashOut);
 
 

+ 1 - 0
tools/clang/unittests/HLSL/CMakeLists.txt

@@ -20,6 +20,7 @@ set( LLVM_LINK_COMPONENTS
   analysis
   analysis
   ipa
   ipa
   irreader
   irreader
+  transformutils  # for CloneModule
   )
   )
 
 
 if(WIN32)
 if(WIN32)

+ 9 - 1
tools/clang/unittests/HLSL/CompilerTest.cpp

@@ -234,7 +234,13 @@ public:
 
 
 #if _ITERATOR_DEBUG_LEVEL==0 
 #if _ITERATOR_DEBUG_LEVEL==0 
   // CompileWhenNoMemThenOOM can properly detect leaks only when debug iterators are disabled
   // CompileWhenNoMemThenOOM can properly detect leaks only when debug iterators are disabled
-  TEST_METHOD(CompileWhenNoMemThenOOM)
+  BEGIN_TEST_METHOD(CompileWhenNoMemThenOOM)
+    // Disabled because there are problems where we try to allocate memory in destructors,
+    // which causes more bad_alloc() throws while unwinding bad_alloc(), which asserts
+    // If only failing one allocation, there are allocations where failing them is lost,
+    // such as in ~raw_string_ostream(), where it flushes, then eats bad_alloc(), if thrown.
+    TEST_METHOD_PROPERTY(L"Ignore", L"true")
+  END_TEST_METHOD()
 #endif
 #endif
   TEST_METHOD(CompileWhenShaderModelMismatchAttributeThenFail)
   TEST_METHOD(CompileWhenShaderModelMismatchAttributeThenFail)
   TEST_METHOD(CompileBadHlslThenFail)
   TEST_METHOD(CompileBadHlslThenFail)
@@ -2871,5 +2877,7 @@ TEST_F(CompilerTest, CodeGenBatch) {
 }
 }
 
 
 TEST_F(CompilerTest, Mesh) {
 TEST_F(CompilerTest, Mesh) {
+  if (m_ver.SkipDxilVersion(1, 5))
+    return;
   CodeGenTestCheckBatchDir(L"mesh");
   CodeGenTestCheckBatchDir(L"mesh");
 }
 }

+ 30 - 0
tools/clang/unittests/HLSL/DxcTestUtils.cpp

@@ -15,6 +15,7 @@
 #include "dxc/Support/HLSLOptions.h"
 #include "dxc/Support/HLSLOptions.h"
 #include "dxc/Support/Global.h"
 #include "dxc/Support/Global.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/APInt.h"
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/Regex.h"
 #include "llvm/Support/Regex.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/FileSystem.h"
@@ -318,6 +319,35 @@ void VerifyCompileOK(dxc::DxcDllSupport &dllSupport, LPCSTR pText,
   VERIFY_SUCCEEDED(pResult->GetResult(ppResult));
   VERIFY_SUCCEEDED(pResult->GetResult(ppResult));
 }
 }
 
 
+HRESULT GetVersion(dxc::DxcDllSupport& DllSupport, REFCLSID clsid, unsigned &Major, unsigned &Minor) {
+  CComPtr<IUnknown> pUnk;
+  if (SUCCEEDED(DllSupport.CreateInstance(clsid, &pUnk))) {
+    CComPtr<IDxcVersionInfo> pVersionInfo;
+    IFR(pUnk.QueryInterface(&pVersionInfo));
+    IFR(pVersionInfo->GetVersion(&Major, &Minor));
+  }
+  return S_OK;
+}
+
+bool ParseTargetProfile(llvm::StringRef targetProfile, llvm::StringRef &outStage, unsigned &outMajor, unsigned &outMinor) {
+  auto stage_model = targetProfile.split("_");
+  auto major_minor = stage_model.second.split("_");
+  llvm::APInt major;
+  if (major_minor.first.getAsInteger(16, major))
+    return false;
+  if (major_minor.second.compare("x") == 0) {
+    outMinor = 0xF;   // indicates offline target
+  } else {
+    llvm::APInt minor;
+    if (major_minor.second.getAsInteger(16, minor))
+      return false;
+    outMinor = (unsigned)minor.getLimitedValue();
+  }
+  outStage = stage_model.first;
+  outMajor = (unsigned)major.getLimitedValue();
+  return true;
+}
+
 // VersionSupportInfo Implementation
 // VersionSupportInfo Implementation
 VersionSupportInfo::VersionSupportInfo()
 VersionSupportInfo::VersionSupportInfo()
     : m_CompilerIsDebugBuild(false), m_InternalValidator(false), m_DxilMajor(0),
     : m_CompilerIsDebugBuild(false), m_InternalValidator(false), m_DxilMajor(0),

+ 4 - 0
tools/clang/unittests/HLSL/DxcTestUtils.h

@@ -16,6 +16,7 @@
 #include "dxc/dxcapi.h"
 #include "dxc/dxcapi.h"
 #include "dxc/Support/dxcapi.use.h"
 #include "dxc/Support/dxcapi.use.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
 
 
 namespace hlsl {
 namespace hlsl {
 namespace options {
 namespace options {
@@ -162,6 +163,9 @@ void VerifyCompileOK(dxc::DxcDllSupport &dllSupport, LPCSTR pText,
                      LPWSTR pTargetProfile, std::vector<LPCWSTR> &args,
                      LPWSTR pTargetProfile, std::vector<LPCWSTR> &args,
                      _Outptr_ IDxcBlob **ppResult);
                      _Outptr_ IDxcBlob **ppResult);
 
 
+HRESULT GetVersion(dxc::DxcDllSupport& DllSupport, REFCLSID clsid, unsigned &Major, unsigned &Minor);
+bool ParseTargetProfile(llvm::StringRef targetProfile, llvm::StringRef &outStage, unsigned &outMajor, unsigned &outMinor);
+
 class VersionSupportInfo {
 class VersionSupportInfo {
 private:
 private:
   bool m_CompilerIsDebugBuild;
   bool m_CompilerIsDebugBuild;

+ 73 - 12
tools/clang/unittests/HLSL/DxilContainerTest.cpp

@@ -160,8 +160,12 @@ public:
     VERIFY_ARE_EQUAL(pTestDesc->ComponentType, pBaseDesc->ComponentType);
     VERIFY_ARE_EQUAL(pTestDesc->ComponentType, pBaseDesc->ComponentType);
     VERIFY_ARE_EQUAL(MaskCount(pTestDesc->Mask), MaskCount(pBaseDesc->Mask));
     VERIFY_ARE_EQUAL(MaskCount(pTestDesc->Mask), MaskCount(pBaseDesc->Mask));
     VERIFY_ARE_EQUAL(pTestDesc->MinPrecision, pBaseDesc->MinPrecision);
     VERIFY_ARE_EQUAL(pTestDesc->MinPrecision, pBaseDesc->MinPrecision);
-    if (!isInput)
-      VERIFY_ARE_EQUAL(pTestDesc->ReadWriteMask != 0, pBaseDesc->ReadWriteMask != 0); // VERIFY_ARE_EQUAL(pTestDesc->ReadWriteMask, pBaseDesc->ReadWriteMask);
+    if (!isInput) {
+      if (hlsl::DXIL::CompareVersions(m_ver.m_ValMajor, m_ver.m_ValMinor, 1, 5) < 0)
+        VERIFY_ARE_EQUAL(pTestDesc->ReadWriteMask != 0, pBaseDesc->ReadWriteMask != 0);
+      else
+        VERIFY_ARE_EQUAL(MaskCount(pTestDesc->ReadWriteMask), MaskCount(pBaseDesc->ReadWriteMask));
+    }
     // VERIFY_ARE_EQUAL(pTestDesc->Register, pBaseDesc->Register);
     // VERIFY_ARE_EQUAL(pTestDesc->Register, pBaseDesc->Register);
     //VERIFY_ARE_EQUAL(pTestDesc->SemanticIndex, pBaseDesc->SemanticIndex);
     //VERIFY_ARE_EQUAL(pTestDesc->SemanticIndex, pBaseDesc->SemanticIndex);
     VERIFY_ARE_EQUAL(pTestDesc->Stream, pBaseDesc->Stream);
     VERIFY_ARE_EQUAL(pTestDesc->Stream, pBaseDesc->Stream);
@@ -332,8 +336,12 @@ public:
     std::vector<FileRunCommandPart> parts;
     std::vector<FileRunCommandPart> parts;
     ParseCommandPartsFromFile(path, parts);
     ParseCommandPartsFromFile(path, parts);
     VERIFY_IS_TRUE(parts.size() > 0);
     VERIFY_IS_TRUE(parts.size() > 0);
-    VERIFY_ARE_EQUAL_STR(parts[0].Command.c_str(), "%dxc");
-    FileRunCommandPart &dxc = parts[0];
+    unsigned partIdx = 0;
+    if (parts[0].Command.compare("%dxilver") == 0) {
+      partIdx = 1;
+    }
+    FileRunCommandPart &dxc = parts[partIdx];
+    VERIFY_ARE_EQUAL_STR(dxc.Command.c_str(), "%dxc");
     m_dllSupport.Initialize();
     m_dllSupport.Initialize();
 
 
     hlsl::options::MainArgs args;
     hlsl::options::MainArgs args;
@@ -500,6 +508,18 @@ public:
 
 
   void ReflectionTest(LPCWSTR name, bool ignoreIfDXBCFails) {
   void ReflectionTest(LPCWSTR name, bool ignoreIfDXBCFails) {
     WEX::Logging::Log::Comment(WEX::Common::String().Format(L"Reflection comparison for %s", name));
     WEX::Logging::Log::Comment(WEX::Common::String().Format(L"Reflection comparison for %s", name));
+
+    // Skip if unsupported.
+    std::vector<FileRunCommandPart> parts;
+    ParseCommandPartsFromFile(name, parts);
+    VERIFY_IS_TRUE(parts.size() > 0);
+    if (parts[0].Command.compare("%dxilver") == 0) {
+      VERIFY_IS_TRUE(parts.size() > 1);
+      auto result = parts[0].Run(m_dllSupport, nullptr);
+      if (result.ExitCode != 0)
+        return;
+    }
+
     CComPtr<IDxcBlob> pProgram;
     CComPtr<IDxcBlob> pProgram;
     CComPtr<IDxcBlob> pProgramDXBC;
     CComPtr<IDxcBlob> pProgramDXBC;
     HRESULT hrDXBC = CompileFromFile(name, true, &pProgramDXBC);
     HRESULT hrDXBC = CompileFromFile(name, true, &pProgramDXBC);
@@ -608,8 +628,8 @@ TEST_F(DxilContainerTest, CompileWhenOKThenIncludesSignatures) {
 
 
   {
   {
     std::string s = DisassembleProgram(program, L"VSMain", L"vs_6_0");
     std::string s = DisassembleProgram(program, L"VSMain", L"vs_6_0");
-    // NOTE: this will change when proper packing is done, and when 'always-writes' is accurately implemented.
-    const char expected[] =
+    // NOTE: this will change when proper packing is done, and when 'always-reads' is accurately implemented.
+    const char expected_1_4[] =
       ";\n"
       ";\n"
       "; Input signature:\n"
       "; Input signature:\n"
       ";\n"
       ";\n"
@@ -625,14 +645,35 @@ TEST_F(DxilContainerTest, CompileWhenOKThenIncludesSignatures) {
       "; -------------------- ----- ------ -------- -------- ------- ------\n"
       "; -------------------- ----- ------ -------- -------- ------- ------\n"
       "; SV_Position              0   xyzw        0      POS   float   xyzw\n"  // could read SV_POSITION
       "; SV_Position              0   xyzw        0      POS   float   xyzw\n"  // could read SV_POSITION
       "; COLOR                    0   xyzw        1     NONE   float   xyzw\n"; // should read '1' in register
       "; COLOR                    0   xyzw        1     NONE   float   xyzw\n"; // should read '1' in register
-    std::string start(s.c_str(), strlen(expected));
-    VERIFY_ARE_EQUAL_STR(expected, start.c_str());
+    const char expected[] =
+      ";\n"
+      "; Input signature:\n"
+      ";\n"
+      "; Name                 Index   Mask Register SysValue  Format   Used\n"
+      "; -------------------- ----- ------ -------- -------- ------- ------\n"
+      "; POSITION                 0   xyzw        0     NONE   float   xyzw\n" // should read 'xyzw' in Used
+      "; COLOR                    0   xyzw        1     NONE   float   xyzw\n" // should read '1' in register
+      ";\n"
+      ";\n"
+      "; Output signature:\n"
+      ";\n"
+      "; Name                 Index   Mask Register SysValue  Format   Used\n"
+      "; -------------------- ----- ------ -------- -------- ------- ------\n"
+      "; SV_Position              0   xyzw        0      POS   float   xyzw\n"  // could read SV_POSITION
+      "; COLOR                    0   xyzw        1     NONE   float   xyzw\n"; // should read '1' in register
+    if (hlsl::DXIL::CompareVersions(m_ver.m_ValMajor, m_ver.m_ValMinor, 1, 5) < 0) {
+      std::string start(s.c_str(), strlen(expected_1_4));
+      VERIFY_ARE_EQUAL_STR(expected_1_4, start.c_str());
+    } else {
+      std::string start(s.c_str(), strlen(expected));
+      VERIFY_ARE_EQUAL_STR(expected, start.c_str());
+    }
   }
   }
 
 
   {
   {
     std::string s = DisassembleProgram(program, L"PSMain", L"ps_6_0");
     std::string s = DisassembleProgram(program, L"PSMain", L"ps_6_0");
-    // NOTE: this will change when proper packing is done, and when 'always-writes' is accurately implemented.
-    const char expected[] =
+    // NOTE: this will change when proper packing is done, and when 'always-reads' is accurately implemented.
+    const char expected_1_4[] =
       ";\n"
       ";\n"
       "; Input signature:\n"
       "; Input signature:\n"
       ";\n"
       ";\n"
@@ -647,8 +688,28 @@ TEST_F(DxilContainerTest, CompileWhenOKThenIncludesSignatures) {
       "; Name                 Index   Mask Register SysValue  Format   Used\n"
       "; Name                 Index   Mask Register SysValue  Format   Used\n"
       "; -------------------- ----- ------ -------- -------- ------- ------\n"
       "; -------------------- ----- ------ -------- -------- ------- ------\n"
       "; SV_Target                0   xyzw        0   TARGET   float   xyzw\n";// could read SV_TARGET
       "; SV_Target                0   xyzw        0   TARGET   float   xyzw\n";// could read SV_TARGET
-    std::string start(s.c_str(), strlen(expected));
-    VERIFY_ARE_EQUAL_STR(expected, start.c_str());
+    const char expected[] =
+      ";\n"
+      "; Input signature:\n"
+      ";\n"
+      "; Name                 Index   Mask Register SysValue  Format   Used\n"
+      "; -------------------- ----- ------ -------- -------- ------- ------\n"
+      "; SV_Position              0   xyzw        0      POS   float       \n" // could read SV_POSITION
+      "; COLOR                    0   xyzw        1     NONE   float   xyzw\n" // should read '1' in register, xyzw in Used
+      ";\n"
+      ";\n"
+      "; Output signature:\n"
+      ";\n"
+      "; Name                 Index   Mask Register SysValue  Format   Used\n"
+      "; -------------------- ----- ------ -------- -------- ------- ------\n"
+      "; SV_Target                0   xyzw        0   TARGET   float   xyzw\n";// could read SV_TARGET
+    if (hlsl::DXIL::CompareVersions(m_ver.m_ValMajor, m_ver.m_ValMinor, 1, 5) < 0) {
+      std::string start(s.c_str(), strlen(expected_1_4));
+      VERIFY_ARE_EQUAL_STR(expected_1_4, start.c_str());
+    } else {
+      std::string start(s.c_str(), strlen(expected));
+      VERIFY_ARE_EQUAL_STR(expected, start.c_str());
+    }
   }
   }
 }
 }
 
 

+ 92 - 1
tools/clang/unittests/HLSL/DxilModuleTest.cpp

@@ -65,6 +65,15 @@ public:
   TEST_METHOD(CSGetNumThreads)
   TEST_METHOD(CSGetNumThreads)
   TEST_METHOD(MSGetNumThreads)
   TEST_METHOD(MSGetNumThreads)
   TEST_METHOD(ASGetNumThreads)
   TEST_METHOD(ASGetNumThreads)
+
+  TEST_METHOD(SetValidatorVersion)
+
+  void VerifyValidatorVersionFails(
+    LPCWSTR shaderModel, const std::vector<LPCWSTR> &arguments,
+    const std::vector<LPCSTR> &expectedErrors);
+  void VerifyValidatorVersionMatches(
+    LPCWSTR shaderModel, const std::vector<LPCWSTR> &arguments,
+    unsigned expectedMajor = UINT_MAX, unsigned expectedMinor = UINT_MAX);
 };
 };
 
 
 bool DxilModuleTest::InitSupport() {
 bool DxilModuleTest::InitSupport() {
@@ -154,7 +163,7 @@ public:
     return *DM;
     return *DM;
   }
   }
 
 
-private:
+public:
   static ::llvm::sys::fs::MSFileSystem *CreateMSFileSystem() {
   static ::llvm::sys::fs::MSFileSystem *CreateMSFileSystem() {
     ::llvm::sys::fs::MSFileSystem *msfPtr;
     ::llvm::sys::fs::MSFileSystem *msfPtr;
     VERIFY_SUCCEEDED(CreateMSFileSystemForDisk(&msfPtr));
     VERIFY_SUCCEEDED(CreateMSFileSystemForDisk(&msfPtr));
@@ -487,3 +496,85 @@ TEST_F(DxilModuleTest, ASGetNumThreads) {
   VERIFY_ARE_EQUAL(4, DM.GetNumThreads(1));
   VERIFY_ARE_EQUAL(4, DM.GetNumThreads(1));
   VERIFY_ARE_EQUAL(2, DM.GetNumThreads(2));
   VERIFY_ARE_EQUAL(2, DM.GetNumThreads(2));
 }
 }
+
+void DxilModuleTest::VerifyValidatorVersionFails(
+    LPCWSTR shaderModel, const std::vector<LPCWSTR> &arguments,
+    const std::vector<LPCSTR> &expectedErrors) {
+
+  LPCSTR shader =
+    "[shader(\"pixel\")]"
+    "float4 main() : SV_Target {\n"
+    "  return 0;\n"
+    "}\n";
+
+  Compiler c(m_dllSupport);
+  c.Compile(shader, shaderModel, arguments, {});
+  CheckOperationResultMsgs(c.pCompileResult, expectedErrors, false, false);
+}
+
+void DxilModuleTest::VerifyValidatorVersionMatches(
+    LPCWSTR shaderModel, const std::vector<LPCWSTR> &arguments,
+    unsigned expectedMajor, unsigned expectedMinor) {
+
+  LPCSTR shader =
+    "[shader(\"pixel\")]"
+    "float4 main() : SV_Target {\n"
+    "  return 0;\n"
+    "}\n";
+
+  Compiler c(m_dllSupport);
+  c.Compile(shader, shaderModel, arguments, {});
+  DxilModule &DM = c.GetDxilModule();
+  unsigned vMajor, vMinor;
+  DM.GetValidatorVersion(vMajor, vMinor);
+
+  if (expectedMajor == UINT_MAX) {
+    // Expect current version
+    VERIFY_ARE_EQUAL(vMajor, c.m_ver.m_ValMajor);
+    VERIFY_ARE_EQUAL(vMinor, c.m_ver.m_ValMinor);
+  } else {
+    VERIFY_ARE_EQUAL(vMajor, expectedMajor);
+    VERIFY_ARE_EQUAL(vMinor, expectedMinor);
+  }
+}
+
+TEST_F(DxilModuleTest, SetValidatorVersion) {
+  Compiler c(m_dllSupport);
+  if (c.SkipDxil_Test(1, 4)) return;
+
+  // Current version
+  VerifyValidatorVersionMatches(L"ps_6_2", {});
+  VerifyValidatorVersionMatches(L"lib_6_3", {});
+
+  // Current version, with validation disabled
+  VerifyValidatorVersionMatches(L"ps_6_2", {L"-Vd"});
+  VerifyValidatorVersionMatches(L"lib_6_3", {L"-Vd"});
+
+  // Override validator version
+  VerifyValidatorVersionMatches(L"ps_6_2", {L"-validator-version", L"1.2"}, 1,2);
+  VerifyValidatorVersionMatches(L"lib_6_3", {L"-validator-version", L"1.3"}, 1,3);
+
+  // Override validator version, with validation disabled
+  VerifyValidatorVersionMatches(L"ps_6_2", {L"-Vd", L"-validator-version", L"1.2"}, 1,2);
+  VerifyValidatorVersionMatches(L"lib_6_3", {L"-Vd", L"-validator-version", L"1.3"}, 1,3);
+
+  // Never can validate (version 0,0):
+  VerifyValidatorVersionMatches(L"lib_6_1", {L"-Vd"}, 0, 0);
+  VerifyValidatorVersionMatches(L"lib_6_2", {L"-Vd"}, 0, 0);
+  VerifyValidatorVersionMatches(L"lib_6_2", {L"-Vd", L"-validator-version", L"0.0"}, 0, 0);
+  VerifyValidatorVersionMatches(L"lib_6_x", {}, 0, 0);
+  VerifyValidatorVersionMatches(L"lib_6_x", {L"-validator-version", L"0.0"}, 0, 0);
+
+  // Failure cases:
+  VerifyValidatorVersionFails(L"ps_6_2", {L"-validator-version", L"1.1"}, {
+    "validator version 1,1 does not support target profile."});
+
+  VerifyValidatorVersionFails(L"lib_6_2", {L"-Tlib_6_2"}, {
+    "Must disable validation for unsupported lib_6_1 or lib_6_2 targets"});
+
+  VerifyValidatorVersionFails(L"lib_6_2", {L"-Vd", L"-validator-version", L"1.2"}, {
+    "-validator-version cannot be used with library profiles lib_6_1 or lib_6_2."});
+
+  VerifyValidatorVersionFails(L"lib_6_x", {L"-validator-version", L"1.3"}, {
+    "Offline library profile cannot be used with non-zero -validator-version."});
+}

+ 55 - 31
tools/clang/unittests/HLSL/FileCheckerTest.cpp

@@ -368,6 +368,35 @@ FileRunCommandResult FileRunCommandPart::RunDxcHashTest(dxc::DxcDllSupport &DllS
   return FileRunCommandResult::Success();
   return FileRunCommandResult::Success();
 }
 }
 
 
+static FileRunCommandResult CheckDxilVer(dxc::DxcDllSupport& DllSupport,
+                                         unsigned RequiredDxilMajor,
+                                         unsigned RequiredDxilMinor,
+                                         bool bCheckValidator = true) {
+  bool Supported = true;
+
+  // If the following fails, we have Dxil 1.0 compiler
+  unsigned DxilMajor = 1, DxilMinor = 0;
+  GetVersion(DllSupport, CLSID_DxcCompiler, DxilMajor, DxilMinor);
+  Supported &= hlsl::DXIL::CompareVersions(DxilMajor, DxilMinor, RequiredDxilMajor, RequiredDxilMinor) >= 0;
+
+  if (bCheckValidator) {
+    // If the following fails, we have validator 1.0
+    unsigned ValMajor = 1, ValMinor = 0;
+    GetVersion(DllSupport, CLSID_DxcValidator, ValMajor, ValMinor);
+    Supported &= hlsl::DXIL::CompareVersions(ValMajor, ValMinor, RequiredDxilMajor, RequiredDxilMinor) >= 0;
+  }
+
+  if (!Supported) {
+    FileRunCommandResult result {};
+    result.StdErr = "Skipping test due to unsupported dxil version";
+    result.ExitCode = 0; // Succeed the test
+    result.AbortPipeline = true;
+    return result;
+  }
+
+  return FileRunCommandResult::Success();
+}
+
 FileRunCommandResult FileRunCommandPart::RunDxc(dxc::DxcDllSupport &DllSupport, const FileRunCommandResult *Prior) {
 FileRunCommandResult FileRunCommandPart::RunDxc(dxc::DxcDllSupport &DllSupport, const FileRunCommandResult *Prior) {
   // Support piping stdin from prior if needed.
   // Support piping stdin from prior if needed.
   UNREFERENCED_PARAMETER(Prior);
   UNREFERENCED_PARAMETER(Prior);
@@ -385,6 +414,31 @@ FileRunCommandResult FileRunCommandPart::RunDxc(dxc::DxcDllSupport &DllSupport,
     flags.push_back(L"-fcgl");
     flags.push_back(L"-fcgl");
   }
   }
 
 
+  // Skip targets that require a newer compiler or validator.
+  // Some features may require newer compiler/validator than indicated by the
+  // shader model, but these should use %dxilver explicitly.
+  {
+    unsigned RequiredDxilMajor = 1, RequiredDxilMinor = 0;
+    llvm::StringRef stage;
+    IFTBOOL(ParseTargetProfile(opts.TargetProfile, stage, RequiredDxilMajor, RequiredDxilMinor), E_INVALIDARG);
+    if (RequiredDxilMinor != 0xF && stage.compare("rootsig") != 0) {
+      // Convert stage to minimum dxil/validator version:
+      RequiredDxilMajor = std::max(RequiredDxilMajor, (unsigned)6) - 5;
+      FileRunCommandResult result = CheckDxilVer(DllSupport, RequiredDxilMajor, RequiredDxilMinor, !opts.DisableValidation);
+      if (result.AbortPipeline) {
+        return result;
+      }
+    }
+  }
+
+  // For now, too many tests are sensitive to stripping the refleciton info
+  // from the main module, so use this flag to prevent this until tests
+  // can be updated.
+  // That is, unless the test explicitly requests -Qstrip_reflect_from_dxil or -Qstrip_reflect
+  if (!opts.StripReflectionFromDxil && !opts.StripReflection) {
+    flags.push_back(L"-Qkeep_reflect_in_dxil");
+  }
+
   std::vector<std::wstring> argWStrings;
   std::vector<std::wstring> argWStrings;
   CopyArgsToWStrings(opts.Args, hlsl::options::CoreOption, argWStrings);
   CopyArgsToWStrings(opts.Args, hlsl::options::CoreOption, argWStrings);
   for (const std::wstring &a : argWStrings)
   for (const std::wstring &a : argWStrings)
@@ -643,38 +697,8 @@ FileRunCommandResult FileRunCommandPart::RunDxilVer(dxc::DxcDllSupport& DllSuppo
 
 
   unsigned RequiredDxilMajor = Arguments[0] - '0';
   unsigned RequiredDxilMajor = Arguments[0] - '0';
   unsigned RequiredDxilMinor = Arguments[2] - '0';
   unsigned RequiredDxilMinor = Arguments[2] - '0';
-  bool Supported = RequiredDxilMajor >= 1;
-  CComPtr<IDxcCompiler> pCompiler;
-
-  // If the following fails, we have Dxil 1.0 compiler
-  if (SUCCEEDED(DllSupport.CreateInstance(CLSID_DxcCompiler, &pCompiler))) {
-    CComPtr<IDxcVersionInfo> pVersionInfo;
-    IFT(pCompiler.QueryInterface(&pVersionInfo));
-    unsigned DxilMajor, DxilMinor;
-    IFT(pVersionInfo->GetVersion(&DxilMajor, &DxilMinor));
-    if (DxilMajor < RequiredDxilMajor || (DxilMajor == RequiredDxilMajor && DxilMinor < RequiredDxilMinor))
-      Supported = false;
-  }
-
-  CComPtr<IDxcValidator> pValidator;
-  if (SUCCEEDED(DllSupport.CreateInstance(CLSID_DxcValidator, &pValidator))) {
-    CComPtr<IDxcVersionInfo> pVersionInfo;
-    IFT(pValidator.QueryInterface(&pVersionInfo));
-    unsigned DxilMajor, DxilMinor;
-    VERIFY_SUCCEEDED(pVersionInfo->GetVersion(&DxilMajor, &DxilMinor));
-    if (DxilMajor < RequiredDxilMajor || (DxilMajor == RequiredDxilMajor && DxilMinor < RequiredDxilMinor))
-      Supported = false;
-  }
 
 
-  if (!Supported) {
-    FileRunCommandResult result {};
-    result.StdErr = "Skipping test due to unsupported dxil version";
-    result.ExitCode = 0; // Succeed the test
-    result.AbortPipeline = true;
-    return result;
-  }
-
-  return FileRunCommandResult::Success();
+  return CheckDxilVer(DllSupport, RequiredDxilMajor, RequiredDxilMinor);
 }
 }
 
 
 class FileRunTestResultImpl : public FileRunTestResult {
 class FileRunTestResultImpl : public FileRunTestResult {

+ 30 - 4
tools/clang/unittests/HLSL/LinkerTest.cpp

@@ -61,6 +61,7 @@ public:
   TEST_METHOD(RunLinkToLibWithUnusedExport);
   TEST_METHOD(RunLinkToLibWithUnusedExport);
   TEST_METHOD(RunLinkToLibWithNoExports);
   TEST_METHOD(RunLinkToLibWithNoExports);
   TEST_METHOD(RunLinkWithPotentialIntrinsicNameCollisions);
   TEST_METHOD(RunLinkWithPotentialIntrinsicNameCollisions);
+  TEST_METHOD(RunLinkWithValidatorVersion);
 
 
 
 
   dxc::DxcDllSupport m_dllSupport;
   dxc::DxcDllSupport m_dllSupport;
@@ -72,7 +73,8 @@ public:
   }
   }
 
 
   void CompileLib(LPCWSTR filename, IDxcBlob **pResultBlob,
   void CompileLib(LPCWSTR filename, IDxcBlob **pResultBlob,
-                  llvm::ArrayRef<LPCWSTR> pArguments = {}) {
+                  llvm::ArrayRef<LPCWSTR> pArguments = {},
+                  LPCWSTR pShaderTarget = L"lib_6_x") {
     std::wstring fullPath = hlsl_test::GetPathToHlslDataFile(filename);
     std::wstring fullPath = hlsl_test::GetPathToHlslDataFile(filename);
     CComPtr<IDxcBlobEncoding> pSource;
     CComPtr<IDxcBlobEncoding> pSource;
     CComPtr<IDxcLibrary> pLibrary;
     CComPtr<IDxcLibrary> pLibrary;
@@ -85,10 +87,9 @@ public:
     CComPtr<IDxcOperationResult> pResult;
     CComPtr<IDxcOperationResult> pResult;
     CComPtr<IDxcBlob> pProgram;
     CComPtr<IDxcBlob> pProgram;
 
 
-    CA2W shWide("lib_6_x", CP_UTF8);
     VERIFY_SUCCEEDED(
     VERIFY_SUCCEEDED(
         m_dllSupport.CreateInstance(CLSID_DxcCompiler, &pCompiler));
         m_dllSupport.CreateInstance(CLSID_DxcCompiler, &pCompiler));
-    VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"hlsl.hlsl", L"", shWide,
+    VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"hlsl.hlsl", L"", pShaderTarget,
                                         const_cast<LPCWSTR*>(pArguments.data()), pArguments.size(),
                                         const_cast<LPCWSTR*>(pArguments.data()), pArguments.size(),
                                         nullptr, 0,
                                         nullptr, 0,
                                         nullptr, &pResult));
                                         nullptr, &pResult));
@@ -218,7 +219,7 @@ TEST_F(LinkerTest, RunLinkFailReDefine) {
 
 
 TEST_F(LinkerTest, RunLinkGlobalInit) {
 TEST_F(LinkerTest, RunLinkGlobalInit) {
   CComPtr<IDxcBlob> pEntryLib;
   CComPtr<IDxcBlob> pEntryLib;
-  CompileLib(L"..\\CodeGenHLSL\\lib_global.hlsl", &pEntryLib);
+  CompileLib(L"..\\CodeGenHLSL\\lib_global.hlsl", &pEntryLib, {}, L"lib_6_3");
   CComPtr<IDxcLinker> pLinker;
   CComPtr<IDxcLinker> pLinker;
   CreateLinker(&pLinker);
   CreateLinker(&pLinker);
 
 
@@ -636,3 +637,28 @@ TEST_F(LinkerTest, RunLinkWithPotentialIntrinsicNameCollisions) {
     "declare %dx.types.Handle @\"dx.op.createHandleForLib.class.Texture2D<float>\"(i32, %\"class.Texture2D<float>\")"
     "declare %dx.types.Handle @\"dx.op.createHandleForLib.class.Texture2D<float>\"(i32, %\"class.Texture2D<float>\")"
   }, { });
   }, { });
 }
 }
+
+TEST_F(LinkerTest, RunLinkWithValidatorVersion) {
+  if (m_ver.SkipDxilVersion(1, 4)) return;
+
+  CComPtr<IDxcBlob> pEntryLib;
+  CompileLib(L"..\\CodeGenHLSL\\linker\\lib_mat_entry2.hlsl",
+             &pEntryLib, {});
+  CComPtr<IDxcBlob> pLib;
+  CompileLib(
+      L"..\\CodeGenHLSL\\linker\\lib_mat_cast2.hlsl",
+      &pLib, {});
+
+  CComPtr<IDxcLinker> pLinker;
+  CreateLinker(&pLinker);
+
+  LPCWSTR libName = L"ps_main";
+  RegisterDxcModule(libName, pEntryLib, pLinker);
+
+  LPCWSTR libName2 = L"test";
+  RegisterDxcModule(libName2, pLib, pLinker);
+
+  Link(L"", L"lib_6_3", pLinker, {libName, libName2},
+       {"!dx.valver = !{(![0-9]+)}.*\n\\1 = !{i32 1, i32 3}"},
+       {}, {L"-validator-version", L"1.3"}, /*regex*/ true);
+}

+ 2 - 0
tools/clang/unittests/HLSL/OptimizerTest.cpp

@@ -179,12 +179,14 @@ void OptimizerTest::OptimizerWhenSliceNThenOK(int optLevel, LPCWSTR pText, LPCWS
   highLevelArgs.insert(highLevelArgs.end(), args.begin(), args.end());
   highLevelArgs.insert(highLevelArgs.end(), args.begin(), args.end());
 
 
   // Create the target program with a single invocation.
   // Create the target program with a single invocation.
+  highLevelArgs.emplace_back(L"/Qkeep_reflect_in_dxil");
   VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main", pTarget,
   VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main", pTarget,
     highLevelArgs.data(), static_cast<UINT32>(highLevelArgs.size()), nullptr, 0, nullptr, &pResult));
     highLevelArgs.data(), static_cast<UINT32>(highLevelArgs.size()), nullptr, 0, nullptr, &pResult));
   VerifyOperationSucceeded(pResult);
   VerifyOperationSucceeded(pResult);
   VERIFY_SUCCEEDED(pResult->GetResult(&pProgram));
   VERIFY_SUCCEEDED(pResult->GetResult(&pProgram));
   pResult.Release();
   pResult.Release();
   std::string originalAssembly = DisassembleProgram(m_dllSupport, pProgram);
   std::string originalAssembly = DisassembleProgram(m_dllSupport, pProgram);
+  highLevelArgs.pop_back(); // Remove /keep_reflect_in_dxil
 
 
   // Get a list of passes for this configuration.
   // Get a list of passes for this configuration.
   highLevelArgs.emplace_back(L"/Odump");
   highLevelArgs.emplace_back(L"/Odump");

+ 116 - 90
tools/clang/unittests/HLSL/ValidationTest.cpp

@@ -8,6 +8,8 @@
 //                                                                           //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
+#define NOMINMAX
+
 #include <memory>
 #include <memory>
 #include <vector>
 #include <vector>
 #include <string>
 #include <string>
@@ -331,7 +333,7 @@ public:
     CheckValidationMsgs(pBlobEncoding, pErrorMsgs, bRegex);
     CheckValidationMsgs(pBlobEncoding, pErrorMsgs, bRegex);
   }
   }
 
 
-  void CompileSource(IDxcBlobEncoding *pSource, LPCSTR pShaderModel,
+  bool CompileSource(IDxcBlobEncoding *pSource, LPCSTR pShaderModel,
                      LPCWSTR *pArguments, UINT32 argCount, const DxcDefine *pDefines,
                      LPCWSTR *pArguments, UINT32 argCount, const DxcDefine *pDefines,
                      UINT32 defineCount, IDxcBlob **pResultBlob) {
                      UINT32 defineCount, IDxcBlob **pResultBlob) {
     CComPtr<IDxcCompiler> pCompiler;
     CComPtr<IDxcCompiler> pCompiler;
@@ -341,35 +343,51 @@ public:
     CA2W shWide(pShaderModel, CP_UTF8);
     CA2W shWide(pShaderModel, CP_UTF8);
 
 
     wchar_t *pEntryName = L"main";
     wchar_t *pEntryName = L"main";
-    if (llvm::StringRef(pShaderModel).startswith("lib_"))
-      pEntryName = L"";
+
+    llvm::StringRef stage;
+    unsigned RequiredDxilMajor = 1, RequiredDxilMinor = 0;
+    if (ParseTargetProfile(pShaderModel, stage, RequiredDxilMajor, RequiredDxilMinor)) {
+      if (stage.compare("lib") == 0)
+        pEntryName = L"";
+      if (stage.compare("rootsig") != 0) {
+        RequiredDxilMajor = std::max(RequiredDxilMajor, (unsigned)6) - 5;
+        if (m_ver.SkipDxilVersion(RequiredDxilMajor, RequiredDxilMinor))
+          return false;
+      }
+    }
+
+    std::vector<LPCWSTR> args;
+    args.reserve(argCount + 1);
+    args.insert(args.begin(), pArguments, pArguments + argCount);
+    args.emplace_back(L"-Qkeep_reflect_in_dxil");
 
 
     VERIFY_SUCCEEDED(
     VERIFY_SUCCEEDED(
         m_dllSupport.CreateInstance(CLSID_DxcCompiler, &pCompiler));
         m_dllSupport.CreateInstance(CLSID_DxcCompiler, &pCompiler));
     VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"hlsl.hlsl", pEntryName, shWide,
     VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"hlsl.hlsl", pEntryName, shWide,
-                                        pArguments, argCount, pDefines,
+                                        args.data(), (UINT32)args.size(), pDefines,
                                         defineCount, nullptr, &pResult));
                                         defineCount, nullptr, &pResult));
     CheckOperationResultMsgs(pResult, nullptr, false, false);
     CheckOperationResultMsgs(pResult, nullptr, false, false);
     VERIFY_SUCCEEDED(pResult->GetResult(pResultBlob));
     VERIFY_SUCCEEDED(pResult->GetResult(pResultBlob));
+    return true;
   }
   }
 
 
-  void CompileSource(IDxcBlobEncoding *pSource, LPCSTR pShaderModel,
+  bool CompileSource(IDxcBlobEncoding *pSource, LPCSTR pShaderModel,
                      IDxcBlob **pResultBlob) {
                      IDxcBlob **pResultBlob) {
-    CompileSource(pSource, pShaderModel, nullptr, 0, nullptr, 0, pResultBlob);
+    return CompileSource(pSource, pShaderModel, nullptr, 0, nullptr, 0, pResultBlob);
   }
   }
 
 
-  void CompileSource(LPCSTR pSource, LPCSTR pShaderModel,
+  bool CompileSource(LPCSTR pSource, LPCSTR pShaderModel,
                      IDxcBlob **pResultBlob) {
                      IDxcBlob **pResultBlob) {
     CComPtr<IDxcBlobEncoding> pSourceBlob;
     CComPtr<IDxcBlobEncoding> pSourceBlob;
     Utf8ToBlob(m_dllSupport, pSource, &pSourceBlob);
     Utf8ToBlob(m_dllSupport, pSource, &pSourceBlob);
-    CompileSource(pSourceBlob, pShaderModel, nullptr, 0, nullptr, 0, pResultBlob);
+    return CompileSource(pSourceBlob, pShaderModel, nullptr, 0, nullptr, 0, pResultBlob);
   }
   }
 
 
   void DisassembleProgram(IDxcBlob *pProgram, std::string *text) {
   void DisassembleProgram(IDxcBlob *pProgram, std::string *text) {
     *text = ::DisassembleProgram(m_dllSupport, pProgram);
     *text = ::DisassembleProgram(m_dllSupport, pProgram);
   }
   }
 
 
-  void RewriteAssemblyCheckMsg(IDxcBlobEncoding *pSource, LPCSTR pShaderModel,
+  bool RewriteAssemblyCheckMsg(IDxcBlobEncoding *pSource, LPCSTR pShaderModel,
     LPCWSTR *pArguments, UINT32 argCount,
     LPCWSTR *pArguments, UINT32 argCount,
     const DxcDefine *pDefines, UINT32 defineCount,
     const DxcDefine *pDefines, UINT32 defineCount,
     llvm::ArrayRef<LPCSTR> pLookFors,
     llvm::ArrayRef<LPCSTR> pLookFors,
@@ -377,7 +395,8 @@ public:
     llvm::ArrayRef<LPCSTR> pErrorMsgs,
     llvm::ArrayRef<LPCSTR> pErrorMsgs,
     bool bRegex = false) {
     bool bRegex = false) {
     CComPtr<IDxcBlob> pText;
     CComPtr<IDxcBlob> pText;
-    RewriteAssemblyToText(pSource, pShaderModel, pArguments, argCount, pDefines, defineCount, pLookFors, pReplacements, &pText, bRegex);
+    if (!RewriteAssemblyToText(pSource, pShaderModel, pArguments, argCount, pDefines, defineCount, pLookFors, pReplacements, &pText, bRegex))
+      return false;
     CComPtr<IDxcAssembler> pAssembler;
     CComPtr<IDxcAssembler> pAssembler;
     CComPtr<IDxcOperationResult> pAssembleResult;
     CComPtr<IDxcOperationResult> pAssembleResult;
     VERIFY_SUCCEEDED(
     VERIFY_SUCCEEDED(
@@ -390,6 +409,7 @@ public:
       VERIFY_SUCCEEDED(pAssembleResult->GetResult(&pBlob));
       VERIFY_SUCCEEDED(pAssembleResult->GetResult(&pBlob));
       CheckValidationMsgs(pBlob, pErrorMsgs, bRegex);
       CheckValidationMsgs(pBlob, pErrorMsgs, bRegex);
     }
     }
+    return true;
   }
   }
 
 
   void RewriteAssemblyCheckMsg(LPCSTR pSource, LPCSTR pShaderModel,
   void RewriteAssemblyCheckMsg(LPCSTR pSource, LPCSTR pShaderModel,
@@ -439,7 +459,7 @@ public:
       pLookFors, pReplacements, pErrorMsgs, bRegex);
       pLookFors, pReplacements, pErrorMsgs, bRegex);
   }
   }
 
 
-  void RewriteAssemblyToText(IDxcBlobEncoding *pSource, LPCSTR pShaderModel,
+  bool RewriteAssemblyToText(IDxcBlobEncoding *pSource, LPCSTR pShaderModel,
                              LPCWSTR *pArguments, UINT32 argCount,
                              LPCWSTR *pArguments, UINT32 argCount,
                              const DxcDefine *pDefines, UINT32 defineCount,
                              const DxcDefine *pDefines, UINT32 defineCount,
                              llvm::ArrayRef<LPCSTR> pLookFors,
                              llvm::ArrayRef<LPCSTR> pLookFors,
@@ -447,7 +467,8 @@ public:
                              IDxcBlob **pBlob, bool bRegex = false) {
                              IDxcBlob **pBlob, bool bRegex = false) {
     CComPtr<IDxcBlob> pProgram;
     CComPtr<IDxcBlob> pProgram;
     std::string disassembly;
     std::string disassembly;
-    CompileSource(pSource, pShaderModel, pArguments, argCount, pDefines, defineCount, &pProgram);
+    if (!CompileSource(pSource, pShaderModel, pArguments, argCount, pDefines, defineCount, &pProgram))
+      return false;
     DisassembleProgram(pProgram, &disassembly);
     DisassembleProgram(pProgram, &disassembly);
     for (unsigned i = 0; i < pLookFors.size(); ++i) {
     for (unsigned i = 0; i < pLookFors.size(); ++i) {
       LPCSTR pLookFor = pLookFors[i];
       LPCSTR pLookFor = pLookFors[i];
@@ -488,18 +509,21 @@ public:
       }
       }
     }
     }
     Utf8ToBlob(m_dllSupport, disassembly.c_str(), pBlob);
     Utf8ToBlob(m_dllSupport, disassembly.c_str(), pBlob);
+    return true;
   }
   }
 
 
 
 
   // compile one or two sources, validate module from 1 with container parts from 2, check messages
   // compile one or two sources, validate module from 1 with container parts from 2, check messages
-  void ReplaceContainerPartsCheckMsgs(LPCSTR pSource1, LPCSTR pSource2, LPCSTR pShaderModel,
+  bool ReplaceContainerPartsCheckMsgs(LPCSTR pSource1, LPCSTR pSource2, LPCSTR pShaderModel,
                                      llvm::ArrayRef<DxilFourCC> PartsToReplace,
                                      llvm::ArrayRef<DxilFourCC> PartsToReplace,
                                      llvm::ArrayRef<LPCSTR> pErrorMsgs) {
                                      llvm::ArrayRef<LPCSTR> pErrorMsgs) {
     CComPtr<IDxcBlob> pProgram1, pProgram2;
     CComPtr<IDxcBlob> pProgram1, pProgram2;
-    CompileSource(pSource1, pShaderModel, &pProgram1);
+    if (!CompileSource(pSource1, pShaderModel, &pProgram1))
+      return false;
     VERIFY_IS_NOT_NULL(pProgram1);
     VERIFY_IS_NOT_NULL(pProgram1);
     if (pSource2) {
     if (pSource2) {
-      CompileSource(pSource2, pShaderModel, &pProgram2);
+      if (!CompileSource(pSource2, pShaderModel, &pProgram2))
+        return false;
       VERIFY_IS_NOT_NULL(pProgram2);
       VERIFY_IS_NOT_NULL(pProgram2);
     } else {
     } else {
       pProgram2 = pProgram1;
       pProgram2 = pProgram1;
@@ -551,6 +575,7 @@ public:
     pContainerWriter->write(pOutputStream);
     pContainerWriter->write(pOutputStream);
 
 
     CheckValidationMsgs((const char *)pOutputStream->GetPtr(), pOutputStream->GetPtrSize(), pErrorMsgs, /*bRegex*/false);
     CheckValidationMsgs((const char *)pOutputStream->GetPtr(), pOutputStream->GetPtrSize(), pErrorMsgs, /*bRegex*/false);
+    return true;
   }
   }
 };
 };
 
 
@@ -798,9 +823,9 @@ TEST_F(ValidationTest, InnerCoverageFail) {
 TEST_F(ValidationTest, InterpChangeFail) {
 TEST_F(ValidationTest, InterpChangeFail) {
   RewriteAssemblyCheckMsg(
   RewriteAssemblyCheckMsg(
       L"..\\CodeGenHLSL\\interpChange.hlsl", "ps_6_0",
       L"..\\CodeGenHLSL\\interpChange.hlsl", "ps_6_0",
-      { "i32 1, i8 0, null}",
+      { "i32 1, i8 0, (.*)}",
         "?!dx.viewIdState ="},
         "?!dx.viewIdState ="},
-      { "i32 0, i8 2, null}",
+      { "i32 0, i8 2, \\1}",
         "!1012 ="},
         "!1012 ="},
       "interpolation mode that differs from another element packed",
       "interpolation mode that differs from another element packed",
       /*bRegex*/true);
       /*bRegex*/true);
@@ -892,18 +917,17 @@ TEST_F(ValidationTest, SamplerKindFail) {
       {"Invalid sampler mode",
       {"Invalid sampler mode",
        "require sampler declared in comparison mode",
        "require sampler declared in comparison mode",
        "requires sampler declared in default mode",
        "requires sampler declared in default mode",
-       "should be on srv resource"});
+       // 1.4: "should", 1.5: "should be "
+       "on srv resource"});
 }
 }
 TEST_F(ValidationTest, SemaOverlapFail) {
 TEST_F(ValidationTest, SemaOverlapFail) {
   RewriteAssemblyCheckMsg(
   RewriteAssemblyCheckMsg(
       L"..\\CodeGenHLSL\\semaOverlap1.hlsl", "ps_6_0",
       L"..\\CodeGenHLSL\\semaOverlap1.hlsl", "ps_6_0",
-      {"!([0-9]+) = !\\{i32 0, !\"A\", i8 9, i8 0, !([0-9]+), i8 2, i32 1, i8 4, i32 0, i8 0, null\\}\n"
-      "!([0-9]+) = !\\{i32 0\\}\n"
-      "!([0-9]+) = !\\{i32 1, !\"A\", i8 9, i8 0, !([0-9]+)",
+      {"!\\{i32 0, !\"A\", i8 9, i8 0, !([0-9]+), i8 2, i32 1, i8 4, i32 0, i8 0, (.*)"
+      "!\\{i32 1, !\"A\", i8 9, i8 0, !([0-9]+)",
       },
       },
-      {"!\\1 = !\\{i32 0, !\"A\", i8 9, i8 0, !\\2, i8 2, i32 1, i8 4, i32 0, i8 0, null\\}\n"
-      "!\\3 = !\\{i32 0\\}\n"
-      "!\\4 = !\\{i32 1, !\"A\", i8 9, i8 0, !\\2",
+      {"!\\{i32 0, !\"A\", i8 9, i8 0, !\\1, i8 2, i32 1, i8 4, i32 0, i8 0, \\2"
+      "!\\{i32 1, !\"A\", i8 9, i8 0, !\\1",
       },
       },
       {"Semantic 'A' overlap at 0"},
       {"Semantic 'A' overlap at 0"},
       /*bRegex*/true);
       /*bRegex*/true);
@@ -921,9 +945,9 @@ TEST_F(ValidationTest, SigOutOfRangeFail) {
 TEST_F(ValidationTest, SigOverlapFail) {
 TEST_F(ValidationTest, SigOverlapFail) {
   RewriteAssemblyCheckMsg(
   RewriteAssemblyCheckMsg(
       L"..\\CodeGenHLSL\\semaOverlap1.hlsl", "ps_6_0",
       L"..\\CodeGenHLSL\\semaOverlap1.hlsl", "ps_6_0",
-      { "i32 1, i8 0, null}",
+      { "i8 2, i32 1, i8 4, i32 1, i8 0,",
         "?!dx.viewIdState =" },
         "?!dx.viewIdState =" },
-      { "i32 0, i8 0, null}",
+      { "i8 2, i32 1, i8 4, i32 0, i8 0,",
         "!1012 =" },
         "!1012 =" },
       {"signature element A at location (0,0) size (1,4) overlaps another signature element"});
       {"signature element A at location (0,0) size (1,4) overlaps another signature element"});
 }
 }
@@ -1016,7 +1040,8 @@ TEST_F(ValidationTest, UavBarrierFail) {
       {"uav load don't support offset",
       {"uav load don't support offset",
        "uav load don't support mipLevel/sampleIndex",
        "uav load don't support mipLevel/sampleIndex",
        "store on typed uav must write to all four components of the UAV",
        "store on typed uav must write to all four components of the UAV",
-       "sync in a non-Compute/Amplification/Mesh Shader must only sync UAV (sync_uglobal)"});
+       "sync in a non-",    // 1.4: "Compute" 1.5: "Compute/Amplification/Mesh"
+       " Shader must only sync UAV (sync_uglobal)"});
 }
 }
 TEST_F(ValidationTest, UndefValueFail) {
 TEST_F(ValidationTest, UndefValueFail) {
   TestCheck(L"..\\CodeGenHLSL\\UndefValue.hlsl");
   TestCheck(L"..\\CodeGenHLSL\\UndefValue.hlsl");
@@ -1106,11 +1131,12 @@ TEST_F(ValidationTest, SignatureDataWidth) {
 TEST_F(ValidationTest, SignatureStreamIDForNonGS) {
 TEST_F(ValidationTest, SignatureStreamIDForNonGS) {
   RewriteAssemblyCheckMsg(
   RewriteAssemblyCheckMsg(
     L"..\\CodeGenHLSL\\validation\\abs1.hlsl", "ps_6_0",
     L"..\\CodeGenHLSL\\validation\\abs1.hlsl", "ps_6_0",
-    { ", i8 0, i32 1, i8 4, i32 0, i8 0, null}",
+    { ", i8 0, i32 1, i8 4, i32 0, i8 0, [^,]+}",
       "?!dx.viewIdState ="},
       "?!dx.viewIdState ="},
-    { ", i8 0, i32 1, i8 4, i32 0, i8 0, !19}\n!19 = !{i32 0, i32 1}",
+    { ", i8 0, i32 1, i8 4, i32 0, i8 0, !1019}\n!1019 = !{i32 0, i32 1}",
       "!1012 =" },
       "!1012 =" },
-    "Stream index (1) must between 0 and 0");
+    "Stream index \\(1\\) must between 0 and 0",
+    true);
 }
 }
 
 
 TEST_F(ValidationTest, TypedUAVStoreFullMask0) {
 TEST_F(ValidationTest, TypedUAVStoreFullMask0) {
@@ -1377,8 +1403,8 @@ TEST_F(ValidationTest, PsOutputSemantic) {
 TEST_F(ValidationTest, ArrayOfSVTarget) {
 TEST_F(ValidationTest, ArrayOfSVTarget) {
     RewriteAssemblyCheckMsg(
     RewriteAssemblyCheckMsg(
       L"..\\CodeGenHLSL\\targetArray.hlsl", "ps_6_0",
       L"..\\CodeGenHLSL\\targetArray.hlsl", "ps_6_0",
-      "i32 2, !\"SV_Target\", i8 9, i8 16, !([0-9]+), i8 0, i32 1, i8 4, i32 0, i8 0, null}",
-      "i32 2, !\"SV_Target\", i8 9, i8 16, !101, i8 0, i32 2, i8 4, i32 0, i8 0, null}\n!101 = !{i32 5, i32 6}",
+      "i32 2, !\"SV_Target\", i8 9, i8 16, !([0-9]+), i8 0, i32 1, i8 4, i32 0, i8 0, (.*)}",
+      "i32 2, !\"SV_Target\", i8 9, i8 16, !101, i8 0, i32 2, i8 4, i32 0, i8 0, \\2}\n!101 = !{i32 5, i32 6}",
       "Pixel shader output registers are not indexable.",
       "Pixel shader output registers are not indexable.",
       /*bRegex*/true);
       /*bRegex*/true);
 }
 }
@@ -1830,9 +1856,9 @@ TEST_F(ValidationTest, SemTargetMax) {
 float4 main(float4 col : COLOR) : SV_Target7 { return col; } \
 float4 main(float4 col : COLOR) : SV_Target7 { return col; } \
     ",
     ",
     "ps_6_0", 
     "ps_6_0", 
-    { "!{i32 0, !\"SV_Target\", i8 9, i8 16, ![0-9]+, i8 0, i32 1, i8 4, i32 7, i8 0, null}",
+    { "!{i32 0, !\"SV_Target\", i8 9, i8 16, ![0-9]+, i8 0, i32 1, i8 4, i32 7, i8 0, (.*)}",
       "?!dx.viewIdState ="},
       "?!dx.viewIdState ="},
-    { "!{i32 0, !\"SV_Target\", i8 9, i8 16, !101, i8 0, i32 1, i8 4, i32 8, i8 0, null}\n!101 = !{i32 8}",
+    { "!{i32 0, !\"SV_Target\", i8 9, i8 16, !101, i8 0, i32 1, i8 4, i32 8, i8 0, \\1}\n!101 = !{i32 8}",
       "!1012 ="},
       "!1012 ="},
     "SV_Target semantic index exceeds maximum \\(7\\)",
     "SV_Target semantic index exceeds maximum \\(7\\)",
     /*bRegex*/true);
     /*bRegex*/true);
@@ -1843,9 +1869,9 @@ TEST_F(ValidationTest, SemTargetIndexMatchesRow) {
 float4 main(float4 col : COLOR) : SV_Target7 { return col; } \
 float4 main(float4 col : COLOR) : SV_Target7 { return col; } \
     ",
     ",
     "ps_6_0", 
     "ps_6_0", 
-    { "!{i32 0, !\"SV_Target\", i8 9, i8 16, !([0-9]+), i8 0, i32 1, i8 4, i32 7, i8 0, null}",
+    { "!{i32 0, !\"SV_Target\", i8 9, i8 16, !([0-9]+), i8 0, i32 1, i8 4, i32 7, i8 0, (.*)}",
       "?!dx.viewIdState ="},
       "?!dx.viewIdState ="},
-    { "!{i32 0, !\"SV_Target\", i8 9, i8 16, !\\1, i8 0, i32 1, i8 4, i32 6, i8 0, null}",
+    { "!{i32 0, !\"SV_Target\", i8 9, i8 16, !\\1, i8 0, i32 1, i8 4, i32 6, i8 0, \\2}",
       "!1012 ="},
       "!1012 ="},
     "SV_Target semantic index must match packed row location",
     "SV_Target semantic index must match packed row location",
     /*bRegex*/true);
     /*bRegex*/true);
@@ -1856,8 +1882,8 @@ TEST_F(ValidationTest, SemTargetCol0) {
 float3 main(float4 col : COLOR) : SV_Target7 { return col.xyz; } \
 float3 main(float4 col : COLOR) : SV_Target7 { return col.xyz; } \
     ",
     ",
     "ps_6_0", 
     "ps_6_0", 
-    "!{i32 0, !\"SV_Target\", i8 9, i8 16, !([0-9]+), i8 0, i32 1, i8 3, i32 7, i8 0, null}",
-    "!{i32 0, !\"SV_Target\", i8 9, i8 16, !\\1, i8 0, i32 1, i8 3, i32 7, i8 1, null}",
+    "!{i32 0, !\"SV_Target\", i8 9, i8 16, !([0-9]+), i8 0, i32 1, i8 3, i32 7, i8 0, (.*)}",
+    "!{i32 0, !\"SV_Target\", i8 9, i8 16, !\\1, i8 0, i32 1, i8 3, i32 7, i8 1, \\2}",
     "SV_Target packed location must start at column 0",
     "SV_Target packed location must start at column 0",
     /*bRegex*/true);
     /*bRegex*/true);
 }
 }
@@ -1869,8 +1895,8 @@ float4 main(uint vid : SV_VertexID, uint iid : SV_InstanceID) : SV_Position { \
 } \
 } \
     ",
     ",
     "vs_6_0", 
     "vs_6_0", 
-    "!{i32 0, !\"SV_VertexID\", i8 5, i8 1, ![0-9]+, i8 0, i32 1, i8 1, i32 0, i8 0, null}",
-    "!{i32 0, !\"SV_VertexID\", i8 5, i8 1, !101, i8 0, i32 1, i8 1, i32 0, i8 0, null}\n!101 = !{i32 1}",
+    "!{i32 0, !\"SV_VertexID\", i8 5, i8 1, ![0-9]+, i8 0, i32 1, i8 1, i32 0, i8 0, (.*)}",
+    "!{i32 0, !\"SV_VertexID\", i8 5, i8 1, !101, i8 0, i32 1, i8 1, i32 0, i8 0, \\1}\n!101 = !{i32 1}",
     "SV_VertexID semantic index exceeds maximum \\(0\\)",
     "SV_VertexID semantic index exceeds maximum \\(0\\)",
     /*bRegex*/true);
     /*bRegex*/true);
 }
 }
@@ -1902,8 +1928,8 @@ Vertex main(uint id : SV_OutputControlPointID, InputPatch< Vertex, 3 > patch) {
 } \
 } \
     ",
     ",
     "hs_6_0",
     "hs_6_0",
-    "!{i32 0, !\"SV_TessFactor\", i8 9, i8 25, ![0-9]+, i8 0, i32 3, i8 1, i32 0, i8 3, null}",
-    "!{i32 0, !\"SV_TessFactor\", i8 9, i8 25, !101, i8 0, i32 2, i8 1, i32 0, i8 3, null}\n!101 = !{i32 0, i32 1}",
+    "!{i32 0, !\"SV_TessFactor\", i8 9, i8 25, ![0-9]+, i8 0, i32 3, i8 1, i32 0, i8 3, (.*)}",
+    "!{i32 0, !\"SV_TessFactor\", i8 9, i8 25, !101, i8 0, i32 2, i8 1, i32 0, i8 3, \\1}\n!101 = !{i32 0, i32 1}",
     "TessFactor rows, columns \\(2, 1\\) invalid for domain Tri.  Expected 3 rows and 1 column.",
     "TessFactor rows, columns \\(2, 1\\) invalid for domain Tri.  Expected 3 rows and 1 column.",
     /*bRegex*/true);
     /*bRegex*/true);
 }
 }
@@ -1935,9 +1961,9 @@ Vertex main(uint id : SV_OutputControlPointID, InputPatch< Vertex, 3 > patch) {
 } \
 } \
     ",
     ",
     "hs_6_0",
     "hs_6_0",
-    { "!{i32 1, !\"SV_InsideTessFactor\", i8 9, i8 26, !([0-9]+), i8 0, i32 1, i8 1, i32 3, i8 0, null}",
+    { "!{i32 1, !\"SV_InsideTessFactor\", i8 9, i8 26, !([0-9]+), i8 0, i32 1, i8 1, i32 3, i8 0, (.*)}",
       "?!dx.viewIdState =" },
       "?!dx.viewIdState =" },
-    { "!{i32 1, !\"SV_InsideTessFactor\", i8 9, i8 26, !101, i8 0, i32 2, i8 1, i32 3, i8 0, null}\n!101 = !{i32 0, i32 1}",
+    { "!{i32 1, !\"SV_InsideTessFactor\", i8 9, i8 26, !101, i8 0, i32 2, i8 1, i32 3, i8 0, \\2}\n!101 = !{i32 0, i32 1}",
       "!1012 =" },
       "!1012 =" },
     "InsideTessFactor rows, columns \\(2, 1\\) invalid for domain Tri.  Expected 1 rows and 1 column.",
     "InsideTessFactor rows, columns \\(2, 1\\) invalid for domain Tri.  Expected 1 rows and 1 column.",
     /*bRegex*/true);
     /*bRegex*/true);
@@ -1970,8 +1996,8 @@ Vertex main(uint id : SV_OutputControlPointID, InputPatch< Vertex, 3 > patch) {
 } \
 } \
     ",
     ",
     "hs_6_0",
     "hs_6_0",
-    "!{i32 0, !\"SV_TessFactor\", i8 9, i8 25, !([0-9]+), i8 0, i32 3, i8 1, i32 0, i8 3, null}",
-    "!{i32 0, !\"SV_TessFactor\", i8 9, i8 25, !\\1, i8 0, i32 3, i8 1, i32 -1, i8 -1, null}",
+    "!{i32 0, !\"SV_TessFactor\", i8 9, i8 25, !([0-9]+), i8 0, i32 3, i8 1, i32 0, i8 3, (.*)}",
+    "!{i32 0, !\"SV_TessFactor\", i8 9, i8 25, !\\1, i8 0, i32 3, i8 1, i32 -1, i8 -1, \\2}",
     "PatchConstant Semantic 'SV_TessFactor' should have a valid packing location",
     "PatchConstant Semantic 'SV_TessFactor' should have a valid packing location",
     /*bRegex*/true);
     /*bRegex*/true);
 }
 }
@@ -1981,8 +2007,8 @@ TEST_F(ValidationTest, SemShouldNotBeAllocated) {
 float4 main(float4 col : COLOR, out uint coverage : SV_Coverage) : SV_Target7 { coverage = 7; return col; } \
 float4 main(float4 col : COLOR, out uint coverage : SV_Coverage) : SV_Target7 { coverage = 7; return col; } \
     ",
     ",
     "ps_6_0",
     "ps_6_0",
-    "!\"SV_Coverage\", i8 5, i8 14, !([0-9]+), i8 0, i32 1, i8 1, i32 -1, i8 -1, null}",
-    "!\"SV_Coverage\", i8 5, i8 14, !\\1, i8 0, i32 1, i8 1, i32 2, i8 0, null}",
+    "!\"SV_Coverage\", i8 5, i8 14, !([0-9]+), i8 0, i32 1, i8 1, i32 -1, i8 -1, (.*)}",
+    "!\"SV_Coverage\", i8 5, i8 14, !\\1, i8 0, i32 1, i8 1, i32 2, i8 0, \\2}",
     "Output Semantic 'SV_Coverage' should have a packing location of -1",
     "Output Semantic 'SV_Coverage' should have a packing location of -1",
     /*bRegex*/true);
     /*bRegex*/true);
 }
 }
@@ -2007,16 +2033,16 @@ void main( \
     ",
     ",
     "vs_6_0",
     "vs_6_0",
 
 
-    { "= !{i32 1, !\"f2out\", i8 9, i8 0, !([0-9]+), i8 2, i32 1, i8 2, i32 1, i8 0, null}\n"
-      "!([0-9]+) = !{i32 2, !\"f3out\", i8 9, i8 0, !([0-9]+), i8 2, i32 1, i8 3, i32 2, i8 0, null}\n"
-      "!([0-9]+) = !{i32 3, !\"SV_ClipDistance\", i8 9, i8 6, !([0-9]+), i8 2, i32 1, i8 2, i32 3, i8 0, null}\n"
-      "!([0-9]+) = !{i32 4, !\"SV_CullDistance\", i8 9, i8 7, !([0-9]+), i8 2, i32 1, i8 1, i32 3, i8 2, null}\n",
+    { "= !{i32 1, !\"f2out\", i8 9, i8 0, !([0-9]+), i8 2, i32 1, i8 2, i32 1, i8 0, (.*)}\n"
+      "!([0-9]+) = !{i32 2, !\"f3out\", i8 9, i8 0, !([0-9]+), i8 2, i32 1, i8 3, i32 2, i8 0, (.*)}\n"
+      "!([0-9]+) = !{i32 3, !\"SV_ClipDistance\", i8 9, i8 6, !([0-9]+), i8 2, i32 1, i8 2, i32 3, i8 0, (.*)}\n"
+      "!([0-9]+) = !{i32 4, !\"SV_CullDistance\", i8 9, i8 7, !([0-9]+), i8 2, i32 1, i8 1, i32 3, i8 2, (.*)}\n",
       "?!dx.viewIdState =" },
       "?!dx.viewIdState =" },
 
 
-    { "= !{i32 1, !\"f2out\", i8 9, i8 0, !\\1, i8 2, i32 1, i8 2, i32 1, i8 2, null}\n"
-      "!\\2 = !{i32 2, !\"f3out\", i8 9, i8 0, !\\3, i8 2, i32 1, i8 3, i32 2, i8 1, null}\n"
-      "!\\4 = !{i32 3, !\"SV_ClipDistance\", i8 9, i8 6, !\\5, i8 2, i32 1, i8 2, i32 2, i8 0, null}\n"
-      "!\\6 = !{i32 4, !\"SV_CullDistance\", i8 9, i8 7, !\\7, i8 2, i32 1, i8 1, i32 1, i8 0, null}\n",
+    { "= !{i32 1, !\"f2out\", i8 9, i8 0, !\\1, i8 2, i32 1, i8 2, i32 1, i8 2, \\2}\n"
+      "!\\3 = !{i32 2, !\"f3out\", i8 9, i8 0, !\\4, i8 2, i32 1, i8 3, i32 2, i8 1, \\5}\n"
+      "!\\6 = !{i32 3, !\"SV_ClipDistance\", i8 9, i8 6, !\\7, i8 2, i32 1, i8 2, i32 2, i8 0, \\8}\n"
+      "!\\9 = !{i32 4, !\"SV_CullDistance\", i8 9, i8 7, !\\10, i8 2, i32 1, i8 1, i32 1, i8 0, \\11}\n",
       "!1012 =" },
       "!1012 =" },
 
 
     "signature element SV_ClipDistance at location \\(2,0\\) size \\(1,2\\) violates component ordering rule \\(arb < sv < sgv\\).\n"
     "signature element SV_ClipDistance at location \\(2,0\\) size \\(1,2\\) violates component ordering rule \\(arb < sv < sgv\\).\n"
@@ -2102,8 +2128,8 @@ void main( \
     ",
     ",
     "vs_6_0",
     "vs_6_0",
 
 
-    "!{i32 2, !\"SV_ViewportArrayIndex\", i8 5, i8 5, !([0-9]+), i8 1, i32 1, i8 1, i32 3, i8 0, null}",
-    "!{i32 2, !\"SV_ViewportArrayIndex\", i8 5, i8 5, !\\1, i8 1, i32 1, i8 1, i32 1, i8 3, null}",
+    "!{i32 2, !\"SV_ViewportArrayIndex\", i8 5, i8 5, !([0-9]+), i8 1, i32 1, i8 1, i32 3, i8 0, (.*)}",
+    "!{i32 2, !\"SV_ViewportArrayIndex\", i8 5, i8 5, !\\1, i8 1, i32 1, i8 1, i32 1, i8 3, \\2}",
 
 
     "signature element SV_ViewportArrayIndex at location \\(1,3\\) size \\(1,1\\) has an indexing conflict with another signature element packed into the same row.",
     "signature element SV_ViewportArrayIndex at location \\(1,3\\) size \\(1,1\\) has an indexing conflict with another signature element packed into the same row.",
     /*bRegex*/true);
     /*bRegex*/true);
@@ -2137,9 +2163,9 @@ Vertex main(uint id : SV_OutputControlPointID, InputPatch< Vertex, 4 > patch) {
     ",
     ",
     "hs_6_0",
     "hs_6_0",
     //!{i32 0, !"SV_TessFactor", i8 9, i8 25, !23, i8 0, i32 4, i8 1, i32 0, i8 3, null}
     //!{i32 0, !"SV_TessFactor", i8 9, i8 25, !23, i8 0, i32 4, i8 1, i32 0, i8 3, null}
-    { "!{i32 1, !\"SV_InsideTessFactor\", i8 9, i8 26, !([0-9]+), i8 0, i32 2, i8 1, i32 4, i8 3, null}",
+    { "!{i32 1, !\"SV_InsideTessFactor\", i8 9, i8 26, !([0-9]+), i8 0, i32 2, i8 1, i32 4, i8 3, (.*)}",
       "?!dx.viewIdState =" },
       "?!dx.viewIdState =" },
-    { "!{i32 1, !\"SV_InsideTessFactor\", i8 9, i8 26, !\\1, i8 0, i32 2, i8 1, i32 0, i8 2, null}",
+    { "!{i32 1, !\"SV_InsideTessFactor\", i8 9, i8 26, !\\1, i8 0, i32 2, i8 1, i32 0, i8 2, \\2}",
       "!1012 =" },
       "!1012 =" },
     "signature element SV_InsideTessFactor at location \\(0,2\\) size \\(2,1\\) has an indexing conflict with another signature element packed into the same row.",
     "signature element SV_InsideTessFactor at location \\(0,2\\) size \\(2,1\\) has an indexing conflict with another signature element packed into the same row.",
     /*bRegex*/true);
     /*bRegex*/true);
@@ -2174,8 +2200,8 @@ Vertex main(uint id : SV_OutputControlPointID, InputPatch< Vertex, 4 > patch) {
 } \
 } \
     ",
     ",
     "hs_6_0",
     "hs_6_0",
-    "!{i32 2, !\"Arb\", i8 9, i8 0, !([0-9]+), i8 0, i32 3, i8 1, i32 0, i8 0, null}",
-    "!{i32 2, !\"Arb\", i8 9, i8 0, !\\1, i8 0, i32 3, i8 1, i32 2, i8 0, null}",
+    "!{i32 2, !\"Arb\", i8 9, i8 0, !([0-9]+), i8 0, i32 3, i8 1, i32 0, i8 0, (.*)}",
+    "!{i32 2, !\"Arb\", i8 9, i8 0, !\\1, i8 0, i32 3, i8 1, i32 2, i8 0, \\2}",
     "signature element Arb at location \\(2,0\\) size \\(3,1\\) has an indexing conflict with another signature element packed into the same row.",
     "signature element Arb at location \\(2,0\\) size \\(3,1\\) has an indexing conflict with another signature element packed into the same row.",
     /*bRegex*/true);
     /*bRegex*/true);
 }
 }
@@ -2209,9 +2235,9 @@ Vertex main(uint id : SV_OutputControlPointID, InputPatch< Vertex, 4 > patch) {
 } \
 } \
     ",
     ",
     "hs_6_0",
     "hs_6_0",
-    { "!{i32 2, !\"Arb\", i8 9, i8 0, !([0-9]+), i8 0, i32 3, i8 1, i32 0, i8 0, null}",
+    { "!{i32 2, !\"Arb\", i8 9, i8 0, !([0-9]+), i8 0, i32 3, i8 1, i32 0, i8 0, (.*)}",
       "?!dx.viewIdState =" },
       "?!dx.viewIdState =" },
-    { "!{i32 2, !\"Arb\", i8 9, i8 0, !\\1, i8 0, i32 3, i8 1, i32 31, i8 0, null}",
+    { "!{i32 2, !\"Arb\", i8 9, i8 0, !\\1, i8 0, i32 3, i8 1, i32 31, i8 0, \\2}",
       "!1012 =" },
       "!1012 =" },
     "signature element Arb at location \\(31,0\\) size \\(3,1\\) is out of range.",
     "signature element Arb at location \\(31,0\\) size \\(3,1\\) is out of range.",
     /*bRegex*/true);
     /*bRegex*/true);
@@ -2246,8 +2272,8 @@ Vertex main(uint id : SV_OutputControlPointID, InputPatch< Vertex, 4 > patch) {
 } \
 } \
     ",
     ",
     "hs_6_0",
     "hs_6_0",
-    "!{i32 2, !\"Arb\", i8 9, i8 0, !([0-9]+), i8 0, i32 3, i8 1, i32 0, i8 0, null}",
-    "!{i32 2, !\"Arb\", i8 9, i8 0, !\\1, i8 0, i32 3, i8 1, i32 1, i8 3, null}",
+    "!{i32 2, !\"Arb\", i8 9, i8 0, !([0-9]+), i8 0, i32 3, i8 1, i32 0, i8 0, (.*)}",
+    "!{i32 2, !\"Arb\", i8 9, i8 0, !\\1, i8 0, i32 3, i8 1, i32 1, i8 3, \\2}",
     "signature element Arb at location \\(1,3\\) size \\(3,1\\) overlaps another signature element.",
     "signature element Arb at location \\(1,3\\) size \\(3,1\\) overlaps another signature element.",
     /*bRegex*/true);
     /*bRegex*/true);
 }
 }
@@ -2273,13 +2299,13 @@ void main( \
     ",
     ",
     "vs_6_0",
     "vs_6_0",
 
 
-    {"!{i32 1, !\"Array\", i8 5, i8 0, !([0-9]+), i8 1, i32 2, i8 1, i32 1, i8 0, null}(.*)"
+    {"!{i32 1, !\"Array\", i8 5, i8 0, !([0-9]+), i8 1, i32 2, i8 1, i32 1, i8 0, (.*)}(.*)"
     "!\\1 = !{i32 0, i32 1}\n",
     "!\\1 = !{i32 0, i32 1}\n",
-    "= !{i32 2, !\"Value\", i8 5, i8 0, !([0-9]+), i8 1, i32 1, i8 3, i32 1, i8 1, null}"},
+    "= !{i32 2, !\"Value\", i8 5, i8 0, !([0-9]+), i8 1, i32 1, i8 3, i32 1, i8 1, (.*)}"},
 
 
-    {"!{i32 1, !\"Array\", i8 5, i8 0, !\\1, i8 1, i32 2, i8 1, i32 1, i8 1, null}\\2"
+    {"!{i32 1, !\"Array\", i8 5, i8 0, !\\1, i8 1, i32 2, i8 1, i32 1, i8 1, \\2}\\3"
     "!\\1 = !{i32 0, i32 1}\n",
     "!\\1 = !{i32 0, i32 1}\n",
-    "= !{i32 2, !\"Value\", i8 5, i8 0, !\\1, i8 1, i32 1, i8 3, i32 2, i8 0, null}"},
+    "= !{i32 2, !\"Value\", i8 5, i8 0, !\\1, i8 1, i32 1, i8 3, i32 2, i8 0, \\2}"},
 
 
     "signature element Value at location \\(2,0\\) size \\(1,3\\) overlaps another signature element.",
     "signature element Value at location \\(2,0\\) size \\(1,3\\) overlaps another signature element.",
     /*bRegex*/true);
     /*bRegex*/true);
@@ -2291,8 +2317,8 @@ float4 main(float4 f4 : Input, out float d0 : SV_Depth, out float d1 : SV_Target
 { d0 = f4.z; d1 = f4.w; return f4; } \
 { d0 = f4.z; d1 = f4.w; return f4; } \
     ",
     ",
     "ps_6_0",
     "ps_6_0",
-    {"!{i32 2, !\"SV_Target\", i8 9, i8 16, !([0-9]+), i8 0, i32 1, i8 1, i32 0, i8 0, null}"},
-    {"!{i32 2, !\"SV_DepthGreaterEqual\", i8 9, i8 19, !\\1, i8 0, i32 1, i8 1, i32 -1, i8 -1, null}"},
+    {"!{i32 2, !\"SV_Target\", i8 9, i8 16, !([0-9]+), i8 0, i32 1, i8 1, i32 0, i8 0, (.*)}"},
+    {"!{i32 2, !\"SV_DepthGreaterEqual\", i8 9, i8 19, !\\1, i8 0, i32 1, i8 1, i32 -1, i8 -1, \\2}"},
     "Pixel Shader only allows one type of depth semantic to be declared",
     "Pixel Shader only allows one type of depth semantic to be declared",
     /*bRegex*/true);
     /*bRegex*/true);
 }
 }
@@ -2863,7 +2889,7 @@ TEST_F(ValidationTest, WhenProgramSigMismatchThenFail) {
     {
     {
       "Container part 'Program Input Signature' does not match expected for module.",
       "Container part 'Program Input Signature' does not match expected for module.",
       "Container part 'Program Output Signature' does not match expected for module.",
       "Container part 'Program Output Signature' does not match expected for module.",
-      "Container part 'Program Patch Constant or Primitive Signature' does not match expected for module.",
+      "Container part 'Program Patch Constant Signature' does not match expected for module.",
       "Validation failed."
       "Validation failed."
     }
     }
   );
   );
@@ -2909,7 +2935,7 @@ TEST_F(ValidationTest, WhenProgramSigMismatchThenFail2) {
     {
     {
       "Container part 'Program Input Signature' does not match expected for module.",
       "Container part 'Program Input Signature' does not match expected for module.",
       "Container part 'Program Output Signature' does not match expected for module.",
       "Container part 'Program Output Signature' does not match expected for module.",
-      "Container part 'Program Patch Constant or Primitive Signature' does not match expected for module.",
+      "Container part 'Program Patch Constant Signature' does not match expected for module.",
       "Validation failed."
       "Validation failed."
     }
     }
   );
   );
@@ -3649,10 +3675,10 @@ TEST_F(ValidationTest, MeshGreaterThanMaxXYZ) {
 
 
 TEST_F(ValidationTest, MeshGreaterThanMaxVSigRowCount) {
 TEST_F(ValidationTest, MeshGreaterThanMaxVSigRowCount) {
   RewriteAssemblyCheckMsg(L"..\\CodeGenHLSL\\mesh-val\\mesh.hlsl", "ms_6_5",
   RewriteAssemblyCheckMsg(L"..\\CodeGenHLSL\\mesh-val\\mesh.hlsl", "ms_6_5",
-                          "!([0-9]+) = !{i32 1, !\"COLOR\", i8 9, i8 0, !([0-9]+), i8 2, i32 4, i8 1, i32 1, i8 0, null}\n"
-                          "!([0-9]+) = !{i32 0, i32 1, i32 2, i32 3}",
-                          "!\\1 = !{i32 1, !\"COLOR\", i8 9, i8 0, !\\2, i8 2, i32 32, i8 1, i32 1, i8 0, null}\n"
-                          "!\\3 = !{i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10,"
+                          "!([0-9]+) = !{i32 1, !\"COLOR\", i8 9, i8 0, !([0-9]+), i8 2, i32 4, i8 1, i32 1, i8 0, (.*)"
+                          "!\\2 = !{i32 0, i32 1, i32 2, i32 3}",
+                          "!\\1 = !{i32 1, !\"COLOR\", i8 9, i8 0, !\\2, i8 2, i32 32, i8 1, i32 1, i8 0, \\3"
+                          "!\\2 = !{i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10,"
                           "i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20,"
                           "i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20,"
                           "i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31}",
                           "i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31}",
                           "For shader 'main', vertex output signatures are taking up more than 32 rows",
                           "For shader 'main', vertex output signatures are taking up more than 32 rows",
@@ -3661,10 +3687,10 @@ TEST_F(ValidationTest, MeshGreaterThanMaxVSigRowCount) {
 
 
 TEST_F(ValidationTest, MeshGreaterThanMaxPSigRowCount) {
 TEST_F(ValidationTest, MeshGreaterThanMaxPSigRowCount) {
   RewriteAssemblyCheckMsg(L"..\\CodeGenHLSL\\mesh-val\\mesh.hlsl", "ms_6_5",
   RewriteAssemblyCheckMsg(L"..\\CodeGenHLSL\\mesh-val\\mesh.hlsl", "ms_6_5",
-                          "!([0-9]+) = !{i32 4, !\"LAYER\", i8 4, i8 0, !([0-9]+), i8 1, i32 6, i8 1, i32 1, i8 0, null}\n"
-                          "!([0-9]+) = !{i32 0, i32 1, i32 2, i32 3, i32 4, i32 5}",
-                          "!\\1 = !{i32 4, !\"LAYER\", i8 4, i8 0, !\\2, i8 1, i32 32, i8 1, i32 1, i8 0, null}\n"
-                          "!\\3 = !{i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10,"
+                          "!([0-9]+) = !{i32 4, !\"LAYER\", i8 4, i8 0, !([0-9]+), i8 1, i32 6, i8 1, i32 1, i8 0, (.*)"
+                          "!\\2 = !{i32 0, i32 1, i32 2, i32 3, i32 4, i32 5}",
+                          "!\\1 = !{i32 4, !\"LAYER\", i8 4, i8 0, !\\2, i8 1, i32 32, i8 1, i32 1, i8 0, \\3"
+                          "!\\2 = !{i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10,"
                           "i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20,"
                           "i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20,"
                           "i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31}",
                           "i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31}",
                           "For shader 'main', primitive output signatures are taking up more than 32 rows",
                           "For shader 'main', primitive output signatures are taking up more than 32 rows",
@@ -3673,15 +3699,15 @@ TEST_F(ValidationTest, MeshGreaterThanMaxPSigRowCount) {
 
 
 TEST_F(ValidationTest, MeshGreaterThanMaxTotalSigRowCount) {
 TEST_F(ValidationTest, MeshGreaterThanMaxTotalSigRowCount) {
   RewriteAssemblyCheckMsg(L"..\\CodeGenHLSL\\mesh-val\\mesh.hlsl", "ms_6_5",
   RewriteAssemblyCheckMsg(L"..\\CodeGenHLSL\\mesh-val\\mesh.hlsl", "ms_6_5",
-                          { "!([0-9]+) = !{i32 1, !\"COLOR\", i8 9, i8 0, !([0-9]+), i8 2, i32 4, i8 1, i32 1, i8 0, null}\n"
-                            "!([0-9]+) = !{i32 0, i32 1, i32 2, i32 3}",
-                            "!([0-9]+) = !{i32 4, !\"LAYER\", i8 4, i8 0, !([0-9]+), i8 1, i32 6, i8 1, i32 1, i8 0, null}\n"
-                            "!([0-9]+) = !{i32 0, i32 1, i32 2, i32 3, i32 4, i32 5}" },
-                          { "!\\1 = !{i32 1, !\"COLOR\", i8 9, i8 0, !\\2, i8 2, i32 16, i8 1, i32 1, i8 0, null}\n"
-                            "!\\3 = !{i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10,"
+                          { "!([0-9]+) = !{i32 1, !\"COLOR\", i8 9, i8 0, !([0-9]+), i8 2, i32 4, i8 1, i32 1, i8 0, (.*)"
+                            "!\\2 = !{i32 0, i32 1, i32 2, i32 3}",
+                            "!([0-9]+) = !{i32 4, !\"LAYER\", i8 4, i8 0, !([0-9]+), i8 1, i32 6, i8 1, i32 1, i8 0, (.*)"
+                            "!\\2 = !{i32 0, i32 1, i32 2, i32 3, i32 4, i32 5}" },
+                          { "!\\1 = !{i32 1, !\"COLOR\", i8 9, i8 0, !\\2, i8 2, i32 16, i8 1, i32 1, i8 0, \\3"
+                            "!\\2 = !{i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10,"
                             "i32 11, i32 12, i32 13, i32 14, i32 15}",
                             "i32 11, i32 12, i32 13, i32 14, i32 15}",
-                            "!\\1 = !{i32 4, !\"LAYER\", i8 4, i8 0, !\\2, i8 1, i32 16, i8 1, i32 1, i8 0, null}\n"
-                            "!\\3 = !{i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10,"
+                            "!\\1 = !{i32 4, !\"LAYER\", i8 4, i8 0, !\\2, i8 1, i32 16, i8 1, i32 1, i8 0, \\3"
+                            "!\\2 = !{i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10,"
                             "i32 11, i32 12, i32 13, i32 14, i32 15}",
                             "i32 11, i32 12, i32 13, i32 14, i32 15}",
                           },
                           },
                           "For shader 'main', vertex and primitive output signatures are taking up more than 32 rows",
                           "For shader 'main', vertex and primitive output signatures are taking up more than 32 rows",

+ 0 - 1
utils/hct/hctdb.py

@@ -2271,7 +2271,6 @@ class db_dxil(object):
         self.add_valrule("Meta.TessellatorOutputPrimitive", "Invalid Tessellator Output Primitive specified. Must be point, line, triangleCW or triangleCCW.")
         self.add_valrule("Meta.TessellatorOutputPrimitive", "Invalid Tessellator Output Primitive specified. Must be point, line, triangleCW or triangleCCW.")
         self.add_valrule("Meta.MaxTessFactor", "Hull Shader MaxTessFactor must be [%0..%1].  %2 specified")
         self.add_valrule("Meta.MaxTessFactor", "Hull Shader MaxTessFactor must be [%0..%1].  %2 specified")
         self.add_valrule("Meta.ValidSamplerMode", "Invalid sampler mode on sampler ")
         self.add_valrule("Meta.ValidSamplerMode", "Invalid sampler mode on sampler ")
-        self.add_valrule("Meta.FunctionAnnotation", "Cannot find function annotation for %0")
         self.add_valrule("Meta.GlcNotOnAppendConsume", "globallycoherent cannot be used with append/consume buffers")
         self.add_valrule("Meta.GlcNotOnAppendConsume", "globallycoherent cannot be used with append/consume buffers")
         self.add_valrule_msg("Meta.StructBufAlignment", "StructuredBuffer stride not aligned","structured buffer element size must be a multiple of %0 bytes (actual size %1 bytes)")
         self.add_valrule_msg("Meta.StructBufAlignment", "StructuredBuffer stride not aligned","structured buffer element size must be a multiple of %0 bytes (actual size %1 bytes)")
         self.add_valrule_msg("Meta.StructBufAlignmentOutOfBound", "StructuredBuffer stride out of bounds","structured buffer elements cannot be larger than %0 bytes (actual size %1 bytes)")
         self.add_valrule_msg("Meta.StructBufAlignmentOutOfBound", "StructuredBuffer stride out of bounds","structured buffer elements cannot be larger than %0 bytes (actual size %1 bytes)")