Explorar el Código

Merge pull request #76 from tex3d/integration

Integrate validation, dxc option, and other changes
Tex Riddell hace 8 años
padre
commit
a6433c18f8
Se han modificado 40 ficheros con 2959 adiciones y 923 borrados
  1. 7 1
      docs/DXIL.rst
  2. 25 2
      include/dxc/HLSL/DxilContainer.h
  3. 5 3
      include/dxc/HLSL/DxilMetadataHelper.h
  4. 6 0
      include/dxc/HLSL/DxilModule.h
  5. 51 48
      include/dxc/HLSL/DxilPipelineStateValidation.h
  6. 23 5
      include/dxc/HLSL/DxilRootSignature.h
  7. 56 4
      include/dxc/HLSL/DxilValidation.h
  8. 10 1
      include/dxc/Support/ErrorCodes.h
  9. 3 1
      include/dxc/Support/Global.h
  10. 10 6
      include/dxc/Support/HLSLOptions.h
  11. 38 34
      include/dxc/Support/HLSLOptions.td
  12. 3 3
      include/dxc/Support/dxcapi.use.h
  13. 2 1
      include/dxc/dxcapi.h
  14. 10 5
      lib/DxcSupport/HLSLOptions.cpp
  15. 17 8
      lib/DxcSupport/dxcapi.use.cpp
  16. 90 55
      lib/HLSL/DxilContainerAssembler.cpp
  17. 7 1
      lib/HLSL/DxilGenerationPass.cpp
  18. 20 5
      lib/HLSL/DxilMetadataHelper.cpp
  19. 58 9
      lib/HLSL/DxilModule.cpp
  20. 17 17
      lib/HLSL/DxilOperations.cpp
  21. 386 320
      lib/HLSL/DxilRootSignature.cpp
  22. 514 53
      lib/HLSL/DxilValidation.cpp
  23. 9 25
      lib/HLSL/HLModule.cpp
  24. 34 34
      tools/clang/lib/Sema/gen_intrin_main_tables_15.h
  25. 1 1
      tools/clang/test/CodeGenHLSL/RaceCond.hlsl
  26. 16 0
      tools/clang/test/CodeGenHLSL/RaceCond2.hlsl
  27. 1 1
      tools/clang/test/CodeGenHLSL/UndefValue.hlsl
  28. 213 47
      tools/clang/tools/dxc/dxc.cpp
  29. 1 1
      tools/clang/tools/dxcompiler/dxcassembler.cpp
  30. 1 1
      tools/clang/tools/dxcompiler/dxcompilerobj.cpp
  31. 43 5
      tools/clang/tools/dxcompiler/dxcontainerbuilder.cpp
  32. 80 85
      tools/clang/tools/dxcompiler/dxcvalidator.cpp
  33. 2 0
      tools/clang/unittests/HLSL/CMakeLists.txt
  34. 50 0
      tools/clang/unittests/HLSL/CompilerTest.cpp
  35. 845 64
      tools/clang/unittests/HLSL/ValidationTest.cpp
  36. 34 34
      utils/hct/gen_intrin_main.txt
  37. 26 18
      utils/hct/hctdb.py
  38. 2 2
      utils/hct/hcttest.cmd
  39. 240 21
      utils/hct/hcttestcmds.cmd
  40. 3 2
      utils/hct/smoke.hlsl

+ 7 - 1
docs/DXIL.rst

@@ -2104,6 +2104,11 @@ The set of validation rules that are known to hold for a DXIL program is identif
 Rule Code                             Description
 Rule Code                             Description
 ===================================== =======================================================================================================================================================================================================================================================================================================
 ===================================== =======================================================================================================================================================================================================================================================================================================
 BITCODE.VALID                         TODO - Module must be bitcode-valid
 BITCODE.VALID                         TODO - Module must be bitcode-valid
+CONTAINER.PARTINVALID                 DXIL Container must not contain unknown parts
+CONTAINER.PARTMATCHES                 DXIL Container Parts must match Module
+CONTAINER.PARTMISSING                 DXIL Container requires certain parts, corresponding to module
+CONTAINER.PARTREPEATED                DXIL Container must have only one of each part type
+CONTAINER.ROOTSIGNATUREINCOMPATIBLE   Root Signature in DXIL Container must be compatible with shader
 DECL.DXILFNEXTERN                     External function must be a DXIL function
 DECL.DXILFNEXTERN                     External function must be a DXIL function
 DECL.DXILNSRESERVED                   The DXIL reserved prefixes must only be used by built-in functions and types
 DECL.DXILNSRESERVED                   The DXIL reserved prefixes must only be used by built-in functions and types
 DECL.FNFLATTENPARAM                   Function parameters must not use struct types
 DECL.FNFLATTENPARAM                   Function parameters must not use struct types
@@ -2236,7 +2241,7 @@ SM.GSOUTPUTVERTEXCOUNTRANGE           GS output vertex count must be [0..%0].  %
 SM.GSTOTALOUTPUTVERTEXDATARANGE       Declared output vertex count (%0) multiplied by the total number of declared scalar components of output data (%1) equals %2.  This value cannot be greater than %3
 SM.GSTOTALOUTPUTVERTEXDATARANGE       Declared output vertex count (%0) multiplied by the total number of declared scalar components of output data (%1) equals %2.  This value cannot be greater than %3
 SM.GSVALIDINPUTPRIMITIVE              GS input primitive unrecognized
 SM.GSVALIDINPUTPRIMITIVE              GS input primitive unrecognized
 SM.GSVALIDOUTPUTPRIMITIVETOPOLOGY     GS output primitive topology unrecognized
 SM.GSVALIDOUTPUTPRIMITIVETOPOLOGY     GS output primitive topology unrecognized
-SM.HSINPUTCONTROLPOINTCOUNTRANGE      HS input control point count must be [1..%0].  %1 specified
+SM.HSINPUTCONTROLPOINTCOUNTRANGE      HS input control point count must be [0..%0].  %1 specified
 SM.HULLPASSTHRUCONTROLPOINTCOUNTMATCH For pass thru hull shader, input control point count must match output control point count
 SM.HULLPASSTHRUCONTROLPOINTCOUNTMATCH For pass thru hull shader, input control point count must match output control point count
 SM.INSIDETESSFACTORSIZEMATCHDOMAIN    InsideTessFactor rows, columns (%0, %1) invalid for domain %2.  Expected %3 rows and 1 column.
 SM.INSIDETESSFACTORSIZEMATCHDOMAIN    InsideTessFactor rows, columns (%0, %1) invalid for domain %2.  Expected %3 rows and 1 column.
 SM.INVALIDRESOURCECOMPTYPE            Invalid resource return type
 SM.INVALIDRESOURCECOMPTYPE            Invalid resource return type
@@ -2272,6 +2277,7 @@ SM.THREADGROUPCHANNELRANGE            Declared Thread Group %0 size %1 outside v
 SM.TRIOUTPUTPRIMITIVEMISMATCH         Hull Shader declared with Tri Domain must specify output primitive point, triangle_cw or triangle_ccw. Line output is not compatible with the Tri domain
 SM.TRIOUTPUTPRIMITIVEMISMATCH         Hull Shader declared with Tri Domain must specify output primitive point, triangle_cw or triangle_ccw. Line output is not compatible with the Tri domain
 SM.UNDEFINEDOUTPUT                    Not all elements of output %0 were written
 SM.UNDEFINEDOUTPUT                    Not all elements of output %0 were written
 SM.VALIDDOMAIN                        Invalid Tessellator Domain specified. Must be isoline, tri or quad
 SM.VALIDDOMAIN                        Invalid Tessellator Domain specified. Must be isoline, tri or quad
+SM.ZEROHSINPUTCONTROLPOINTWITHINPUT   When HS input control point count is 0, no input signature should exist
 TYPES.DEFINED                         Type must be defined based on DXIL primitives
 TYPES.DEFINED                         Type must be defined based on DXIL primitives
 TYPES.I8                              I8 can only used as immediate value for intrinsic
 TYPES.I8                              I8 can only used as immediate value for intrinsic
 TYPES.INTWIDTH                        Int type must be of valid width
 TYPES.INTWIDTH                        Int type must be of valid width

+ 25 - 2
include/dxc/HLSL/DxilContainer.h

@@ -16,6 +16,7 @@
 
 
 #include <stdint.h>
 #include <stdint.h>
 #include <iterator>
 #include <iterator>
+#include <functional>
 #include "dxc/HLSL/DxilConstants.h"
 #include "dxc/HLSL/DxilConstants.h"
 
 
 struct IDxcContainerReflection;
 struct IDxcContainerReflection;
@@ -23,6 +24,10 @@ namespace llvm { class Module; }
 
 
 namespace hlsl {
 namespace hlsl {
 
 
+class AbstractMemoryStream;
+class RootSignatureHandle;
+class DxilModule;
+
 #pragma pack(push, 1)
 #pragma pack(push, 1)
 
 
 static const size_t DxilContainerHashSize = 16;
 static const size_t DxilContainerHashSize = 16;
@@ -368,8 +373,26 @@ inline uint32_t EncodeVersion(DXIL::ShaderKind shaderType, uint32_t major,
   return ((unsigned)shaderType << 16) | (major << 4) | minor;
   return ((unsigned)shaderType << 16) | (major << 4) | minor;
 }
 }
 
 
-class AbstractMemoryStream;
-void SerializeDxilContainerForModule(llvm::Module *pModule,
+class DxilPartWriter {
+public:
+  virtual uint32_t size() const = 0;
+  virtual void write(AbstractMemoryStream *pStream) = 0;
+};
+
+DxilPartWriter *NewProgramSignatureWriter(const DxilModule &M, DXIL::SignatureKind Kind);
+DxilPartWriter *NewRootSignatureWriter(const RootSignatureHandle &S);
+DxilPartWriter *NewFeatureInfoWriter(const DxilModule &M);
+DxilPartWriter *NewPSVWriter(const DxilModule &M);
+
+class DxilContainerWriter : public DxilPartWriter  {
+public:
+  typedef std::function<void(AbstractMemoryStream*)> WriteFn;
+  virtual void AddPart(uint32_t FourCC, uint32_t Size, WriteFn Write) = 0;
+};
+
+DxilContainerWriter *NewDxilContainerWriter();
+
+void SerializeDxilContainerForModule(hlsl::DxilModule *pModule,
                                      AbstractMemoryStream *pModuleBitcode,
                                      AbstractMemoryStream *pModuleBitcode,
                                      AbstractMemoryStream *pStream);
                                      AbstractMemoryStream *pStream);
 void CreateDxcContainerReflection(IDxcContainerReflection **ppResult);
 void CreateDxcContainerReflection(IDxcContainerReflection **ppResult);

+ 5 - 3
include/dxc/HLSL/DxilMetadataHelper.h

@@ -72,6 +72,9 @@ public:
   // Entry points.
   // Entry points.
   static const char kDxilEntryPointsMDName[];
   static const char kDxilEntryPointsMDName[];
 
 
+  // Root Signature, for intermediate use, not valid in final DXIL module.
+  static const char kDxilRootSignatureMDName[];
+
   static const unsigned kDxilEntryPointNumFields  = 5;
   static const unsigned kDxilEntryPointNumFields  = 5;
   static const unsigned kDxilEntryPointFunction   = 0;  // Entry point function symbol.
   static const unsigned kDxilEntryPointFunction   = 0;  // Entry point function symbol.
   static const unsigned kDxilEntryPointName       = 1;  // Entry point unmangled name.
   static const unsigned kDxilEntryPointName       = 1;  // Entry point unmangled name.
@@ -181,7 +184,6 @@ public:
   static const unsigned kDxilDSStateTag         = 2;
   static const unsigned kDxilDSStateTag         = 2;
   static const unsigned kDxilHSStateTag         = 3;
   static const unsigned kDxilHSStateTag         = 3;
   static const unsigned kDxilNumThreadsTag      = 4;
   static const unsigned kDxilNumThreadsTag      = 4;
-  static const unsigned kDxilRootSignatureTag   = 5;
 
 
   // GSState.
   // GSState.
   static const unsigned kDxilGSStateNumFields               = 5;
   static const unsigned kDxilGSStateNumFields               = 5;
@@ -261,11 +263,11 @@ public:
   void LoadDxilSignatures(const llvm::MDOperand &MDO, DxilSignature &InputSig, 
   void LoadDxilSignatures(const llvm::MDOperand &MDO, DxilSignature &InputSig, 
                           DxilSignature &OutputSig, DxilSignature &PCSig);
                           DxilSignature &OutputSig, DxilSignature &PCSig);
   llvm::MDTuple *EmitSignatureMetadata(const DxilSignature &Sig);
   llvm::MDTuple *EmitSignatureMetadata(const DxilSignature &Sig);
-  llvm::Metadata *EmitRootSignature(RootSignatureHandle &RootSig);
+  void EmitRootSignature(RootSignatureHandle &RootSig);
   void LoadSignatureMetadata(const llvm::MDOperand &MDO, DxilSignature &Sig);
   void LoadSignatureMetadata(const llvm::MDOperand &MDO, DxilSignature &Sig);
   llvm::MDTuple *EmitSignatureElement(const DxilSignatureElement &SE);
   llvm::MDTuple *EmitSignatureElement(const DxilSignatureElement &SE);
   void LoadSignatureElement(const llvm::MDOperand &MDO, DxilSignatureElement &SE);
   void LoadSignatureElement(const llvm::MDOperand &MDO, DxilSignatureElement &SE);
-  void LoadRootSignature(const llvm::MDOperand &MDO, RootSignatureHandle &RootSig);
+  void LoadRootSignature(RootSignatureHandle &RootSig);
 
 
   // Resources.
   // Resources.
   llvm::MDTuple *EmitDxilResourceTuple(llvm::MDTuple *pSRVs, llvm::MDTuple *pUAVs, 
   llvm::MDTuple *EmitDxilResourceTuple(llvm::MDTuple *pSRVs, llvm::MDTuple *pUAVs, 

+ 6 - 0
include/dxc/HLSL/DxilModule.h

@@ -97,6 +97,9 @@ public:
   const DxilSignature &GetPatchConstantSignature() const;
   const DxilSignature &GetPatchConstantSignature() const;
   const RootSignatureHandle &GetRootSignature() const;
   const RootSignatureHandle &GetRootSignature() const;
 
 
+  // Remove Root Signature from module metadata
+  void StripRootSignatureFromMetadata();
+
   // DXIL type system.
   // DXIL type system.
   DxilTypeSystem &GetTypeSystem();
   DxilTypeSystem &GetTypeSystem();
 
 
@@ -121,6 +124,9 @@ public:
 
 
   void StripDebugRelatedCode();
   void StripDebugRelatedCode();
   llvm::DebugInfoFinder &GetOrCreateDebugInfoFinder();
   llvm::DebugInfoFinder &GetOrCreateDebugInfoFinder();
+
+  static DxilModule *TryGetDxilModule(llvm::Module *pModule);
+
 public:
 public:
   // Shader properties.
   // Shader properties.
   class ShaderFlags {
   class ShaderFlags {

+ 51 - 48
include/dxc/HLSL/DxilPipelineStateValidation.h

@@ -12,6 +12,9 @@
 #ifndef __DXIL_PIPELINE_STATE_VALIDATION__H__
 #ifndef __DXIL_PIPELINE_STATE_VALIDATION__H__
 #define __DXIL_PIPELINE_STATE_VALIDATION__H__
 #define __DXIL_PIPELINE_STATE_VALIDATION__H__
 
 
+#include <stdint.h>
+#include <string.h>
+
 // Versioning is additive and based on size
 // Versioning is additive and based on size
 struct PSVRuntimeInfo0
 struct PSVRuntimeInfo0
 {
 {
@@ -20,20 +23,20 @@ struct PSVRuntimeInfo0
       char OutputPositionPresent;
       char OutputPositionPresent;
     } VS;
     } VS;
     struct HSInfo {
     struct HSInfo {
-      UINT InputControlPointCount;      // max control points == 32
-      UINT OutputControlPointCount;     // max control points == 32
-      UINT TessellatorDomain;           // hlsl::DXIL::TessellatorDomain/D3D11_SB_TESSELLATOR_DOMAIN
-      UINT TessellatorOutputPrimitive;  // hlsl::DXIL::TessellatorOutputPrimitive/D3D11_SB_TESSELLATOR_OUTPUT_PRIMITIVE
+      uint32_t InputControlPointCount;      // max control points == 32
+      uint32_t OutputControlPointCount;     // max control points == 32
+      uint32_t TessellatorDomain;           // hlsl::DXIL::TessellatorDomain/D3D11_SB_TESSELLATOR_DOMAIN
+      uint32_t TessellatorOutputPrimitive;  // hlsl::DXIL::TessellatorOutputPrimitive/D3D11_SB_TESSELLATOR_OUTPUT_PRIMITIVE
     } HS;
     } HS;
     struct DSInfo {
     struct DSInfo {
-      UINT InputControlPointCount;      // max control points == 32
+      uint32_t InputControlPointCount;      // max control points == 32
       char OutputPositionPresent;
       char OutputPositionPresent;
-      UINT TessellatorDomain;           // hlsl::DXIL::TessellatorDomain/D3D11_SB_TESSELLATOR_DOMAIN
+      uint32_t TessellatorDomain;           // hlsl::DXIL::TessellatorDomain/D3D11_SB_TESSELLATOR_DOMAIN
     } DS;
     } DS;
     struct GSInfo {
     struct GSInfo {
-      UINT InputPrimitive;              // hlsl::DXIL::InputPrimitive/D3D10_SB_PRIMITIVE
-      UINT OutputTopology;              // hlsl::DXIL::PrimitiveTopology/D3D10_SB_PRIMITIVE_TOPOLOGY
-      UINT OutputStreamMask;            // max streams == 4
+      uint32_t InputPrimitive;              // hlsl::DXIL::InputPrimitive/D3D10_SB_PRIMITIVE
+      uint32_t OutputTopology;              // hlsl::DXIL::PrimitiveTopology/D3D10_SB_PRIMITIVE_TOPOLOGY
+      uint32_t OutputStreamMask;            // max streams == 4
       char OutputPositionPresent;
       char OutputPositionPresent;
     } GS;
     } GS;
     struct PSInfo {
     struct PSInfo {
@@ -41,8 +44,8 @@ struct PSVRuntimeInfo0
       char SampleFrequency;
       char SampleFrequency;
     } PS;
     } PS;
   };
   };
-  UINT MinimumExpectedWaveLaneCount;  // minimum lane count required, 0 if unused
-  UINT MaximumExpectedWaveLaneCount;  // maximum lane count required, 0xffffffff if unused
+  uint32_t MinimumExpectedWaveLaneCount;  // minimum lane count required, 0 if unused
+  uint32_t MaximumExpectedWaveLaneCount;  // maximum lane count required, 0xffffffff if unused
 };
 };
 // PSVRuntimeInfo1 would derive and extend
 // PSVRuntimeInfo1 would derive and extend
 
 
@@ -66,21 +69,21 @@ enum class PSVResourceType
 // Versioning is additive and based on size
 // Versioning is additive and based on size
 struct PSVResourceBindInfo0
 struct PSVResourceBindInfo0
 {
 {
-  UINT ResType;     // PSVResourceType
-  UINT Space;
-  UINT LowerBound;
-  UINT UpperBound;
+  uint32_t ResType;     // PSVResourceType
+  uint32_t Space;
+  uint32_t LowerBound;
+  uint32_t UpperBound;
 };
 };
 // PSVResourceBindInfo1 would derive and extend
 // PSVResourceBindInfo1 would derive and extend
 
 
 class DxilPipelineStateValidation
 class DxilPipelineStateValidation
 {
 {
-  UINT m_uPSVRuntimeInfoSize;
+  uint32_t m_uPSVRuntimeInfoSize;
   PSVRuntimeInfo0* m_pPSVRuntimeInfo0;
   PSVRuntimeInfo0* m_pPSVRuntimeInfo0;
-  UINT m_uResourceCount;
-  UINT m_uPSVResourceBindInfoSize;
+  uint32_t m_uResourceCount;
+  uint32_t m_uPSVResourceBindInfoSize;
   void* m_pPSVResourceBindInfo;
   void* m_pPSVResourceBindInfo;
-  UINT m_uSize;
+  uint32_t m_uSize;
 
 
 public:
 public:
   DxilPipelineStateValidation() : 
   DxilPipelineStateValidation() : 
@@ -93,47 +96,47 @@ public:
   }
   }
 
 
   // Init() from PSV0 blob part that looks like:
   // Init() from PSV0 blob part that looks like:
-  // UINT PSVRuntimeInfo_size
+  // uint32_t PSVRuntimeInfo_size
   // { PSVRuntimeInfoN structure }
   // { PSVRuntimeInfoN structure }
-  // UINT ResourceCount
+  // uint32_t ResourceCount
   // ---  end of blob if ResourceCount == 0  ---
   // ---  end of blob if ResourceCount == 0  ---
-  // UINT PSVResourceBindInfo_size
+  // uint32_t PSVResourceBindInfo_size
   // { PSVResourceBindInfoN structure } * ResourceCount
   // { PSVResourceBindInfoN structure } * ResourceCount
   // returns true if no errors occurred.
   // returns true if no errors occurred.
-  bool InitFromPSV0(const void* pBits, UINT size) {
+  bool InitFromPSV0(const void* pBits, uint32_t size) {
     if(!(pBits != nullptr)) return false;
     if(!(pBits != nullptr)) return false;
-    const BYTE* pCurBits = (BYTE*)pBits;
-    UINT minsize = sizeof(PSVRuntimeInfo0) + sizeof(UINT) * 2;
+    const uint8_t* pCurBits = (uint8_t*)pBits;
+    uint32_t minsize = sizeof(PSVRuntimeInfo0) + sizeof(uint32_t) * 2;
     if(!(size >= minsize)) return false;
     if(!(size >= minsize)) return false;
-    m_uPSVRuntimeInfoSize = *((const UINT*)pCurBits);
+    m_uPSVRuntimeInfoSize = *((const uint32_t*)pCurBits);
     if(!(m_uPSVRuntimeInfoSize >= sizeof(PSVRuntimeInfo0))) return false;
     if(!(m_uPSVRuntimeInfoSize >= sizeof(PSVRuntimeInfo0))) return false;
-    pCurBits += sizeof(UINT);
-    minsize = m_uPSVRuntimeInfoSize + sizeof(UINT) * 2;
+    pCurBits += sizeof(uint32_t);
+    minsize = m_uPSVRuntimeInfoSize + sizeof(uint32_t) * 2;
     if(!(size >= minsize)) return false;
     if(!(size >= minsize)) return false;
     m_pPSVRuntimeInfo0 = const_cast<PSVRuntimeInfo0*>((const PSVRuntimeInfo0*)pCurBits);
     m_pPSVRuntimeInfo0 = const_cast<PSVRuntimeInfo0*>((const PSVRuntimeInfo0*)pCurBits);
     pCurBits += m_uPSVRuntimeInfoSize;
     pCurBits += m_uPSVRuntimeInfoSize;
-    m_uResourceCount = *(const UINT*)pCurBits;
-    pCurBits += sizeof(UINT);
+    m_uResourceCount = *(const uint32_t*)pCurBits;
+    pCurBits += sizeof(uint32_t);
     if (m_uResourceCount > 0) {
     if (m_uResourceCount > 0) {
-      minsize += sizeof(UINT);
+      minsize += sizeof(uint32_t);
       if(!(size >= minsize)) return false;
       if(!(size >= minsize)) return false;
-      m_uPSVResourceBindInfoSize = *(const UINT*)pCurBits;
-      pCurBits += sizeof(UINT);
+      m_uPSVResourceBindInfoSize = *(const uint32_t*)pCurBits;
+      pCurBits += sizeof(uint32_t);
       minsize += m_uPSVResourceBindInfoSize * m_uResourceCount;
       minsize += m_uPSVResourceBindInfoSize * m_uResourceCount;
       if(!(m_uPSVResourceBindInfoSize >= sizeof(PSVResourceBindInfo0))) return false;
       if(!(m_uPSVResourceBindInfoSize >= sizeof(PSVResourceBindInfo0))) return false;
       if(!(size >= minsize)) return false;
       if(!(size >= minsize)) return false;
-      m_pPSVResourceBindInfo = static_cast<void*>(const_cast<BYTE*>(pCurBits));
+      m_pPSVResourceBindInfo = static_cast<void*>(const_cast<uint8_t*>(pCurBits));
     }
     }
     return true;
     return true;
   }
   }
 
 
   // Initialize a new buffer
   // Initialize a new buffer
   // call with null pBuffer to get required size
   // call with null pBuffer to get required size
-  bool InitNew(UINT ResourceCount, void *pBuffer, UINT *pSize) {
+  bool InitNew(uint32_t ResourceCount, void *pBuffer, uint32_t *pSize) {
     if(!(pSize)) return false;
     if(!(pSize)) return false;
-    UINT size = sizeof(PSVRuntimeInfo0) + sizeof(UINT) * 2;
+    uint32_t size = sizeof(PSVRuntimeInfo0) + sizeof(uint32_t) * 2;
     if (ResourceCount) {
     if (ResourceCount) {
-      size += sizeof(UINT) + (sizeof(PSVResourceBindInfo0) * ResourceCount);
+      size += sizeof(uint32_t) + (sizeof(PSVResourceBindInfo0) * ResourceCount);
     }
     }
     if (pBuffer) {
     if (pBuffer) {
       if(!(*pSize >= size)) return false;
       if(!(*pSize >= size)) return false;
@@ -141,22 +144,22 @@ public:
       *pSize = size;
       *pSize = size;
       return true;
       return true;
     }
     }
-    ::ZeroMemory(pBuffer, size);
+    memset(pBuffer, 0, size);
     m_uPSVRuntimeInfoSize = sizeof(PSVRuntimeInfo0);
     m_uPSVRuntimeInfoSize = sizeof(PSVRuntimeInfo0);
-    BYTE* pCurBits = (BYTE*)pBuffer;
-    *(UINT*)pCurBits = sizeof(PSVRuntimeInfo0);
-    pCurBits += sizeof(UINT);
+    uint8_t* pCurBits = (uint8_t*)pBuffer;
+    *(uint32_t*)pCurBits = sizeof(PSVRuntimeInfo0);
+    pCurBits += sizeof(uint32_t);
     m_pPSVRuntimeInfo0 = (PSVRuntimeInfo0*)pCurBits;
     m_pPSVRuntimeInfo0 = (PSVRuntimeInfo0*)pCurBits;
     pCurBits += sizeof(PSVRuntimeInfo0);
     pCurBits += sizeof(PSVRuntimeInfo0);
 
 
     // Set resource info:
     // Set resource info:
     m_uResourceCount = ResourceCount;
     m_uResourceCount = ResourceCount;
-    *(UINT*)pCurBits = ResourceCount;
-    pCurBits += sizeof(UINT);
+    *(uint32_t*)pCurBits = ResourceCount;
+    pCurBits += sizeof(uint32_t);
     if (ResourceCount > 0) {
     if (ResourceCount > 0) {
       m_uPSVResourceBindInfoSize = sizeof(PSVResourceBindInfo0);
       m_uPSVResourceBindInfoSize = sizeof(PSVResourceBindInfo0);
-      *(UINT*)pCurBits = m_uPSVResourceBindInfoSize;
-      pCurBits += sizeof(UINT);
+      *(uint32_t*)pCurBits = m_uPSVResourceBindInfoSize;
+      pCurBits += sizeof(uint32_t);
       m_pPSVResourceBindInfo = pCurBits;
       m_pPSVResourceBindInfo = pCurBits;
     }
     }
     return true;
     return true;
@@ -166,14 +169,14 @@ public:
     return m_pPSVRuntimeInfo0;
     return m_pPSVRuntimeInfo0;
   }
   }
 
 
-  UINT GetBindCount() const {
+  uint32_t GetBindCount() const {
     return m_uResourceCount;
     return m_uResourceCount;
   }
   }
 
 
-  PSVResourceBindInfo0* GetPSVResourceBindInfo0(UINT index) {
+  PSVResourceBindInfo0* GetPSVResourceBindInfo0(uint32_t index) {
     if (index < m_uResourceCount && m_pPSVResourceBindInfo &&
     if (index < m_uResourceCount && m_pPSVResourceBindInfo &&
         sizeof(PSVResourceBindInfo0) <= m_uPSVResourceBindInfoSize) {
         sizeof(PSVResourceBindInfo0) <= m_uPSVResourceBindInfoSize) {
-      return (PSVResourceBindInfo0*)((BYTE*)m_pPSVResourceBindInfo +
+      return (PSVResourceBindInfo0*)((uint8_t*)m_pPSVResourceBindInfo +
         (index * m_uPSVResourceBindInfoSize));
         (index * m_uPSVResourceBindInfoSize));
     }
     }
     return nullptr;
     return nullptr;

+ 23 - 5
include/dxc/HLSL/DxilRootSignature.h

@@ -19,6 +19,10 @@
 struct IDxcBlob;
 struct IDxcBlob;
 struct IDxcBlobEncoding;
 struct IDxcBlobEncoding;
 
 
+namespace llvm {
+  class raw_ostream;
+}
+
 namespace hlsl {
 namespace hlsl {
 
 
 // Forward declarations.
 // Forward declarations.
@@ -318,13 +322,17 @@ public:
   bool IsEmpty() const {
   bool IsEmpty() const {
     return m_pDesc == nullptr && m_pSerialized == nullptr;
     return m_pDesc == nullptr && m_pSerialized == nullptr;
   }
   }
+  IDxcBlob *GetSerialized() const { return m_pSerialized; }
   const uint8_t *GetSerializedBytes() const;
   const uint8_t *GetSerializedBytes() const;
   unsigned GetSerializedSize() const;
   unsigned GetSerializedSize() const;
 
 
   void Assign(const DxilVersionedRootSignatureDesc *pDesc, IDxcBlob *pSerialized);
   void Assign(const DxilVersionedRootSignatureDesc *pDesc, IDxcBlob *pSerialized);
   void Clear();
   void Clear();
-  void LoadSerialized(const uint8_t *pData, unsigned length);
+  void LoadSerialized(const uint8_t *pData, uint32_t length);
   void EnsureSerializedAvailable();
   void EnsureSerializedAvailable();
+  void Deserialize();
+
+  const DxilVersionedRootSignatureDesc *GetDesc() const { return m_pDesc; }
 };
 };
 
 
 void DeleteRootSignature(const DxilVersionedRootSignatureDesc *pRootSignature);  
 void DeleteRootSignature(const DxilVersionedRootSignatureDesc *pRootSignature);  
@@ -334,10 +342,20 @@ void ConvertRootSignature(const DxilVersionedRootSignatureDesc* pRootSignatureIn
                           DxilRootSignatureVersion RootSignatureVersionOut,  
                           DxilRootSignatureVersion RootSignatureVersionOut,  
                           const DxilVersionedRootSignatureDesc ** ppRootSignatureOut);
                           const DxilVersionedRootSignatureDesc ** ppRootSignatureOut);
 
 
-void SerializeRootSignature(
-    const DxilVersionedRootSignatureDesc *pRootSignature,
-    _Outptr_ IDxcBlob **ppBlob, _Outptr_ IDxcBlobEncoding **ppErrorBlob,
-    bool bAllowReservedRegisterSpace);
+void SerializeRootSignature(const DxilVersionedRootSignatureDesc *pRootSignature,
+                            _Outptr_ IDxcBlob **ppBlob, _Outptr_ IDxcBlobEncoding **ppErrorBlob,
+                            bool bAllowReservedRegisterSpace);
+
+void DeserializeRootSignature(__in_bcount(SrcDataSizeInBytes) const void *pSrcData,
+                              __in uint32_t SrcDataSizeInBytes,
+                              __out const DxilVersionedRootSignatureDesc **ppRootSignature);
+
+// Takes PSV - pipeline state validation data, not shader container.
+bool VerifyRootSignatureWithShaderPSV(__in const DxilVersionedRootSignatureDesc *pDesc,
+                                      __in DXIL::ShaderKind ShaderKind,
+                                      _In_reads_bytes_(PSVSize) const void *pPSVData,
+                                      __in uint32_t PSVSize,
+                                      __in llvm::raw_ostream &DiagStream);
 
 
 } // namespace hlsl
 } // namespace hlsl
 
 

+ 56 - 4
include/dxc/HLSL/DxilValidation.h

@@ -11,10 +11,14 @@
 
 
 #pragma once
 #pragma once
 
 
-#include <system_error>
+#include <memory>
+#include "dxc/Support/Global.h"
+#include "dxc/HLSL/DxilConstants.h"
 
 
 namespace llvm {
 namespace llvm {
 class Module;
 class Module;
+class LLVMContext;
+class raw_ostream;
 }
 }
 
 
 namespace hlsl {
 namespace hlsl {
@@ -26,6 +30,13 @@ enum class ValidationRule : unsigned {
   // Bitcode
   // Bitcode
   BitcodeValid, // TODO - Module must be bitcode-valid
   BitcodeValid, // TODO - Module must be bitcode-valid
 
 
+  // Container
+  ContainerPartInvalid, // DXIL Container must not contain unknown parts
+  ContainerPartMatches, // DXIL Container Parts must match Module
+  ContainerPartMissing, // DXIL Container requires certain parts, corresponding to module
+  ContainerPartRepeated, // DXIL Container must have only one of each part type
+  ContainerRootSignatureIncompatible, // Root Signature in DXIL Container must be compatible with shader
+
   // Declaration
   // Declaration
   DeclDxilFnExtern, // External function must be a DXIL function
   DeclDxilFnExtern, // External function must be a DXIL function
   DeclDxilNsReserved, // The DXIL reserved prefixes must only be used by built-in functions and types
   DeclDxilNsReserved, // The DXIL reserved prefixes must only be used by built-in functions and types
@@ -167,7 +178,7 @@ enum class ValidationRule : unsigned {
   SmGSTotalOutputVertexDataRange, // Declared output vertex count (%0) multiplied by the total number of declared scalar components of output data (%1) equals %2.  This value cannot be greater than %3
   SmGSTotalOutputVertexDataRange, // Declared output vertex count (%0) multiplied by the total number of declared scalar components of output data (%1) equals %2.  This value cannot be greater than %3
   SmGSValidInputPrimitive, // GS input primitive unrecognized
   SmGSValidInputPrimitive, // GS input primitive unrecognized
   SmGSValidOutputPrimitiveTopology, // GS output primitive topology unrecognized
   SmGSValidOutputPrimitiveTopology, // GS output primitive topology unrecognized
-  SmHSInputControlPointCountRange, // HS input control point count must be [1..%0].  %1 specified
+  SmHSInputControlPointCountRange, // HS input control point count must be [0..%0].  %1 specified
   SmHullPassThruControlPointCountMatch, // For pass thru hull shader, input control point count must match output control point count
   SmHullPassThruControlPointCountMatch, // For pass thru hull shader, input control point count must match output control point count
   SmInsideTessFactorSizeMatchDomain, // InsideTessFactor rows, columns (%0, %1) invalid for domain %2.  Expected %3 rows and 1 column.
   SmInsideTessFactorSizeMatchDomain, // InsideTessFactor rows, columns (%0, %1) invalid for domain %2.  Expected %3 rows and 1 column.
   SmInvalidResourceCompType, // Invalid resource return type
   SmInvalidResourceCompType, // Invalid resource return type
@@ -203,6 +214,7 @@ enum class ValidationRule : unsigned {
   SmTriOutputPrimitiveMismatch, // Hull Shader declared with Tri Domain must specify output primitive point, triangle_cw or triangle_ccw. Line output is not compatible with the Tri domain
   SmTriOutputPrimitiveMismatch, // Hull Shader declared with Tri Domain must specify output primitive point, triangle_cw or triangle_ccw. Line output is not compatible with the Tri domain
   SmUndefinedOutput, // Not all elements of output %0 were written
   SmUndefinedOutput, // Not all elements of output %0 were written
   SmValidDomain, // Invalid Tessellator Domain specified. Must be isoline, tri or quad
   SmValidDomain, // Invalid Tessellator Domain specified. Must be isoline, tri or quad
+  SmZeroHSInputControlPointWithInput, // When HS input control point count is 0, no input signature should exist
 
 
   // Type system
   // Type system
   TypesDefined, // Type must be defined based on DXIL primitives
   TypesDefined, // Type must be defined based on DXIL primitives
@@ -218,7 +230,47 @@ enum class ValidationRule : unsigned {
 
 
 const char *GetValidationRuleText(ValidationRule value);
 const char *GetValidationRuleText(ValidationRule value);
 void GetValidationVersion(_Out_ unsigned *pMajor, _Out_ unsigned *pMinor);
 void GetValidationVersion(_Out_ unsigned *pMajor, _Out_ unsigned *pMinor);
-std::error_code ValidateDxilModule(_In_ llvm::Module *pModule,
-                                   _In_opt_ llvm::Module *pDebugModule);
+HRESULT ValidateDxilModule(_In_ llvm::Module *pModule,
+                           _In_opt_ llvm::Module *pDebugModule);
+
+// DXIL Container Verification Functions (return false on failure)
+
+bool VerifySignatureMatches(_In_ llvm::Module *pModule,
+                            hlsl::DXIL::SignatureKind SigKind,
+                            _In_reads_bytes_(SigSize) const void *pSigData,
+                            _In_ uint32_t SigSize);
+
+// PSV = data for Pipeline State Validation
+bool VerifyPSVMatches(_In_ llvm::Module *pModule,
+                      _In_reads_bytes_(PSVSize) const void *pPSVData,
+                      _In_ uint32_t PSVSize);
+
+bool VerifyFeatureInfoMatches(_In_ llvm::Module *pModule,
+                              _In_reads_bytes_(FeatureInfoSize) const void *pFeatureInfoData,
+                              _In_ uint32_t FeatureInfoSize);
+
+// Validate the container parts, assuming supplied module is valid, loaded from the container provided
+struct DxilContainerHeader;
+HRESULT ValidateDxilContainerParts(_In_ llvm::Module *pModule,
+                                   _In_opt_ llvm::Module *pDebugModule,
+                                   _In_reads_bytes_(ContainerSize) const DxilContainerHeader *pContainer,
+                                   _In_ uint32_t ContainerSize);
+
+// Loads module, validating load, but not module.
+HRESULT ValidateLoadModule(_In_reads_bytes_(ILLength) const char *pIL,
+                           _In_ uint32_t ILLength,
+                           _In_ std::unique_ptr<llvm::Module> &pModule,
+                           _In_ llvm::LLVMContext &Ctx,
+                           _In_ llvm::raw_ostream &DiagStream);
+
+// Load and validate Dxil module from bitcode.
+HRESULT ValidateDxilBitcode(_In_reads_bytes_(ILLength) const char *pIL,
+                            _In_ uint32_t ILLength,
+                            _In_ llvm::raw_ostream &DiagStream);
+
+// Full container validation, including ValidateDxilModule
+HRESULT ValidateDxilContainer(_In_reads_bytes_(ContainerSize) const void *pContainer,
+                              _In_ uint32_t ContainerSize,
+                              _In_ llvm::raw_ostream &DiagStream);
 
 
 }
 }

+ 10 - 1
include/dxc/Support/ErrorCodes.h

@@ -82,4 +82,13 @@
 #define DXC_E_DUPLICATE_PART                          DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0011))
 #define DXC_E_DUPLICATE_PART                          DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0011))
 
 
 // 0x80AA0012 - Error finding part in dxil container.
 // 0x80AA0012 - Error finding part in dxil container.
-#define DXC_E_MISSING_PART                            DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0012))
+#define DXC_E_MISSING_PART                            DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0012))
+
+// 0x80AA0013 - Malformed DXIL Container.
+#define DXC_E_MALFORMED_CONTAINER                     DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0013))
+
+// 0x80AA0014 - Incorrect Root Signature for shader.
+#define DXC_E_INCORRECT_ROOT_SIGNATURE                DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0014))
+
+// 0X80AA0015 - DXIL container is missing DebugInfo part.
+#define DXC_E_CONTAINER_MISSING_DEBUG                 DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0015))

+ 3 - 1
include/dxc/Support/Global.h

@@ -43,6 +43,7 @@ void CheckLLVMErrorCode(const std::error_code &ec);
 #define IFC(x)      { hr = (x); if (DXC_FAILED(hr)) goto Cleanup; }
 #define IFC(x)      { hr = (x); if (DXC_FAILED(hr)) goto Cleanup; }
 #define IFR(x)      { HRESULT __hr = (x); if (DXC_FAILED(__hr)) return __hr; }
 #define IFR(x)      { HRESULT __hr = (x); if (DXC_FAILED(__hr)) return __hr; }
 #define IFRBOOL(x,y){ if (!(x)) return (y); }
 #define IFRBOOL(x,y){ if (!(x)) return (y); }
+#define IFCBOOL(x,y){ if (!(x)) { hr = (y); goto Cleanup; } }
 #define IFCOOM(x)   { if (nullptr == (x)) { hr = E_OUTOFMEMORY; goto Cleanup; } }
 #define IFCOOM(x)   { if (nullptr == (x)) { hr = E_OUTOFMEMORY; goto Cleanup; } }
 #define IFROOM(x)   { if (nullptr == (x)) { return E_OUTOFMEMORY; } }
 #define IFROOM(x)   { if (nullptr == (x)) { return E_OUTOFMEMORY; } }
 #define IFCPTR(x)   { if (nullptr == (x)) { hr = E_POINTER; goto Cleanup; }}
 #define IFCPTR(x)   { if (nullptr == (x)) { hr = E_POINTER; goto Cleanup; }}
@@ -53,13 +54,14 @@ void CheckLLVMErrorCode(const std::error_code &ec);
 #define IFTARG(x)   { if (!(x)) { throw ::hlsl::Exception(E_INVALIDARG); }}
 #define IFTARG(x)   { if (!(x)) { throw ::hlsl::Exception(E_INVALIDARG); }}
 #define IFTLLVM(x)  { CheckLLVMErrorCode(x); }
 #define IFTLLVM(x)  { CheckLLVMErrorCode(x); }
 #define IFTMSG(x, msg) { HRESULT __hr = (x); if (DXC_FAILED(__hr)) throw ::hlsl::Exception(__hr, msg); }
 #define IFTMSG(x, msg) { HRESULT __hr = (x); if (DXC_FAILED(__hr)) throw ::hlsl::Exception(__hr, msg); }
+#define IFTBOOLMSG(x, y, msg) { if (!(x)) throw ::hlsl::Exception(y, msg); }
 
 
 // Propagate an C++ exception into an HRESULT.
 // Propagate an C++ exception into an HRESULT.
 #define CATCH_CPP_ASSIGN_HRESULT() \
 #define CATCH_CPP_ASSIGN_HRESULT() \
   catch (std::bad_alloc&)                   { hr = E_OUTOFMEMORY; } \
   catch (std::bad_alloc&)                   { hr = E_OUTOFMEMORY; } \
   catch (hlsl::Exception& _hlsl_exception_) {                       \
   catch (hlsl::Exception& _hlsl_exception_) {                       \
     _Analysis_assume_(DXC_FAILED(_hlsl_exception_.hr));             \
     _Analysis_assume_(DXC_FAILED(_hlsl_exception_.hr));             \
-    return hr = _hlsl_exception_.hr;                                \
+    hr = _hlsl_exception_.hr;                                       \
   }                                                                 \
   }                                                                 \
   catch (...)                               { hr = E_FAIL; }
   catch (...)                               { hr = E_FAIL; }
 #define CATCH_CPP_RETURN_HRESULT() \
 #define CATCH_CPP_RETURN_HRESULT() \

+ 10 - 6
include/dxc/Support/HLSLOptions.h

@@ -39,7 +39,7 @@ enum HlslFlags {
   DriverOption = (1 << 13),
   DriverOption = (1 << 13),
   NoArgumentUnused = (1 << 14),
   NoArgumentUnused = (1 << 14),
   CoreOption = (1 << 15),
   CoreOption = (1 << 15),
-  ISenseOption = (1 << 15),
+  ISenseOption = (1 << 16),
 };
 };
 
 
 enum ID {
 enum ID {
@@ -93,7 +93,6 @@ public:
   llvm::StringRef EntryPoint;   // OPT_entrypoint
   llvm::StringRef EntryPoint;   // OPT_entrypoint
   llvm::StringRef ExternalFn;   // OPT_external_fn
   llvm::StringRef ExternalFn;   // OPT_external_fn
   llvm::StringRef ExternalLib;  // OPT_external_lib
   llvm::StringRef ExternalLib;  // OPT_external_lib
-  llvm::StringRef ExtractRootSignatureFile; // OPT_extractrootsignature
   llvm::StringRef ExtractPrivateFile; // OPT_getprivate
   llvm::StringRef ExtractPrivateFile; // OPT_getprivate
   llvm::StringRef ForceRootSigVer; // OPT_force_rootsig_ver
   llvm::StringRef ForceRootSigVer; // OPT_force_rootsig_ver
   llvm::StringRef InputFile; // OPT_INPUT
   llvm::StringRef InputFile; // OPT_INPUT
@@ -105,6 +104,7 @@ public:
   llvm::StringRef VariableName; // OPT_Vn
   llvm::StringRef VariableName; // OPT_Vn
   llvm::StringRef PrivateSource; // OPT_setprivate
   llvm::StringRef PrivateSource; // OPT_setprivate
   llvm::StringRef RootSignatureSource; // OPT_setrootsignature
   llvm::StringRef RootSignatureSource; // OPT_setrootsignature
+  llvm::StringRef VerifyRootSignatureSource; //OPT_verifyrootsignature
 
 
   bool AllResourcesBound; // OPT_all_resources_bound
   bool AllResourcesBound; // OPT_all_resources_bound
   bool AstDump; // OPT_ast_dump
   bool AstDump; // OPT_ast_dump
@@ -112,7 +112,6 @@ public:
   bool CodeGenHighLevel; // OPT_fcgl
   bool CodeGenHighLevel; // OPT_fcgl
   bool DebugInfo; // OPT__SLASH_Zi
   bool DebugInfo; // OPT__SLASH_Zi
   bool DumpBin;        // OPT_dumpbin
   bool DumpBin;        // OPT_dumpbin
-  bool EnableUnboundedDescriptorTables; // OPT_enable_unbounded_descriptor_tables
   bool WarningAsError; // OPT__SLASH_WX
   bool WarningAsError; // OPT__SLASH_WX
   bool IEEEStrict;     // OPT_Gis
   bool IEEEStrict;     // OPT_Gis
   bool DefaultColMajor;  // OPT_Zpc
   bool DefaultColMajor;  // OPT_Zpc
@@ -136,9 +135,14 @@ public:
   bool DisplayIncludeProcess; // OPT__vi
   bool DisplayIncludeProcess; // OPT__vi
   bool RecompileFromBinary; // OPT _Recompile (Recompiling the DXBC binary file not .hlsl file)
   bool RecompileFromBinary; // OPT _Recompile (Recompiling the DXBC binary file not .hlsl file)
   bool StripDebug; // OPT Qstrip_debug
   bool StripDebug; // OPT Qstrip_debug
-  bool StripRootSignature; // OPT Qstrip_rootsignature
-  bool StripPrivate; // OPT Qstrip_priv
-  bool StripReflection; // OPT Qstrip_reflect
+  bool StripRootSignature; // OPT_Qstrip_rootsignature
+  bool StripPrivate; // OPT_Qstrip_priv
+  bool StripReflection; // OPT_Qstrip_reflect
+  bool ExtractRootSignature; // OPT_extractrootsignature
+  bool DisassembleColorCoded; // OPT_Cc
+  bool DisassembleInstNumbers; //OPT_Ni
+  bool DisassembleByteOffset; //OPT_No
+  bool DisaseembleHex; //OPT_Lx
 };
 };
 
 
 /// Use this class to capture, convert and handle the lifetime for the
 /// Use this class to capture, convert and handle the lifetime for the

+ 38 - 34
include/dxc/Support/HLSLOptions.td

@@ -87,27 +87,27 @@ def H : Flag<["-"], "H">, Flags<[CoreOption]>, Group<hlslcomp_Group>,
 def I : JoinedOrSeparate<["-", "/"], "I">, Group<hlslcomp_Group>, Flags<[CoreOption]>,
 def I : JoinedOrSeparate<["-", "/"], "I">, Group<hlslcomp_Group>, Flags<[CoreOption]>,
     HelpText<"Add directory to include search path">;
     HelpText<"Add directory to include search path">;
 def O0 : Flag<["-", "/"], "O0">, Group<hlsloptz_Group>, Flags<[CoreOption]>,
 def O0 : Flag<["-", "/"], "O0">, Group<hlsloptz_Group>, Flags<[CoreOption]>,
-    HelpText<"Optimization Level 0 - Disables instruction reordering">;
+    HelpText<"Optimization Level 0">;
 def O1 : Flag<["-", "/"], "O1">, Group<hlsloptz_Group>, Flags<[CoreOption]>,
 def O1 : Flag<["-", "/"], "O1">, Group<hlsloptz_Group>, Flags<[CoreOption]>,
-    HelpText<"Optimization Level 1 - All standard optimizations">;
+    HelpText<"Optimization Level 1">;
 def O2 : Flag<["-", "/"], "O2">, Group<hlsloptz_Group>, Flags<[CoreOption]>,
 def O2 : Flag<["-", "/"], "O2">, Group<hlsloptz_Group>, Flags<[CoreOption]>,
-    HelpText<"Optimization Level 2 - Same as O1. Reserved for future use.">;
+    HelpText<"Optimization Level 2">;
 def O3 : Flag<["-", "/"], "O3">, Group<hlsloptz_Group>, Flags<[CoreOption]>,
 def O3 : Flag<["-", "/"], "O3">, Group<hlsloptz_Group>, Flags<[CoreOption]>,
-    HelpText<"Optimization Level 3 - Same as O1. Reserved for future use.">;
+    HelpText<"Optimization Level 3 (Default)">;
 def O4 : Flag<["-", "/"], "O4">, Group<hlsloptz_Group>, Flags<[CoreOption]>,
 def O4 : Flag<["-", "/"], "O4">, Group<hlsloptz_Group>, Flags<[CoreOption]>,
-    HelpText<"Optimization Level 4 - Same as O1. Reserved for future use.">;
+    HelpText<"Optimization Level 4">;
 def Odump : Flag<["-", "/"], "Odump">, Group<hlslcomp_Group>, Flags<[CoreOption]>,
 def Odump : Flag<["-", "/"], "Odump">, Group<hlslcomp_Group>, Flags<[CoreOption]>,
     HelpText<"Print the optimizer commands.">;
     HelpText<"Print the optimizer commands.">;
 def Qunused_arguments : Flag<["-"], "Qunused-arguments">, Group<hlslcore_Group>, Flags<[CoreOption]>,
 def Qunused_arguments : Flag<["-"], "Qunused-arguments">, Group<hlslcore_Group>, Flags<[CoreOption]>,
   HelpText<"Don't emit warning for unused driver arguments">;
   HelpText<"Don't emit warning for unused driver arguments">;
 def Wall : Flag<["-"], "Wall">, Group<hlslcomp_Group>, Flags<[CoreOption]>;
 def Wall : Flag<["-"], "Wall">, Group<hlslcomp_Group>, Flags<[CoreOption]>;
 def Wdeprecated : Flag<["-"], "Wdeprecated">, Group<hlslcomp_Group>, Flags<[CoreOption]>;
 def Wdeprecated : Flag<["-"], "Wdeprecated">, Group<hlslcomp_Group>, Flags<[CoreOption]>;
-def W_Joined : Joined<["-"], "W">, Group<hlslcomp_Group>, Flags<[CoreOption]>,
-  MetaVarName<"<warning>">, HelpText<"Enable the specified warning">;
+//def W_Joined : Joined<["-"], "W">, Group<hlslcomp_Group>, Flags<[CoreOption]>,
+//  MetaVarName<"<warning>">, HelpText<"Enable the specified warning">;
 def d_Flag : Flag<["-"], "d">, Group<d_Group>;
 def d_Flag : Flag<["-"], "d">, Group<d_Group>;
 def d_Joined : Joined<["-"], "d">, Group<d_Group>;
 def d_Joined : Joined<["-"], "d">, Group<d_Group>;
-def fcolor_diagnostics : Flag<["-"], "fcolor-diagnostics">, Group<hlslcomp_Group>,
-  Flags<[CoreOption, DriverOption]>, HelpText<"Use colors in diagnostics">;
+//def fcolor_diagnostics : Flag<["-"], "fcolor-diagnostics">, Group<hlslcomp_Group>,
+//  Flags<[CoreOption, DriverOption]>, HelpText<"Use colors in diagnostics">;
 def fdiagnostics_color : Flag<["-"], "fdiagnostics-color">, Group<hlslcomp_Group>,
 def fdiagnostics_color : Flag<["-"], "fdiagnostics-color">, Group<hlslcomp_Group>,
   Flags<[CoreOption, DriverOption]>;
   Flags<[CoreOption, DriverOption]>;
 def fdiagnostics_color_EQ : Joined<["-"], "fdiagnostics-color=">, Group<hlslcomp_Group>;
 def fdiagnostics_color_EQ : Joined<["-"], "fdiagnostics-color=">, Group<hlslcomp_Group>;
@@ -117,8 +117,8 @@ def fconstexpr_depth_EQ : Joined<["-"], "fconstexpr-depth=">, Group<f_Group>;
 def fconstexpr_steps_EQ : Joined<["-"], "fconstexpr-steps=">, Group<f_Group>;
 def fconstexpr_steps_EQ : Joined<["-"], "fconstexpr-steps=">, Group<f_Group>;
 def fconstexpr_backtrace_limit_EQ : Joined<["-"], "fconstexpr-backtrace-limit=">,
 def fconstexpr_backtrace_limit_EQ : Joined<["-"], "fconstexpr-backtrace-limit=">,
                                     Group<f_Group>;
                                     Group<f_Group>;
-def fdiagnostics_show_option : Flag<["-"], "fdiagnostics-show-option">, Group<hlslcomp_Group>,
-    Flags<[CoreOption]>, HelpText<"Print option name with mappable diagnostics">;
+//def fdiagnostics_show_option : Flag<["-"], "fdiagnostics-show-option">, Group<hlslcomp_Group>,
+//    Flags<[CoreOption]>, HelpText<"Print option name with mappable diagnostics">;
 def fdiagnostics_show_category_EQ : Joined<["-"], "fdiagnostics-show-category=">, Group<hlslcomp_Group>;
 def fdiagnostics_show_category_EQ : Joined<["-"], "fdiagnostics-show-category=">, Group<hlslcomp_Group>;
 def ferror_limit_EQ : Joined<["-"], "ferror-limit=">, Group<hlslcomp_Group>, Flags<[CoreOption]>;
 def ferror_limit_EQ : Joined<["-"], "ferror-limit=">, Group<hlslcomp_Group>, Flags<[CoreOption]>;
 
 
@@ -128,27 +128,29 @@ def fno_unsafe_math_optimizations : Flag<["-"], "fno-unsafe-math-optimizations">
   Group<hlsloptz_Group>;
   Group<hlsloptz_Group>;
 def fassociative_math : Flag<["-"], "fassociative-math">, Group<hlsloptz_Group>;
 def fassociative_math : Flag<["-"], "fassociative-math">, Group<hlsloptz_Group>;
 def fno_associative_math : Flag<["-"], "fno-associative-math">, Group<hlsloptz_Group>;
 def fno_associative_math : Flag<["-"], "fno-associative-math">, Group<hlsloptz_Group>;
-def freciprocal_math :
-  Flag<["-"], "freciprocal-math">, Group<hlsloptz_Group>, Flags<[CoreOption]>,
-  HelpText<"Allow division operations to be reassociated">;
+//def freciprocal_math :
+//  Flag<["-"], "freciprocal-math">, Group<hlsloptz_Group>, Flags<[CoreOption]>,
+//  HelpText<"Allow division operations to be reassociated">;
 def fno_reciprocal_math : Flag<["-"], "fno-reciprocal-math">, Group<hlsloptz_Group>;
 def fno_reciprocal_math : Flag<["-"], "fno-reciprocal-math">, Group<hlsloptz_Group>;
 def ffinite_math_only : Flag<["-"], "ffinite-math-only">, Group<hlsloptz_Group>, Flags<[CoreOption]>;
 def ffinite_math_only : Flag<["-"], "ffinite-math-only">, Group<hlsloptz_Group>, Flags<[CoreOption]>;
 def fno_finite_math_only : Flag<["-"], "fno-finite-math-only">, Group<hlsloptz_Group>;
 def fno_finite_math_only : Flag<["-"], "fno-finite-math-only">, Group<hlsloptz_Group>;
 def fsigned_zeros : Flag<["-"], "fsigned-zeros">, Group<hlsloptz_Group>;
 def fsigned_zeros : Flag<["-"], "fsigned-zeros">, Group<hlsloptz_Group>;
-def fno_signed_zeros :
-  Flag<["-"], "fno-signed-zeros">, Group<hlsloptz_Group>, Flags<[CoreOption]>,
-  HelpText<"Allow optimizations that ignore the sign of floating point zeros">;
+//def fno_signed_zeros :
+//  Flag<["-"], "fno-signed-zeros">, Group<hlsloptz_Group>, Flags<[CoreOption]>,
+//  HelpText<"Allow optimizations that ignore the sign of floating point zeros">;
 def fhonor_nans : Flag<["-"], "fhonor-nans">, Group<hlsloptz_Group>;
 def fhonor_nans : Flag<["-"], "fhonor-nans">, Group<hlsloptz_Group>;
 def fno_honor_nans : Flag<["-"], "fno-honor-nans">, Group<hlsloptz_Group>;
 def fno_honor_nans : Flag<["-"], "fno-honor-nans">, Group<hlsloptz_Group>;
 def fhonor_infinities : Flag<["-"], "fhonor-infinities">, Group<hlsloptz_Group>;
 def fhonor_infinities : Flag<["-"], "fhonor-infinities">, Group<hlsloptz_Group>;
 def fno_honor_infinities : Flag<["-"], "fno-honor-infinities">, Group<hlsloptz_Group>;
 def fno_honor_infinities : Flag<["-"], "fno-honor-infinities">, Group<hlsloptz_Group>;
 //def ftrapping_math : Flag<["-"], "ftrapping-math">, Group<f_Group>;
 //def ftrapping_math : Flag<["-"], "ftrapping-math">, Group<f_Group>;
 //def fno_trapping_math : Flag<["-"], "fno-trapping-math">, Group<f_Group>;
 //def fno_trapping_math : Flag<["-"], "fno-trapping-math">, Group<f_Group>;
-def ffp_contract : Joined<["-"], "ffp-contract=">, Group<hlsloptz_Group>,
-  Flags<[CoreOption]>, HelpText<"Form fused FP ops (e.g. FMAs): fast (everywhere)"
-  " | on (according to FP_CONTRACT pragma, default) | off (never fuse)">;
+//def ffp_contract : Joined<["-"], "ffp-contract=">, Group<hlsloptz_Group>,
+//  Flags<[CoreOption]>, HelpText<"Form fused FP ops (e.g. FMAs): fast (everywhere)"
+//  " | on (according to FP_CONTRACT pragma, default) | off (never fuse)">;
 def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group<hlsloptz_Group>;
 def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group<hlsloptz_Group>;
 
 
+
+/*
 def fno_caret_diagnostics : Flag<["-"], "fno-caret-diagnostics">, Group<hlslcomp_Group>,
 def fno_caret_diagnostics : Flag<["-"], "fno-caret-diagnostics">, Group<hlslcomp_Group>,
  Flags<[CoreOption]>;
  Flags<[CoreOption]>;
 def fno_color_diagnostics : Flag<["-"], "fno-color-diagnostics">, Group<hlslcomp_Group>,
 def fno_color_diagnostics : Flag<["-"], "fno-color-diagnostics">, Group<hlslcomp_Group>,
@@ -171,7 +173,7 @@ def freroll_loops : Flag<["-"], "freroll-loops">, Group<hlsloptz_Group>,
   HelpText<"Turn on loop reroller">, Flags<[CoreOption]>;
   HelpText<"Turn on loop reroller">, Flags<[CoreOption]>;
 def fno_reroll_loops : Flag<["-"], "fno-reroll-loops">, Group<hlsloptz_Group>,
 def fno_reroll_loops : Flag<["-"], "fno-reroll-loops">, Group<hlsloptz_Group>,
   HelpText<"Turn off loop reroller">;
   HelpText<"Turn off loop reroller">;
-
+*/
 def help : Flag<["-", "--", "/"], "help">, Flags<[DriverOption]>, Group<hlslcore_Group>,
 def help : Flag<["-", "--", "/"], "help">, Flags<[DriverOption]>, Group<hlslcore_Group>,
   HelpText<"Display available options">;
   HelpText<"Display available options">;
 /*
 /*
@@ -216,7 +218,7 @@ def fcgl : Flag<["-", "/"], "fcgl">, Group<hlslcore_Group>, Flags<[CoreOption, H
 def not_use_legacy_cbuf_load : Flag<["-", "/"], "not_use_legacy_cbuf_load">, Group<hlslcomp_Group>, Flags<[CoreOption]>,
 def not_use_legacy_cbuf_load : Flag<["-", "/"], "not_use_legacy_cbuf_load">, Group<hlslcomp_Group>, Flags<[CoreOption]>,
   HelpText<"Not use legacy cbuffer load">;  
   HelpText<"Not use legacy cbuffer load">;  
 def hlsl_version : Separate<["-", "/"], "HV">, Group<hlslcomp_Group>, Flags<[CoreOption]>,
 def hlsl_version : Separate<["-", "/"], "HV">, Group<hlslcomp_Group>, Flags<[CoreOption]>,
-  HelpText<"HLSL version (2015, 2016)">;
+  HelpText<"HLSL version (Only supports 2016 for now)">;
 def no_warnings : Flag<["-", "/"], "no-warnings">, Group<hlslcomp_Group>, Flags<[CoreOption]>,
 def no_warnings : Flag<["-", "/"], "no-warnings">, Group<hlslcomp_Group>, Flags<[CoreOption]>,
   HelpText<"Suppress warnings">;
   HelpText<"Suppress warnings">;
 
 
@@ -239,7 +241,7 @@ def VD : Flag<["-", "/"], "Vd">, Flags<[CoreOption]>, Group<hlslcomp_Group>,
 def _SLASH_Zi : Flag<["-", "/"], "Zi">, Flags<[CoreOption]>, Group<hlslcomp_Group>,
 def _SLASH_Zi : Flag<["-", "/"], "Zi">, Flags<[CoreOption]>, Group<hlslcomp_Group>,
   HelpText<"Enable debug information">;
   HelpText<"Enable debug information">;
 def recompile : Flag<["-", "/"], "recompile">, Flags<[CoreOption]>, Group<hlslcomp_Group>,
 def recompile : Flag<["-", "/"], "recompile">, Flags<[CoreOption]>, Group<hlslcomp_Group>,
-  HelpText<"recompile from Container or DXIL Bitcode file (not .hlsl file)">;
+  HelpText<"recompile from DXIL container with Debug Info or Debug Info bitcode file">;
 def Zpr : Flag<["-", "/"], "Zpr">, Flags<[CoreOption]>, Group<hlslcomp_Group>,
 def Zpr : Flag<["-", "/"], "Zpr">, Flags<[CoreOption]>, Group<hlslcomp_Group>,
   HelpText<"Pack matrices in row-major order">;
   HelpText<"Pack matrices in row-major order">;
 def Zpc : Flag<["-", "/"], "Zpc">, Flags<[CoreOption]>, Group<hlslcomp_Group>,
 def Zpc : Flag<["-", "/"], "Zpc">, Flags<[CoreOption]>, Group<hlslcomp_Group>,
@@ -258,12 +260,12 @@ def Fc : JoinedOrSeparate<["-", "/"], "Fc">, MetaVarName<"<file>">, HelpText<"Ou
 //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 a specific file">, Flags<[DriverOption]>, Group<hlslcomp_Group>;
 def Fe : JoinedOrSeparate<["-", "/"], "Fe">, MetaVarName<"<file>">, HelpText<"Output warnings and errors to a specific file">, Flags<[DriverOption]>, Group<hlslcomp_Group>;
-def Fd : JoinedOrSeparate<["-", "/"], "Fd">, MetaVarName<"<file>">, HelpText<"Extract shader PDB and write to given file">, Flags<[DriverOption]>, Group<hlslcomp_Group>;
+def Fd : JoinedOrSeparate<["-", "/"], "Fd">, MetaVarName<"<file>">, HelpText<"Extract LLVM Debug IR and write to given file">, Flags<[DriverOption]>, Group<hlslcomp_Group>;
 def Vn : JoinedOrSeparate<["-", "/"], "Vn">, MetaVarName<"<name>">, HelpText<"Use <name> as variable name in header file">, Flags<[DriverOption]>, Group<hlslcomp_Group>;
 def Vn : JoinedOrSeparate<["-", "/"], "Vn">, MetaVarName<"<name>">, HelpText<"Use <name> as variable name in header file">, Flags<[DriverOption]>, Group<hlslcomp_Group>;
-def Cc : Flag<["-", "/"], "Cc">, HelpText<"Output color coded assembly listings">, Group<hlslcomp_Group>;
-def Ni : Flag<["-", "/"], "Ni">, HelpText<"Output instruction numbers in assembly listings">, Group<hlslcomp_Group>;
-def No : Flag<["-", "/"], "No">, HelpText<"Output instruction byte offsets in assembly listings">, Group<hlslcomp_Group>;
-def Lx : Flag<["-", "/"], "Lx">, HelpText<"Output hexadecimal literals">, Group<hlslcomp_Group>;
+def Cc : Flag<["-", "/"], "Cc">, HelpText<"Output color coded assembly listings">, Group<hlslcomp_Group>, Flags<[DriverOption]>;
+def Ni : Flag<["-", "/"], "Ni">, HelpText<"Output instruction numbers in assembly listings">, Group<hlslcomp_Group>, Flags<[DriverOption]>;
+def No : Flag<["-", "/"], "No">, HelpText<"Output instruction byte offsets in assembly listings">, 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<[DriverOption]>, Group<hlslutil_Group>,
@@ -274,18 +276,19 @@ def P : Separate<["-", "/"], "P">, Flags<[DriverOption]>, Group<hlslutil_Group>,
 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<[DriverOption]>, Group<hlslutil_Group>,
 def Qstrip_reflect : Flag<["-", "/"], "Qstrip_reflect">, Flags<[DriverOption]>, Group<hlslutil_Group>,
-  HelpText<"Strip reflection data from shader bytecode">;
+  HelpText<"Strip reflection data from shader bytecode  (must be used with /Fo <file>)">;
 def Qstrip_debug : Flag<["-", "/"], "Qstrip_debug">, Flags<[DriverOption]>, Group<hlslutil_Group>,
 def Qstrip_debug : Flag<["-", "/"], "Qstrip_debug">, Flags<[DriverOption]>, Group<hlslutil_Group>,
-  HelpText<"Strip debug information from 4_0+ shader bytecode">;
+  HelpText<"Strip debug information from 4_0+ shader bytecode  (must be used with /Fo <file>)">;
 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">;
+  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">;
+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 setrootsignature     : JoinedOrSeparate<["-", "/"], "setrootsignature">,     MetaVarName<"<file>">, Flags<[DriverOption]>, Group<hlslutil_Group>, HelpText<"Attach root signature to shader bytecode">;
-def extractrootsignature : JoinedOrSeparate<["-", "/"], "extractrootsignature">, MetaVarName<"<file>">, Flags<[DriverOption]>, Group<hlslutil_Group>, HelpText<"Extract root signature from 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 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)">;
 
 
+/*
 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">;
 def mergeUAVs : JoinedOrSeparate<["-", "/"], "mergeUAVs">, MetaVarName<"<file>">, Group<hlslcomp_Group>,
 def mergeUAVs : JoinedOrSeparate<["-", "/"], "mergeUAVs">, MetaVarName<"<file>">, Group<hlslcomp_Group>,
@@ -296,6 +299,7 @@ def res_may_alias : Flag<["-", "/"], "res_may_alias">, Flags<[CoreOption]>, Grou
   HelpText<"Assume that UAVs/SRVs may alias">;
   HelpText<"Assume that UAVs/SRVs may alias">;
 def enable_unbounded_descriptor_tables : Flag<["-", "/"], "enable_unbounded_descriptor_tables">, Flags<[CoreOption]>, Group<hlslcomp_Group>,
 def enable_unbounded_descriptor_tables : Flag<["-", "/"], "enable_unbounded_descriptor_tables">, Flags<[CoreOption]>, Group<hlslcomp_Group>,
   HelpText<"Enables unbounded descriptor tables">;
   HelpText<"Enables unbounded descriptor tables">;
+*/
 def all_resources_bound : Flag<["-", "/"], "all_resources_bound">, Flags<[CoreOption]>, Group<hlslcomp_Group>,
 def all_resources_bound : Flag<["-", "/"], "all_resources_bound">, Flags<[CoreOption]>, Group<hlslcomp_Group>,
   HelpText<"Enables agressive flattening">;
   HelpText<"Enables agressive flattening">;
 
 
@@ -304,7 +308,7 @@ def setprivate : JoinedOrSeparate<["-", "/"], "setprivate">, Flags<[DriverOption
 def getprivate : JoinedOrSeparate<["-", "/"], "getprivate">, Flags<[DriverOption]>, MetaVarName<"<file>">, Group<hlslutil_Group>,
 def getprivate : JoinedOrSeparate<["-", "/"], "getprivate">, Flags<[DriverOption]>, MetaVarName<"<file>">, Group<hlslutil_Group>,
   HelpText<"Save private data from shader blob">;
   HelpText<"Save private data from shader blob">;
 
 
-def nologo : Flag<["-", "/"], "nologo">, Group<hlslcore_Group>,
+def nologo : Flag<["-", "/"], "nologo">, Group<hlslcore_Group>, Flags<[DriverOption]>,
   HelpText<"Suppress copyright message">;
   HelpText<"Suppress copyright message">;
 
 
 // Also removed: compress, decompress, /Gch (child effect), /Gec (back compat), /Gpp (partial precision)
 // Also removed: compress, decompress, /Gch (child effect), /Gec (back compat), /Gpp (partial precision)

+ 3 - 3
include/dxc/Support/dxcapi.use.h

@@ -104,13 +104,13 @@ void IFT_Data(HRESULT hr, _In_opt_ LPCWSTR data);
 void EnsureEnabled(DxcDllSupport &dxcSupport);
 void EnsureEnabled(DxcDllSupport &dxcSupport);
 void ReadFileIntoBlob(DxcDllSupport &dxcSupport, _In_ LPCWSTR pFileName,
 void ReadFileIntoBlob(DxcDllSupport &dxcSupport, _In_ LPCWSTR pFileName,
                       _Outptr_ IDxcBlobEncoding **ppBlobEncoding);
                       _Outptr_ IDxcBlobEncoding **ppBlobEncoding);
-void WriteBlobToConsole(_In_opt_ IDxcBlob *pBlob);
+void WriteBlobToConsole(_In_opt_ IDxcBlob *pBlob, DWORD streamType = STD_OUTPUT_HANDLE);
 void WriteBlobToFile(_In_opt_ IDxcBlob *pBlob, _In_ LPCWSTR pFileName);
 void WriteBlobToFile(_In_opt_ IDxcBlob *pBlob, _In_ LPCWSTR pFileName);
 void WriteBlobToHandle(_In_opt_ IDxcBlob *pBlob, HANDLE hFile, _In_opt_ LPCWSTR pFileName);
 void WriteBlobToHandle(_In_opt_ IDxcBlob *pBlob, HANDLE hFile, _In_opt_ LPCWSTR pFileName);
 void WriteUtf8ToConsole(_In_opt_count_(charCount) const char *pText,
 void WriteUtf8ToConsole(_In_opt_count_(charCount) const char *pText,
-                        int charCount);
+                        int charCount, DWORD streamType = STD_OUTPUT_HANDLE);
 void WriteUtf8ToConsoleSizeT(_In_opt_count_(charCount) const char *pText,
 void WriteUtf8ToConsoleSizeT(_In_opt_count_(charCount) const char *pText,
-                             size_t charCount);
+                             size_t charCount, DWORD streamType = STD_OUTPUT_HANDLE);
 void WriteOperationErrorsToConsole(_In_ IDxcOperationResult *pResult,
 void WriteOperationErrorsToConsole(_In_ IDxcOperationResult *pResult,
                                    bool outputWarnings);
                                    bool outputWarnings);
 void WriteOperationResultToConsole(_In_ IDxcOperationResult *pRewriteResult,
 void WriteOperationResultToConsole(_In_ IDxcOperationResult *pRewriteResult,

+ 2 - 1
include/dxc/dxcapi.h

@@ -163,7 +163,8 @@ IDxcCompiler : public IUnknown {
 
 
 static const UINT32 DxcValidatorFlags_Default = 0;
 static const UINT32 DxcValidatorFlags_Default = 0;
 static const UINT32 DxcValidatorFlags_InPlaceEdit = 1;  // Validator is allowed to update shader blob in-place.
 static const UINT32 DxcValidatorFlags_InPlaceEdit = 1;  // Validator is allowed to update shader blob in-place.
-static const UINT32 DxcValidatorFlags_ValidMask = 0x1;
+static const UINT32 DxcValidatorFlags_RootSignatureOnly = 2;
+static const UINT32 DxcValidatorFlags_ValidMask = 0x3;
 
 
 struct __declspec(uuid("A6E82BD2-1FD7-4826-9811-2857E797F49A"))
 struct __declspec(uuid("A6E82BD2-1FD7-4826-9811-2857E797F49A"))
 IDxcValidator : public IUnknown {
 IDxcValidator : public IUnknown {

+ 10 - 5
lib/DxcSupport/HLSLOptions.cpp

@@ -236,7 +236,6 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
   // OutputLibrary not supported (Fl)
   // OutputLibrary not supported (Fl)
   opts.AssemblyCode = Args.getLastArgValue(OPT_Fc);
   opts.AssemblyCode = Args.getLastArgValue(OPT_Fc);
   opts.DebugFile = Args.getLastArgValue(OPT_Fd);
   opts.DebugFile = Args.getLastArgValue(OPT_Fd);
-  opts.ExtractRootSignatureFile = Args.getLastArgValue(OPT_extractrootsignature);
   opts.ExtractPrivateFile = Args.getLastArgValue(OPT_getprivate);
   opts.ExtractPrivateFile = Args.getLastArgValue(OPT_getprivate);
   opts.OutputObject = Args.getLastArgValue(OPT_Fo);
   opts.OutputObject = Args.getLastArgValue(OPT_Fo);
   opts.OutputHeader = Args.getLastArgValue(OPT_Fh);
   opts.OutputHeader = Args.getLastArgValue(OPT_Fh);
@@ -254,6 +253,7 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
   opts.ForceRootSigVer = Args.getLastArgValue(OPT_force_rootsig_ver);
   opts.ForceRootSigVer = Args.getLastArgValue(OPT_force_rootsig_ver);
   opts.PrivateSource = Args.getLastArgValue(OPT_setprivate);
   opts.PrivateSource = Args.getLastArgValue(OPT_setprivate);
   opts.RootSignatureSource = Args.getLastArgValue(OPT_setrootsignature);
   opts.RootSignatureSource = Args.getLastArgValue(OPT_setrootsignature);
+  opts.VerifyRootSignatureSource = Args.getLastArgValue(OPT_verifyrootsignature);
 
 
   if (!opts.ForceRootSigVer.empty() && opts.ForceRootSigVer != "rootsig_1_0" &&
   if (!opts.ForceRootSigVer.empty() && opts.ForceRootSigVer != "rootsig_1_0" &&
       opts.ForceRootSigVer != "rootsig_1_1") {
       opts.ForceRootSigVer != "rootsig_1_1") {
@@ -287,7 +287,6 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
   opts.DefaultRowMajor = Args.hasFlag(OPT_Zpr, OPT_INVALID, false);
   opts.DefaultRowMajor = Args.hasFlag(OPT_Zpr, OPT_INVALID, false);
   opts.DefaultColMajor = Args.hasFlag(OPT_Zpc, OPT_INVALID, false);
   opts.DefaultColMajor = Args.hasFlag(OPT_Zpc, OPT_INVALID, false);
   opts.DumpBin = Args.hasFlag(OPT_dumpbin, OPT_INVALID, false);
   opts.DumpBin = Args.hasFlag(OPT_dumpbin, OPT_INVALID, false);
-  opts.EnableUnboundedDescriptorTables = Args.hasFlag(OPT_enable_unbounded_descriptor_tables, OPT_INVALID, false);
   opts.NotUseLegacyCBufLoad = Args.hasFlag(OPT_not_use_legacy_cbuf_load, OPT_INVALID, false);
   opts.NotUseLegacyCBufLoad = Args.hasFlag(OPT_not_use_legacy_cbuf_load, OPT_INVALID, false);
   opts.DisplayIncludeProcess = Args.hasFlag(OPT_H, OPT_INVALID, false);
   opts.DisplayIncludeProcess = Args.hasFlag(OPT_H, OPT_INVALID, false);
   opts.WarningAsError = Args.hasFlag(OPT__SLASH_WX, OPT_INVALID, false);
   opts.WarningAsError = Args.hasFlag(OPT__SLASH_WX, OPT_INVALID, false);
@@ -298,6 +297,12 @@ 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.ExtractRootSignature = Args.hasFlag(OPT_extractrootsignature, OPT_INVALID, false);
+  opts.DisassembleColorCoded = Args.hasFlag(OPT_Cc, OPT_INVALID, false);
+  opts.DisassembleInstNumbers = Args.hasFlag(OPT_Ni, OPT_INVALID, false);
+  opts.DisassembleByteOffset = Args.hasFlag(OPT_No, OPT_INVALID, false);
+  opts.DisaseembleHex = Args.hasFlag(OPT_Lx, OPT_INVALID, false);
+
   if (opts.DefaultColMajor && opts.DefaultRowMajor) {
   if (opts.DefaultColMajor && opts.DefaultRowMajor) {
     errors << "Cannot specify /Zpr and /Zpc together, use /? to get usage information";
     errors << "Cannot specify /Zpr and /Zpc together, use /? to get usage information";
     return 1;
     return 1;
@@ -318,7 +323,7 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
 
 
   if ((flagsToInclude & hlsl::options::DriverOption) && opts.InputFile.empty()) {
   if ((flagsToInclude & hlsl::options::DriverOption) && opts.InputFile.empty()) {
     // Input file is required in arguments only for drivers; APIs take this through an argument.
     // Input file is required in arguments only for drivers; APIs take this through an argument.
-    errors << "Required input file argument is missing.";
+    errors << "Required input file argument is missing. use -help to get more information.";
     return 1;
     return 1;
   }
   }
   if (opts.OutputHeader.empty() && !opts.VariableName.empty()) {
   if (opts.OutputHeader.empty() && !opts.VariableName.empty()) {
@@ -328,7 +333,7 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
 
 
   if (!opts.Preprocess.empty() &&
   if (!opts.Preprocess.empty() &&
       (!opts.OutputHeader.empty() || !opts.OutputObject.empty() ||
       (!opts.OutputHeader.empty() || !opts.OutputObject.empty() ||
-       opts.OutputWarnings || !opts.OutputWarningsFile.empty())) {
+       !opts.OutputWarnings || !opts.OutputWarningsFile.empty())) {
     errors << "Preprocess cannot be specified with other options.";
     errors << "Preprocess cannot be specified with other options.";
     return 1;
     return 1;
   }
   }
@@ -341,7 +346,7 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
     if (opts.AllResourcesBound || opts.AvoidFlowControl ||
     if (opts.AllResourcesBound || opts.AvoidFlowControl ||
         opts.CodeGenHighLevel || opts.DebugInfo || opts.DefaultColMajor ||
         opts.CodeGenHighLevel || opts.DebugInfo || opts.DefaultColMajor ||
         opts.DefaultRowMajor || opts.Defines.size() != 0 ||
         opts.DefaultRowMajor || opts.Defines.size() != 0 ||
-        opts.DisableOptimizations || opts.EnableUnboundedDescriptorTables ||
+        opts.DisableOptimizations || 
         !opts.EntryPoint.empty() || !opts.ForceRootSigVer.empty() ||
         !opts.EntryPoint.empty() || !opts.ForceRootSigVer.empty() ||
         opts.PreferFlowControl || !opts.TargetProfile.empty()) {
         opts.PreferFlowControl || !opts.TargetProfile.empty()) {
       errors << "Cannot specify compilation options when reading a binary file.";
       errors << "Cannot specify compilation options when reading a binary file.";

+ 17 - 8
lib/DxcSupport/dxcapi.use.cpp

@@ -76,7 +76,7 @@ void WriteOperationErrorsToConsole(_In_ IDxcOperationResult *pResult,
     CComPtr<IDxcBlobEncoding> pErrors;
     CComPtr<IDxcBlobEncoding> pErrors;
     IFT(pResult->GetErrorBuffer(&pErrors));
     IFT(pResult->GetErrorBuffer(&pErrors));
     if (pErrors.p != nullptr) {
     if (pErrors.p != nullptr) {
-      WriteBlobToConsole(pErrors);
+      WriteBlobToConsole(pErrors, STD_ERROR_HANDLE);
     }
     }
   }
   }
 }
 }
@@ -87,16 +87,16 @@ void WriteOperationResultToConsole(_In_ IDxcOperationResult *pRewriteResult,
 
 
   CComPtr<IDxcBlob> pBlob;
   CComPtr<IDxcBlob> pBlob;
   IFT(pRewriteResult->GetResult(&pBlob));
   IFT(pRewriteResult->GetResult(&pBlob));
-  WriteBlobToConsole(pBlob);
+  WriteBlobToConsole(pBlob, STD_OUTPUT_HANDLE);
 }
 }
 
 
-void WriteBlobToConsole(_In_opt_ IDxcBlob *pBlob) {
+void WriteBlobToConsole(_In_opt_ IDxcBlob *pBlob, DWORD streamType) {
   if (pBlob == nullptr) {
   if (pBlob == nullptr) {
     return;
     return;
   }
   }
 
 
   // Assume UTF-8 for now, which is typically the case for dxcompiler ouput.
   // Assume UTF-8 for now, which is typically the case for dxcompiler ouput.
-  WriteUtf8ToConsoleSizeT((char *)pBlob->GetBufferPointer(), pBlob->GetBufferSize());
+  WriteUtf8ToConsoleSizeT((char *)pBlob->GetBufferPointer(), pBlob->GetBufferSize(), streamType);
 }
 }
 
 
 void WriteBlobToFile(_In_opt_ IDxcBlob *pBlob, _In_ LPCWSTR pFileName) {
 void WriteBlobToFile(_In_opt_ IDxcBlob *pBlob, _In_ LPCWSTR pFileName) {
@@ -125,7 +125,7 @@ void WriteBlobToHandle(_In_opt_ IDxcBlob *pBlob, _In_ HANDLE hFile, _In_opt_ LPC
 }
 }
 
 
 void WriteUtf8ToConsole(_In_opt_count_(charCount) const char *pText,
 void WriteUtf8ToConsole(_In_opt_count_(charCount) const char *pText,
-                        int charCount) {
+                        int charCount, DWORD streamType) {
   if (charCount == 0 || pText == nullptr) {
   if (charCount == 0 || pText == nullptr) {
     return;
     return;
   }
   }
@@ -139,19 +139,28 @@ void WriteUtf8ToConsole(_In_opt_count_(charCount) const char *pText,
 
 
   std::string consoleMessage;
   std::string consoleMessage;
   Unicode::UTF16ToConsoleString(utf16Message, &consoleMessage, &lossy);
   Unicode::UTF16ToConsoleString(utf16Message, &consoleMessage, &lossy);
-  printf("%s\n", consoleMessage.c_str());
+  if (streamType == STD_OUTPUT_HANDLE) {
+    fprintf(stdout, "%s\n", consoleMessage.c_str());
+  }
+  else if (streamType == STD_ERROR_HANDLE) {
+    fprintf(stderr, "%s\n", consoleMessage.c_str());
+  }
+  else {
+    throw hlsl::Exception(E_INVALIDARG);
+  }
+
   delete[] utf16Message;
   delete[] utf16Message;
 }
 }
 
 
 void WriteUtf8ToConsoleSizeT(_In_opt_count_(charCount) const char *pText,
 void WriteUtf8ToConsoleSizeT(_In_opt_count_(charCount) const char *pText,
-  size_t charCount) {
+  size_t charCount, DWORD streamType) {
   if (charCount == 0) {
   if (charCount == 0) {
     return;
     return;
   }
   }
 
 
   int charCountInt;
   int charCountInt;
   IFT(SizeTToInt(charCount, &charCountInt));
   IFT(SizeTToInt(charCount, &charCountInt));
-  WriteUtf8ToConsole(pText, charCountInt);
+  WriteUtf8ToConsole(pText, charCountInt, streamType);
 }
 }
 
 
 } // namespace dxc
 } // namespace dxc

+ 90 - 55
lib/HLSL/DxilContainerAssembler.cpp

@@ -132,7 +132,7 @@ struct sort_sig {
   }
   }
 };
 };
 
 
-class DxilProgramSignatureWriter {
+class DxilProgramSignatureWriter : public DxilPartWriter {
 private:
 private:
   const DxilSignature &m_signature;
   const DxilSignature &m_signature;
   DXIL::TessellatorDomain m_domain;
   DXIL::TessellatorDomain m_domain;
@@ -174,6 +174,7 @@ private:
       eltRows = pElement->GetRows() / eltCount;
       eltRows = pElement->GetRows() / eltCount;
 
 
     DxilProgramSignatureElement sig;
     DxilProgramSignatureElement sig;
+    memset(&sig, 0, sizeof(DxilProgramSignatureElement));
     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);
@@ -229,11 +230,11 @@ public:
     calcSizes();
     calcSizes();
   }
   }
 
 
-  uint32_t size() const {
+  __override uint32_t size() const {
     return m_lastOffset;
     return m_lastOffset;
   }
   }
 
 
-  void write(AbstractMemoryStream *pStream) {
+  __override void write(AbstractMemoryStream *pStream) {
     UINT64 startPos = pStream->GetPosition();
     UINT64 startPos = pStream->GetPosition();
     const std::vector<std::unique_ptr<hlsl::DxilSignatureElement>> &elements = m_signature.GetElements();
     const std::vector<std::unique_ptr<hlsl::DxilSignatureElement>> &elements = m_signature.GetElements();
 
 
@@ -274,7 +275,22 @@ public:
   }
   }
 };
 };
 
 
-class DxilProgramRootSignatureWriter {
+DxilPartWriter *hlsl::NewProgramSignatureWriter(const DxilModule &M, DXIL::SignatureKind Kind) {
+  switch (Kind) {
+  case DXIL::SignatureKind::Input:
+    return new DxilProgramSignatureWriter(M.GetInputSignature(),
+      M.GetTessellatorDomain(), true);
+  case DXIL::SignatureKind::Output:
+    return new DxilProgramSignatureWriter(M.GetOutputSignature(),
+      M.GetTessellatorDomain(), false);
+  case DXIL::SignatureKind::PatchConstant:
+    return new DxilProgramSignatureWriter(M.GetPatchConstantSignature(),
+      M.GetTessellatorDomain(), /*IsInput*/ M.GetShaderModel()->IsDS());
+  }
+  return nullptr;
+}
+
+class DxilProgramRootSignatureWriter : public DxilPartWriter {
 private:
 private:
   const RootSignatureHandle &m_Sig;
   const RootSignatureHandle &m_Sig;
 public:
 public:
@@ -288,7 +304,11 @@ public:
   }
   }
 };
 };
 
 
-class DxilFeatureInfoWriter {
+DxilPartWriter *hlsl::NewRootSignatureWriter(const RootSignatureHandle &S) {
+  return new DxilProgramRootSignatureWriter(S);
+}
+
+class DxilFeatureInfoWriter : public DxilPartWriter  {
 private:
 private:
   // Only save the shader properties after create class for it.
   // Only save the shader properties after create class for it.
   DxilShaderFeatureInfo featureInfo;
   DxilShaderFeatureInfo featureInfo;
@@ -296,24 +316,28 @@ public:
   DxilFeatureInfoWriter(const DxilModule &M) {
   DxilFeatureInfoWriter(const DxilModule &M) {
     featureInfo.FeatureFlags = M.m_ShaderFlags.GetFeatureInfo();
     featureInfo.FeatureFlags = M.m_ShaderFlags.GetFeatureInfo();
   }
   }
-  uint32_t size() const {
+  __override uint32_t size() const {
     return sizeof(DxilShaderFeatureInfo);
     return sizeof(DxilShaderFeatureInfo);
   }
   }
-  void write(AbstractMemoryStream *pStream) {
+  __override void write(AbstractMemoryStream *pStream) {
     IFT(WriteStreamValue(pStream, featureInfo.FeatureFlags));
     IFT(WriteStreamValue(pStream, featureInfo.FeatureFlags));
   }
   }
 };
 };
 
 
-class DxilPSVWriter {
+DxilPartWriter *hlsl::NewFeatureInfoWriter(const DxilModule &M) {
+  return new DxilFeatureInfoWriter(M);
+}
+
+class DxilPSVWriter : public DxilPartWriter  {
 private:
 private:
-  DxilModule &m_Module;
+  const DxilModule &m_Module;
   UINT m_uTotalResources;
   UINT m_uTotalResources;
   DxilPipelineStateValidation m_PSV;
   DxilPipelineStateValidation m_PSV;
   uint32_t m_PSVBufferSize;
   uint32_t m_PSVBufferSize;
   SmallVector<char, 512> m_PSVBuffer;
   SmallVector<char, 512> m_PSVBuffer;
 
 
 public:
 public:
-  DxilPSVWriter(DxilModule &module) : m_Module(module) {
+  DxilPSVWriter(const DxilModule &module) : m_Module(module) {
     UINT uCBuffers = m_Module.GetCBuffers().size();
     UINT uCBuffers = m_Module.GetCBuffers().size();
     UINT uSamplers = m_Module.GetSamplers().size();
     UINT uSamplers = m_Module.GetSamplers().size();
     UINT uSRVs = m_Module.GetSRVs().size();
     UINT uSRVs = m_Module.GetSRVs().size();
@@ -321,11 +345,11 @@ public:
     m_uTotalResources = uCBuffers + uSamplers + uSRVs + uUAVs;
     m_uTotalResources = uCBuffers + uSamplers + uSRVs + uUAVs;
     m_PSV.InitNew(m_uTotalResources, nullptr, &m_PSVBufferSize);
     m_PSV.InitNew(m_uTotalResources, nullptr, &m_PSVBufferSize);
   }
   }
-  size_t size() {
+  __override uint32_t size() const {
     return m_PSVBufferSize;
     return m_PSVBufferSize;
   }
   }
 
 
-  void write(AbstractMemoryStream *pStream) {
+  __override void write(AbstractMemoryStream *pStream) {
     m_PSVBuffer.resize(m_PSVBufferSize);
     m_PSVBuffer.resize(m_PSVBufferSize);
     m_PSV.InitNew(m_uTotalResources, m_PSVBuffer.data(), &m_PSVBufferSize);
     m_PSV.InitNew(m_uTotalResources, m_PSVBuffer.data(), &m_PSVBufferSize);
     DXASSERT_NOMSG(m_PSVBuffer.size() == m_PSVBufferSize);
     DXASSERT_NOMSG(m_PSVBuffer.size() == m_PSVBufferSize);
@@ -339,7 +363,7 @@ public:
     switch (SM->GetKind()) {
     switch (SM->GetKind()) {
       case ShaderModel::Kind::Vertex: {
       case ShaderModel::Kind::Vertex: {
         pInfo->VS.OutputPositionPresent = 0;
         pInfo->VS.OutputPositionPresent = 0;
-        DxilSignature &S = m_Module.GetOutputSignature();
+        const DxilSignature &S = m_Module.GetOutputSignature();
         for (auto &&E : S.GetElements()) {
         for (auto &&E : S.GetElements()) {
           if (E->GetKind() == Semantic::Kind::Position) {
           if (E->GetKind() == Semantic::Kind::Position) {
             // Ideally, we might check never writes mask here,
             // Ideally, we might check never writes mask here,
@@ -360,7 +384,7 @@ public:
       case ShaderModel::Kind::Domain: {
       case ShaderModel::Kind::Domain: {
         pInfo->DS.InputControlPointCount = (UINT)m_Module.GetInputControlPointCount();
         pInfo->DS.InputControlPointCount = (UINT)m_Module.GetInputControlPointCount();
         pInfo->DS.OutputPositionPresent = 0;
         pInfo->DS.OutputPositionPresent = 0;
-        DxilSignature &S = m_Module.GetOutputSignature();
+        const DxilSignature &S = m_Module.GetOutputSignature();
         for (auto &&E : S.GetElements()) {
         for (auto &&E : S.GetElements()) {
           if (E->GetKind() == Semantic::Kind::Position) {
           if (E->GetKind() == Semantic::Kind::Position) {
             // Ideally, we might check never writes mask here,
             // Ideally, we might check never writes mask here,
@@ -382,7 +406,7 @@ public:
           pInfo->GS.OutputStreamMask = 1; // This is what runtime expects.
           pInfo->GS.OutputStreamMask = 1; // This is what runtime expects.
         }
         }
         pInfo->GS.OutputPositionPresent = 0;
         pInfo->GS.OutputPositionPresent = 0;
-        DxilSignature &S = m_Module.GetOutputSignature();
+        const DxilSignature &S = m_Module.GetOutputSignature();
         for (auto &&E : S.GetElements()) {
         for (auto &&E : S.GetElements()) {
           if (E->GetKind() == Semantic::Kind::Position) {
           if (E->GetKind() == Semantic::Kind::Position) {
             // Ideally, we might check never writes mask here,
             // Ideally, we might check never writes mask here,
@@ -397,7 +421,7 @@ public:
         pInfo->PS.DepthOutput = 0;
         pInfo->PS.DepthOutput = 0;
         pInfo->PS.SampleFrequency = 0;
         pInfo->PS.SampleFrequency = 0;
         {
         {
-          DxilSignature &S = m_Module.GetInputSignature();
+          const DxilSignature &S = m_Module.GetInputSignature();
           for (auto &&E : S.GetElements()) {
           for (auto &&E : S.GetElements()) {
             if (E->GetInterpolationMode()->IsAnySample() ||
             if (E->GetInterpolationMode()->IsAnySample() ||
                 E->GetKind() == Semantic::Kind::SampleIndex) {
                 E->GetKind() == Semantic::Kind::SampleIndex) {
@@ -406,7 +430,7 @@ public:
           }
           }
         }
         }
         {
         {
-          DxilSignature &S = m_Module.GetOutputSignature();
+          const DxilSignature &S = m_Module.GetOutputSignature();
           for (auto &&E : S.GetElements()) {
           for (auto &&E : S.GetElements()) {
             if (E->IsAnyDepth()) {
             if (E->IsAnyDepth()) {
               pInfo->PS.DepthOutput = 1;
               pInfo->PS.DepthOutput = 1;
@@ -483,10 +507,11 @@ public:
   }
   }
 };
 };
 
 
-class DxilContainerWriter {
-public:
-  typedef std::function<void(AbstractMemoryStream*)> WriteFn;
+DxilPartWriter *hlsl::NewPSVWriter(const DxilModule &M) {
+  return new DxilPSVWriter(M);
+}
 
 
+class DxilContainerWriter_impl : public DxilContainerWriter  {
 private:
 private:
   class DxilPart {
   class DxilPart {
   public:
   public:
@@ -501,24 +526,26 @@ private:
   llvm::SmallVector<DxilPart, 8> m_Parts;
   llvm::SmallVector<DxilPart, 8> m_Parts;
 
 
 public:
 public:
-  void AddPart(uint32_t FourCC, uint32_t Size, WriteFn Write) {
+  __override void AddPart(uint32_t FourCC, uint32_t Size, WriteFn Write) {
     m_Parts.emplace_back(FourCC, Size, Write);
     m_Parts.emplace_back(FourCC, Size, Write);
   }
   }
 
 
-  void write(AbstractMemoryStream *pStream) {
+  __override uint32_t size() const {
+    uint32_t partSize = 0;
+    for (auto &part : m_Parts) {
+      partSize += part.Header.PartSize;
+    }
+    return (uint32_t)GetDxilContainerSizeFromParts((uint32_t)m_Parts.size(), partSize);
+  }
+
+  __override void write(AbstractMemoryStream *pStream) {
     DxilContainerHeader header;
     DxilContainerHeader header;
     const uint32_t PartCount = (uint32_t)m_Parts.size();
     const uint32_t PartCount = (uint32_t)m_Parts.size();
-    const uint32_t OffsetTableSize = sizeof(uint32_t) * PartCount;
-    uint32_t containerSizeInBytes =
-      (uint32_t)sizeof(DxilContainerHeader) + OffsetTableSize +
-      (uint32_t)sizeof(DxilPartHeader) * PartCount;
-    for (auto &&part : m_Parts) {
-      containerSizeInBytes += part.Header.PartSize;
-    }
+    uint32_t containerSizeInBytes = size();
     InitDxilContainer(&header, PartCount, containerSizeInBytes);
     InitDxilContainer(&header, PartCount, containerSizeInBytes);
     IFT(pStream->Reserve(header.ContainerSizeInBytes));
     IFT(pStream->Reserve(header.ContainerSizeInBytes));
     IFT(WriteStreamValue(pStream, header));
     IFT(WriteStreamValue(pStream, header));
-    uint32_t offset = sizeof(header) + OffsetTableSize;
+    uint32_t offset = sizeof(header) + (uint32_t)GetOffsetTableSize(PartCount);
     for (auto &&part : m_Parts) {
     for (auto &&part : m_Parts) {
       IFT(WriteStreamValue(pStream, offset));
       IFT(WriteStreamValue(pStream, offset));
       offset += sizeof(DxilPartHeader) + part.Header.PartSize;
       offset += sizeof(DxilPartHeader) + part.Header.PartSize;
@@ -533,6 +560,10 @@ public:
   }
   }
 };
 };
 
 
+DxilContainerWriter *hlsl::NewDxilContainerWriter() {
+  return new DxilContainerWriter_impl();
+}
+
 static bool HasDebugInfo(const Module &M) {
 static bool HasDebugInfo(const Module &M) {
   for (Module::const_named_metadata_iterator NMI = M.named_metadata_begin(),
   for (Module::const_named_metadata_iterator NMI = M.named_metadata_begin(),
                                              NME = M.named_metadata_end();
                                              NME = M.named_metadata_end();
@@ -575,7 +606,7 @@ static void WriteProgramPart(const ShaderModel *pModel,
   }
   }
 }
 }
 
 
-void hlsl::SerializeDxilContainerForModule(Module *pModule,
+void hlsl::SerializeDxilContainerForModule(DxilModule *pModule,
                                            AbstractMemoryStream *pModuleBitcode,
                                            AbstractMemoryStream *pModuleBitcode,
                                            AbstractMemoryStream *pFinalStream) {
                                            AbstractMemoryStream *pFinalStream) {
   // 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
@@ -585,21 +616,17 @@ void hlsl::SerializeDxilContainerForModule(Module *pModule,
   DXASSERT_NOMSG(pModuleBitcode != nullptr);
   DXASSERT_NOMSG(pModuleBitcode != nullptr);
   DXASSERT_NOMSG(pFinalStream != nullptr);
   DXASSERT_NOMSG(pFinalStream != nullptr);
 
 
-  CComPtr<AbstractMemoryStream> pProgramStream;
-  DxilModule dxilModule(pModule);
-  dxilModule.LoadDxilMetadata();
-
-  DxilProgramSignatureWriter inputSigWriter(dxilModule.GetInputSignature(),
-                                            dxilModule.GetTessellatorDomain(),
+  DxilProgramSignatureWriter inputSigWriter(pModule->GetInputSignature(),
+                                            pModule->GetTessellatorDomain(),
                                             /*IsInput*/ true);
                                             /*IsInput*/ true);
-  DxilProgramSignatureWriter outputSigWriter(dxilModule.GetOutputSignature(),
-                                             dxilModule.GetTessellatorDomain(),
+  DxilProgramSignatureWriter outputSigWriter(pModule->GetOutputSignature(),
+                                             pModule->GetTessellatorDomain(),
                                              /*IsInput*/ false);
                                              /*IsInput*/ false);
-  DxilPSVWriter PSVWriter(dxilModule);
-  DxilContainerWriter writer;
+  DxilPSVWriter PSVWriter(*pModule);
+  DxilContainerWriter_impl writer;
 
 
   // Write the feature part.
   // Write the feature part.
-  DxilFeatureInfoWriter featureInfoWriter(dxilModule);
+  DxilFeatureInfoWriter featureInfoWriter(*pModule);
   writer.AddPart(DFCC_FeatureInfo, featureInfoWriter.size(), [&](AbstractMemoryStream *pStream) {
   writer.AddPart(DFCC_FeatureInfo, featureInfoWriter.size(), [&](AbstractMemoryStream *pStream) {
     featureInfoWriter.write(pStream);
     featureInfoWriter.write(pStream);
   });
   });
@@ -613,10 +640,10 @@ void hlsl::SerializeDxilContainerForModule(Module *pModule,
   });
   });
 
 
   DxilProgramSignatureWriter patchConstantSigWriter(
   DxilProgramSignatureWriter patchConstantSigWriter(
-      dxilModule.GetPatchConstantSignature(), dxilModule.GetTessellatorDomain(),
-      /*IsInput*/ dxilModule.GetShaderModel()->IsDS());
+      pModule->GetPatchConstantSignature(), pModule->GetTessellatorDomain(),
+      /*IsInput*/ pModule->GetShaderModel()->IsDS());
 
 
-  if (dxilModule.GetPatchConstantSignature().GetElements().size()) {
+  if (pModule->GetPatchConstantSignature().GetElements().size()) {
     writer.AddPart(DFCC_PatchConstantSignature, patchConstantSigWriter.size(),
     writer.AddPart(DFCC_PatchConstantSignature, patchConstantSigWriter.size(),
                    [&](AbstractMemoryStream *pStream) {
                    [&](AbstractMemoryStream *pStream) {
                      patchConstantSigWriter.write(pStream);
                      patchConstantSigWriter.write(pStream);
@@ -629,32 +656,40 @@ void hlsl::SerializeDxilContainerForModule(Module *pModule,
   });
   });
 
 
   // Write the root signature (RTS0) part.
   // Write the root signature (RTS0) part.
-  DxilProgramRootSignatureWriter rootSigWriter(dxilModule.GetRootSignature());
-  if (!dxilModule.GetRootSignature().IsEmpty()) {
+  DxilProgramRootSignatureWriter rootSigWriter(pModule->GetRootSignature());
+  CComPtr<AbstractMemoryStream> pInputProgramStream = pModuleBitcode;
+  if (!pModule->GetRootSignature().IsEmpty()) {
     writer.AddPart(
     writer.AddPart(
         DFCC_RootSignature, rootSigWriter.size(),
         DFCC_RootSignature, rootSigWriter.size(),
         [&](AbstractMemoryStream *pStream) { rootSigWriter.write(pStream); });
         [&](AbstractMemoryStream *pStream) { rootSigWriter.write(pStream); });
+    pModule->StripRootSignatureFromMetadata();
+    pInputProgramStream.Release();
+    CComPtr<IMalloc> pMalloc;
+    IFT(CoGetMalloc(1, &pMalloc));
+    IFT(CreateMemoryStream(pMalloc, &pInputProgramStream));
+    raw_stream_ostream outStream(pInputProgramStream.p);
+    WriteBitcodeToFile(pModule->GetModule(), outStream, true);
   }
   }
 
 
   // If we have debug information present, serialize it to a debug part, then use the stripped version as the canonical program version.
   // If we have debug information present, serialize it to a debug part, then use the stripped version as the canonical program version.
-  pProgramStream = pModuleBitcode;
-  if (HasDebugInfo(*pModule)) {
+  CComPtr<AbstractMemoryStream> pProgramStream = pInputProgramStream;
+  if (HasDebugInfo(*pModule->GetModule())) {
     uint32_t debugInUInt32, debugPaddingBytes;
     uint32_t debugInUInt32, debugPaddingBytes;
-    GetPaddedProgramPartSize(pModuleBitcode, debugInUInt32, debugPaddingBytes);
+    GetPaddedProgramPartSize(pInputProgramStream, debugInUInt32, debugPaddingBytes);
     writer.AddPart(DFCC_ShaderDebugInfoDXIL, debugInUInt32 * sizeof(uint32_t) + sizeof(DxilProgramHeader), [&](AbstractMemoryStream *pStream) {
     writer.AddPart(DFCC_ShaderDebugInfoDXIL, debugInUInt32 * sizeof(uint32_t) + sizeof(DxilProgramHeader), [&](AbstractMemoryStream *pStream) {
-      WriteProgramPart(dxilModule.GetShaderModel(), pModuleBitcode, pStream);
+      WriteProgramPart(pModule->GetShaderModel(), pInputProgramStream, pStream);
     });
     });
 
 
     pProgramStream.Release();
     pProgramStream.Release();
 
 
-    llvm::StripDebugInfo(*pModule);
-    dxilModule.StripDebugRelatedCode();
+    llvm::StripDebugInfo(*pModule->GetModule());
+    pModule->StripDebugRelatedCode();
 
 
     CComPtr<IMalloc> pMalloc;
     CComPtr<IMalloc> pMalloc;
     IFT(CoGetMalloc(1, &pMalloc));
     IFT(CoGetMalloc(1, &pMalloc));
     IFT(CreateMemoryStream(pMalloc, &pProgramStream));
     IFT(CreateMemoryStream(pMalloc, &pProgramStream));
     raw_stream_ostream outStream(pProgramStream.p);
     raw_stream_ostream outStream(pProgramStream.p);
-    WriteBitcodeToFile(pModule, outStream, true);
+    WriteBitcodeToFile(pModule->GetModule(), outStream, true);
   }
   }
 
 
   // Compute padded bitcode size.
   // Compute padded bitcode size.
@@ -663,7 +698,7 @@ void hlsl::SerializeDxilContainerForModule(Module *pModule,
 
 
   // Write the program part.
   // Write the program part.
   writer.AddPart(DFCC_DXIL, programInUInt32 * sizeof(uint32_t) + sizeof(DxilProgramHeader), [&](AbstractMemoryStream *pStream) {
   writer.AddPart(DFCC_DXIL, programInUInt32 * sizeof(uint32_t) + sizeof(DxilProgramHeader), [&](AbstractMemoryStream *pStream) {
-    WriteProgramPart(dxilModule.GetShaderModel(), pProgramStream, pStream);
+    WriteProgramPart(pModule->GetShaderModel(), pProgramStream, pStream);
   });
   });
 
 
   writer.write(pFinalStream);
   writer.write(pFinalStream);

+ 7 - 1
lib/HLSL/DxilGenerationPass.cpp

@@ -523,7 +523,6 @@ static DxilSignatureElement *FindArgInSignature(Argument &arg, llvm::StringRef s
       return &SE;
       return &SE;
     }
     }
   }
   }
-  DXASSERT(0, "must find a match");
   return nullptr;
   return nullptr;
 }
 }
 
 
@@ -702,6 +701,13 @@ void DxilGenerationPass::ProcessArgument(Function *func,
         sigKind != DXIL::SignatureKind::PatchConstant) {
         sigKind != DXIL::SignatureKind::PatchConstant) {
       pSE = FindArgInSignature(arg, paramAnnotation.GetSemanticString(),
       pSE = FindArgInSignature(arg, paramAnnotation.GetSemanticString(),
                                interpMode, sigPoint->GetKind(), *pSig);
                                interpMode, sigPoint->GetKind(), *pSig);
+      if (!pSE) {
+        m_pHLModule->GetModule()->getContext().emitError(
+          Twine("Signature element ") + semanticStr +
+          Twine(", referred to by patch constant function, is not found in corresponding hull shader ") + 
+          (sigKind == DXIL::SignatureKind::Input ? "input." : "output."));
+        return;
+      }
       m_patchConstantInputsSigMap[arg.getArgNo()] = pSE;
       m_patchConstantInputsSigMap[arg.getArgNo()] = pSE;
     } else {
     } else {
       std::unique_ptr<DxilSignatureElement> SE = pSig->CreateElement();
       std::unique_ptr<DxilSignatureElement> SE = pSig->CreateElement();

+ 20 - 5
lib/HLSL/DxilMetadataHelper.cpp

@@ -46,6 +46,9 @@ const char DxilMDHelper::kDxilControlFlowHintMDName[]                 = "dx.cont
 const char DxilMDHelper::kDxilPreciseAttributeMDName[]                = "dx.precise";
 const char DxilMDHelper::kDxilPreciseAttributeMDName[]                = "dx.precise";
 const char DxilMDHelper::kDxilValidatorVersionMDName[]                = "dx.valver";
 const char DxilMDHelper::kDxilValidatorVersionMDName[]                = "dx.valver";
 
 
+// This named metadata is not valid in final module (should be moved to DxilContainer)
+const char DxilMDHelper::kDxilRootSignatureMDName[]                   = "dx.rootSignature";
+
 static std::array<const char *, 6> DxilMDNames = {
 static std::array<const char *, 6> DxilMDNames = {
   DxilMDHelper::kDxilVersionMDName,
   DxilMDHelper::kDxilVersionMDName,
   DxilMDHelper::kDxilShaderModelMDName,
   DxilMDHelper::kDxilShaderModelMDName,
@@ -224,16 +227,21 @@ MDTuple *DxilMDHelper::EmitDxilSignatures(const DxilSignature &InputSig,
   return pSignatureTupleMD;
   return pSignatureTupleMD;
 }
 }
 
 
-llvm::Metadata *DxilMDHelper::EmitRootSignature(RootSignatureHandle &RootSig) {
+void DxilMDHelper::EmitRootSignature(RootSignatureHandle &RootSig) {
   if (RootSig.IsEmpty()) {
   if (RootSig.IsEmpty()) {
-    return nullptr;
+    return;
   }
   }
 
 
   RootSig.EnsureSerializedAvailable();
   RootSig.EnsureSerializedAvailable();
   Constant *V = llvm::ConstantDataArray::get(
   Constant *V = llvm::ConstantDataArray::get(
       m_Ctx, llvm::ArrayRef<uint8_t>(RootSig.GetSerializedBytes(),
       m_Ctx, llvm::ArrayRef<uint8_t>(RootSig.GetSerializedBytes(),
                                      RootSig.GetSerializedSize()));
                                      RootSig.GetSerializedSize()));
-  return ConstantAsMetadata::get(V);
+
+  NamedMDNode *pRootSignatureNamedMD = m_pModule->getNamedMetadata(kDxilRootSignatureMDName);
+  IFTBOOL(pRootSignatureNamedMD == nullptr, DXC_E_INCORRECT_DXIL_METADATA);
+  pRootSignatureNamedMD = m_pModule->getOrInsertNamedMetadata(kDxilRootSignatureMDName);
+  pRootSignatureNamedMD->addOperand(MDNode::get(m_Ctx, {ConstantAsMetadata::get(V)}));
+  return ;
 }
 }
 
 
 void DxilMDHelper::LoadDxilSignatures(const MDOperand &MDO, 
 void DxilMDHelper::LoadDxilSignatures(const MDOperand &MDO, 
@@ -279,10 +287,17 @@ void DxilMDHelper::LoadSignatureMetadata(const MDOperand &MDO, DxilSignature &Si
   }
   }
 }
 }
 
 
-void DxilMDHelper::LoadRootSignature(const MDOperand &MDO, RootSignatureHandle &Sig) {
-  if (MDO.get() == nullptr)
+void DxilMDHelper::LoadRootSignature(RootSignatureHandle &Sig) {
+  NamedMDNode *pRootSignatureNamedMD = m_pModule->getNamedMetadata(kDxilRootSignatureMDName);
+  if(!pRootSignatureNamedMD)
     return;
     return;
 
 
+  IFTBOOL(pRootSignatureNamedMD->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
+
+  MDNode *pNode = pRootSignatureNamedMD->getOperand(0);
+  IFTBOOL(pNode->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
+  const MDOperand &MDO = pNode->getOperand(0);
+
   const ConstantAsMetadata *pMetaData = dyn_cast<ConstantAsMetadata>(MDO.get());
   const ConstantAsMetadata *pMetaData = dyn_cast<ConstantAsMetadata>(MDO.get());
   IFTBOOL(pMetaData != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
   IFTBOOL(pMetaData != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
   const ConstantDataArray *pData =
   const ConstantDataArray *pData =

+ 58 - 9
lib/HLSL/DxilModule.cpp

@@ -22,6 +22,8 @@
 #include "llvm/IR/Metadata.h"
 #include "llvm/IR/Metadata.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/DiagnosticPrinter.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/raw_ostream.h"
 #include <unordered_set>
 #include <unordered_set>
 
 
@@ -31,6 +33,21 @@ using std::vector;
 using std::unique_ptr;
 using std::unique_ptr;
 
 
 
 
+namespace {
+class DxilErrorDiagnosticInfo : public DiagnosticInfo {
+private:
+  const char *m_message;
+public:
+  DxilErrorDiagnosticInfo(const char *str)
+    : DiagnosticInfo(DK_FirstPluginKind, DiagnosticSeverity::DS_Error),
+    m_message(str) { }
+
+  __override void print(DiagnosticPrinter &DP) const {
+    DP << m_message;
+  }
+};
+} // anon namespace
+
 namespace hlsl {
 namespace hlsl {
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
@@ -817,6 +834,13 @@ const RootSignatureHandle &DxilModule::GetRootSignature() const {
   return *m_RootSignature;
   return *m_RootSignature;
 }
 }
 
 
+void DxilModule::StripRootSignatureFromMetadata() {
+  NamedMDNode *pRootSignatureNamedMD = GetModule()->getNamedMetadata(DxilMDHelper::kDxilRootSignatureMDName);
+  if (pRootSignatureNamedMD) {
+    GetModule()->eraseNamedMetadata(pRootSignatureNamedMD);
+  }
+}
+
 void DxilModule::ResetInputSignature(DxilSignature *pValue) {
 void DxilModule::ResetInputSignature(DxilSignature *pValue) {
   m_InputSignature.reset(pValue);
   m_InputSignature.reset(pValue);
 }
 }
@@ -896,6 +920,10 @@ void DxilModule::EmitDxilMetadata() {
   vector<MDNode *> Entries;
   vector<MDNode *> Entries;
   Entries.emplace_back(pEntry);
   Entries.emplace_back(pEntry);
   m_pMDHelper->EmitDxilEntryPoints(Entries);
   m_pMDHelper->EmitDxilEntryPoints(Entries);
+
+  if (!m_RootSignature->IsEmpty()) {
+    m_pMDHelper->EmitRootSignature(*m_RootSignature.get());
+  }
 }
 }
 
 
 bool DxilModule::IsKnownNamedMetaData(llvm::NamedMDNode &Node) {
 bool DxilModule::IsKnownNamedMetaData(llvm::NamedMDNode &Node) {
@@ -925,6 +953,8 @@ void DxilModule::LoadDxilMetadata() {
   LoadDxilResources(*pResources);
   LoadDxilResources(*pResources);
   LoadDxilShaderProperties(*pProperties);
   LoadDxilShaderProperties(*pProperties);
   m_pMDHelper->LoadDxilTypeSystem(*m_pTypeSystem.get());
   m_pMDHelper->LoadDxilTypeSystem(*m_pTypeSystem.get());
+
+  m_pMDHelper->LoadRootSignature(*m_RootSignature.get());
 }
 }
 
 
 MDTuple *DxilModule::EmitDxilResources() {
 MDTuple *DxilModule::EmitDxilResources() {
@@ -1071,11 +1101,6 @@ MDTuple *DxilModule::EmitDxilShaderProperties() {
     MDVals.emplace_back(pMDTuple);
     MDVals.emplace_back(pMDTuple);
   }
   }
 
 
-  if (!m_RootSignature->IsEmpty()) {
-    MDVals.emplace_back(m_pMDHelper->Uint32ToConstMD(DxilMDHelper::kDxilRootSignatureTag));
-    MDVals.emplace_back(m_pMDHelper->EmitRootSignature(*m_RootSignature.get()));
-  }
-
   if (!MDVals.empty())
   if (!MDVals.empty())
     return MDNode::get(m_Ctx, MDVals);
     return MDNode::get(m_Ctx, MDVals);
   else
   else
@@ -1129,10 +1154,6 @@ void DxilModule::LoadDxilShaderProperties(const MDOperand &MDO) {
                                    m_MaxTessellationFactor);
                                    m_MaxTessellationFactor);
       break;
       break;
 
 
-    case DxilMDHelper::kDxilRootSignatureTag:
-      m_pMDHelper->LoadRootSignature(MDO, *m_RootSignature.get());
-      break;
-
     default:
     default:
       DXASSERT(false, "Unknown extended shader properties tag");
       DXASSERT(false, "Unknown extended shader properties tag");
       break;
       break;
@@ -1197,6 +1218,34 @@ DebugInfoFinder &DxilModule::GetOrCreateDebugInfoFinder() {
   }
   }
   return *m_pDebugInfoFinder;
   return *m_pDebugInfoFinder;
 }
 }
+
+hlsl::DxilModule *hlsl::DxilModule::TryGetDxilModule(llvm::Module *pModule) {
+  LLVMContext &Ctx = pModule->getContext();
+  std::string diagStr;
+  raw_string_ostream diagStream(diagStr);
+
+  hlsl::DxilModule *pDxilModule = nullptr;
+  // TODO: add detail error in DxilMDHelper.
+  try {
+    pDxilModule = &pModule->GetOrCreateDxilModule();
+  } catch (const ::hlsl::Exception &hlslException) {
+    diagStream << "load dxil metadata failed -";
+    try {
+      const char *msg = hlslException.what();
+      if (msg == nullptr || *msg == '\0')
+        diagStream << " error code " << hlslException.hr << "\n";
+      else
+        diagStream << msg;
+    } catch (...) {
+      diagStream << " unable to retrieve error message.\n";
+    }
+    Ctx.diagnose(DxilErrorDiagnosticInfo(diagStream.str().c_str()));
+  } catch (...) {
+    Ctx.diagnose(DxilErrorDiagnosticInfo("load dxil metadata failed - unknown error.\n"));
+  }
+  return pDxilModule;
+}
+
 } // namespace hlsl
 } // namespace hlsl
 
 
 namespace llvm {
 namespace llvm {

+ 17 - 17
lib/HLSL/DxilOperations.cpp

@@ -200,23 +200,23 @@ const OP::OpCodeProperty OP::m_OpCodeProps[(unsigned)OP::OpCode::NumOpCodes] = {
   {  OC::PrimitiveID,             "PrimitiveID",              OCC::PrimitiveID,              "primitiveID",                false, false, false, false, false, false, false,  true, false, Attribute::ReadNone, },
   {  OC::PrimitiveID,             "PrimitiveID",              OCC::PrimitiveID,              "primitiveID",                false, false, false, false, false, false, false,  true, false, Attribute::ReadNone, },
 
 
   // Other                                                                                                                  void,     h,     f,     d,    i1,    i8,   i16,   i32,   i64  function attribute
   // Other                                                                                                                  void,     h,     f,     d,    i1,    i8,   i16,   i32,   i64  function attribute
-  {  OC::CycleCounterLegacy,      "CycleCounterLegacy",       OCC::CycleCounterLegacy,       "cycleCounterLegacy",          true, false, false, false, false, false, false, false, false, Attribute::ReadNone, },
+  {  OC::CycleCounterLegacy,      "CycleCounterLegacy",       OCC::CycleCounterLegacy,       "cycleCounterLegacy",          true, false, false, false, false, false, false, false, false, Attribute::None,     },
 
 
   // Wave                                                                                                                   void,     h,     f,     d,    i1,    i8,   i16,   i32,   i64  function attribute
   // Wave                                                                                                                   void,     h,     f,     d,    i1,    i8,   i16,   i32,   i64  function attribute
-  {  OC::WaveIsFirstLane,         "WaveIsFirstLane",          OCC::WaveIsFirstLane,          "waveIsFirstLane",             true, false, false, false, false, false, false, false, false, Attribute::ReadOnly, },
-  {  OC::WaveGetLaneIndex,        "WaveGetLaneIndex",         OCC::WaveGetLaneIndex,         "waveGetLaneIndex",            true, false, false, false, false, false, false, false, false, Attribute::ReadOnly, },
-  {  OC::WaveGetLaneCount,        "WaveGetLaneCount",         OCC::WaveGetLaneCount,         "waveGetLaneCount",            true, false, false, false, false, false, false, false, false, Attribute::ReadOnly, },
-  {  OC::WaveAnyTrue,             "WaveAnyTrue",              OCC::WaveAnyTrue,              "waveAnyTrue",                 true, false, false, false, false, false, false, false, false, Attribute::ReadOnly, },
-  {  OC::WaveAllTrue,             "WaveAllTrue",              OCC::WaveAllTrue,              "waveAllTrue",                 true, false, false, false, false, false, false, false, false, Attribute::ReadOnly, },
-  {  OC::WaveActiveAllEqual,      "WaveActiveAllEqual",       OCC::WaveActiveAllEqual,       "waveActiveAllEqual",         false,  true,  true,  true,  true,  true,  true,  true,  true, Attribute::ReadOnly, },
-  {  OC::WaveActiveBallot,        "WaveActiveBallot",         OCC::WaveActiveBallot,         "waveActiveBallot",            true, false, false, false, false, false, false, false, false, Attribute::ReadOnly, },
-  {  OC::WaveReadLaneAt,          "WaveReadLaneAt",           OCC::WaveReadLaneAt,           "waveReadLaneAt",             false,  true,  true,  true,  true,  true,  true,  true,  true, Attribute::ReadOnly, },
-  {  OC::WaveReadLaneFirst,       "WaveReadLaneFirst",        OCC::WaveReadLaneFirst,        "waveReadLaneFirst",          false,  true,  true, false,  true,  true,  true,  true,  true, Attribute::ReadOnly, },
-  {  OC::WaveActiveOp,            "WaveActiveOp",             OCC::WaveActiveOp,             "waveActiveOp",               false,  true,  true,  true,  true,  true,  true,  true,  true, Attribute::ReadOnly, },
-  {  OC::WaveActiveBit,           "WaveActiveBit",            OCC::WaveActiveBit,            "waveActiveBit",              false, false, false, false, false,  true,  true,  true,  true, Attribute::ReadOnly, },
-  {  OC::WavePrefixOp,            "WavePrefixOp",             OCC::WavePrefixOp,             "wavePrefixOp",               false,  true,  true,  true, false,  true,  true,  true,  true, Attribute::ReadOnly, },
-  {  OC::QuadReadLaneAt,          "QuadReadLaneAt",           OCC::QuadReadLaneAt,           "quadReadLaneAt",             false,  true,  true,  true,  true,  true,  true,  true,  true, Attribute::ReadOnly, },
-  {  OC::QuadOp,                  "QuadOp",                   OCC::QuadOp,                   "quadOp",                     false,  true,  true,  true, false,  true,  true,  true,  true, Attribute::ReadOnly, },
+  {  OC::WaveIsFirstLane,         "WaveIsFirstLane",          OCC::WaveIsFirstLane,          "waveIsFirstLane",             true, false, false, false, false, false, false, false, false, Attribute::None,     },
+  {  OC::WaveGetLaneIndex,        "WaveGetLaneIndex",         OCC::WaveGetLaneIndex,         "waveGetLaneIndex",            true, false, false, false, false, false, false, false, false, Attribute::ReadNone, },
+  {  OC::WaveGetLaneCount,        "WaveGetLaneCount",         OCC::WaveGetLaneCount,         "waveGetLaneCount",            true, false, false, false, false, false, false, false, false, Attribute::ReadNone, },
+  {  OC::WaveAnyTrue,             "WaveAnyTrue",              OCC::WaveAnyTrue,              "waveAnyTrue",                 true, false, false, false, false, false, false, false, false, Attribute::None,     },
+  {  OC::WaveAllTrue,             "WaveAllTrue",              OCC::WaveAllTrue,              "waveAllTrue",                 true, false, false, false, false, false, false, false, false, Attribute::None,     },
+  {  OC::WaveActiveAllEqual,      "WaveActiveAllEqual",       OCC::WaveActiveAllEqual,       "waveActiveAllEqual",         false,  true,  true,  true,  true,  true,  true,  true,  true, Attribute::None,     },
+  {  OC::WaveActiveBallot,        "WaveActiveBallot",         OCC::WaveActiveBallot,         "waveActiveBallot",            true, false, false, false, false, false, false, false, false, Attribute::None,     },
+  {  OC::WaveReadLaneAt,          "WaveReadLaneAt",           OCC::WaveReadLaneAt,           "waveReadLaneAt",             false,  true,  true,  true,  true,  true,  true,  true,  true, Attribute::None,     },
+  {  OC::WaveReadLaneFirst,       "WaveReadLaneFirst",        OCC::WaveReadLaneFirst,        "waveReadLaneFirst",          false,  true,  true, false,  true,  true,  true,  true,  true, Attribute::None,     },
+  {  OC::WaveActiveOp,            "WaveActiveOp",             OCC::WaveActiveOp,             "waveActiveOp",               false,  true,  true,  true,  true,  true,  true,  true,  true, Attribute::None,     },
+  {  OC::WaveActiveBit,           "WaveActiveBit",            OCC::WaveActiveBit,            "waveActiveBit",              false, false, false, false, false,  true,  true,  true,  true, Attribute::None,     },
+  {  OC::WavePrefixOp,            "WavePrefixOp",             OCC::WavePrefixOp,             "wavePrefixOp",               false,  true,  true,  true, false,  true,  true,  true,  true, Attribute::None,     },
+  {  OC::QuadReadLaneAt,          "QuadReadLaneAt",           OCC::QuadReadLaneAt,           "quadReadLaneAt",             false,  true,  true,  true,  true,  true,  true,  true,  true, Attribute::None,     },
+  {  OC::QuadOp,                  "QuadOp",                   OCC::QuadOp,                   "quadOp",                     false,  true,  true,  true, false,  true,  true,  true,  true, Attribute::None,     },
 
 
   // Bitcasts with different sizes                                                                                          void,     h,     f,     d,    i1,    i8,   i16,   i32,   i64  function attribute
   // Bitcasts with different sizes                                                                                          void,     h,     f,     d,    i1,    i8,   i16,   i32,   i64  function attribute
   {  OC::BitcastI16toF16,         "BitcastI16toF16",          OCC::BitcastI16toF16,          "bitcastI16toF16",             true, false, false, false, false, false, false, false, false, Attribute::ReadNone, },
   {  OC::BitcastI16toF16,         "BitcastI16toF16",          OCC::BitcastI16toF16,          "bitcastI16toF16",             true, false, false, false, false, false, false, false, false, Attribute::ReadNone, },
@@ -236,8 +236,8 @@ const OP::OpCodeProperty OP::m_OpCodeProps[(unsigned)OP::OpCode::NumOpCodes] = {
   {  OC::LegacyDoubleToUInt32,    "LegacyDoubleToUInt32",     OCC::LegacyDoubleToUInt32,     "legacyDoubleToUInt32",        true, false, false, false, false, false, false, false, false, Attribute::ReadNone, },
   {  OC::LegacyDoubleToUInt32,    "LegacyDoubleToUInt32",     OCC::LegacyDoubleToUInt32,     "legacyDoubleToUInt32",        true, false, false, false, false, false, false, false, false, Attribute::ReadNone, },
 
 
   // Wave                                                                                                                   void,     h,     f,     d,    i1,    i8,   i16,   i32,   i64  function attribute
   // Wave                                                                                                                   void,     h,     f,     d,    i1,    i8,   i16,   i32,   i64  function attribute
-  {  OC::WaveAllBitCount,         "WaveAllBitCount",          OCC::WaveAllOp,                "waveAllOp",                   true, false, false, false, false, false, false, false, false, Attribute::ReadOnly, },
-  {  OC::WavePrefixBitCount,      "WavePrefixBitCount",       OCC::WavePrefixOp,             "wavePrefixOp",                true, false, false, false, false, false, false, false, false, Attribute::ReadOnly, },
+  {  OC::WaveAllBitCount,         "WaveAllBitCount",          OCC::WaveAllOp,                "waveAllOp",                   true, false, false, false, false, false, false, false, false, Attribute::None,     },
+  {  OC::WavePrefixBitCount,      "WavePrefixBitCount",       OCC::WavePrefixOp,             "wavePrefixOp",                true, false, false, false, false, false, false, false, false, Attribute::None,     },
 };
 };
 // OPCODE-OLOADS:END
 // OPCODE-OLOADS:END
 
 

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 386 - 320
lib/HLSL/DxilRootSignature.cpp


+ 514 - 53
lib/HLSL/DxilValidation.cpp

@@ -19,6 +19,8 @@
 #include "dxc/HLSL/HLModule.h"
 #include "dxc/HLSL/HLModule.h"
 #include "dxc/HLSL/DxilInstructions.h"
 #include "dxc/HLSL/DxilInstructions.h"
 #include "dxc/HLSL/ReducibilityAnalysis.h"
 #include "dxc/HLSL/ReducibilityAnalysis.h"
+#include "dxc/Support/WinIncludes.h"
+#include "dxc/Support/FileIOHelper.h"
 
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/Analysis/CallGraph.h"
 #include "llvm/Analysis/CallGraph.h"
@@ -32,14 +34,16 @@
 #include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/DiagnosticPrinter.h"
 #include "llvm/IR/DiagnosticPrinter.h"
 #include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/BitVector.h"
-#include <winerror.h>
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Bitcode/ReaderWriter.h"
 #include <unordered_set>
 #include <unordered_set>
 #include "llvm/Analysis/LoopInfo.h"
 #include "llvm/Analysis/LoopInfo.h"
 #include "llvm/IR/Dominators.h"
 #include "llvm/IR/Dominators.h"
 #include "llvm/Analysis/PostDominators.h"
 #include "llvm/Analysis/PostDominators.h"
 #include "dxc/HLSL/DxilSpanAllocator.h"
 #include "dxc/HLSL/DxilSpanAllocator.h"
 #include "dxc/HLSL/DxilSignatureAllocator.h"
 #include "dxc/HLSL/DxilSignatureAllocator.h"
+#include "dxc/HLSL/DxilRootSignature.h"
 #include <algorithm>
 #include <algorithm>
 
 
 
 
@@ -54,6 +58,11 @@ const char *hlsl::GetValidationRuleText(ValidationRule value) {
   // VALRULE-TEXT:BEGIN
   // VALRULE-TEXT:BEGIN
   switch(value) {
   switch(value) {
     case hlsl::ValidationRule::BitcodeValid: return "Module bitcode is invalid";
     case hlsl::ValidationRule::BitcodeValid: return "Module bitcode is invalid";
+    case hlsl::ValidationRule::ContainerPartMatches: return "Container part '%0' does not match expected for module.";
+    case hlsl::ValidationRule::ContainerPartRepeated: return "More than one container part '%0'.";
+    case hlsl::ValidationRule::ContainerPartMissing: return "Missing part '%0' required by module.";
+    case hlsl::ValidationRule::ContainerPartInvalid: return "Unknown part '%0' found in DXIL container.";
+    case hlsl::ValidationRule::ContainerRootSignatureIncompatible: return "Root Signature in DXIL container is not compatible with shader.";
     case hlsl::ValidationRule::MetaRequired: return "TODO - Required metadata missing";
     case hlsl::ValidationRule::MetaRequired: return "TODO - Required metadata missing";
     case hlsl::ValidationRule::MetaKnown: return "Named metadata '%0' is unknown";
     case hlsl::ValidationRule::MetaKnown: return "Named metadata '%0' is unknown";
     case hlsl::ValidationRule::MetaUsed: return "All metadata must be used by dxil";
     case hlsl::ValidationRule::MetaUsed: return "All metadata must be used by dxil";
@@ -196,7 +205,8 @@ const char *hlsl::GetValidationRuleText(ValidationRule value) {
     case hlsl::ValidationRule::SmGSOutputVertexCountRange: return "GS output vertex count must be [0..%0].  %1 specified";
     case hlsl::ValidationRule::SmGSOutputVertexCountRange: return "GS output vertex count must be [0..%0].  %1 specified";
     case hlsl::ValidationRule::SmGSInstanceCountRange: return "GS instance count must be [1..%0].  %1 specified";
     case hlsl::ValidationRule::SmGSInstanceCountRange: return "GS instance count must be [1..%0].  %1 specified";
     case hlsl::ValidationRule::SmDSInputControlPointCountRange: return "DS input control point count must be [0..%0].  %1 specified";
     case hlsl::ValidationRule::SmDSInputControlPointCountRange: return "DS input control point count must be [0..%0].  %1 specified";
-    case hlsl::ValidationRule::SmHSInputControlPointCountRange: return "HS input control point count must be [1..%0].  %1 specified";
+    case hlsl::ValidationRule::SmHSInputControlPointCountRange: return "HS input control point count must be [0..%0].  %1 specified";
+    case hlsl::ValidationRule::SmZeroHSInputControlPointWithInput: return "When HS input control point count is 0, no input signature should exist";
     case hlsl::ValidationRule::SmOutputControlPointCountRange: return "output control point count must be [0..%0].  %1 specified";
     case hlsl::ValidationRule::SmOutputControlPointCountRange: return "output control point count must be [0..%0].  %1 specified";
     case hlsl::ValidationRule::SmGSValidInputPrimitive: return "GS input primitive unrecognized";
     case hlsl::ValidationRule::SmGSValidInputPrimitive: return "GS input primitive unrecognized";
     case hlsl::ValidationRule::SmGSValidOutputPrimitiveTopology: return "GS output primitive topology unrecognized";
     case hlsl::ValidationRule::SmGSValidOutputPrimitiveTopology: return "GS output primitive topology unrecognized";
@@ -234,6 +244,57 @@ const char *hlsl::GetValidationRuleText(ValidationRule value) {
   return "<unknown>";
   return "<unknown>";
 }
 }
 
 
+namespace {
+
+class PrintDiagnosticContext {
+private:
+  DiagnosticPrinter &m_Printer;
+  bool m_errorsFound;
+  bool m_warningsFound;
+public:
+  PrintDiagnosticContext(DiagnosticPrinter &printer)
+      : m_Printer(printer), m_errorsFound(false), m_warningsFound(false) {}
+
+  bool HasErrors() const {
+    return m_errorsFound;
+  }
+  bool HasWarnings() const {
+    return m_warningsFound;
+  }
+  void Handle(const DiagnosticInfo &DI) {
+    DI.print(m_Printer);
+    switch (DI.getSeverity()) {
+    case llvm::DiagnosticSeverity::DS_Error:
+      m_errorsFound = true;
+      break;
+    case llvm::DiagnosticSeverity::DS_Warning:
+      m_warningsFound = true;
+      break;
+    }
+    m_Printer << "\n";
+  }
+};
+
+static void PrintDiagnosticHandler(const DiagnosticInfo &DI, void *Context) {
+  reinterpret_cast<PrintDiagnosticContext *>(Context)->Handle(DI);
+}
+
+// Utility class for setting and restoring the diagnostic context so we may capture errors/warnings
+struct DiagRestore {
+  LLVMContext &Ctx;
+  void *OrigDiagContext;
+  LLVMContext::DiagnosticHandlerTy OrigHandler;
+
+  DiagRestore(llvm::LLVMContext &Ctx, void *DiagContext) : Ctx(Ctx) {
+    OrigHandler = Ctx.getDiagnosticHandler();
+    OrigDiagContext = Ctx.getDiagnosticContext();
+    Ctx.setDiagnosticHandler(PrintDiagnosticHandler, DiagContext);
+  }
+  ~DiagRestore() {
+    Ctx.setDiagnosticHandler(OrigHandler, OrigDiagContext);
+  }
+};
+
 class DxilErrorDiagnosticInfo : public DiagnosticInfo {
 class DxilErrorDiagnosticInfo : public DiagnosticInfo {
 private:
 private:
   const char *m_message;
   const char *m_message;
@@ -262,6 +323,8 @@ static inline DiagnosticPrinter &operator<<(DiagnosticPrinter &OS, Type &T) {
   return OS;
   return OS;
 }
 }
 
 
+} // anon namespace
+
 namespace hlsl {
 namespace hlsl {
 
 
 struct PSExecutionInfo {
 struct PSExecutionInfo {
@@ -2558,26 +2621,30 @@ static void ValidateGlobalVariable(GlobalVariable &GV,
   }
   }
 }
 }
 
 
-static void
-CollectFixAddressAccess(Value *V, std::vector<Instruction *> &fixAddrTGSMList) {
+static void CollectFixAddressAccess(Value *V,
+                                    std::vector<StoreInst *> &fixAddrTGSMList) {
   for (User *U : V->users()) {
   for (User *U : V->users()) {
     if (GEPOperator *GEP = dyn_cast<GEPOperator>(U)) {
     if (GEPOperator *GEP = dyn_cast<GEPOperator>(U)) {
       if (isa<ConstantExpr>(GEP) || GEP->hasAllConstantIndices()) {
       if (isa<ConstantExpr>(GEP) || GEP->hasAllConstantIndices()) {
         CollectFixAddressAccess(GEP, fixAddrTGSMList);
         CollectFixAddressAccess(GEP, fixAddrTGSMList);
       }
       }
-    } else if (isa<StoreInst>(U)) {
-      fixAddrTGSMList.emplace_back(cast<Instruction>(U));
+    } else if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
+      fixAddrTGSMList.emplace_back(SI);
     }
     }
   }
   }
 }
 }
 
 
-static void
-ValidateTGSMRaceCondition(std::vector<Instruction *> &fixAddrTGSMList,
-                          ValidationContext &ValCtx) {
+static bool IsDivergent(Value *V) {
+  // TODO: return correct result.
+  return false;
+}
+
+static void ValidateTGSMRaceCondition(std::vector<StoreInst *> &fixAddrTGSMList,
+                                      ValidationContext &ValCtx) {
   std::unordered_set<Function *> fixAddrTGSMFuncSet;
   std::unordered_set<Function *> fixAddrTGSMFuncSet;
-  for (Instruction *I : fixAddrTGSMList) {
-	BasicBlock *BB = I->getParent();
-	fixAddrTGSMFuncSet.insert(BB->getParent());
+  for (StoreInst *I : fixAddrTGSMList) {
+    BasicBlock *BB = I->getParent();
+    fixAddrTGSMFuncSet.insert(BB->getParent());
   }
   }
 
 
   for (auto &F : ValCtx.DxilMod.GetModule()->functions()) {
   for (auto &F : ValCtx.DxilMod.GetModule()->functions()) {
@@ -2589,11 +2656,12 @@ ValidateTGSMRaceCondition(std::vector<Instruction *> &fixAddrTGSMList,
 
 
     BasicBlock *Entry = &F.getEntryBlock();
     BasicBlock *Entry = &F.getEntryBlock();
 
 
-    for (Instruction *I : fixAddrTGSMList) {
-      BasicBlock *BB = I->getParent();
+    for (StoreInst *SI : fixAddrTGSMList) {
+      BasicBlock *BB = SI->getParent();
       if (BB->getParent() == &F) {
       if (BB->getParent() == &F) {
         if (PDT.dominates(BB, Entry)) {
         if (PDT.dominates(BB, Entry)) {
-          ValCtx.EmitInstrError(I, ValidationRule::InstrTGSMRaceCond);
+          if (IsDivergent(SI->getValueOperand()))
+            ValCtx.EmitInstrError(SI, ValidationRule::InstrTGSMRaceCond);
         }
         }
       }
       }
     }
     }
@@ -2604,7 +2672,7 @@ static void ValidateGlobalVariables(ValidationContext &ValCtx) {
   DxilModule &M = ValCtx.DxilMod;
   DxilModule &M = ValCtx.DxilMod;
 
 
   unsigned TGSMSize = 0;
   unsigned TGSMSize = 0;
-  std::vector<Instruction*> fixAddrTGSMList;
+  std::vector<StoreInst*> fixAddrTGSMList;
   const DataLayout &DL = M.GetModule()->getDataLayout();
   const DataLayout &DL = M.GetModule()->getDataLayout();
   for (GlobalVariable &GV : M.GetModule()->globals()) {
   for (GlobalVariable &GV : M.GetModule()->globals()) {
     ValidateGlobalVariable(GV, ValCtx);
     ValidateGlobalVariable(GV, ValCtx);
@@ -2656,16 +2724,13 @@ static void ValidateMetadata(ValidationContext &ValCtx) {
     ValCtx.EmitFormatError(ValidationRule::MetaTarget, {target});
     ValCtx.EmitFormatError(ValidationRule::MetaTarget, {target});
   }
   }
 
 
+  // The llvm.dbg.(cu/contents/defines/mainFileName/arg) named metadata nodes
+  // are only available in debug modules, not in the validated ones.
+  // llvm.bitsets is also disallowed.
+  //
+  // These are verified in lib/IR/Verifier.cpp.
   StringMap<bool> llvmNamedMeta;
   StringMap<bool> llvmNamedMeta;
-  // These llvm named metadata is verified in lib/IR/Verifier.cpp.
-  llvmNamedMeta["llvm.dbg.cu"];
-  llvmNamedMeta["llvm.dbg.contents"];
-  llvmNamedMeta["llvm.dbg.defines"];
-  llvmNamedMeta["llvm.dbg.mainFileName"];
-  llvmNamedMeta["llvm.dbg.args"];
   llvmNamedMeta["llvm.ident"];
   llvmNamedMeta["llvm.ident"];
-  // Not for HLSL which does not have vtable.
-  // llvmNamedMeta["llvm.bitsets"];
   llvmNamedMeta["llvm.module.flags"];
   llvmNamedMeta["llvm.module.flags"];
 
 
   for (auto &NamedMetaNode : pModule->named_metadata()) {
   for (auto &NamedMetaNode : pModule->named_metadata()) {
@@ -3672,8 +3737,12 @@ static void ValidateShaderState(ValidationContext &ValCtx) {
     if (domain >= DXIL::TessellatorDomain::LastEntry)
     if (domain >= DXIL::TessellatorDomain::LastEntry)
       domain = DXIL::TessellatorDomain::Undefined;
       domain = DXIL::TessellatorDomain::Undefined;
     unsigned inputControlPointCount = M.GetInputControlPointCount();
     unsigned inputControlPointCount = M.GetInputControlPointCount();
-    if (inputControlPointCount < 1 ||
-        inputControlPointCount > DXIL::kMaxIAPatchControlPointCount) {
+    if (inputControlPointCount == 0) {
+      if (!M.GetInputSignature().GetElements().empty()) {
+        ValCtx.EmitError(
+            ValidationRule::SmZeroHSInputControlPointWithInput);
+      }
+    } else if (inputControlPointCount > DXIL::kMaxIAPatchControlPointCount) {
       ValCtx.EmitFormatError(
       ValCtx.EmitFormatError(
           ValidationRule::SmHSInputControlPointCountRange,
           ValidationRule::SmHSInputControlPointCountRange,
           {std::to_string(DXIL::kMaxIAPatchControlPointCount),
           {std::to_string(DXIL::kMaxIAPatchControlPointCount),
@@ -3910,33 +3979,15 @@ void GetValidationVersion(_Out_ unsigned *pMajor, _Out_ unsigned *pMinor) {
   *pMinor = 0;
   *pMinor = 0;
 }
 }
 
 
-_Use_decl_annotations_ std::error_code
+_Use_decl_annotations_ HRESULT
 ValidateDxilModule(llvm::Module *pModule, llvm::Module *pDebugModule) {
 ValidateDxilModule(llvm::Module *pModule, llvm::Module *pDebugModule) {
-  const LLVMContext &Ctx = pModule->getContext();
   std::string diagStr;
   std::string diagStr;
   raw_string_ostream diagStream(diagStr);
   raw_string_ostream diagStream(diagStr);
   DiagnosticPrinterRawOStream DiagPrinter(diagStream);
   DiagnosticPrinterRawOStream DiagPrinter(diagStream);
 
 
-  DxilModule *pDxilModule;
-  // TODO: add detail error in DxilMDHelper.
-  try {
-    pDxilModule = &pModule->GetOrCreateDxilModule();
-  } catch (const ::hlsl::Exception &hlslException) {
-    DiagPrinter << "load dxil metadata failed -";
-    try {
-      const char *msg = hlslException.what();
-      if (msg == nullptr || *msg == '\0')
-        DiagPrinter << " error code " << hlslException.hr << "\n";
-      else
-        DiagPrinter << msg;
-    } catch (...) {
-      DiagPrinter << " unable to retrieve error message.\n";
-    }
-    emitDxilDiag(Ctx, diagStr.c_str());
-    return std::error_code(ERROR_INVALID_DATA, std::system_category());
-  } catch (...) {
-    emitDxilDiag(Ctx, "load dxil metadata failed - unknown error.\n");
-    return std::error_code(ERROR_INVALID_DATA, std::system_category());
+  DxilModule *pDxilModule = DxilModule::TryGetDxilModule(pModule);
+  if (!pDxilModule) {
+    return DXC_E_IR_VERIFICATION_FAILED;
   }
   }
 
 
   ValidationContext ValCtx(*pModule, pDebugModule, *pDxilModule, DiagPrinter);
   ValidationContext ValCtx(*pModule, pDebugModule, *pDxilModule, DiagPrinter);
@@ -3982,13 +4033,423 @@ ValidateDxilModule(llvm::Module *pModule, llvm::Module *pDebugModule) {
 
 
   // Ensure error messages are flushed out on error.
   // Ensure error messages are flushed out on error.
   if (ValCtx.Failed) {
   if (ValCtx.Failed) {
-    diagStream.flush();
-    emitDxilDiag(Ctx, diagStr.c_str());
+    emitDxilDiag(pModule->getContext(), diagStream.str().c_str());
+    return DXC_E_IR_VERIFICATION_FAILED;
+  }
+  return S_OK;
+}
+
+// DXIL Container Verification Functions
+
+static void VerifyBlobPartMatches(_In_ ValidationContext &ValCtx,
+                                  _In_ LPCSTR pName,
+                                  DxilPartWriter *pWriter,
+                                  _In_reads_bytes_opt_(Size) const void *pData,
+                                  _In_ uint32_t Size) {
+  if (!pData && pWriter->size()) {
+    // No blob part, but writer says non-zero size is expected.
+    ValCtx.EmitFormatError(ValidationRule::ContainerPartMissing, pName);
+    return;
+  }
+
+  // Compare sizes
+  if (pWriter->size() != Size) {
+    ValCtx.EmitFormatError(ValidationRule::ContainerPartMatches, pName);
+    return;
+  }
+
+  if (Size == 0) {
+    return;
+  }
+
+  CComPtr<IMalloc> pMalloc;
+  IFT(CoGetMalloc(1, &pMalloc));
+  CComPtr<AbstractMemoryStream> pOutputStream;
+  IFT(CreateMemoryStream(pMalloc, &pOutputStream));
+  pOutputStream->Reserve(Size);
+
+  pWriter->write(pOutputStream);
+  DXASSERT(pOutputStream->GetPtrSize() == Size, "otherwise, DxilPartWriter misreported size");
+
+  if (memcmp(pData, pOutputStream->GetPtr(), Size)) {
+    ValCtx.EmitFormatError(ValidationRule::ContainerPartMatches, pName);
+    return;
+  }
+
+  return;
+}
+
+static void VerifySignatureMatches(_In_ ValidationContext &ValCtx,
+                                   DXIL::SignatureKind SigKind,
+                                   _In_reads_bytes_opt_(SigSize) const void *pSigData,
+                                   _In_ uint32_t SigSize) {
+  // Generate corresponding signature from module and memcmp
+
+  const char *pName = nullptr;
+  switch (SigKind)
+  {
+  case hlsl::DXIL::SignatureKind::Input:
+    pName = "Program Input Signature";
+    break;
+  case hlsl::DXIL::SignatureKind::Output:
+    pName = "Program Output Signature";
+    break;
+  case hlsl::DXIL::SignatureKind::PatchConstant:
+    pName = "Program Patch Constant Signature";
+    break;
+  }
+
+  unique_ptr<DxilPartWriter> pWriter(NewProgramSignatureWriter(ValCtx.DxilMod, SigKind));
+  VerifyBlobPartMatches(ValCtx, pName, pWriter.get(), pSigData, SigSize);
+}
+
+_Use_decl_annotations_
+bool VerifySignatureMatches(llvm::Module *pModule,
+                            DXIL::SignatureKind SigKind,
+                            const void *pSigData,
+                            uint32_t SigSize) {
+  std::string diagStr;
+  raw_string_ostream diagStream(diagStr);
+  DiagnosticPrinterRawOStream DiagPrinter(diagStream);
+  ValidationContext ValCtx(*pModule, nullptr, pModule->GetOrCreateDxilModule(), DiagPrinter);
+  VerifySignatureMatches(ValCtx, SigKind, pSigData, SigSize);
+  if (ValCtx.Failed) {
+    emitDxilDiag(pModule->getContext(), diagStream.str().c_str());
+  }
+  return !ValCtx.Failed;
+}
+
+static void VerifyPSVMatches(_In_ ValidationContext &ValCtx,
+                             _In_reads_bytes_(PSVSize) const void *pPSVData,
+                             _In_ uint32_t PSVSize) {
+  // generate PSV data from module and memcmp
+  unique_ptr<DxilPartWriter> pWriter(NewPSVWriter(ValCtx.DxilMod));
+  VerifyBlobPartMatches(ValCtx, "Pipeline State Validation", pWriter.get(), pPSVData, PSVSize);
+}
+
+_Use_decl_annotations_
+bool VerifyPSVMatches(llvm::Module *pModule,
+                      const void *pPSVData,
+                      uint32_t PSVSize) {
+  std::string diagStr;
+  raw_string_ostream diagStream(diagStr);
+  DiagnosticPrinterRawOStream DiagPrinter(diagStream);
+  ValidationContext ValCtx(*pModule, nullptr, pModule->GetOrCreateDxilModule(), DiagPrinter);
+  VerifyPSVMatches(ValCtx, pPSVData, PSVSize);
+  if (ValCtx.Failed) {
+    emitDxilDiag(pModule->getContext(), diagStream.str().c_str());
+  }
+  return !ValCtx.Failed;
+}
+
+static void VerifyFeatureInfoMatches(_In_ ValidationContext &ValCtx,
+                                     _In_reads_bytes_(FeatureInfoSize) const void *pFeatureInfoData,
+                                     _In_ uint32_t FeatureInfoSize) {
+  // generate Feature Info data from module and memcmp
+  unique_ptr<DxilPartWriter> pWriter(NewFeatureInfoWriter(ValCtx.DxilMod));
+  VerifyBlobPartMatches(ValCtx, "Feature Info", pWriter.get(), pFeatureInfoData, FeatureInfoSize);
+}
+
+_Use_decl_annotations_
+bool VerifyFeatureInfoMatches(llvm::Module *pModule,
+                              const void *pFeatureInfoData,
+                              uint32_t FeatureInfoSize) {
+  std::string diagStr;
+  raw_string_ostream diagStream(diagStr);
+  DiagnosticPrinterRawOStream DiagPrinter(diagStream);
+  ValidationContext ValCtx(*pModule, nullptr, pModule->GetOrCreateDxilModule(), DiagPrinter);
+  VerifyFeatureInfoMatches(ValCtx, pFeatureInfoData, FeatureInfoSize);
+  if (ValCtx.Failed) {
+    emitDxilDiag(pModule->getContext(), diagStream.str().c_str());
+  }
+  return !ValCtx.Failed;
+}
+
+_Use_decl_annotations_
+HRESULT ValidateDxilContainerParts(llvm::Module *pModule,
+                                   llvm::Module *pDebugModule,
+                                   const DxilContainerHeader *pContainer,
+                                   uint32_t ContainerSize) {
+
+  DXASSERT_NOMSG(pModule);
+  if (!pContainer || !IsValidDxilContainer(pContainer, ContainerSize)) {
+    return DXC_E_CONTAINER_INVALID;
+  }
+
+  DxilModule *pDxilModule = DxilModule::TryGetDxilModule(pModule);
+  if (!pDxilModule) {
+    return DXC_E_IR_VERIFICATION_FAILED;
+  }
+
+  std::string diagStr;
+  raw_string_ostream DiagStream(diagStr);
+  DiagnosticPrinterRawOStream DiagPrinter(DiagStream);
+  ValidationContext ValCtx(*pModule, pDebugModule, *pDxilModule, DiagPrinter);
+
+  DXIL::ShaderKind ShaderKind = pDxilModule->GetShaderModel()->GetKind();
+  bool bTess = ShaderKind == DXIL::ShaderKind::Hull || ShaderKind == DXIL::ShaderKind::Domain;
+
+  std::unordered_set<uint32_t> FourCCFound;
+  const DxilPartHeader *pRootSignaturePart = nullptr;
+  const DxilPartHeader *pPSVPart = nullptr;
+
+  for (auto it = begin(pContainer), itEnd = end(pContainer); it != itEnd; ++it) {
+    const DxilPartHeader *pPart = *it;
+
+    char szFourCC[5];
+    PartKindToCharArray(pPart->PartFourCC, szFourCC);
+    if (FourCCFound.find(pPart->PartFourCC) != FourCCFound.end()) {
+      // Two parts with same FourCC found
+      ValCtx.EmitFormatError(ValidationRule::ContainerPartRepeated, szFourCC);
+      continue;
+    }
+    FourCCFound.insert(pPart->PartFourCC);
+
+    switch (pPart->PartFourCC)
+    {
+    case DFCC_InputSignature:
+      VerifySignatureMatches(ValCtx, DXIL::SignatureKind::Input, GetDxilPartData(pPart), pPart->PartSize);
+      break;
+    case DFCC_OutputSignature:
+      VerifySignatureMatches(ValCtx, DXIL::SignatureKind::Output, GetDxilPartData(pPart), pPart->PartSize);
+      break;
+    case DFCC_PatchConstantSignature:
+      if (bTess) {
+        VerifySignatureMatches(ValCtx, DXIL::SignatureKind::PatchConstant, GetDxilPartData(pPart), pPart->PartSize);
+      } else {
+        ValCtx.EmitFormatError(ValidationRule::ContainerPartMatches, "Program Patch Constant Signature");
+      }
+      break;
+    case DFCC_FeatureInfo:
+      VerifyFeatureInfoMatches(ValCtx, GetDxilPartData(pPart), pPart->PartSize);
+      break;
+    case DFCC_RootSignature:
+      pRootSignaturePart = pPart;
+      break;
+    case DFCC_PipelineStateValidation:
+      pPSVPart = pPart;
+      VerifyPSVMatches(ValCtx, GetDxilPartData(pPart), pPart->PartSize);
+      break;
+
+    // Skip these
+    case DFCC_ResourceDef:
+    case DFCC_ShaderStatistics:
+    case DFCC_PrivateData:
+    case DFCC_DXIL:
+    case DFCC_ShaderDebugInfoDXIL:
+      continue;
+
+    case DFCC_Container:
+    default:
+      ValCtx.EmitFormatError(ValidationRule::ContainerPartInvalid, szFourCC);
+      break;
+    }
+  }
+
+  // Verify required parts found
+  if (FourCCFound.find(DFCC_InputSignature) == FourCCFound.end()) {
+    VerifySignatureMatches(ValCtx, DXIL::SignatureKind::Input, nullptr, 0);
+  }
+  if (FourCCFound.find(DFCC_OutputSignature) == FourCCFound.end()) {
+    VerifySignatureMatches(ValCtx, DXIL::SignatureKind::Output, nullptr, 0);
+  }
+  if (bTess && FourCCFound.find(DFCC_PatchConstantSignature) == FourCCFound.end() &&
+      pDxilModule->GetPatchConstantSignature().GetElements().size())
+  {
+    ValCtx.EmitFormatError(ValidationRule::ContainerPartMissing, "Program Patch Constant Signature");
+  }
+  if (FourCCFound.find(DFCC_FeatureInfo) == FourCCFound.end()) {
+    // Could be optional, but RS1 runtime doesn't handle this case properly.
+    ValCtx.EmitFormatError(ValidationRule::ContainerPartMissing, "Feature Info");
+  }
+
+  // Validate Root Signature
+  if (pPSVPart) {
+    if (pRootSignaturePart) {
+      try {
+        RootSignatureHandle RS;
+        RS.LoadSerialized((const uint8_t*)GetDxilPartData(pRootSignaturePart), pRootSignaturePart->PartSize);
+        RS.Deserialize();
+        IFTBOOL(VerifyRootSignatureWithShaderPSV(RS.GetDesc(),
+                                                  pDxilModule->GetShaderModel()->GetKind(),
+                                                  GetDxilPartData(pPSVPart), pPSVPart->PartSize,
+                                                  DiagStream), DXC_E_INCORRECT_ROOT_SIGNATURE);
+      } catch (...) {
+        ValCtx.EmitError(ValidationRule::ContainerRootSignatureIncompatible);
+      }
+    }
+  } else {
+    ValCtx.EmitFormatError(ValidationRule::ContainerPartMissing, "Pipeline State Validation");
+  }
+
+  if (ValCtx.Failed) {
+    emitDxilDiag(pModule->getContext(), DiagStream.str().c_str());
+    return DXC_E_MALFORMED_CONTAINER;
+  }
+  return S_OK;
+}
+
+static HRESULT FindDxilPart(_In_reads_bytes_(ContainerSize) const void *pContainerBytes,
+                            _In_ uint32_t ContainerSize,
+                            _In_ DxilFourCC FourCC,
+                            _In_ const DxilPartHeader **ppPart) {
+
+  const DxilContainerHeader *pContainer =
+    IsDxilContainerLike(pContainerBytes, ContainerSize);
+
+  if (!pContainer) {
+    IFR(DXC_E_CONTAINER_INVALID);
+  }
+  if (!IsValidDxilContainer(pContainer, ContainerSize)) {
+    IFR(DXC_E_CONTAINER_INVALID);
+  }
+
+  DxilPartIterator it = std::find_if(begin(pContainer), end(pContainer),
+    DxilPartIsType(FourCC));
+  if (it == end(pContainer)) {
+    IFR(DXC_E_CONTAINER_MISSING_DXIL);
+  }
+
+  const DxilProgramHeader *pProgramHeader =
+    reinterpret_cast<const DxilProgramHeader *>(GetDxilPartData(*it));
+  if (!IsValidDxilProgramHeader(pProgramHeader, (*it)->PartSize)) {
+    IFR(DXC_E_CONTAINER_INVALID);
+  }
+
+  *ppPart = *it;
+  return S_OK;
+}
+
+_Use_decl_annotations_
+HRESULT ValidateLoadModule(const char *pIL,
+                           uint32_t ILLength,
+                           unique_ptr<llvm::Module> &pModule,
+                           LLVMContext &Ctx,
+                           llvm::raw_ostream &DiagStream) {
+
+  llvm::DiagnosticPrinterRawOStream DiagPrinter(DiagStream);
+  PrintDiagnosticContext DiagContext(DiagPrinter);
+  DiagRestore DR(Ctx, &DiagContext);
+
+  std::unique_ptr<llvm::MemoryBuffer> pBitcodeBuf;
+  pBitcodeBuf.reset(llvm::MemoryBuffer::getMemBuffer(
+      llvm::StringRef(pIL, ILLength), "", false).release());
+  ErrorOr<std::unique_ptr<llvm::Module>> loadedModuleResult(llvm::parseBitcodeFile(
+    pBitcodeBuf->getMemBufferRef(), Ctx));
+
+  // DXIL disallows some LLVM bitcode constructs, like unaccounted-for sub-blocks.
+  // These appear as warnings, which the validator should reject.
+  if (DiagContext.HasErrors() || DiagContext.HasWarnings() || loadedModuleResult.getError())
+    return DXC_E_IR_VERIFICATION_FAILED;
+
+  pModule = std::move(loadedModuleResult.get());
+  return S_OK;
+}
+
+HRESULT ValidateDxilBitcode(
+  _In_reads_bytes_(ILLength) const char *pIL,
+  _In_ uint32_t ILLength,
+  _In_ llvm::raw_ostream &DiagStream) {
+
+  LLVMContext Ctx;
+  std::unique_ptr<llvm::Module> pModule;
+
+  llvm::DiagnosticPrinterRawOStream DiagPrinter(DiagStream);
+  PrintDiagnosticContext DiagContext(DiagPrinter);
+  Ctx.setDiagnosticHandler(PrintDiagnosticHandler, &DiagContext, true);
+
+  HRESULT hr;
+  if (FAILED(hr = ValidateLoadModule(pIL, ILLength, pModule, Ctx, DiagStream)))
+    return hr;
+
+  if (FAILED(hr = ValidateDxilModule(pModule.get(), nullptr)))
+    return hr;
+
+  DxilModule &dxilModule = pModule->GetDxilModule();
+  if (!dxilModule.GetRootSignature().IsEmpty()) {
+    unique_ptr<DxilPartWriter> pWriter(NewPSVWriter(dxilModule));
+    DXASSERT_NOMSG(pWriter->size());
+    CComPtr<IMalloc> pMalloc;
+    IFT(CoGetMalloc(1, &pMalloc));
+    CComPtr<AbstractMemoryStream> pOutputStream;
+    IFT(CreateMemoryStream(pMalloc, &pOutputStream));
+    pOutputStream->Reserve(pWriter->size());
+    pWriter->write(pOutputStream);
+    const DxilVersionedRootSignatureDesc* pDesc = dxilModule.GetRootSignature().GetDesc();
+    RootSignatureHandle RS;
+    try {
+      if (!pDesc) {
+        RS.Assign(nullptr, dxilModule.GetRootSignature().GetSerialized());
+        RS.Deserialize();
+        pDesc = RS.GetDesc();
+        if (!pDesc)
+          return DXC_E_INCORRECT_ROOT_SIGNATURE;
+      }
+      IFTBOOL(VerifyRootSignatureWithShaderPSV(pDesc,
+                                               dxilModule.GetShaderModel()->GetKind(),
+                                               pOutputStream->GetPtr(), pWriter->size(),
+                                               DiagStream), DXC_E_INCORRECT_ROOT_SIGNATURE);
+    } catch (...) {
+      return DXC_E_INCORRECT_ROOT_SIGNATURE;
+    }
+  }
+
+  if (DiagContext.HasErrors() || DiagContext.HasWarnings()) {
+    return DXC_E_IR_VERIFICATION_FAILED;
+  }
+
+  return S_OK;
+}
+
+_Use_decl_annotations_
+HRESULT ValidateDxilContainer(const void *pContainer,
+                              uint32_t ContainerSize,
+                              llvm::raw_ostream &DiagStream) {
+
+  LLVMContext Ctx, DbgCtx;
+  std::unique_ptr<llvm::Module> pModule, pDebugModule;
+
+  llvm::DiagnosticPrinterRawOStream DiagPrinter(DiagStream);
+  PrintDiagnosticContext DiagContext(DiagPrinter);
+  Ctx.setDiagnosticHandler(PrintDiagnosticHandler, &DiagContext, true);
+  DbgCtx.setDiagnosticHandler(PrintDiagnosticHandler, &DiagContext, true);
+
+  HRESULT hr;
+  const DxilPartHeader *pPart = nullptr;
+  IFR(FindDxilPart(pContainer, ContainerSize, DFCC_DXIL, &pPart));
+
+  const char *pIL = nullptr;
+  uint32_t ILLength = 0;
+  GetDxilProgramBitcode(
+    reinterpret_cast<const DxilProgramHeader *>(GetDxilPartData(pPart)),
+    &pIL, &ILLength);
+
+  IFR(ValidateLoadModule(pIL, ILLength, pModule, Ctx, DiagStream));
+
+  const DxilPartHeader *pDbgPart = nullptr;
+  if (FAILED(hr = FindDxilPart(pContainer, ContainerSize, DFCC_ShaderDebugInfoDXIL, &pDbgPart)) &&
+      hr != DXC_E_CONTAINER_MISSING_DXIL) {
+    return hr;
+  }
+
+  if (pDbgPart) {
+    GetDxilProgramBitcode(
+      reinterpret_cast<const DxilProgramHeader *>(GetDxilPartData(pDbgPart)),
+      &pIL, &ILLength);
+    if (FAILED(hr = ValidateLoadModule(pIL, ILLength, pDebugModule, DbgCtx, DiagStream))) {
+      return hr;
+    }
+  }
+
+  // Validate DXIL Module
+  IFR(ValidateDxilModule(pModule.get(), pDebugModule.get()));
+
+  if (DiagContext.HasErrors() || DiagContext.HasWarnings()) {
+    return DXC_E_IR_VERIFICATION_FAILED;
   }
   }
 
 
-  if (ValCtx.Failed)
-    return std::error_code(ERROR_INVALID_DATA, std::system_category());
-  return std::error_code();
+  return ValidateDxilContainerParts(pModule.get(), pDebugModule.get(),
+    IsDxilContainerLike(pContainer, ContainerSize), ContainerSize);
 }
 }
 
 
 } // namespace hlsl
 } // namespace hlsl

+ 9 - 25
lib/HLSL/HLModule.cpp

@@ -467,6 +467,10 @@ void HLModule::EmitHLMetadata() {
     NamedMDNode * resTyAnnotations = m_pModule->getOrInsertNamedMetadata(kHLDxilResourceTypeAnnotationMDName);
     NamedMDNode * resTyAnnotations = m_pModule->getOrInsertNamedMetadata(kHLDxilResourceTypeAnnotationMDName);
     resTyAnnotations->addOperand(EmitResTyAnnotations());
     resTyAnnotations->addOperand(EmitResTyAnnotations());
   }
   }
+
+  if (!m_RootSignature->IsEmpty()) {
+    m_pMDHelper->EmitRootSignature(*m_RootSignature.get());
+  }
 }
 }
 
 
 void HLModule::LoadHLMetadata() {
 void HLModule::LoadHLMetadata() {
@@ -541,6 +545,8 @@ void HLModule::LoadHLMetadata() {
     if (MDResTyAnnotations->getNumOperands())
     if (MDResTyAnnotations->getNumOperands())
       LoadResTyAnnotations(MDResTyAnnotations->getOperand(0));
       LoadResTyAnnotations(MDResTyAnnotations->getOperand(0));
   }
   }
+
+  m_pMDHelper->LoadRootSignature(*m_RootSignature.get());
 }
 }
 
 
 void HLModule::ClearHLMetadata(llvm::Module &M) {
 void HLModule::ClearHLMetadata(llvm::Module &M) {
@@ -553,6 +559,7 @@ void HLModule::ClearHLMetadata(llvm::Module &M) {
     if (name == DxilMDHelper::kDxilVersionMDName ||
     if (name == DxilMDHelper::kDxilVersionMDName ||
         name == DxilMDHelper::kDxilShaderModelMDName ||
         name == DxilMDHelper::kDxilShaderModelMDName ||
         name == DxilMDHelper::kDxilEntryPointsMDName ||
         name == DxilMDHelper::kDxilEntryPointsMDName ||
+        name == DxilMDHelper::kDxilRootSignatureMDName ||
         name == DxilMDHelper::kDxilResourcesMDName ||
         name == DxilMDHelper::kDxilResourcesMDName ||
         name == DxilMDHelper::kDxilTypeSystemMDName ||
         name == DxilMDHelper::kDxilTypeSystemMDName ||
         name == kHLDxilFunctionPropertiesMDName || // TODO: adjust to proper name
         name == kHLDxilFunctionPropertiesMDName || // TODO: adjust to proper name
@@ -691,34 +698,11 @@ void HLModule::LoadResTyAnnotations(const llvm::MDOperand &MDO) {
 }
 }
 
 
 MDTuple *HLModule::EmitHLShaderProperties() {
 MDTuple *HLModule::EmitHLShaderProperties() {
-  vector<Metadata *> MDVals;
-  if (!m_RootSignature->IsEmpty()) {
-    MDVals.emplace_back(m_pMDHelper->Uint32ToConstMD(DxilMDHelper::kDxilRootSignatureTag));
-    MDVals.emplace_back(m_pMDHelper->EmitRootSignature(*m_RootSignature.get()));
-  }
-  return MDNode::get(m_Ctx, MDVals);
+  return nullptr;
 }
 }
 
 
 void HLModule::LoadHLShaderProperties(const MDOperand &MDO) {
 void HLModule::LoadHLShaderProperties(const MDOperand &MDO) {
-  if (MDO.get() == nullptr)
-    return;
-
-  const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
-  IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
-  IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0, DXC_E_INCORRECT_DXIL_METADATA);
-  for (unsigned iNode = 0; iNode < pTupleMD->getNumOperands(); iNode += 2) {
-    unsigned Tag = DxilMDHelper::ConstMDToUint32(pTupleMD->getOperand(iNode));
-    const MDOperand &MDO = pTupleMD->getOperand(iNode + 1);
-    IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
-    switch (Tag) {
-    case DxilMDHelper::kDxilRootSignatureTag:
-      m_pMDHelper->LoadRootSignature(MDO, *m_RootSignature.get());
-      break;
-    default:
-      // Ignore other extended properties for now.
-      break;
-    }
-  }
+  return;
 }
 }
 
 
 // TODO: Don't check names.
 // TODO: Don't check names.

+ 34 - 34
tools/clang/lib/Sema/gen_intrin_main_tables_15.h

@@ -1246,8 +1246,8 @@ static const HLSL_INTRINSIC g_Intrinsics[] =
     (UINT)hlsl::IntrinsicOp::IOP_EvaluateAttributeAtSample, false, true, -1, 3, g_Intrinsics_Args7,
     (UINT)hlsl::IntrinsicOp::IOP_EvaluateAttributeAtSample, false, true, -1, 3, g_Intrinsics_Args7,
     (UINT)hlsl::IntrinsicOp::IOP_EvaluateAttributeCentroid, false, true, -1, 2, g_Intrinsics_Args8,
     (UINT)hlsl::IntrinsicOp::IOP_EvaluateAttributeCentroid, false, true, -1, 2, g_Intrinsics_Args8,
     (UINT)hlsl::IntrinsicOp::IOP_EvaluateAttributeSnapped, false, true, -1, 3, g_Intrinsics_Args9,
     (UINT)hlsl::IntrinsicOp::IOP_EvaluateAttributeSnapped, false, true, -1, 3, g_Intrinsics_Args9,
-    (UINT)hlsl::IntrinsicOp::IOP_GetRenderTargetSampleCount, false, false, -1, 1, g_Intrinsics_Args10,
-    (UINT)hlsl::IntrinsicOp::IOP_GetRenderTargetSamplePosition, false, false, -1, 2, g_Intrinsics_Args11,
+    (UINT)hlsl::IntrinsicOp::IOP_GetRenderTargetSampleCount, false, true, -1, 1, g_Intrinsics_Args10,
+    (UINT)hlsl::IntrinsicOp::IOP_GetRenderTargetSamplePosition, false, true, -1, 2, g_Intrinsics_Args11,
     (UINT)hlsl::IntrinsicOp::IOP_GroupMemoryBarrier, false, false, -1, 1, g_Intrinsics_Args12,
     (UINT)hlsl::IntrinsicOp::IOP_GroupMemoryBarrier, false, false, -1, 1, g_Intrinsics_Args12,
     (UINT)hlsl::IntrinsicOp::IOP_GroupMemoryBarrierWithGroupSync, false, false, -1, 1, g_Intrinsics_Args13,
     (UINT)hlsl::IntrinsicOp::IOP_GroupMemoryBarrierWithGroupSync, false, false, -1, 1, g_Intrinsics_Args13,
     (UINT)hlsl::IntrinsicOp::IOP_InterlockedAdd, false, false, -1, 3, g_Intrinsics_Args14,
     (UINT)hlsl::IntrinsicOp::IOP_InterlockedAdd, false, false, -1, 3, g_Intrinsics_Args14,
@@ -1266,40 +1266,40 @@ static const HLSL_INTRINSIC g_Intrinsics[] =
     (UINT)hlsl::IntrinsicOp::IOP_InterlockedXor, false, false, -1, 3, g_Intrinsics_Args27,
     (UINT)hlsl::IntrinsicOp::IOP_InterlockedXor, false, false, -1, 3, g_Intrinsics_Args27,
     (UINT)hlsl::IntrinsicOp::IOP_InterlockedXor, false, false, -1, 4, g_Intrinsics_Args28,
     (UINT)hlsl::IntrinsicOp::IOP_InterlockedXor, false, false, -1, 4, g_Intrinsics_Args28,
     (UINT)hlsl::IntrinsicOp::IOP_NonUniformResourceIndex, false, true, -1, 2, g_Intrinsics_Args29,
     (UINT)hlsl::IntrinsicOp::IOP_NonUniformResourceIndex, false, true, -1, 2, g_Intrinsics_Args29,
-    (UINT)hlsl::IntrinsicOp::IOP_Process2DQuadTessFactorsAvg, false, false, -1, 6, g_Intrinsics_Args30,
-    (UINT)hlsl::IntrinsicOp::IOP_Process2DQuadTessFactorsMax, false, false, -1, 6, g_Intrinsics_Args31,
-    (UINT)hlsl::IntrinsicOp::IOP_Process2DQuadTessFactorsMin, false, false, -1, 6, g_Intrinsics_Args32,
-    (UINT)hlsl::IntrinsicOp::IOP_ProcessIsolineTessFactors, false, false, -1, 5, g_Intrinsics_Args33,
-    (UINT)hlsl::IntrinsicOp::IOP_ProcessQuadTessFactorsAvg, false, false, -1, 6, g_Intrinsics_Args34,
-    (UINT)hlsl::IntrinsicOp::IOP_ProcessQuadTessFactorsMax, false, false, -1, 6, g_Intrinsics_Args35,
-    (UINT)hlsl::IntrinsicOp::IOP_ProcessQuadTessFactorsMin, false, false, -1, 6, g_Intrinsics_Args36,
-    (UINT)hlsl::IntrinsicOp::IOP_ProcessTriTessFactorsAvg, false, false, -1, 6, g_Intrinsics_Args37,
-    (UINT)hlsl::IntrinsicOp::IOP_ProcessTriTessFactorsMax, false, false, -1, 6, g_Intrinsics_Args38,
-    (UINT)hlsl::IntrinsicOp::IOP_ProcessTriTessFactorsMin, false, false, -1, 6, g_Intrinsics_Args39,
-    (UINT)hlsl::IntrinsicOp::IOP_QuadReadAcrossDiagonal, false, true, -1, 2, g_Intrinsics_Args40,
-    (UINT)hlsl::IntrinsicOp::IOP_QuadReadAcrossX, false, true, -1, 2, g_Intrinsics_Args41,
-    (UINT)hlsl::IntrinsicOp::IOP_QuadReadAcrossY, false, true, -1, 2, g_Intrinsics_Args42,
-    (UINT)hlsl::IntrinsicOp::IOP_QuadReadLaneAt, false, true, -1, 3, g_Intrinsics_Args43,
-    (UINT)hlsl::IntrinsicOp::IOP_WaveActiveAllEqual, false, true, -1, 2, g_Intrinsics_Args44,
-    (UINT)hlsl::IntrinsicOp::IOP_WaveActiveAllTrue, false, true, -1, 2, g_Intrinsics_Args45,
-    (UINT)hlsl::IntrinsicOp::IOP_WaveActiveAnyTrue, false, true, -1, 2, g_Intrinsics_Args46,
-    (UINT)hlsl::IntrinsicOp::IOP_WaveActiveBallot, false, true, -1, 2, g_Intrinsics_Args47,
-    (UINT)hlsl::IntrinsicOp::IOP_WaveActiveBitAnd, false, true, -1, 2, g_Intrinsics_Args48,
-    (UINT)hlsl::IntrinsicOp::IOP_WaveActiveBitOr, false, true, -1, 2, g_Intrinsics_Args49,
-    (UINT)hlsl::IntrinsicOp::IOP_WaveActiveBitXor, false, true, -1, 2, g_Intrinsics_Args50,
-    (UINT)hlsl::IntrinsicOp::IOP_WaveActiveCountBits, false, true, -1, 2, g_Intrinsics_Args51,
-    (UINT)hlsl::IntrinsicOp::IOP_WaveActiveMax, false, true, -1, 2, g_Intrinsics_Args52,
-    (UINT)hlsl::IntrinsicOp::IOP_WaveActiveMin, false, true, -1, 2, g_Intrinsics_Args53,
-    (UINT)hlsl::IntrinsicOp::IOP_WaveActiveProduct, false, true, -1, 2, g_Intrinsics_Args54,
-    (UINT)hlsl::IntrinsicOp::IOP_WaveActiveSum, false, true, -1, 2, g_Intrinsics_Args55,
+    (UINT)hlsl::IntrinsicOp::IOP_Process2DQuadTessFactorsAvg, false, true, -1, 6, g_Intrinsics_Args30,
+    (UINT)hlsl::IntrinsicOp::IOP_Process2DQuadTessFactorsMax, false, true, -1, 6, g_Intrinsics_Args31,
+    (UINT)hlsl::IntrinsicOp::IOP_Process2DQuadTessFactorsMin, false, true, -1, 6, g_Intrinsics_Args32,
+    (UINT)hlsl::IntrinsicOp::IOP_ProcessIsolineTessFactors, false, true, -1, 5, g_Intrinsics_Args33,
+    (UINT)hlsl::IntrinsicOp::IOP_ProcessQuadTessFactorsAvg, false, true, -1, 6, g_Intrinsics_Args34,
+    (UINT)hlsl::IntrinsicOp::IOP_ProcessQuadTessFactorsMax, false, true, -1, 6, g_Intrinsics_Args35,
+    (UINT)hlsl::IntrinsicOp::IOP_ProcessQuadTessFactorsMin, false, true, -1, 6, g_Intrinsics_Args36,
+    (UINT)hlsl::IntrinsicOp::IOP_ProcessTriTessFactorsAvg, false, true, -1, 6, g_Intrinsics_Args37,
+    (UINT)hlsl::IntrinsicOp::IOP_ProcessTriTessFactorsMax, false, true, -1, 6, g_Intrinsics_Args38,
+    (UINT)hlsl::IntrinsicOp::IOP_ProcessTriTessFactorsMin, false, true, -1, 6, g_Intrinsics_Args39,
+    (UINT)hlsl::IntrinsicOp::IOP_QuadReadAcrossDiagonal, false, false, -1, 2, g_Intrinsics_Args40,
+    (UINT)hlsl::IntrinsicOp::IOP_QuadReadAcrossX, false, false, -1, 2, g_Intrinsics_Args41,
+    (UINT)hlsl::IntrinsicOp::IOP_QuadReadAcrossY, false, false, -1, 2, g_Intrinsics_Args42,
+    (UINT)hlsl::IntrinsicOp::IOP_QuadReadLaneAt, false, false, -1, 3, g_Intrinsics_Args43,
+    (UINT)hlsl::IntrinsicOp::IOP_WaveActiveAllEqual, false, false, -1, 2, g_Intrinsics_Args44,
+    (UINT)hlsl::IntrinsicOp::IOP_WaveActiveAllTrue, false, false, -1, 2, g_Intrinsics_Args45,
+    (UINT)hlsl::IntrinsicOp::IOP_WaveActiveAnyTrue, false, false, -1, 2, g_Intrinsics_Args46,
+    (UINT)hlsl::IntrinsicOp::IOP_WaveActiveBallot, false, false, -1, 2, g_Intrinsics_Args47,
+    (UINT)hlsl::IntrinsicOp::IOP_WaveActiveBitAnd, false, false, -1, 2, g_Intrinsics_Args48,
+    (UINT)hlsl::IntrinsicOp::IOP_WaveActiveBitOr, false, false, -1, 2, g_Intrinsics_Args49,
+    (UINT)hlsl::IntrinsicOp::IOP_WaveActiveBitXor, false, false, -1, 2, g_Intrinsics_Args50,
+    (UINT)hlsl::IntrinsicOp::IOP_WaveActiveCountBits, false, false, -1, 2, g_Intrinsics_Args51,
+    (UINT)hlsl::IntrinsicOp::IOP_WaveActiveMax, false, false, -1, 2, g_Intrinsics_Args52,
+    (UINT)hlsl::IntrinsicOp::IOP_WaveActiveMin, false, false, -1, 2, g_Intrinsics_Args53,
+    (UINT)hlsl::IntrinsicOp::IOP_WaveActiveProduct, false, false, -1, 2, g_Intrinsics_Args54,
+    (UINT)hlsl::IntrinsicOp::IOP_WaveActiveSum, false, false, -1, 2, g_Intrinsics_Args55,
     (UINT)hlsl::IntrinsicOp::IOP_WaveGetLaneCount, false, true, -1, 1, g_Intrinsics_Args56,
     (UINT)hlsl::IntrinsicOp::IOP_WaveGetLaneCount, false, true, -1, 1, g_Intrinsics_Args56,
     (UINT)hlsl::IntrinsicOp::IOP_WaveGetLaneIndex, false, true, -1, 1, g_Intrinsics_Args57,
     (UINT)hlsl::IntrinsicOp::IOP_WaveGetLaneIndex, false, true, -1, 1, g_Intrinsics_Args57,
-    (UINT)hlsl::IntrinsicOp::IOP_WaveIsFirstLane, false, true, -1, 1, g_Intrinsics_Args58,
-    (UINT)hlsl::IntrinsicOp::IOP_WavePrefixCountBits, false, true, -1, 2, g_Intrinsics_Args59,
-    (UINT)hlsl::IntrinsicOp::IOP_WavePrefixProduct, false, true, -1, 2, g_Intrinsics_Args60,
-    (UINT)hlsl::IntrinsicOp::IOP_WavePrefixSum, false, true, -1, 2, g_Intrinsics_Args61,
-    (UINT)hlsl::IntrinsicOp::IOP_WaveReadLaneAt, false, true, -1, 3, g_Intrinsics_Args62,
-    (UINT)hlsl::IntrinsicOp::IOP_WaveReadLaneFirst, false, true, -1, 2, g_Intrinsics_Args63,
+    (UINT)hlsl::IntrinsicOp::IOP_WaveIsFirstLane, false, false, -1, 1, g_Intrinsics_Args58,
+    (UINT)hlsl::IntrinsicOp::IOP_WavePrefixCountBits, false, false, -1, 2, g_Intrinsics_Args59,
+    (UINT)hlsl::IntrinsicOp::IOP_WavePrefixProduct, false, false, -1, 2, g_Intrinsics_Args60,
+    (UINT)hlsl::IntrinsicOp::IOP_WavePrefixSum, false, false, -1, 2, g_Intrinsics_Args61,
+    (UINT)hlsl::IntrinsicOp::IOP_WaveReadLaneAt, false, false, -1, 3, g_Intrinsics_Args62,
+    (UINT)hlsl::IntrinsicOp::IOP_WaveReadLaneFirst, false, false, -1, 2, g_Intrinsics_Args63,
     (UINT)hlsl::IntrinsicOp::IOP_abort, false, false, -1, 1, g_Intrinsics_Args64,
     (UINT)hlsl::IntrinsicOp::IOP_abort, false, false, -1, 1, g_Intrinsics_Args64,
     (UINT)hlsl::IntrinsicOp::IOP_abs, false, true, -1, 2, g_Intrinsics_Args65,
     (UINT)hlsl::IntrinsicOp::IOP_abs, false, true, -1, 2, g_Intrinsics_Args65,
     (UINT)hlsl::IntrinsicOp::IOP_acos, false, true, -1, 2, g_Intrinsics_Args66,
     (UINT)hlsl::IntrinsicOp::IOP_acos, false, true, -1, 2, g_Intrinsics_Args66,

+ 1 - 1
tools/clang/test/CodeGenHLSL/RaceCond.hlsl

@@ -9,7 +9,7 @@ groupshared int sharedData;
 [ numthreads( 64, 2, 2 ) ]
 [ numthreads( 64, 2, 2 ) ]
 void main( uint GI : SV_GroupIndex)
 void main( uint GI : SV_GroupIndex)
 {
 {
-sharedData = 0;
+sharedData = GI;
 InterlockedAdd(sharedData, g_Intensities[GI]);
 InterlockedAdd(sharedData, g_Intensities[GI]);
 g_Intensities[GI] = sharedData;
 g_Intensities[GI] = sharedData;
 }
 }

+ 16 - 0
tools/clang/test/CodeGenHLSL/RaceCond2.hlsl

@@ -0,0 +1,16 @@
+// RUN: %dxc -E main  -T cs_6_0 %s
+
+
+RWBuffer< int > g_Intensities : register(u1);
+
+groupshared int sharedData;
+
+int a;
+int b[2];
+[ numthreads( 64, 2, 2 ) ]
+void main( uint GI : SV_GroupIndex)
+{
+sharedData = b[0];
+InterlockedAdd(sharedData, g_Intensities[GI]);
+g_Intensities[GI] = sharedData;
+}

+ 1 - 1
tools/clang/test/CodeGenHLSL/UndefValue.hlsl

@@ -1,6 +1,6 @@
 // RUN: %dxc -E main -T ps_6_0 %s | FileCheck %s
 // RUN: %dxc -E main -T ps_6_0 %s | FileCheck %s
 
 
-// CHECK: @main
+// CHECK: Instructions should not read uninitialized value
 
 
 float main(snorm float b : B) : SV_DEPTH
 float main(snorm float b : B) : SV_DEPTH
 {
 {

+ 213 - 47
tools/clang/tools/dxc/dxc.cpp

@@ -26,18 +26,12 @@
 //
 //
 // Unimplemented but on roadmap:
 // Unimplemented but on roadmap:
 //
 //
-// /getprivate  - Save private data to a file.
 // /matchUAVs   - Match template shader UAV slot allocations in the current shader
 // /matchUAVs   - Match template shader UAV slot allocations in the current shader
 // /mergeUAVs   - Merge UAV slot allocations of template shader and the current shader
 // /mergeUAVs   - Merge UAV slot allocations of template shader and the current shader
 // /Ni          - Output instruction numbers in assembly listings
 // /Ni          - Output instruction numbers in assembly listings
 // /No          - Output instruction byte offset in assembly listings
 // /No          - Output instruction byte offset in assembly listings
-// /Qstrip_debug
-// /Qstrip_priv
 // /Qstrip_reflect
 // /Qstrip_reflect
-// /Qstrip_rootsignature
 // /res_may_alias
 // /res_may_alias
-// /setprivate
-// /setrootsignature
 // /shtemplate
 // /shtemplate
 // /verifyrootsignature
 // /verifyrootsignature
 //
 //
@@ -56,6 +50,7 @@
 #include "dxc/Support/HLSLOptions.h"
 #include "dxc/Support/HLSLOptions.h"
 #include "dxc/HLSL/DxilContainer.h"
 #include "dxc/HLSL/DxilContainer.h"
 #include "dxc/HLSL/DxilShaderModel.h"
 #include "dxc/HLSL/DxilShaderModel.h"
+#include "dxc/HLSL/DxilRootSignature.h"
 #include "dxc/Support/FileIOHelper.h"
 #include "dxc/Support/FileIOHelper.h"
 #include "dxc/Support/microcom.h"
 #include "dxc/Support/microcom.h"
 #include "llvm/Option/OptTable.h"
 #include "llvm/Option/OptTable.h"
@@ -82,14 +77,18 @@ private:
   DxcOpts &m_Opts;
   DxcOpts &m_Opts;
   DxcDllSupport &m_dxcSupport;
   DxcDllSupport &m_dxcSupport;
 
 
-  void ActOnBlob(IDxcBlob *pBlob);
+  int ActOnBlob(IDxcBlob *pBlob);
   void UpdatePart(IDxcBlob *pBlob, IDxcBlob **ppResult);
   void UpdatePart(IDxcBlob *pBlob, IDxcBlob **ppResult);
   bool UpdatePartRequired();
   bool UpdatePartRequired();
   void WriteHeader(IDxcBlobEncoding *pDisassembly, IDxcBlob *pCode,
   void WriteHeader(IDxcBlobEncoding *pDisassembly, IDxcBlob *pCode,
                    llvm::Twine &pVariableName, LPCWSTR pPath);
                    llvm::Twine &pVariableName, LPCWSTR pPath);
+  HRESULT ReadFileIntoPartContent(hlsl::DxilFourCC fourCC, LPCWSTR fileName, IDxcBlob **ppResult);
+  
   // TODO : Refactor two functions below. There are duplicate functions in DxcContext in dxa.cpp
   // TODO : Refactor two functions below. There are duplicate functions in DxcContext in dxa.cpp
   HRESULT GetDxcDiaTable(IDxcLibrary *pLibrary, IDxcBlob *pTargetBlob, IDiaTable **ppTable, LPCWSTR tableName);
   HRESULT GetDxcDiaTable(IDxcLibrary *pLibrary, IDxcBlob *pTargetBlob, IDiaTable **ppTable, LPCWSTR tableName);
   HRESULT FindModuleBlob(hlsl::DxilFourCC fourCC, IDxcBlob *pSource, IDxcLibrary *pLibrary, IDxcBlob **ppTargetBlob);
   HRESULT FindModuleBlob(hlsl::DxilFourCC fourCC, IDxcBlob *pSource, IDxcLibrary *pLibrary, IDxcBlob **ppTargetBlob);
+  void ExtractRootSignature(IDxcBlob *pBlob, IDxcBlob **ppResult);
+  int VerifyRootSignature();
 
 
 public:
 public:
   DxcContext(DxcOpts &Opts, DxcDllSupport &dxcSupport)
   DxcContext(DxcOpts &Opts, DxcDllSupport &dxcSupport)
@@ -97,7 +96,7 @@ public:
 
 
   int  Compile();
   int  Compile();
   void Recompile(IDxcBlob *pSource, IDxcLibrary *pLibrary, IDxcCompiler *pCompiler, std::vector<LPCWSTR> &args, IDxcOperationResult **pCompileResult);
   void Recompile(IDxcBlob *pSource, IDxcLibrary *pLibrary, IDxcCompiler *pCompiler, std::vector<LPCWSTR> &args, IDxcOperationResult **pCompileResult);
-  void DumpBinary();
+  int DumpBinary();
   void Preprocess();
   void Preprocess();
 };
 };
 
 
@@ -135,28 +134,44 @@ static void WritePartToFile(IDxcBlob *pBlob, hlsl::DxilFourCC CC,
 
 
 // This function is called either after the compilation is done or /dumpbin option is provided
 // This function is called either after the compilation is done or /dumpbin option is provided
 // Performing options that are used to process dxil container.
 // Performing options that are used to process dxil container.
-void DxcContext::ActOnBlob(IDxcBlob *pBlob) {
+int DxcContext::ActOnBlob(IDxcBlob *pBlob) {
+  int retVal = 0;
   // Text output.
   // Text output.
   if (m_Opts.AstDump || m_Opts.OptDump) {
   if (m_Opts.AstDump || m_Opts.OptDump) {
     WriteBlobToConsole(pBlob);
     WriteBlobToConsole(pBlob);
-    return;
+    return retVal;
   }
   }
 
 
   // Write the output blob.
   // Write the output blob.
   if (!m_Opts.OutputObject.empty()) {
   if (!m_Opts.OutputObject.empty()) {
-    CComPtr<IDxcBlob> pResult;
-    UpdatePart(pBlob, &pResult);
-    WriteBlobToFile(pResult, m_Opts.OutputObject);
+    // For backward compatability: fxc requires /Fo for /extractrootsignature
+    if (!m_Opts.ExtractRootSignature) {
+      CComPtr<IDxcBlob> pResult;
+      UpdatePart(pBlob, &pResult);
+      WriteBlobToFile(pResult, m_Opts.OutputObject);
+    }
+  }
+
+  // Verify Root Signature
+  if (!m_Opts.VerifyRootSignatureSource.empty()) {
+    return VerifyRootSignature();
   }
   }
 
 
   // Extract and write the PDB/debug information.
   // Extract and write the PDB/debug information.
   if (!m_Opts.DebugFile.empty()) {
   if (!m_Opts.DebugFile.empty()) {
+    IFTBOOLMSG(m_Opts.DebugInfo, E_INVALIDARG, "/Fd specified, but no Debug Info was "
+      "found in the shader, please use the "
+      "/Zi switch to generate debug "
+      "information compiling this shader.");
+
     WritePartToFile(pBlob, hlsl::DFCC_ShaderDebugInfoDXIL, m_Opts.DebugFile);
     WritePartToFile(pBlob, hlsl::DFCC_ShaderDebugInfoDXIL, m_Opts.DebugFile);
   }
   }
 
 
   // Extract and write root signature information.
   // Extract and write root signature information.
-  if (!m_Opts.ExtractRootSignatureFile.empty()) {
-    WritePartToFile(pBlob, hlsl::DFCC_RootSignature, m_Opts.ExtractRootSignatureFile);
+  if (m_Opts.ExtractRootSignature) {
+    CComPtr<IDxcBlob> pRootSignatureContainer;
+    ExtractRootSignature(pBlob, &pRootSignatureContainer);
+    WriteBlobToFile(pRootSignatureContainer, m_Opts.OutputObject);
   }
   }
 
 
   // Extract and write private data.
   // Extract and write private data.
@@ -165,11 +180,14 @@ void DxcContext::ActOnBlob(IDxcBlob *pBlob) {
   }
   }
 
 
   // OutputObject suppresses console dump.
   // OutputObject suppresses console dump.
-  bool needDisassembly = !m_Opts.OutputHeader.empty() ||
-                         !m_Opts.AssemblyCode.empty() ||
-                         m_Opts.OutputObject.empty();
+  bool needDisassembly =
+      !m_Opts.OutputHeader.empty() || !m_Opts.AssemblyCode.empty() ||
+      (m_Opts.OutputObject.empty() && m_Opts.DebugFile.empty() &&
+       m_Opts.ExtractPrivateFile.empty() &&
+       m_Opts.VerifyRootSignatureSource.empty() && !m_Opts.ExtractRootSignature);
+
   if (!needDisassembly)
   if (!needDisassembly)
-    return;
+     return retVal;
 
 
   CComPtr<IDxcCompiler> pCompiler;
   CComPtr<IDxcCompiler> pCompiler;
   IFT(m_dxcSupport.CreateInstance(CLSID_DxcCompiler, &pCompiler));
   IFT(m_dxcSupport.CreateInstance(CLSID_DxcCompiler, &pCompiler));
@@ -187,6 +205,7 @@ void DxcContext::ActOnBlob(IDxcBlob *pBlob) {
   } else {
   } else {
     WriteBlobToConsole(pDisassembleResult);
     WriteBlobToConsole(pDisassembleResult);
   }
   }
+  return retVal;
 }
 }
 
 
 // Given a dxil container, update the dxil container by processing container specific options.
 // Given a dxil container, update the dxil container by processing container specific options.
@@ -216,13 +235,27 @@ void DxcContext::UpdatePart(IDxcBlob *pSource, IDxcBlob **ppResult) {
     IFT(pContainerBuilder->RemovePart(hlsl::DxilFourCC::DFCC_RootSignature));
     IFT(pContainerBuilder->RemovePart(hlsl::DxilFourCC::DFCC_RootSignature));
   }
   }
   if (!m_Opts.PrivateSource.empty()) {
   if (!m_Opts.PrivateSource.empty()) {
-    CComPtr<IDxcBlobEncoding> privateBlob;
-    ReadFileIntoBlob(m_dxcSupport, StringRefUtf16(m_Opts.PrivateSource), &privateBlob);
+    CComPtr<IDxcBlob> privateBlob;
+    IFT(ReadFileIntoPartContent(hlsl::DxilFourCC::DFCC_PrivateData,
+                                StringRefUtf16(m_Opts.PrivateSource),
+                                &privateBlob));
+
+    // setprivate option can replace existing private part. 
+    // Try removing the private data if exists
+    pContainerBuilder->RemovePart(hlsl::DxilFourCC::DFCC_PrivateData);
     IFT(pContainerBuilder->AddPart(hlsl::DxilFourCC::DFCC_PrivateData, privateBlob));
     IFT(pContainerBuilder->AddPart(hlsl::DxilFourCC::DFCC_PrivateData, privateBlob));
   }
   }
   if (!m_Opts.RootSignatureSource.empty()) {
   if (!m_Opts.RootSignatureSource.empty()) {
-    CComPtr<IDxcBlobEncoding> RootSignatureBlob;
-    ReadFileIntoBlob(m_dxcSupport, StringRefUtf16(m_Opts.RootSignatureSource), &RootSignatureBlob);
+    // set rootsignature assumes that the given input is a dxil container. 
+    // We only want to add RTS0 part to the container builder. 
+    CComPtr<IDxcBlob> RootSignatureBlob;
+    IFT(ReadFileIntoPartContent(hlsl::DxilFourCC::DFCC_RootSignature,
+                                StringRefUtf16(m_Opts.RootSignatureSource),
+                                &RootSignatureBlob));
+
+    // setrootsignature option can replace existing rootsignature part
+    // Try removing rootsignature if exists
+    pContainerBuilder->RemovePart(hlsl::DxilFourCC::DFCC_RootSignature);
     IFT(pContainerBuilder->AddPart(hlsl::DxilFourCC::DFCC_RootSignature, RootSignatureBlob));
     IFT(pContainerBuilder->AddPart(hlsl::DxilFourCC::DFCC_RootSignature, RootSignatureBlob));
   }
   }
   
   
@@ -251,6 +284,128 @@ bool DxcContext::UpdatePartRequired() {
     !m_Opts.RootSignatureSource.empty();
     !m_Opts.RootSignatureSource.empty();
 }
 }
 
 
+// This function reads the file from input file and constructs a blob with fourCC parts
+// Used for setprivate and setrootsignature option
+HRESULT DxcContext::ReadFileIntoPartContent(hlsl::DxilFourCC fourCC, LPCWSTR fileName, IDxcBlob **ppResult) {
+  DXASSERT(fourCC == hlsl::DxilFourCC::DFCC_PrivateData ||
+           fourCC == hlsl::DxilFourCC::DFCC_RootSignature,
+           "Otherwise we provided wrong part to read for updating part.");
+
+  // Read result, if it's private data, then return the blob
+  if (fourCC == hlsl::DxilFourCC::DFCC_PrivateData) {
+    CComPtr<IDxcBlobEncoding> pResult;
+    ReadFileIntoBlob(m_dxcSupport, fileName, &pResult);
+    *ppResult = pResult.Detach();
+  }
+
+  // If root signature, check if it's a dxil container that contains rootsignature part, then construct a blob of root signature part
+  if (fourCC == hlsl::DxilFourCC::DFCC_RootSignature) {
+    CComPtr<IDxcBlob> pResult;
+    CComHeapPtr<BYTE> pData;
+    DWORD dataSize;
+    hlsl::ReadBinaryFile(fileName, (void**)&pData, &dataSize);
+    DXASSERT(pData != nullptr, "otherwise ReadBinaryFile should throw an exception");
+    hlsl::DxilContainerHeader *pHeader = (hlsl::DxilContainerHeader*) pData.m_pData;
+    IFRBOOL(hlsl::IsDxilContainerLike(pHeader, pHeader->ContainerSizeInBytes), E_INVALIDARG);
+    hlsl::DxilPartHeader *pPartHeader = hlsl::GetDxilPartByType(pHeader, hlsl::DxilFourCC::DFCC_RootSignature);
+    IFRBOOL(pPartHeader != nullptr, E_INVALIDARG);
+    hlsl::DxcCreateBlobOnHeapCopy(hlsl::GetDxilPartData(pPartHeader), pPartHeader->PartSize, &pResult);
+    *ppResult = pResult.Detach();
+  }
+  return S_OK;
+}
+
+// Constructs a dxil container builder with only root signature part.
+// Right now IDxcContainerBuilder assumes that we are building a full dxil container,
+// but we are building a container with only rootsignature part
+void DxcContext::ExtractRootSignature(IDxcBlob *pBlob, IDxcBlob **ppResult) {
+  
+  DXASSERT_NOMSG(pBlob != nullptr && ppResult != nullptr);
+  const hlsl::DxilContainerHeader *pHeader = (hlsl::DxilContainerHeader *)(pBlob->GetBufferPointer());
+  IFTBOOL(hlsl::IsValidDxilContainer(pHeader, pHeader->ContainerSizeInBytes), DXC_E_CONTAINER_INVALID);
+  const hlsl::DxilPartHeader *pPartHeader = hlsl::GetDxilPartByType(pHeader, hlsl::DxilFourCC::DFCC_RootSignature);
+  IFTBOOL(pPartHeader != nullptr, DXC_E_MISSING_PART);
+
+  // Get new header and allocate memory for new container
+  hlsl::DxilContainerHeader newHeader;
+  uint32_t containerSize = hlsl::GetDxilContainerSizeFromParts(1, pPartHeader->PartSize);
+  hlsl::InitDxilContainer(&newHeader, 1, containerSize); 
+  CComPtr<IMalloc> pMalloc;
+  CComPtr<hlsl::AbstractMemoryStream> pMemoryStream;
+  IFT(CoGetMalloc(1, &pMalloc));
+  IFT(hlsl::CreateMemoryStream(pMalloc, &pMemoryStream));
+  ULONG cbWritten;
+
+  // Write Container Header
+  IFT(pMemoryStream->Write(&newHeader, sizeof(hlsl::DxilContainerHeader), &cbWritten));
+  IFTBOOL(cbWritten == sizeof(hlsl::DxilContainerHeader), E_OUTOFMEMORY);
+  
+  // Write Part Offset
+  uint32_t offset = sizeof(hlsl::DxilContainerHeader) + hlsl::GetOffsetTableSize(1);
+  IFT(pMemoryStream->Write(&offset, sizeof(uint32_t), &cbWritten));
+  IFTBOOL(cbWritten == sizeof(uint32_t), E_OUTOFMEMORY);
+  
+  // Write Root Signature Header
+  IFT(pMemoryStream->Write(pPartHeader, sizeof(hlsl::DxilPartHeader), &cbWritten));
+  IFTBOOL(cbWritten == sizeof(hlsl::DxilPartHeader), E_OUTOFMEMORY);
+  const char * partContent = hlsl::GetDxilPartData(pPartHeader);
+  
+  // Write Root Signature Content
+  IFT(pMemoryStream->Write(partContent, pPartHeader->PartSize, &cbWritten));
+  IFTBOOL(cbWritten == pPartHeader->PartSize, E_OUTOFMEMORY);
+  
+  // Return Result
+  CComPtr<IDxcBlob> pResult;
+  IFT(pMemoryStream->QueryInterface(&pResult));
+  *ppResult = pResult.Detach();
+}
+
+int DxcContext::VerifyRootSignature() {
+  // Get dxil container from file
+  CComPtr<IDxcBlobEncoding> pSource;
+  ReadFileIntoBlob(m_dxcSupport, StringRefUtf16(m_Opts.InputFile), &pSource);
+  hlsl::DxilContainerHeader *pSourceHeader = (hlsl::DxilContainerHeader *)pSource->GetBufferPointer();
+  IFTBOOLMSG(hlsl::IsValidDxilContainer(pSourceHeader, pSourceHeader->ContainerSizeInBytes), E_INVALIDARG, "invalid DXIL container to verify.");
+
+  // Get rootsignature from file
+  CComPtr<IDxcBlob> pRootSignature;
+
+  IFTMSG(ReadFileIntoPartContent(
+             hlsl::DxilFourCC::DFCC_RootSignature,
+             StringRefUtf16(m_Opts.VerifyRootSignatureSource), &pRootSignature),
+         "invalid root signature to verify.");
+
+  // TODO : Right now we are just going to bild a new blob with updated root signature to verify root signature
+  // Since dxil container builder will verify on its behalf. 
+  // This does unnecessary memory allocation. We can improve this later. 
+  CComPtr<IDxcContainerBuilder> pContainerBuilder;
+  IFT(m_dxcSupport.CreateInstance(CLSID_DxcContainerBuilder, &pContainerBuilder));
+  IFT(pContainerBuilder->Load(pSource));
+  // Try removing root signature if it already exists
+  pContainerBuilder->RemovePart(hlsl::DxilFourCC::DFCC_RootSignature);
+  IFT(pContainerBuilder->AddPart(hlsl::DxilFourCC::DFCC_RootSignature, pRootSignature));  
+  CComPtr<IDxcOperationResult> pOperationResult;
+  IFT(pContainerBuilder->SerializeContainer(&pOperationResult));
+  HRESULT status = E_FAIL;
+  CComPtr<IDxcBlob> pResult;
+  IFT(pOperationResult->GetStatus(&status));
+  if (FAILED(status)) {
+    if (!m_Opts.OutputWarningsFile.empty()) {
+      CComPtr<IDxcBlobEncoding> pErrors;
+      IFT(pOperationResult->GetErrorBuffer(&pErrors));
+      WriteBlobToFile(pErrors, m_Opts.OutputWarningsFile);
+    }
+    else {
+      WriteOperationErrorsToConsole(pOperationResult, m_Opts.OutputWarnings);
+    }
+    return 1;
+  }
+  else {
+    printf("root signature verification succeeded.");
+    return 0;
+  }
+}
+
 class DxcIncludeHandlerForInjectedSources : public IDxcIncludeHandler {
 class DxcIncludeHandlerForInjectedSources : public IDxcIncludeHandler {
 private:
 private:
   DXC_MICROCOM_REF_FIELD(m_dwRef)
   DXC_MICROCOM_REF_FIELD(m_dwRef)
@@ -506,16 +661,16 @@ int DxcContext::Compile() {
   return status;
   return status;
 }
 }
 
 
-void DxcContext::DumpBinary() {
+int DxcContext::DumpBinary() {
   CComPtr<IDxcBlobEncoding> pSource;
   CComPtr<IDxcBlobEncoding> pSource;
   ReadFileIntoBlob(m_dxcSupport, StringRefUtf16(m_Opts.InputFile), &pSource);
   ReadFileIntoBlob(m_dxcSupport, StringRefUtf16(m_Opts.InputFile), &pSource);
-  ActOnBlob(pSource.p);
+  return ActOnBlob(pSource.p);
 }
 }
 
 
 void DxcContext::Preprocess() {
 void DxcContext::Preprocess() {
   DXASSERT(!m_Opts.Preprocess.empty(), "else option reading should have failed");
   DXASSERT(!m_Opts.Preprocess.empty(), "else option reading should have failed");
   CComPtr<IDxcCompiler> pCompiler;
   CComPtr<IDxcCompiler> pCompiler;
-  CComPtr<IDxcOperationResult> pCompileResult;
+  CComPtr<IDxcOperationResult> pPreprocessResult;
   CComPtr<IDxcBlobEncoding> pSource;
   CComPtr<IDxcBlobEncoding> pSource;
   std::vector<LPCWSTR> args;
   std::vector<LPCWSTR> args;
 
 
@@ -526,19 +681,14 @@ void DxcContext::Preprocess() {
 
 
   ReadFileIntoBlob(m_dxcSupport, StringRefUtf16(m_Opts.InputFile), &pSource);
   ReadFileIntoBlob(m_dxcSupport, StringRefUtf16(m_Opts.InputFile), &pSource);
   IFT(m_dxcSupport.CreateInstance(CLSID_DxcCompiler, &pCompiler));
   IFT(m_dxcSupport.CreateInstance(CLSID_DxcCompiler, &pCompiler));
-  IFT(pCompiler->Compile(pSource, StringRefUtf16(m_Opts.InputFile),
-    StringRefUtf16(m_Opts.EntryPoint),
-    StringRefUtf16(m_Opts.TargetProfile), args.data(),
-    args.size(), m_Opts.Defines.data(),
-    m_Opts.Defines.size(), pIncludeHandler, &pCompileResult));
-
-  WriteOperationErrorsToConsole(pCompileResult, m_Opts.OutputWarnings);
+  IFT(pCompiler->Preprocess(pSource, StringRefUtf16(m_Opts.InputFile), args.data(), args.size(), m_Opts.Defines.data(), m_Opts.Defines.size(), pIncludeHandler, &pPreprocessResult));
+  WriteOperationErrorsToConsole(pPreprocessResult, m_Opts.OutputWarnings);
 
 
   HRESULT status;
   HRESULT status;
-  IFT(pCompileResult->GetStatus(&status));
+  IFT(pPreprocessResult->GetStatus(&status));
   if (SUCCEEDED(status)) {
   if (SUCCEEDED(status)) {
     CComPtr<IDxcBlob> pProgram;
     CComPtr<IDxcBlob> pProgram;
-    IFT(pCompileResult->GetResult(&pProgram));
+    IFT(pPreprocessResult->GetResult(&pProgram));
     WriteBlobToFile(pProgram, m_Opts.Preprocess);
     WriteBlobToFile(pProgram, m_Opts.Preprocess);
   }
   }
 }
 }
@@ -579,7 +729,7 @@ void DxcContext::WriteHeader(IDxcBlobEncoding *pDisassembly, IDxcBlob *pCode,
   {
   {
     std::string s;
     std::string s;
     llvm::raw_string_ostream OS(s);
     llvm::raw_string_ostream OS(s);
-    OS << "\r\nconst BYTE " << pVariableName << "[] = {";
+    OS << "\r\nconst unsigned char " << pVariableName << "[] = {";
     const uint8_t *pBytes = (const uint8_t *)pCode->GetBufferPointer();
     const uint8_t *pBytes = (const uint8_t *)pCode->GetBufferPointer();
     size_t len = pCode->GetBufferSize();
     size_t len = pCode->GetBufferSize();
     s.reserve(100 + len * 6 + (len / 12) * 3); // rough estimate
     s.reserve(100 + len * 6 + (len / 12) * 3); // rough estimate
@@ -614,8 +764,8 @@ HRESULT DxcContext::FindModuleBlob(hlsl::DxilFourCC fourCC, IDxcBlob *pSource, I
 
 
   if (hlsl::IsValidDxilContainer((hlsl::DxilContainerHeader*)pSource->GetBufferPointer(), pSource->GetBufferSize())) {
   if (hlsl::IsValidDxilContainer((hlsl::DxilContainerHeader*)pSource->GetBufferPointer(), pSource->GetBufferSize())) {
     hlsl::DxilContainerHeader *pDxilContainerHeader = (hlsl::DxilContainerHeader*)pSource->GetBufferPointer();
     hlsl::DxilContainerHeader *pDxilContainerHeader = (hlsl::DxilContainerHeader*)pSource->GetBufferPointer();
-    pDxilPartHeader = *std::find_if(begin(pDxilContainerHeader), end(pDxilContainerHeader), hlsl::DxilPartIsType(fourCC));
-    IFTARG(pDxilPartHeader != *end(pDxilContainerHeader));
+    pDxilPartHeader = hlsl::GetDxilPartByType(pDxilContainerHeader, fourCC);
+    IFTBOOL(pDxilPartHeader != nullptr, DXC_E_CONTAINER_MISSING_DEBUG);
   }
   }
   if (fourCC == pDxilPartHeader->PartFourCC) {
   if (fourCC == pDxilPartHeader->PartFourCC) {
     UINT32 pBlobSize;
     UINT32 pBlobSize;
@@ -680,7 +830,7 @@ int __cdecl wmain(int argc, const wchar_t **argv_) {
           ReadDxcOpts(optionTable, DxcFlags, argStrings, dxcOpts, errorStream);
           ReadDxcOpts(optionTable, DxcFlags, argStrings, dxcOpts, errorStream);
       errorStream.flush();
       errorStream.flush();
       if (errorString.size()) {
       if (errorString.size()) {
-        fprintf(stderr, "%s", errorString.data());
+        fprintf(stderr, "dxc failed : %s", errorString.data());
       }
       }
       if (optResult != 0) {
       if (optResult != 0) {
         return optResult;
         return optResult;
@@ -724,7 +874,7 @@ int __cdecl wmain(int argc, const wchar_t **argv_) {
     }
     }
     else if (dxcOpts.DumpBin) {
     else if (dxcOpts.DumpBin) {
       pStage = "Dumping existing binary";
       pStage = "Dumping existing binary";
-      context.DumpBinary();
+      retVal = context.DumpBinary();
     }
     }
     else {
     else {
       pStage = "Compilation";
       pStage = "Compilation";
@@ -737,20 +887,36 @@ int __cdecl wmain(int argc, const wchar_t **argv_) {
                                           // UTF-8 because we use ASCII only errors
                                           // UTF-8 because we use ASCII only errors
       if (msg == nullptr || *msg == '\0') {
       if (msg == nullptr || *msg == '\0') {
         if (hlslException.hr == DXC_E_DUPLICATE_PART) {
         if (hlslException.hr == DXC_E_DUPLICATE_PART) {
-          sprintf_s(printBuffer, _countof(printBuffer),
-                    "DXIL container already contains the given part.");
+          sprintf_s(
+              printBuffer, _countof(printBuffer),
+              "dxc failed : DXIL container already contains the given part.");
         } else if (hlslException.hr == DXC_E_MISSING_PART) {
         } else if (hlslException.hr == DXC_E_MISSING_PART) {
+          sprintf_s(
+              printBuffer, _countof(printBuffer),
+              "dxc failed : DXIL container does not contain the given part.");
+        } else if (hlslException.hr == DXC_E_CONTAINER_INVALID) {
           sprintf_s(printBuffer, _countof(printBuffer),
           sprintf_s(printBuffer, _countof(printBuffer),
-                    "DXIL container does not contain the given part.");
-        }
-        else {
+                    "dxc failed : Invalid DXIL container.");
+        } else if (hlslException.hr == DXC_E_CONTAINER_MISSING_DXIL) {
+          sprintf_s(printBuffer, _countof(printBuffer),
+                    "dxc failed : DXIL container is missing DXIL part.");
+        } else if (hlslException.hr == DXC_E_CONTAINER_MISSING_DEBUG) {
+          sprintf_s(printBuffer, _countof(printBuffer),
+                    "dxc failed : DXIL container is missing Debug Info part.");
+        } else if (hlslException.hr == E_OUTOFMEMORY) {
+          sprintf_s(printBuffer, _countof(printBuffer),
+                    "dxc failed : Out of Memory.");
+        } else if (hlslException.hr == E_INVALIDARG) {
+          sprintf_s(printBuffer, _countof(printBuffer),
+                    "dxc failed : Invalid argument.");
+        } else {
           sprintf_s(printBuffer, _countof(printBuffer),
           sprintf_s(printBuffer, _countof(printBuffer),
-            "Compilation failed - error code 0x%08x.\n", hlslException.hr);
+            "dxc failed : error code 0x%08x.\n", hlslException.hr);
         }
         }
         msg = printBuffer;
         msg = printBuffer;
       }
       }
 
 
-      WriteUtf8ToConsoleSizeT(msg, strlen(msg));
+      WriteUtf8ToConsoleSizeT(msg, strlen(msg), STD_ERROR_HANDLE);
       printf("\n");
       printf("\n");
     } catch (...) {
     } catch (...) {
       printf("%s failed - unable to retrieve error message.\n", pStage);
       printf("%s failed - unable to retrieve error message.\n", pStage);

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

@@ -120,7 +120,7 @@ HRESULT STDMETHODCALLTYPE DxcAssembler::AssembleToContainer(
     CComPtr<AbstractMemoryStream> pFinalStream;
     CComPtr<AbstractMemoryStream> pFinalStream;
     IFT(CreateMemoryStream(pMalloc, &pFinalStream));
     IFT(CreateMemoryStream(pMalloc, &pFinalStream));
 
 
-    SerializeDxilContainerForModule(M.get(), pOutputStream, pFinalStream);
+    SerializeDxilContainerForModule(&M->GetOrCreateDxilModule(), pOutputStream, pFinalStream);
 
 
     CComPtr<IDxcBlob> pResultBlob;
     CComPtr<IDxcBlob> pResultBlob;
     IFT(pFinalStream->QueryInterface(&pResultBlob));
     IFT(pFinalStream->QueryInterface(&pResultBlob));

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

@@ -1858,7 +1858,7 @@ public:
  void WrapModuleInDxilContainer(IMalloc *pMalloc,  AbstractMemoryStream *pModuleBitcode, CComPtr<IDxcBlob> &pDxilContainerBlob) {
  void WrapModuleInDxilContainer(IMalloc *pMalloc,  AbstractMemoryStream *pModuleBitcode, CComPtr<IDxcBlob> &pDxilContainerBlob) {
     CComPtr<AbstractMemoryStream> pContainerStream;
     CComPtr<AbstractMemoryStream> pContainerStream;
     IFT(CreateMemoryStream(pMalloc, &pContainerStream));
     IFT(CreateMemoryStream(pMalloc, &pContainerStream));
-    SerializeDxilContainerForModule(m_llvmModule.get(), pModuleBitcode, pContainerStream);
+    SerializeDxilContainerForModule(&m_llvmModule->GetOrCreateDxilModule(), pModuleBitcode, pContainerStream);
 
 
     pDxilContainerBlob.Release();
     pDxilContainerBlob.Release();
     IFT(pContainerStream.QueryInterface(&pDxilContainerBlob));
     IFT(pContainerStream.QueryInterface(&pDxilContainerBlob));

+ 43 - 5
tools/clang/tools/dxcompiler/dxcontainerbuilder.cpp

@@ -24,6 +24,9 @@
 
 
 using namespace hlsl;
 using namespace hlsl;
 
 
+// This declaration is used for the locally-linked validator.
+HRESULT CreateDxcValidator(_In_ REFIID riid, _Out_ LPVOID *ppv);
+
 class DxcContainerBuilder : public IDxcContainerBuilder {
 class DxcContainerBuilder : public IDxcContainerBuilder {
 public:
 public:
   __override HRESULT STDMETHODCALLTYPE Load(_In_ IDxcBlob *pDxilContainerHeader); // Loads DxilContainer to the builder
   __override HRESULT STDMETHODCALLTYPE Load(_In_ IDxcBlob *pDxilContainerHeader); // Loads DxilContainer to the builder
@@ -36,7 +39,7 @@ public:
     return DoBasicQueryInterface<IDxcContainerBuilder>(this, riid, ppvObject);
     return DoBasicQueryInterface<IDxcContainerBuilder>(this, riid, ppvObject);
   }
   }
 
 
-  DxcContainerBuilder(const char *warning) : m_dwRef(0), m_parts(), m_pContainer(), m_warning(warning) {}
+  DxcContainerBuilder(const char *warning) : m_dwRef(0), m_parts(), m_pContainer(), m_warning(warning), m_RequireValidation(false) {}
 
 
 private:
 private:
   DXC_MICROCOM_REF_FIELD(m_dwRef)
   DXC_MICROCOM_REF_FIELD(m_dwRef)
@@ -52,6 +55,7 @@ private:
   PartList m_parts;
   PartList m_parts;
   CComPtr<IDxcBlob> m_pContainer; 
   CComPtr<IDxcBlob> m_pContainer; 
   const char *m_warning;
   const char *m_warning;
+  bool m_RequireValidation;
 
 
   UINT32 ComputeContainerSize();
   UINT32 ComputeContainerSize();
   HRESULT UpdateContainerHeader(AbstractMemoryStream *pStream, uint32_t containerSize);
   HRESULT UpdateContainerHeader(AbstractMemoryStream *pStream, uint32_t containerSize);
@@ -95,6 +99,9 @@ HRESULT STDMETHODCALLTYPE DxcContainerBuilder::AddPart(_In_ UINT32 fourCC, _In_
     });
     });
     IFTBOOL(it == m_parts.end(), DXC_E_DUPLICATE_PART);
     IFTBOOL(it == m_parts.end(), DXC_E_DUPLICATE_PART);
     m_parts.emplace_back(DxilPart(fourCC, pSource));
     m_parts.emplace_back(DxilPart(fourCC, pSource));
+    if (fourCC == DxilFourCC::DFCC_RootSignature) {
+      m_RequireValidation = true;
+    }
     return S_OK;
     return S_OK;
   }
   }
   CATCH_CPP_RETURN_HRESULT();
   CATCH_CPP_RETURN_HRESULT();
@@ -137,9 +144,40 @@ HRESULT STDMETHODCALLTYPE DxcContainerBuilder::SerializeContainer(_Out_ IDxcOper
     // Update Parts
     // Update Parts
     IFT(UpdateParts(pMemoryStream));
     IFT(UpdateParts(pMemoryStream));
 
 
-    CComPtr<IDxcBlobEncoding> pError;
-    DxcCreateBlobWithEncodingOnHeapCopy(m_warning, strlen(m_warning), CP_UTF8, &pError);
-    DxcOperationResult::CreateFromResultErrorStatus(pResult, pError, S_OK, ppResult);
+    CComPtr<IDxcBlobEncoding> pErrorBlob;
+    HRESULT valHR = S_OK;
+    if (m_RequireValidation) {
+      CComPtr<IDxcValidator> pValidator;
+      CComPtr<IDxcLibrary> pLibrary;
+      IFT(CreateDxcValidator(IID_PPV_ARGS(&pValidator)));
+      CComPtr<IDxcOperationResult> pValidationResult;
+      IFT(pValidator->Validate(pResult, DxcValidatorFlags_RootSignatureOnly, &pValidationResult));
+      IFT(pValidationResult->GetStatus(&valHR));
+      if (FAILED(valHR)) {
+        CComPtr<IMalloc> pErrorMalloc;
+        CComPtr<AbstractMemoryStream> pErrorOutputStream;
+        CComPtr<IDxcBlob> pErrorResult;
+        IFT(CoGetMalloc(1, &pErrorMalloc));
+        IFT(CreateMemoryStream(pErrorMalloc, &pErrorOutputStream));
+        IFT(pErrorOutputStream.QueryInterface(&pErrorResult));
+        
+        // Combine existing warnings and errors from validation
+        CComPtr<IDxcBlobEncoding> pValError;
+        IFT(pValidationResult->GetErrorBuffer(&pValError));
+        IFT(pErrorOutputStream->Reserve(strlen(m_warning) + pValError->GetBufferSize()));
+        ULONG cbWritten;
+        IFT(pErrorOutputStream->Write(m_warning, strlen(m_warning), &cbWritten));
+        IFT(pErrorOutputStream->Write(pValError->GetBufferPointer(), pValError->GetBufferSize(), &cbWritten));
+        DxcCreateBlobWithEncodingSet(pErrorResult, CP_UTF8, &pErrorBlob);
+      }
+      else {
+        DxcCreateBlobWithEncodingOnHeapCopy(m_warning, strlen(m_warning), CP_UTF8, &pErrorBlob);
+      }
+    }
+    else {
+      DxcCreateBlobWithEncodingOnHeapCopy(m_warning, strlen(m_warning), CP_UTF8, &pErrorBlob);
+    }
+    DxcOperationResult::CreateFromResultErrorStatus(pResult, pErrorBlob, valHR, ppResult);
     return S_OK;
     return S_OK;
   }
   }
   CATCH_CPP_RETURN_HRESULT();
   CATCH_CPP_RETURN_HRESULT();
@@ -195,7 +233,7 @@ HRESULT CreateDxcContainerBuilder(_In_ REFIID riid, _Out_ LPVOID *ppv) {
   const char *warning;
   const char *warning;
   HRESULT hr = DxilLibCreateInstance(CLSID_DxcContainerBuilder, (IDxcContainerBuilder**)ppv);
   HRESULT hr = DxilLibCreateInstance(CLSID_DxcContainerBuilder, (IDxcContainerBuilder**)ppv);
   if (FAILED(hr)) {
   if (FAILED(hr)) {
-    warning = "Unable to create container builder from dxil.dll, fallback to built-in.";
+    warning = "Unable to create container builder from dxil.dll. Resulting container will not be signed.\n";
   }
   }
   else {
   else {
     return hr;
     return hr;

+ 80 - 85
tools/clang/tools/dxcompiler/dxcvalidator.cpp

@@ -23,6 +23,7 @@
 #include "dxc/Support/microcom.h"
 #include "dxc/Support/microcom.h"
 #include "dxc/Support/FileIOHelper.h"
 #include "dxc/Support/FileIOHelper.h"
 #include "dxc/Support/dxcapi.impl.h"
 #include "dxc/Support/dxcapi.impl.h"
+#include "dxc/HLSL/DxilRootSignature.h"
 #include "dxcetw.h"
 #include "dxcetw.h"
 
 
 using namespace llvm;
 using namespace llvm;
@@ -61,6 +62,22 @@ static void PrintDiagnosticHandler(const DiagnosticInfo &DI, void *Context) {
   reinterpret_cast<PrintDiagnosticContext *>(Context)->Handle(DI);
   reinterpret_cast<PrintDiagnosticContext *>(Context)->Handle(DI);
 }
 }
 
 
+// Utility class for setting and restoring the diagnostic context so we may capture errors/warnings
+struct DiagRestore {
+  LLVMContext &Ctx;
+  void *OrigDiagContext;
+  LLVMContext::DiagnosticHandlerTy OrigHandler;
+
+  DiagRestore(llvm::LLVMContext &Ctx, void *DiagContext) : Ctx(Ctx) {
+    OrigHandler = Ctx.getDiagnosticHandler();
+    OrigDiagContext = Ctx.getDiagnosticContext();
+    Ctx.setDiagnosticHandler(PrintDiagnosticHandler, DiagContext);
+  }
+  ~DiagRestore() {
+    Ctx.setDiagnosticHandler(OrigHandler, OrigDiagContext);
+  }
+};
+
 class DxcValidator : public IDxcValidator, public IDxcVersionInfo {
 class DxcValidator : public IDxcValidator, public IDxcVersionInfo {
 private:
 private:
   DXC_MICROCOM_REF_FIELD(m_dwRef)
   DXC_MICROCOM_REF_FIELD(m_dwRef)
@@ -68,7 +85,11 @@ private:
   HRESULT RunValidation(
   HRESULT RunValidation(
     _In_ IDxcBlob *pShader,                       // Shader to validate.
     _In_ IDxcBlob *pShader,                       // Shader to validate.
     _In_ llvm::Module *pModule,                   // Module to validate, if available.
     _In_ llvm::Module *pModule,                   // Module to validate, if available.
-    _In_ llvm::Module *pDiagModule,               // Diag module to validate, if available
+    _In_ llvm::Module *pDebugModule,              // Debug module to validate, if available
+    _In_ AbstractMemoryStream *pDiagStream);
+
+  HRESULT RunRootSignatureValidation(
+    _In_ IDxcBlob *pShader,                       // Shader to validate.
     _In_ AbstractMemoryStream *pDiagStream);
     _In_ AbstractMemoryStream *pDiagStream);
 
 
 public:
 public:
@@ -84,7 +105,7 @@ public:
     _In_ IDxcBlob *pShader,                       // Shader to validate.
     _In_ IDxcBlob *pShader,                       // Shader to validate.
     _In_ UINT32 Flags,                            // Validation flags.
     _In_ UINT32 Flags,                            // Validation flags.
     _In_ llvm::Module *pModule,                   // Module to validate, if available.
     _In_ llvm::Module *pModule,                   // Module to validate, if available.
-    _In_ llvm::Module *pDiagModule,               // Diag module to validate, if available
+    _In_ llvm::Module *pDebugModule,              // Debug module to validate, if available
     _COM_Outptr_ IDxcOperationResult **ppResult   // Validation output status, buffer, and errors
     _COM_Outptr_ IDxcOperationResult **ppResult   // Validation output status, buffer, and errors
   );
   );
 
 
@@ -115,7 +136,7 @@ HRESULT DxcValidator::ValidateWithOptModules(
   _In_ IDxcBlob *pShader,                       // Shader to validate.
   _In_ IDxcBlob *pShader,                       // Shader to validate.
   _In_ UINT32 Flags,                            // Validation flags.
   _In_ UINT32 Flags,                            // Validation flags.
   _In_ llvm::Module *pModule,                   // Module to validate, if available.
   _In_ llvm::Module *pModule,                   // Module to validate, if available.
-  _In_ llvm::Module *pDiagModule,               // Diag module to validate, if available
+  _In_ llvm::Module *pDebugModule,              // Debug module to validate, if available
   _COM_Outptr_ IDxcOperationResult **ppResult   // Validation output status, buffer, and errors
   _COM_Outptr_ IDxcOperationResult **ppResult   // Validation output status, buffer, and errors
 ) {
 ) {
   *ppResult = nullptr;
   *ppResult = nullptr;
@@ -130,8 +151,16 @@ HRESULT DxcValidator::ValidateWithOptModules(
 
 
     // Run validation may throw, but that indicates an inability to validate,
     // Run validation may throw, but that indicates an inability to validate,
     // not that the validation failed (eg out of memory).
     // not that the validation failed (eg out of memory).
-    validationStatus = RunValidation(pShader, pModule, pDiagModule, pDiagStream);
-
+    if (Flags & DxcValidatorFlags_RootSignatureOnly) {
+      validationStatus = RunRootSignatureValidation(pShader, pDiagStream);
+    } else {
+      validationStatus = RunValidation(pShader, pModule, pDebugModule, pDiagStream);
+    }
+    if (FAILED(validationStatus)) {
+      std::string msg("Validation failed.\n");
+      ULONG cbWritten;
+      pDiagStream->Write(msg.c_str(), msg.size(), &cbWritten);
+    }
     // Assemble the result object.
     // Assemble the result object.
     CComPtr<IDxcBlob> pDiagBlob;
     CComPtr<IDxcBlob> pDiagBlob;
     CComPtr<IDxcBlobEncoding> pDiagBlobEnconding;
     CComPtr<IDxcBlobEncoding> pDiagBlobEnconding;
@@ -173,95 +202,61 @@ HRESULT DxcValidator::RunValidation(
   // not that the validation failed (eg out of memory). That is indicated
   // not that the validation failed (eg out of memory). That is indicated
   // by a failing HRESULT, and possibly error messages in the diagnostics stream.
   // by a failing HRESULT, and possibly error messages in the diagnostics stream.
 
 
-  llvm::LLVMContext llvmContext;
-  std::unique_ptr<llvm::MemoryBuffer> pBitcodeBuf;
-  std::unique_ptr<llvm::Module> pLoadedModule;
-  std::unique_ptr<llvm::MemoryBuffer> pDbgBitcodeBuf;
-  std::unique_ptr<llvm::Module> pLoadedDbgModule;
   raw_stream_ostream DiagStream(pDiagStream);
   raw_stream_ostream DiagStream(pDiagStream);
-  llvm::DiagnosticPrinterRawOStream DiagPrinter(DiagStream);
-  PrintDiagnosticContext DiagContext(DiagPrinter);
-  if (pModule == nullptr) {
+
+  if (!pModule) {
     DXASSERT_NOMSG(pDebugModule == nullptr);
     DXASSERT_NOMSG(pDebugModule == nullptr);
-    // Accept a bitcode buffer or a DXIL container.
-    const char *pIL = (const char*)pShader->GetBufferPointer();
-    uint32_t pILLength = pShader->GetBufferSize();
-    const char *pDbgIL = nullptr;
-    uint32_t pDbgILLength = 0;
-    if (const DxilContainerHeader *pContainer =
-      IsDxilContainerLike(pIL, pILLength)) {
-      if (!IsValidDxilContainer(pContainer, pILLength)) {
-        IFR(DXC_E_CONTAINER_INVALID);
-      }
-
-      DxilPartIterator it = std::find_if(begin(pContainer), end(pContainer),
-        DxilPartIsType(DFCC_DXIL));
-      if (it == end(pContainer)) {
-        IFR(DXC_E_CONTAINER_MISSING_DXIL);
-      }
-
-      const DxilProgramHeader *pProgramHeader =
-        reinterpret_cast<const DxilProgramHeader *>(GetDxilPartData(*it));
-      if (!IsValidDxilProgramHeader(pProgramHeader, (*it)->PartSize)) {
-        IFR(DXC_E_CONTAINER_INVALID);
-      }
-      GetDxilProgramBitcode(pProgramHeader, &pIL, &pILLength);
-
-      // Look for an optional debug version of the module. If it's there,
-      // it should be valid.
-      DxilPartIterator dbgit = std::find_if(begin(pContainer), end(pContainer),
-        DxilPartIsType(DFCC_ShaderDebugInfoDXIL));
-      if (dbgit != end(pContainer)) {
-        const DxilProgramHeader *pDbgHeader =
-          reinterpret_cast<const DxilProgramHeader *>(GetDxilPartData(*dbgit));
-        if (!IsValidDxilProgramHeader(pDbgHeader, (*dbgit)->PartSize)) {
-          IFR(DXC_E_CONTAINER_INVALID);
-        }
-        GetDxilProgramBitcode(pDbgHeader, &pDbgIL, &pDbgILLength);
-      }
+    if (IsDxilContainerLike(pShader->GetBufferPointer(), pShader->GetBufferSize())) {
+      return ValidateDxilContainer(pShader->GetBufferPointer(), pShader->GetBufferSize(), DiagStream);
+    } else {
+      return ValidateDxilBitcode((const char*)pShader->GetBufferPointer(), (uint32_t)pShader->GetBufferSize(), DiagStream);
     }
     }
+  }
 
 
-    llvmContext.setDiagnosticHandler(PrintDiagnosticHandler, &DiagContext, true);
-    pBitcodeBuf.reset(llvm::MemoryBuffer::getMemBuffer(
-        llvm::StringRef(pIL, pILLength), "", false).release());
-    ErrorOr<std::unique_ptr<llvm::Module>> loadedModuleResult(llvm::parseBitcodeFile(
-      pBitcodeBuf->getMemBufferRef(), llvmContext));
+  llvm::DiagnosticPrinterRawOStream DiagPrinter(DiagStream);
+  PrintDiagnosticContext DiagContext(DiagPrinter);
+  DiagRestore DR(pModule->getContext(), &DiagContext);
 
 
-    // DXIL disallows some LLVM bitcode constructs, like unaccounted-for sub-blocks.
-    // These appear as warnings, which the validator should reject.
-    if (DiagContext.HasErrors() || DiagContext.HasWarnings()) {
-      IFR(DXC_E_IR_VERIFICATION_FAILED);
-    }
-    if (std::error_code ec = loadedModuleResult.getError()) {
-      IFR(DXC_E_IR_VERIFICATION_FAILED);
-    }
-    pLoadedModule.swap(loadedModuleResult.get());
-
-    if (pDbgIL != nullptr) {
-      pDbgBitcodeBuf.reset(llvm::MemoryBuffer::getMemBuffer(
-          llvm::StringRef(pDbgIL, pDbgILLength), "", false).release());
-      ErrorOr<std::unique_ptr<llvm::Module>> loadedDbgModuleResult(
-          llvm::parseBitcodeFile(pDbgBitcodeBuf->getMemBufferRef(), llvmContext));
-      if (std::error_code ec = loadedDbgModuleResult.getError()) {
-        IFR(DXC_E_IR_VERIFICATION_FAILED);
-      }
-      pLoadedDbgModule.swap(loadedDbgModuleResult.get());
-    }
-    pModule = pLoadedModule.get();
-    pDebugModule = pLoadedDbgModule.get();
-  }
-  else {
-    // Install the diagnostic handler on the
-    pModule->getContext().setDiagnosticHandler(PrintDiagnosticHandler,
-                                               &DiagContext, true);
+  IFR(hlsl::ValidateDxilModule(pModule, pDebugModule));
+  IFR(ValidateDxilContainerParts(pModule, pDebugModule,
+                    IsDxilContainerLike(pShader->GetBufferPointer(), pShader->GetBufferSize()),
+                    (uint32_t)pShader->GetBufferSize()));
+
+  if (DiagContext.HasErrors() || DiagContext.HasWarnings()) {
+    return DXC_E_IR_VERIFICATION_FAILED;
   }
   }
 
 
-  if (std::error_code ec = hlsl::ValidateDxilModule(pModule, pDebugModule)) {
-    IFR(DXC_E_IR_VERIFICATION_FAILED);
+  return S_OK;
+}
+
+HRESULT DxcValidator::RunRootSignatureValidation(
+  _In_ IDxcBlob *pShader,
+  _In_ AbstractMemoryStream *pDiagStream) {
+
+  const DxilContainerHeader *pDxilContainer = IsDxilContainerLike(
+    pShader->GetBufferPointer(), pShader->GetBufferSize());
+  if (!pDxilContainer) {
+    return DXC_E_IR_VERIFICATION_FAILED;
   }
   }
 
 
-  // TODO: run validation that cross-references other parts in the
-  // DxilContainer if available.
+  const DxilProgramHeader *pProgramHeader = GetDxilProgramHeader(pDxilContainer, DFCC_DXIL);
+  const DxilPartHeader *pPSVPart = GetDxilPartByType(pDxilContainer, DFCC_PipelineStateValidation);
+  const DxilPartHeader *pRSPart = GetDxilPartByType(pDxilContainer, DFCC_RootSignature);
+  IFRBOOL(pPSVPart && pRSPart, DXC_E_MISSING_PART);
+  try {
+    RootSignatureHandle RSH;
+    RSH.LoadSerialized((const uint8_t*)GetDxilPartData(pRSPart), pRSPart->PartSize);
+    RSH.Deserialize();
+    raw_stream_ostream DiagStream(pDiagStream);
+    IFRBOOL(VerifyRootSignatureWithShaderPSV(RSH.GetDesc(),
+                                             GetVersionShaderType(pProgramHeader->ProgramVersion),
+                                             GetDxilPartData(pPSVPart),
+                                             pPSVPart->PartSize,
+                                             DiagStream),
+      DXC_E_INCORRECT_ROOT_SIGNATURE);
+  } catch(...) {
+    return DXC_E_IR_VERIFICATION_FAILED;
+  }
 
 
   return S_OK;
   return S_OK;
 }
 }

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

@@ -10,6 +10,8 @@ set( LLVM_LINK_COMPONENTS
   dxcsupport
   dxcsupport
   hlsl
   hlsl
   option
   option
+  bitwriter
+  analysis
   )
   )
 
 
 add_clang_library(clang-hlsl-tests SHARED
 add_clang_library(clang-hlsl-tests SHARED

+ 50 - 0
tools/clang/unittests/HLSL/CompilerTest.cpp

@@ -435,6 +435,7 @@ public:
   TEST_METHOD(CodeGenPrecise4)
   TEST_METHOD(CodeGenPrecise4)
   TEST_METHOD(CodeGenPreciseOnCall)
   TEST_METHOD(CodeGenPreciseOnCall)
   TEST_METHOD(CodeGenPreciseOnCallNot)
   TEST_METHOD(CodeGenPreciseOnCallNot)
+  TEST_METHOD(CodeGenRaceCond2)
   TEST_METHOD(CodeGenRaw_Buf1)
   TEST_METHOD(CodeGenRaw_Buf1)
   TEST_METHOD(CodeGenRcp1)
   TEST_METHOD(CodeGenRcp1)
   TEST_METHOD(CodeGenReadFromOutput)
   TEST_METHOD(CodeGenReadFromOutput)
@@ -576,6 +577,7 @@ public:
   TEST_METHOD(CodeGenResourceInTBV2)
   TEST_METHOD(CodeGenResourceInTBV2)
   TEST_METHOD(CodeGenCBufferStructArray)
   TEST_METHOD(CodeGenCBufferStructArray)
   TEST_METHOD(PreprocessWhenValidThenOK)
   TEST_METHOD(PreprocessWhenValidThenOK)
+  TEST_METHOD(WhenSigMismatchPCFunctionThenFail)
 
 
   // Dx11 Sample
   // Dx11 Sample
   TEST_METHOD(CodeGenDX11Sample_2Dquadshaders_Blurx_Ps)
   TEST_METHOD(CodeGenDX11Sample_2Dquadshaders_Blurx_Ps)
@@ -2382,6 +2384,10 @@ TEST_F(CompilerTest, CodeGenPreciseOnCallNot) {
   CodeGenTestCheck(L"..\\CodeGenHLSL\\precise_call_not.hlsl");
   CodeGenTestCheck(L"..\\CodeGenHLSL\\precise_call_not.hlsl");
 }
 }
 
 
+TEST_F(CompilerTest, CodeGenRaceCond2) {
+  CodeGenTest(L"..\\CodeGenHLSL\\RaceCond2.hlsl");
+}
+
 TEST_F(CompilerTest, CodeGenRaw_Buf1) {
 TEST_F(CompilerTest, CodeGenRaw_Buf1) {
   CodeGenTest(L"..\\CodeGenHLSL\\raw_buf1.hlsl");
   CodeGenTest(L"..\\CodeGenHLSL\\raw_buf1.hlsl");
 }
 }
@@ -3706,3 +3712,47 @@ TEST_F(CompilerTest, PreprocessWhenValidThenOK) {
     "\n"
     "\n"
     "int BAR;\n", text.c_str());
     "int BAR;\n", text.c_str());
 }
 }
+
+TEST_F(CompilerTest, WhenSigMismatchPCFunctionThenFail) {
+  CComPtr<IDxcCompiler> pCompiler;
+  CComPtr<IDxcOperationResult> pResult;
+  CComPtr<IDxcBlobEncoding> pSource;
+
+  VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
+  CreateBlobFromText(
+    "struct PSSceneIn \n\
+    { \n\
+      float4 pos  : SV_Position; \n\
+      float2 tex  : TEXCOORD0; \n\
+      float3 norm : NORMAL; \n\
+    }; \n"
+    "struct HSPerPatchData {  \n\
+      float edges[ 3 ] : SV_TessFactor; \n\
+      float inside : SV_InsideTessFactor; \n\
+      float foo : FOO; \n\
+    }; \n"
+    "HSPerPatchData HSPerPatchFunc( InputPatch< PSSceneIn, 3 > points, \n\
+      OutputPatch<PSSceneIn, 3> outpoints) { \n\
+      HSPerPatchData d = (HSPerPatchData)0; \n\
+      d.edges[ 0 ] = points[0].tex.x + outpoints[0].tex.x; \n\
+      d.edges[ 1 ] = 1; \n\
+      d.edges[ 2 ] = 1; \n\
+      d.inside = 1; \n\
+      return d; \n\
+    } \n"
+    "[domain(\"tri\")] \n\
+    [partitioning(\"fractional_odd\")] \n\
+    [outputtopology(\"triangle_cw\")] \n\
+    [patchconstantfunc(\"HSPerPatchFunc\")] \n\
+    [outputcontrolpoints(3)] \n"
+    "void main(const uint id : SV_OutputControlPointID, \n\
+               const InputPatch< PSSceneIn, 3 > points ) { \n\
+    } \n"
+    , &pSource);
+
+  VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
+    L"hs_6_0", nullptr, 0, nullptr, 0, nullptr, &pResult));
+  std::string failLog(VerifyOperationFailed(pResult));
+  VERIFY_ARE_NOT_EQUAL(string::npos, failLog.find(
+    "Signature element SV_Position, referred to by patch constant function, is not found in corresponding hull shader output."));
+}

+ 845 - 64
tools/clang/unittests/HLSL/ValidationTest.cpp

@@ -16,14 +16,17 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Regex.h"
 #include "llvm/Support/Regex.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "dxc/HLSL/DxilContainer.h"
 
 
 #include <atlbase.h>
 #include <atlbase.h>
+#include "dxc/Support/FileIOHelper.h"
 
 
 #include "WexTestClass.h"
 #include "WexTestClass.h"
 #include "DxcTestUtils.h"
 #include "DxcTestUtils.h"
 #include "HlslTestUtils.h"
 #include "HlslTestUtils.h"
 
 
 using namespace std;
 using namespace std;
+using namespace hlsl;
 
 
 void CheckOperationSucceeded(IDxcOperationResult *pResult, IDxcBlob **ppBlob) {
 void CheckOperationSucceeded(IDxcOperationResult *pResult, IDxcBlob **ppBlob) {
   HRESULT status;
   HRESULT status;
@@ -66,6 +69,7 @@ public:
   TEST_METHOD(WhenMultipleModulesThenFail);
   TEST_METHOD(WhenMultipleModulesThenFail);
   TEST_METHOD(WhenUnexpectedEOFThenFail);
   TEST_METHOD(WhenUnexpectedEOFThenFail);
   TEST_METHOD(WhenUnknownBlocksThenFail);
   TEST_METHOD(WhenUnknownBlocksThenFail);
+  TEST_METHOD(WhenZeroInputPatchCountWithInputThenFail);
 
 
   TEST_METHOD(LoadOutputControlPointNotInPatchConstantFunction);
   TEST_METHOD(LoadOutputControlPointNotInPatchConstantFunction);
   TEST_METHOD(StorePatchControlNotInPatchConstantFunction);
   TEST_METHOD(StorePatchControlNotInPatchConstantFunction);
@@ -129,8 +133,9 @@ public:
   TEST_METHOD(I8Type)
   TEST_METHOD(I8Type)
   TEST_METHOD(EmptyStructInBuffer)
   TEST_METHOD(EmptyStructInBuffer)
   TEST_METHOD(BigStructInBuffer)
   TEST_METHOD(BigStructInBuffer)
-  TEST_METHOD(TGSMRaceCond)
-  TEST_METHOD(TGSMRaceCond2)
+  // TODO: enable this.
+  //TEST_METHOD(TGSMRaceCond)
+  //TEST_METHOD(TGSMRaceCond2)
   TEST_METHOD(AddUint64Odd)
   TEST_METHOD(AddUint64Odd)
 
 
   TEST_METHOD(ClipCullMaxComponents)
   TEST_METHOD(ClipCullMaxComponents)
@@ -192,6 +197,36 @@ public:
   TEST_METHOD(WhenMetaFlagsUsageDeclThenOK);
   TEST_METHOD(WhenMetaFlagsUsageDeclThenOK);
   TEST_METHOD(WhenMetaFlagsUsageThenFail);
   TEST_METHOD(WhenMetaFlagsUsageThenFail);
 
 
+  TEST_METHOD(WhenRootSigMismatchThenFail);
+  TEST_METHOD(WhenRootSigCompatThenSucceed);
+  TEST_METHOD(WhenRootSigMatchShaderSucceed_RootConstVis);
+  TEST_METHOD(WhenRootSigMatchShaderFail_RootConstVis);
+  TEST_METHOD(WhenRootSigMatchShaderSucceed_RootCBV);
+  TEST_METHOD(WhenRootSigMatchShaderFail_RootCBV_Range);
+  TEST_METHOD(WhenRootSigMatchShaderFail_RootCBV_Space);
+  TEST_METHOD(WhenRootSigMatchShaderSucceed_RootSRV);
+  TEST_METHOD(WhenRootSigMatchShaderFail_RootSRV_ResType);
+  TEST_METHOD(WhenRootSigMatchShaderSucceed_RootUAV);
+  TEST_METHOD(WhenRootSigMatchShaderSucceed_DescTable);
+  TEST_METHOD(WhenRootSigMatchShaderSucceed_DescTable_GoodRange);
+  TEST_METHOD(WhenRootSigMatchShaderSucceed_DescTable_Unbounded);
+  TEST_METHOD(WhenRootSigMatchShaderFail_DescTable_Range1);
+  TEST_METHOD(WhenRootSigMatchShaderFail_DescTable_Range2);
+  TEST_METHOD(WhenRootSigMatchShaderFail_DescTable_Range3);
+  TEST_METHOD(WhenRootSigMatchShaderFail_DescTable_Space);
+  TEST_METHOD(WhenRootSigMatchShaderSucceed_Unbounded);
+  TEST_METHOD(WhenRootSigMatchShaderFail_Unbounded1);
+  TEST_METHOD(WhenRootSigMatchShaderFail_Unbounded2);
+  TEST_METHOD(WhenRootSigMatchShaderFail_Unbounded3);
+  TEST_METHOD(WhenProgramOutSigMissingThenFail);
+  TEST_METHOD(WhenProgramOutSigUnexpectedThenFail);
+  TEST_METHOD(WhenProgramSigMismatchThenFail);
+  TEST_METHOD(WhenProgramInSigMissingThenFail);
+  TEST_METHOD(WhenProgramSigMismatchThenFail2);
+  TEST_METHOD(WhenProgramPCSigMissingThenFail);
+  TEST_METHOD(WhenPSVMismatchThenFail);
+  TEST_METHOD(WhenFeatureInfoMismatchThenFail);
+
   dxc::DxcDllSupport m_dllSupport;
   dxc::DxcDllSupport m_dllSupport;
 
 
   void TestCheck(LPCWSTR name) {
   void TestCheck(LPCWSTR name) {
@@ -204,12 +239,13 @@ public:
     }
     }
   }
   }
 
 
-  bool CheckOperationResultMsg(IDxcOperationResult *pResult,
-                               const char *pErrorMsg, bool maySucceedAnyway,
+  bool CheckOperationResultMsgs(IDxcOperationResult *pResult,
+                               llvm::ArrayRef<LPCSTR> pErrorMsgs, bool maySucceedAnyway,
                                bool bRegex) {
                                bool bRegex) {
     HRESULT status;
     HRESULT status;
     VERIFY_SUCCEEDED(pResult->GetStatus(&status));
     VERIFY_SUCCEEDED(pResult->GetStatus(&status));
-    if (pErrorMsg == nullptr) {
+    if (pErrorMsgs.empty() || 
+        (pErrorMsgs.size() == 1 && !pErrorMsgs[0])) {
       VERIFY_SUCCEEDED(status);
       VERIFY_SUCCEEDED(status);
     }
     }
     else {
     else {
@@ -219,27 +255,29 @@ public:
       //VERIFY_FAILED(status);
       //VERIFY_FAILED(status);
       CComPtr<IDxcBlobEncoding> text;
       CComPtr<IDxcBlobEncoding> text;
       VERIFY_SUCCEEDED(pResult->GetErrorBuffer(&text));
       VERIFY_SUCCEEDED(pResult->GetErrorBuffer(&text));
-      if (bRegex) {
-        llvm::Regex RE(pErrorMsg);
-        std::string reErrors;
-        VERIFY_IS_TRUE(RE.isValid(reErrors));
-        VERIFY_IS_TRUE(RE.match(llvm::StringRef((const char *)text->GetBufferPointer(), text->GetBufferSize())));
-      } else {
-        const char *pStart = (const char *)text->GetBufferPointer();
-        const char *pEnd = pStart + text->GetBufferSize();
-        const char *pMatch = std::search(pStart, pEnd, pErrorMsg, pErrorMsg + strlen(pErrorMsg));
-        if (pEnd == pMatch) {
-          WEX::Logging::Log::Comment(WEX::Common::String().Format(
-              L"Unable to find '%S' in text:\r\n%.*S", pErrorMsg, (pEnd - pStart),
-              pStart));
+      for (auto pErrorMsg : pErrorMsgs) {
+        if (bRegex) {
+          llvm::Regex RE(pErrorMsg);
+          std::string reErrors;
+          VERIFY_IS_TRUE(RE.isValid(reErrors));
+          VERIFY_IS_TRUE(RE.match(llvm::StringRef((const char *)text->GetBufferPointer(), text->GetBufferSize())));
+        } else {
+          const char *pStart = (const char *)text->GetBufferPointer();
+          const char *pEnd = pStart + text->GetBufferSize();
+          const char *pMatch = std::search(pStart, pEnd, pErrorMsg, pErrorMsg + strlen(pErrorMsg));
+          if (pEnd == pMatch) {
+            WEX::Logging::Log::Comment(WEX::Common::String().Format(
+                L"Unable to find '%S' in text:\r\n%.*S", pErrorMsg, (pEnd - pStart),
+                pStart));
+          }
+          VERIFY_ARE_NOT_EQUAL(pEnd, pMatch);
         }
         }
-        VERIFY_ARE_NOT_EQUAL(pEnd, pMatch);
       }
       }
     }
     }
     return true;
     return true;
   }
   }
 
 
-  void CheckValidationMsg(IDxcBlob *pBlob, const char *pErrorMsg, bool bRegex = false) {
+  void CheckValidationMsgs(IDxcBlob *pBlob, llvm::ArrayRef<LPCSTR> pErrorMsgs, bool bRegex = false) {
     CComPtr<IDxcValidator> pValidator;
     CComPtr<IDxcValidator> pValidator;
     CComPtr<IDxcOperationResult> pResult;
     CComPtr<IDxcOperationResult> pResult;
 
 
@@ -250,10 +288,10 @@ public:
     VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcValidator, &pValidator));
     VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcValidator, &pValidator));
     VERIFY_SUCCEEDED(pValidator->Validate(pBlob, DxcValidatorFlags_Default, &pResult));
     VERIFY_SUCCEEDED(pValidator->Validate(pBlob, DxcValidatorFlags_Default, &pResult));
 
 
-    CheckOperationResultMsg(pResult, pErrorMsg, false, bRegex);
+    CheckOperationResultMsgs(pResult, pErrorMsgs, false, bRegex);
   }
   }
 
 
-  void CheckValidationMsg(const char *pBlob, size_t blobSize, const char *pErrorMsg, bool bRegex = false) {
+  void CheckValidationMsgs(const char *pBlob, size_t blobSize, llvm::ArrayRef<LPCSTR> pErrorMsgs, bool bRegex = false) {
     if (!m_dllSupport.IsEnabled()) {
     if (!m_dllSupport.IsEnabled()) {
       VERIFY_SUCCEEDED(m_dllSupport.Initialize());
       VERIFY_SUCCEEDED(m_dllSupport.Initialize());
     }
     }
@@ -261,7 +299,7 @@ public:
     CComPtr<IDxcBlobEncoding> pBlobEncoding; // Encoding doesn't actually matter, it's binary.
     CComPtr<IDxcBlobEncoding> pBlobEncoding; // Encoding doesn't actually matter, it's binary.
     VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcLibrary, &pLibrary));
     VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcLibrary, &pLibrary));
     VERIFY_SUCCEEDED(pLibrary->CreateBlobWithEncodingFromPinned((LPBYTE)pBlob, blobSize, CP_UTF8, &pBlobEncoding));
     VERIFY_SUCCEEDED(pLibrary->CreateBlobWithEncodingFromPinned((LPBYTE)pBlob, blobSize, CP_UTF8, &pBlobEncoding));
-    CheckValidationMsg(pBlobEncoding, pErrorMsg, bRegex);
+    CheckValidationMsgs(pBlobEncoding, pErrorMsgs, bRegex);
   }
   }
 
 
   void CompileSource(IDxcBlobEncoding *pSource, LPCSTR pShaderModel,
   void CompileSource(IDxcBlobEncoding *pSource, LPCSTR pShaderModel,
@@ -280,6 +318,9 @@ public:
     VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"hlsl.hlsl", L"main",
     VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"hlsl.hlsl", L"main",
                                         shWide, nullptr, 0, nullptr, 0, nullptr,
                                         shWide, nullptr, 0, nullptr, 0, nullptr,
                                         &pResult));
                                         &pResult));
+    HRESULT hr;
+    VERIFY_SUCCEEDED(pResult->GetStatus(&hr));
+    VERIFY_SUCCEEDED(hr);
     VERIFY_SUCCEEDED(pResult->GetResult(pResultBlob));
     VERIFY_SUCCEEDED(pResult->GetResult(pResultBlob));
   }
   }
 
 
@@ -317,13 +358,11 @@ public:
         m_dllSupport.CreateInstance(CLSID_DxcAssembler, &pAssembler));
         m_dllSupport.CreateInstance(CLSID_DxcAssembler, &pAssembler));
     VERIFY_SUCCEEDED(pAssembler->AssembleToContainer(pText, &pAssembleResult));
     VERIFY_SUCCEEDED(pAssembler->AssembleToContainer(pText, &pAssembleResult));
 
 
-    for (auto pErrorMsg : pErrorMsgs) {
-      if (!CheckOperationResultMsg(pAssembleResult, pErrorMsg, true, bRegex)) {
-        // Assembly succeeded, try validation.
-        CComPtr<IDxcBlob> pBlob;
-        VERIFY_SUCCEEDED(pAssembleResult->GetResult(&pBlob));
-        CheckValidationMsg(pBlob, pErrorMsg, bRegex);
-      }
+    if (!CheckOperationResultMsgs(pAssembleResult, pErrorMsgs, true, bRegex)) {
+      // Assembly succeeded, try validation.
+      CComPtr<IDxcBlob> pBlob;
+      VERIFY_SUCCEEDED(pAssembleResult->GetResult(&pBlob));
+      CheckValidationMsgs(pBlob, pErrorMsgs, bRegex);
     }
     }
   }
   }
 
 
@@ -388,21 +427,81 @@ public:
     VERIFY_SUCCEEDED(
     VERIFY_SUCCEEDED(
         m_dllSupport.CreateInstance(CLSID_DxcAssembler, &pAssembler));
         m_dllSupport.CreateInstance(CLSID_DxcAssembler, &pAssembler));
     VERIFY_SUCCEEDED(pAssembler->AssembleToContainer(pText, &pAssembleResult));
     VERIFY_SUCCEEDED(pAssembler->AssembleToContainer(pText, &pAssembleResult));
-    for (auto pErrorMsg : pErrorMsgs) {
-      if (!CheckOperationResultMsg(pAssembleResult, pErrorMsg, true, bRegex)) {
-        // Assembly succeeded, try validation.
-        CComPtr<IDxcBlob> pBlob;
-        VERIFY_SUCCEEDED(pAssembleResult->GetResult(&pBlob));
-        CheckValidationMsg(pBlob, pErrorMsg, bRegex);
+    if (!CheckOperationResultMsgs(pAssembleResult, pErrorMsgs, true, bRegex)) {
+      // Assembly succeeded, try validation.
+      CComPtr<IDxcBlob> pBlob;
+      VERIFY_SUCCEEDED(pAssembleResult->GetResult(&pBlob));
+      CheckValidationMsgs(pBlob, pErrorMsgs, bRegex);
+    }
+  }
+
+  // compile one or two sources, validate module from 1 with container parts from 2, check messages
+  void ReplaceContainerPartsCheckMsgs(LPCSTR pSource1, LPCSTR pSource2, LPCSTR pShaderModel,
+                                     llvm::ArrayRef<DxilFourCC> PartsToReplace,
+                                     llvm::ArrayRef<LPCSTR> pErrorMsgs) {
+    CComPtr<IDxcBlob> pProgram1, pProgram2;
+    CompileSource(pSource1, pShaderModel, &pProgram1);
+    VERIFY_IS_NOT_NULL(pProgram1);
+    if (pSource2) {
+      CompileSource(pSource2, pShaderModel, &pProgram2);
+      VERIFY_IS_NOT_NULL(pProgram2);
+    } else {
+      pProgram2 = pProgram1;
+    }
+
+    // construct container with moudle from pProgram1 with other parts from pProgram2:
+    const DxilContainerHeader *pHeader1 = IsDxilContainerLike(pProgram1->GetBufferPointer(), pProgram1->GetBufferSize());
+    VERIFY_IS_NOT_NULL(pHeader1);
+    const DxilContainerHeader *pHeader2 = IsDxilContainerLike(pProgram2->GetBufferPointer(), pProgram2->GetBufferSize());
+    VERIFY_IS_NOT_NULL(pHeader2);
+
+    DxilContainerWriter *pContainerWriter = NewDxilContainerWriter();
+
+    // Add desired parts from first container
+    for (auto pPart : pHeader1) {
+      for (auto dfcc : PartsToReplace) {
+        if (dfcc == pPart->PartFourCC) {
+          pPart = nullptr;
+          break;
+        }
       }
       }
+      if (!pPart)
+        continue;
+      pContainerWriter->AddPart(pPart->PartFourCC, pPart->PartSize, [=](AbstractMemoryStream *pStream) {
+        ULONG cbWritten = 0;
+        pStream->Write(GetDxilPartData(pPart), pPart->PartSize, &cbWritten);
+      });
     }
     }
+
+    // Add desired parts from second container
+    for (auto pPart : pHeader2) {
+      for (auto dfcc : PartsToReplace) {
+        if (dfcc == pPart->PartFourCC) {
+          pContainerWriter->AddPart(pPart->PartFourCC, pPart->PartSize, [=](AbstractMemoryStream *pStream) {
+            ULONG cbWritten = 0;
+            pStream->Write(GetDxilPartData(pPart), pPart->PartSize, &cbWritten);
+          });
+          break;
+        }
+      }
+    }
+
+    // Write the container
+    CComPtr<IMalloc> pMalloc;
+    VERIFY_SUCCEEDED(CoGetMalloc(1, &pMalloc));
+    CComPtr<AbstractMemoryStream> pOutputStream;
+    VERIFY_SUCCEEDED(CreateMemoryStream(pMalloc, &pOutputStream));
+    pOutputStream->Reserve(pContainerWriter->size());
+    pContainerWriter->write(pOutputStream);
+
+    CheckValidationMsgs((const char *)pOutputStream->GetPtr(), pOutputStream->GetPtrSize(), pErrorMsgs, /*bRegex*/false);
   }
   }
 };
 };
 
 
 TEST_F(ValidationTest, WhenCorrectThenOK) {
 TEST_F(ValidationTest, WhenCorrectThenOK) {
   CComPtr<IDxcBlob> pProgram;
   CComPtr<IDxcBlob> pProgram;
   CompileSource("float4 main() : SV_Target { return 1; }", "ps_6_0", &pProgram);
   CompileSource("float4 main() : SV_Target { return 1; }", "ps_6_0", &pProgram);
-  CheckValidationMsg(pProgram, nullptr);
+  CheckValidationMsgs(pProgram, nullptr);
 }
 }
 
 
 // Lots of these going on below for simplicity in setting up payloads.
 // Lots of these going on below for simplicity in setting up payloads.
@@ -417,7 +516,7 @@ TEST_F(ValidationTest, WhenMisalignedThenFail) {
   const char blob[] = {
   const char blob[] = {
     'B', 'C',
     'B', 'C',
   };
   };
-  CheckValidationMsg(blob, _countof(blob), "Invalid bitcode size");
+  CheckValidationMsgs(blob, _countof(blob), "Invalid bitcode size");
 }
 }
 
 
 TEST_F(ValidationTest, WhenEmptyFileThenFail) {
 TEST_F(ValidationTest, WhenEmptyFileThenFail) {
@@ -425,7 +524,7 @@ TEST_F(ValidationTest, WhenEmptyFileThenFail) {
   const char blob[] = {
   const char blob[] = {
     'B', 'C', 0xc0, 0xde
     'B', 'C', 0xc0, 0xde
   };
   };
-  CheckValidationMsg(blob, _countof(blob), "Malformed IR file");
+  CheckValidationMsgs(blob, _countof(blob), "Malformed IR file");
 }
 }
 
 
 TEST_F(ValidationTest, WhenIncorrectMagicThenFail) {
 TEST_F(ValidationTest, WhenIncorrectMagicThenFail) {
@@ -433,14 +532,14 @@ TEST_F(ValidationTest, WhenIncorrectMagicThenFail) {
   const char blob[] = {
   const char blob[] = {
     'B', 'C', 0xc0, 0xdd
     'B', 'C', 0xc0, 0xdd
   };
   };
-  CheckValidationMsg(blob, _countof(blob), "Invalid bitcode signature");
+  CheckValidationMsgs(blob, _countof(blob), "Invalid bitcode signature");
 }
 }
 
 
 TEST_F(ValidationTest, WhenIncorrectTargetTripleThenFail) {
 TEST_F(ValidationTest, WhenIncorrectTargetTripleThenFail) {
   const char blob[] = {
   const char blob[] = {
     'B', 'C', 0xc0, 0xde
     'B', 'C', 0xc0, 0xde
   };
   };
-  CheckValidationMsg(blob, _countof(blob), "Malformed IR file");
+  CheckValidationMsgs(blob, _countof(blob), "Malformed IR file");
 }
 }
 
 
 TEST_F(ValidationTest, WhenMultipleModulesThenFail) {
 TEST_F(ValidationTest, WhenMultipleModulesThenFail) {
@@ -453,7 +552,7 @@ TEST_F(ValidationTest, WhenMultipleModulesThenFail) {
     // Trigger the case we're looking for now
     // Trigger the case we're looking for now
     0x21, 0x0c, 0x00, 0x00, // Enter sub-block, BlockID = 8, Code Size=3, padding x2
     0x21, 0x0c, 0x00, 0x00, // Enter sub-block, BlockID = 8, Code Size=3, padding x2
   };
   };
-  CheckValidationMsg(blob, _countof(blob), "Unused bits in buffer");
+  CheckValidationMsgs(blob, _countof(blob), "Unused bits in buffer");
 }
 }
 
 
 TEST_F(ValidationTest, WhenUnexpectedEOFThenFail) {
 TEST_F(ValidationTest, WhenUnexpectedEOFThenFail) {
@@ -463,7 +562,7 @@ TEST_F(ValidationTest, WhenUnexpectedEOFThenFail) {
     0x21, 0x0c, 0x00, 0x00, // Enter sub-block, BlockID = 8, Code Size=3, padding x2
     0x21, 0x0c, 0x00, 0x00, // Enter sub-block, BlockID = 8, Code Size=3, padding x2
     0x00, 0x00, 0x00, 0x00, // NumWords = 0
     0x00, 0x00, 0x00, 0x00, // NumWords = 0
   };
   };
-  CheckValidationMsg(blob, _countof(blob), "Invalid record");
+  CheckValidationMsgs(blob, _countof(blob), "Invalid record");
 }
 }
 
 
 TEST_F(ValidationTest, WhenUnknownBlocksThenFail) {
 TEST_F(ValidationTest, WhenUnknownBlocksThenFail) {
@@ -471,7 +570,15 @@ TEST_F(ValidationTest, WhenUnknownBlocksThenFail) {
     'B', 'C', 0xc0, 0xde,   // Signature
     'B', 'C', 0xc0, 0xde,   // Signature
     0x31, 0x00, 0x00, 0x00  // Enter sub-block, BlockID != 8
     0x31, 0x00, 0x00, 0x00  // Enter sub-block, BlockID != 8
   };
   };
-  CheckValidationMsg(blob, _countof(blob), "Unrecognized block found");
+  CheckValidationMsgs(blob, _countof(blob), "Unrecognized block found");
+}
+
+TEST_F(ValidationTest, WhenZeroInputPatchCountWithInputThenFail) {
+	RewriteAssemblyCheckMsg(
+		L"..\\CodeGenHLSL\\SimpleHs1.hlsl", "hs_6_0",
+		"void ()* @\"\\01?HSPerPatchFunc@@YA?AUHSPerPatchData@@V?$InputPatch@UPSSceneIn@@$02@@@Z.flat\", i32 3, i32 3",
+		"void ()* @\"\\01?HSPerPatchFunc@@YA?AUHSPerPatchData@@V?$InputPatch@UPSSceneIn@@$02@@@Z.flat\", i32 0, i32 3",
+		"When HS input control point count is 0, no input signature should exist");
 }
 }
 
 
 TEST_F(ValidationTest, WhenInstrDisallowedThenFail) {
 TEST_F(ValidationTest, WhenInstrDisallowedThenFail) {
@@ -603,7 +710,7 @@ TEST_F(ValidationTest, HsAttributeFail) {
       },
       },
       {"i32 36, i32 36, i32 0, i32 0, i32 0, float 6.500000e+01"
       {"i32 36, i32 36, i32 0, i32 0, i32 0, float 6.500000e+01"
       },
       },
-      {"HS input control point count must be [1..32].  36 specified",
+      {"HS input control point count must be [0..32].  36 specified",
        "Invalid Tessellator Domain specified. Must be isoline, tri or quad",
        "Invalid Tessellator Domain specified. Must be isoline, tri or quad",
        "Invalid Tessellator Partitioning specified",
        "Invalid Tessellator Partitioning specified",
        "Invalid Tessellator Output Primitive specified",
        "Invalid Tessellator Output Primitive specified",
@@ -825,14 +932,7 @@ TEST_F(ValidationTest, UavBarrierFail) {
        "sync in a non-Compute Shader must only sync UAV (sync_uglobal)"});
        "sync in a non-Compute Shader must only sync UAV (sync_uglobal)"});
 }
 }
 TEST_F(ValidationTest, UndefValueFail) {
 TEST_F(ValidationTest, UndefValueFail) {
-  RewriteAssemblyCheckMsg(
-      L"..\\CodeGenHLSL\\UndefValue.hlsl", "ps_6_0",
-      {"fadd fast float %([0-9]+)"
-      },
-      {"fadd fast float undef"
-      },
-      {"Instructions should not read uninitialized value"},
-      /*bRegex*/ true);
+  TestCheck(L"..\\CodeGenHLSL\\UndefValue.hlsl");
 }
 }
 TEST_F(ValidationTest, UpdateCounterFail) {
 TEST_F(ValidationTest, UpdateCounterFail) {
   RewriteAssemblyCheckMsg(
   RewriteAssemblyCheckMsg(
@@ -1340,17 +1440,19 @@ TEST_F(ValidationTest, BigStructInBuffer) {
   TestCheck(L"..\\CodeGenHLSL\\BigStructInBuffer.hlsl");
   TestCheck(L"..\\CodeGenHLSL\\BigStructInBuffer.hlsl");
 }
 }
 
 
-TEST_F(ValidationTest, TGSMRaceCond) {
-  TestCheck(L"..\\CodeGenHLSL\\RaceCond.hlsl");
-}
-
-TEST_F(ValidationTest, TGSMRaceCond2) {
-    RewriteAssemblyCheckMsg(L"..\\CodeGenHLSL\\structInBuffer.hlsl", "cs_6_0",
-        "ret void",
-        "store i32 0, i32 addrspace(3)* @\"\\01?sharedData@@3UFoo@@A.3\", align 4\n"
-        "ret void",
-        "Race condition writing to shared memory detected, consider making this write conditional");
-}
+// TODO: enable this.
+//TEST_F(ValidationTest, TGSMRaceCond) {
+//  TestCheck(L"..\\CodeGenHLSL\\RaceCond.hlsl");
+//}
+//
+//TEST_F(ValidationTest, TGSMRaceCond2) {
+//    RewriteAssemblyCheckMsg(L"..\\CodeGenHLSL\\structInBuffer.hlsl", "cs_6_0",
+//        "ret void",
+//        "%TID = call i32 @dx.op.flattenedThreadIdInGroup.i32(i32 96)\n"
+//        "store i32 %TID, i32 addrspace(3)* @\"\\01?sharedData@@3UFoo@@A.3\", align 4\n"
+//        "ret void",
+//        "Race condition writing to shared memory detected, consider making this write conditional");
+//}
 
 
 TEST_F(ValidationTest, AddUint64Odd) {
 TEST_F(ValidationTest, AddUint64Odd) {
   TestCheck(L"..\\CodeGenHLSL\\AddUint64Odd.hlsl");
   TestCheck(L"..\\CodeGenHLSL\\AddUint64Odd.hlsl");
@@ -2037,6 +2139,685 @@ float4 main(float4 f4 : Input, out float d0 : SV_Depth, out float d1 : SV_Target
     /*bRegex*/true);
     /*bRegex*/true);
 }
 }
 
 
+TEST_F(ValidationTest, WhenRootSigMismatchThenFail) {
+  ReplaceContainerPartsCheckMsgs(
+    "float c; [RootSignature ( \"RootConstants(b0, num32BitConstants = 1)\" )] float4 main() : semantic { return c; }",
+    "[RootSignature ( \"\" )] float4 main() : semantic { return 0; }",
+    "vs_6_0",
+    {DFCC_RootSignature},
+    {
+      "Root Signature in DXIL container is not compatible with shader.",
+      "Validation failed."
+    }
+  );
+}
+TEST_F(ValidationTest, WhenRootSigCompatThenSucceed) {
+  ReplaceContainerPartsCheckMsgs(
+    "[RootSignature ( \"\" )] float4 main() : semantic { return 0; }",
+    "float c; [RootSignature ( \"RootConstants(b0, num32BitConstants = 1)\" )] float4 main() : semantic { return c; }",
+    "vs_6_0",
+    {DFCC_RootSignature},
+    {}
+  );
+}
+
+TEST_F(ValidationTest, WhenRootSigMatchShaderSucceed_RootConstVis) {
+  ReplaceContainerPartsCheckMsgs(
+    "float c; float4 main() : semantic { return c; }",
+    "[RootSignature ( \"RootConstants(b0, visibility = SHADER_VISIBILITY_VERTEX, num32BitConstants = 1)\" )]"
+    "  float4 main() : semantic { return 0; }",
+    "vs_6_0",
+    {DFCC_RootSignature},
+    {}
+  );
+}
+TEST_F(ValidationTest, WhenRootSigMatchShaderFail_RootConstVis) {
+  ReplaceContainerPartsCheckMsgs(
+    "float c; float4 main() : semantic { return c; }",
+    "[RootSignature ( \"RootConstants(b0, visibility = SHADER_VISIBILITY_PIXEL, num32BitConstants = 1)\" )]"
+    "  float4 main() : semantic { return 0; }",
+    "vs_6_0",
+    {DFCC_RootSignature},
+    {
+      "Root Signature in DXIL container is not compatible with shader.",
+      "Validation failed."
+    }
+  );
+}
+
+TEST_F(ValidationTest, WhenRootSigMatchShaderSucceed_RootCBV) {
+  ReplaceContainerPartsCheckMsgs(
+    "struct Foo { float a; int4 b; }; "
+    "ConstantBuffer<Foo> cb1 : register(b2, space5); "
+    "float4 main() : semantic { return cb1.b.x; }",
+    "[RootSignature ( \"CBV(b2, space = 5)\" )]"
+    "  float4 main() : semantic { return 0; }",
+    "vs_6_0",
+    {DFCC_RootSignature},
+    {}
+  );
+}
+TEST_F(ValidationTest, WhenRootSigMatchShaderFail_RootCBV_Range) {
+  ReplaceContainerPartsCheckMsgs(
+    "struct Foo { float a; int4 b; }; "
+    "ConstantBuffer<Foo> cb1 : register(b0, space5); "
+    "float4 main() : semantic { return cb1.b.x; }",
+    "[RootSignature ( \"CBV(b2, space = 5)\" )]"
+    "  float4 main() : semantic { return 0; }",
+    "vs_6_0",
+    {DFCC_RootSignature},
+    {
+      "Root Signature in DXIL container is not compatible with shader.",
+      "Validation failed."
+    }
+  );
+}
+TEST_F(ValidationTest, WhenRootSigMatchShaderFail_RootCBV_Space) {
+  ReplaceContainerPartsCheckMsgs(
+    "struct Foo { float a; int4 b; }; "
+    "ConstantBuffer<Foo> cb1 : register(b2, space7); "
+    "float4 main() : semantic { return cb1.b.x; }",
+    "[RootSignature ( \"CBV(b2, space = 5)\" )]"
+    "  float4 main() : semantic { return 0; }",
+    "vs_6_0",
+    {DFCC_RootSignature},
+    {
+      "Root Signature in DXIL container is not compatible with shader.",
+      "Validation failed."
+    }
+  );
+}
+
+TEST_F(ValidationTest, WhenRootSigMatchShaderSucceed_RootSRV) {
+  ReplaceContainerPartsCheckMsgs(
+    "struct Foo { float4 a; }; "
+    "StructuredBuffer<Foo> buf1 : register(t1, space3); "
+    "float4 main(float4 a : AAA) : SV_Target { return buf1[a.x].a; }",
+    "[RootSignature ( \"SRV(t1, space = 3)\" )]"
+    "  float4 main() : SV_Target { return 0; }",
+    "ps_6_0",
+    {DFCC_RootSignature},
+    {}
+  );
+}
+TEST_F(ValidationTest, WhenRootSigMatchShaderFail_RootSRV_ResType) {
+  ReplaceContainerPartsCheckMsgs(
+    "struct Foo { float4 a; }; "
+    "StructuredBuffer<Foo> buf1 : register(t1, space3); "
+    "float4 main(float4 a : AAA) : SV_Target { return buf1[a.x].a; }",
+    "[RootSignature ( \"UAV(u1, space = 3)\" )]"
+    "  float4 main() : SV_Target { return 0; }",
+    "ps_6_0",
+    {DFCC_RootSignature},
+    {
+      "Root Signature in DXIL container is not compatible with shader.",
+      "Validation failed."
+    }
+  );
+}
+
+TEST_F(ValidationTest, WhenRootSigMatchShaderSucceed_RootUAV) {
+  ReplaceContainerPartsCheckMsgs(
+    "struct Foo { float4 a; }; "
+    "RWStructuredBuffer<Foo> buf1 : register(u1, space3); "
+    "float4 main(float4 a : AAA) : SV_Target { return buf1[a.x].a; }",
+    "[RootSignature ( \"UAV(u1, space = 3)\" )]"
+    "  float4 main() : SV_Target { return 0; }",
+    "ps_6_0",
+    {DFCC_RootSignature},
+    {}
+  );
+}
+
+TEST_F(ValidationTest, WhenRootSigMatchShaderSucceed_DescTable) {
+  ReplaceContainerPartsCheckMsgs(
+    "struct Foo { int a; float4 b; };"
+    ""
+    "ConstantBuffer<Foo> cb1[4] : register(b2, space5);"
+    "Texture2D<float4> tex1[8]  : register(t1, space3);"
+    "RWBuffer<float4> buf1[6]   : register(u33, space17);"
+    "SamplerState sampler1[5]   : register(s0, space0);"
+    ""
+    "float4 main(float4 a : AAA) : SV_TARGET"
+    "{"
+    "  return buf1[a.x][a.y] + cb1[a.x].b + tex1[a.x].Sample(sampler1[a.x], a.xy);"
+    "}",
+    "[RootSignature(\"DescriptorTable( SRV(t1,space=3,numDescriptors=8), "
+                                      "CBV(b2,space=5,numDescriptors=4), "
+                                      "UAV(u33,space=17,numDescriptors=6)), "
+                     "DescriptorTable(Sampler(s0, numDescriptors=5))\")]"
+    "  float4 main() : SV_Target { return 0; }",
+    "ps_6_0",
+    {DFCC_RootSignature},
+    {}
+  );
+}
+
+TEST_F(ValidationTest, WhenRootSigMatchShaderSucceed_DescTable_GoodRange) {
+  ReplaceContainerPartsCheckMsgs(
+    "struct Foo { int a; float4 b; };"
+    ""
+    "ConstantBuffer<Foo> cb1[4] : register(b2, space5);"
+    "Texture2D<float4> tex1[8]  : register(t1, space3);"
+    "RWBuffer<float4> buf1[6]   : register(u33, space17);"
+    "SamplerState sampler1[5]   : register(s0, space0);"
+    ""
+    "float4 main(float4 a : AAA) : SV_TARGET"
+    "{"
+    "  return buf1[a.x][a.y] + cb1[a.x].b + tex1[a.x].Sample(sampler1[a.x], a.xy);"
+    "}",
+    "[RootSignature(\"DescriptorTable( SRV(t0,space=3,numDescriptors=20), "
+                                      "CBV(b2,space=5,numDescriptors=4), "
+                                      "UAV(u33,space=17,numDescriptors=6)), "
+                     "DescriptorTable(Sampler(s0, numDescriptors=5))\")]"
+    "  float4 main() : SV_Target { return 0; }",
+    "ps_6_0",
+    {DFCC_RootSignature},
+    {}
+  );
+}
+
+TEST_F(ValidationTest, WhenRootSigMatchShaderSucceed_DescTable_Unbounded) {
+  ReplaceContainerPartsCheckMsgs(
+    "struct Foo { int a; float4 b; };"
+    ""
+    "ConstantBuffer<Foo> cb1[4] : register(b2, space5);"
+    "Texture2D<float4> tex1[8]  : register(t1, space3);"
+    "RWBuffer<float4> buf1[6]   : register(u33, space17);"
+    "SamplerState sampler1[5]   : register(s0, space0);"
+    ""
+    "float4 main(float4 a : AAA) : SV_TARGET"
+    "{"
+    "  return buf1[a.x][a.y] + cb1[a.x].b + tex1[a.x].Sample(sampler1[a.x], a.xy);"
+    "}",
+    "[RootSignature(\"DescriptorTable( CBV(b2,space=5,numDescriptors=4), "
+                                      "SRV(t1,space=3,numDescriptors=8), "
+                                      "UAV(u10,space=17,numDescriptors=unbounded)), "
+                     "DescriptorTable(Sampler(s0, numDescriptors=5))\")]"
+    "  float4 main() : SV_Target { return 0; }",
+    "ps_6_0",
+    {DFCC_RootSignature},
+    {}
+  );
+}
+
+TEST_F(ValidationTest, WhenRootSigMatchShaderFail_DescTable_Range1) {
+  ReplaceContainerPartsCheckMsgs(
+    "struct Foo { int a; float4 b; };"
+    ""
+    "ConstantBuffer<Foo> cb1[4] : register(b2, space5);"
+    "Texture2D<float4> tex1[8]  : register(t1, space3);"
+    "RWBuffer<float4> buf1[6]   : register(u33, space17);"
+    "SamplerState sampler1[5]   : register(s0, space0);"
+    ""
+    "float4 main(float4 a : AAA) : SV_TARGET"
+    "{"
+    "  return buf1[a.x][a.y] + cb1[a.x].b + tex1[a.x].Sample(sampler1[a.x], a.xy);"
+    "}",
+    "[RootSignature(\"DescriptorTable( CBV(b2,space=5,numDescriptors=4), "
+                                      "SRV(t2,space=3,numDescriptors=8), "
+                                      "UAV(u33,space=17,numDescriptors=6)), "
+                     "DescriptorTable(Sampler(s0, numDescriptors=5))\")]"
+    "  float4 main() : SV_Target { return 0; }",
+    "ps_6_0",
+    {DFCC_RootSignature},
+    {
+      "Shader SRV descriptor range (RegisterSpace=3, NumDescriptors=8, BaseShaderRegister=1) is not fully bound in root signature.",
+      "Root Signature in DXIL container is not compatible with shader.",
+      "Validation failed."
+    }
+  );
+}
+
+TEST_F(ValidationTest, WhenRootSigMatchShaderFail_DescTable_Range2) {
+  ReplaceContainerPartsCheckMsgs(
+    "struct Foo { int a; float4 b; };"
+    ""
+    "ConstantBuffer<Foo> cb1[4] : register(b2, space5);"
+    "Texture2D<float4> tex1[8]  : register(t1, space3);"
+    "RWBuffer<float4> buf1[6]   : register(u33, space17);"
+    "SamplerState sampler1[5]   : register(s0, space0);"
+    ""
+    "float4 main(float4 a : AAA) : SV_TARGET"
+    "{"
+    "  return buf1[a.x][a.y] + cb1[a.x].b + tex1[a.x].Sample(sampler1[a.x], a.xy);"
+    "}",
+    "[RootSignature(\"DescriptorTable( SRV(t2,space=3,numDescriptors=8), "
+                                      "CBV(b20,space=5,numDescriptors=4), "
+                                      "UAV(u33,space=17,numDescriptors=6)), "
+                     "DescriptorTable(Sampler(s0, numDescriptors=5))\")]"
+    "  float4 main() : SV_Target { return 0; }",
+    "ps_6_0",
+    {DFCC_RootSignature},
+    {
+      "Root Signature in DXIL container is not compatible with shader.",
+      "Validation failed."
+    }
+  );
+}
+
+TEST_F(ValidationTest, WhenRootSigMatchShaderFail_DescTable_Range3) {
+  ReplaceContainerPartsCheckMsgs(
+    "struct Foo { int a; float4 b; };"
+    ""
+    "ConstantBuffer<Foo> cb1[4] : register(b2, space5);"
+    "Texture2D<float4> tex1[8]  : register(t1, space3);"
+    "RWBuffer<float4> buf1[6]   : register(u33, space17);"
+    "SamplerState sampler1[5]   : register(s0, space0);"
+    ""
+    "float4 main(float4 a : AAA) : SV_TARGET"
+    "{"
+    "  return buf1[a.x][a.y] + cb1[a.x].b + tex1[a.x].Sample(sampler1[a.x], a.xy);"
+    "}",
+    "[RootSignature(\"DescriptorTable( CBV(b2,space=5,numDescriptors=4), "
+                                      "SRV(t1,space=3,numDescriptors=8), "
+                                      "UAV(u33,space=17,numDescriptors=5)), "
+                     "DescriptorTable(Sampler(s0, numDescriptors=5))\")]"
+    "  float4 main() : SV_Target { return 0; }",
+    "ps_6_0",
+    {DFCC_RootSignature},
+    {
+      "Root Signature in DXIL container is not compatible with shader.",
+      "Validation failed."
+    }
+  );
+}
+
+TEST_F(ValidationTest, WhenRootSigMatchShaderFail_DescTable_Space) {
+  ReplaceContainerPartsCheckMsgs(
+    "struct Foo { int a; float4 b; };"
+    ""
+    "ConstantBuffer<Foo> cb1[4] : register(b2, space5);"
+    "Texture2D<float4> tex1[8]  : register(t1, space3);"
+    "RWBuffer<float4> buf1[6]   : register(u33, space17);"
+    "SamplerState sampler1[5]   : register(s0, space0);"
+    ""
+    "float4 main(float4 a : AAA) : SV_TARGET"
+    "{"
+    "  return buf1[a.x][a.y] + cb1[a.x].b + tex1[a.x].Sample(sampler1[a.x], a.xy);"
+    "}",
+    "[RootSignature(\"DescriptorTable( SRV(t2,space=3,numDescriptors=8), "
+                                      "CBV(b2,space=5,numDescriptors=4), "
+                                      "UAV(u33,space=0,numDescriptors=6)), "
+                     "DescriptorTable(Sampler(s0, numDescriptors=5))\")]"
+    "  float4 main() : SV_Target { return 0; }",
+    "ps_6_0",
+    {DFCC_RootSignature},
+    {
+      "Root Signature in DXIL container is not compatible with shader.",
+      "Validation failed."
+    }
+  );
+}
+
+TEST_F(ValidationTest, WhenRootSigMatchShaderSucceed_Unbounded) {
+  ReplaceContainerPartsCheckMsgs(
+    "struct Foo { int a; float4 b; };"
+    ""
+    "ConstantBuffer<Foo> cb1[]  : register(b2, space5);"
+    "Texture2D<float4> tex1[]   : register(t1, space3);"
+    "RWBuffer<float4> buf1[]    : register(u33, space17);"
+    "SamplerState sampler1[]    : register(s0, space0);"
+    ""
+    "float4 main(float4 a : AAA) : SV_TARGET"
+    "{"
+    "  return buf1[a.x][a.y] + cb1[a.x].b + tex1[a.x].Sample(sampler1[a.x], a.xy);"
+    "}",
+    "[RootSignature(\"DescriptorTable( CBV(b2,space=5,numDescriptors=1)), "
+                     "DescriptorTable( SRV(t1,space=3,numDescriptors=unbounded)), "
+                     "DescriptorTable( UAV(u10,space=17,numDescriptors=100)), "
+                     "DescriptorTable(Sampler(s0, numDescriptors=5))\")]"
+    "  float4 main() : SV_Target { return 0; }",
+    "ps_6_0",
+    {DFCC_RootSignature},
+    {}
+  );
+}
+
+TEST_F(ValidationTest, WhenRootSigMatchShaderFail_Unbounded1) {
+  ReplaceContainerPartsCheckMsgs(
+    "struct Foo { int a; float4 b; };"
+    ""
+    "ConstantBuffer<Foo> cb1[]  : register(b2, space5);"
+    "Texture2D<float4> tex1[]   : register(t1, space3);"
+    "RWBuffer<float4> buf1[]    : register(u33, space17);"
+    "SamplerState sampler1[]    : register(s0, space0);"
+    ""
+    "float4 main(float4 a : AAA) : SV_TARGET"
+    "{"
+    "  return buf1[a.x][a.y] + cb1[a.x].b + tex1[a.x].Sample(sampler1[a.x], a.xy);"
+    "}",
+    "[RootSignature(\"DescriptorTable( CBV(b3,space=5,numDescriptors=1)), "
+                     "DescriptorTable( SRV(t1,space=3,numDescriptors=unbounded)), "
+                     "DescriptorTable( UAV(u10,space=17,numDescriptors=unbounded)), "
+                     "DescriptorTable( Sampler(s0, numDescriptors=5))\")]"
+    "  float4 main() : SV_Target { return 0; }",
+    "ps_6_0",
+    {DFCC_RootSignature},
+    {
+      "Root Signature in DXIL container is not compatible with shader.",
+      "Validation failed."
+    }
+  );
+}
+
+TEST_F(ValidationTest, WhenRootSigMatchShaderFail_Unbounded2) {
+  ReplaceContainerPartsCheckMsgs(
+    "struct Foo { int a; float4 b; };"
+    ""
+    "ConstantBuffer<Foo> cb1[]  : register(b2, space5);"
+    "Texture2D<float4> tex1[]   : register(t1, space3);"
+    "RWBuffer<float4> buf1[]    : register(u33, space17);"
+    "SamplerState sampler1[]    : register(s0, space0);"
+    ""
+    "float4 main(float4 a : AAA) : SV_TARGET"
+    "{"
+    "  return buf1[a.x][a.y] + cb1[a.x].b + tex1[a.x].Sample(sampler1[a.x], a.xy);"
+    "}",
+    "[RootSignature(\"DescriptorTable( CBV(b2,space=5,numDescriptors=1)), "
+                     "DescriptorTable( SRV(t1,space=3,numDescriptors=unbounded)), "
+                     "DescriptorTable( UAV(u10,space=17,numDescriptors=unbounded)), "
+                     "DescriptorTable( Sampler(s5, numDescriptors=unbounded))\")]"
+    "  float4 main() : SV_Target { return 0; }",
+    "ps_6_0",
+    {DFCC_RootSignature},
+    {
+      "Root Signature in DXIL container is not compatible with shader.",
+      "Validation failed."
+    }
+  );
+}
+
+TEST_F(ValidationTest, WhenRootSigMatchShaderFail_Unbounded3) {
+  ReplaceContainerPartsCheckMsgs(
+    "struct Foo { int a; float4 b; };"
+    ""
+    "ConstantBuffer<Foo> cb1[]  : register(b2, space5);"
+    "Texture2D<float4> tex1[]   : register(t1, space3);"
+    "RWBuffer<float4> buf1[]    : register(u33, space17);"
+    "SamplerState sampler1[]    : register(s0, space0);"
+    ""
+    "float4 main(float4 a : AAA) : SV_TARGET"
+    "{"
+    "  return buf1[a.x][a.y] + cb1[a.x].b + tex1[a.x].Sample(sampler1[a.x], a.xy);"
+    "}",
+    "[RootSignature(\"DescriptorTable( CBV(b2,space=5,numDescriptors=1)), "
+                     "DescriptorTable( SRV(t1,space=3,numDescriptors=unbounded)), "
+                     "DescriptorTable( UAV(u10,space=17,numDescriptors=7)), "
+                     "DescriptorTable(Sampler(s0, numDescriptors=5))\")]"
+    "  float4 main() : SV_Target { return 0; }",
+    "ps_6_0",
+    {DFCC_RootSignature},
+    {
+      "Root Signature in DXIL container is not compatible with shader.",
+      "Validation failed."
+    }
+  );
+}
+
+#define VERTEX_STRUCT1 \
+    "struct PSSceneIn \n\
+    { \n\
+      float4 pos  : SV_Position; \n\
+      float2 tex  : TEXCOORD0; \n\
+      float3 norm : NORMAL; \n\
+    }; \n"
+#define VERTEX_STRUCT2 \
+    "struct PSSceneIn \n\
+    { \n\
+      float4 pos  : SV_Position; \n\
+      float2 tex  : TEXCOORD0; \n\
+    }; \n"
+#define PC_STRUCT1 "struct HSPerPatchData {  \n\
+      float edges[ 3 ] : SV_TessFactor; \n\
+      float inside : SV_InsideTessFactor; \n\
+      float foo : FOO; \n\
+    }; \n"
+#define PC_STRUCT2 "struct HSPerPatchData {  \n\
+      float edges[ 3 ] : SV_TessFactor; \n\
+      float inside : SV_InsideTessFactor; \n\
+    }; \n"
+#define PC_FUNC "HSPerPatchData HSPerPatchFunc( InputPatch< PSSceneIn, 3 > points, \n\
+      OutputPatch<PSSceneIn, 3> outpoints) { \n\
+      HSPerPatchData d = (HSPerPatchData)0; \n\
+      d.edges[ 0 ] = points[0].tex.x + outpoints[0].tex.x; \n\
+      d.edges[ 1 ] = 1; \n\
+      d.edges[ 2 ] = 1; \n\
+      d.inside = 1; \n\
+      return d; \n\
+    } \n"
+#define PC_FUNC_NOOUT "HSPerPatchData HSPerPatchFunc( InputPatch< PSSceneIn, 3 > points ) { \n\
+      HSPerPatchData d = (HSPerPatchData)0; \n\
+      d.edges[ 0 ] = points[0].tex.x; \n\
+      d.edges[ 1 ] = 1; \n\
+      d.edges[ 2 ] = 1; \n\
+      d.inside = 1; \n\
+      return d; \n\
+    } \n"
+#define PC_FUNC_NOIN "HSPerPatchData HSPerPatchFunc( OutputPatch<PSSceneIn, 3> outpoints) { \n\
+      HSPerPatchData d = (HSPerPatchData)0; \n\
+      d.edges[ 0 ] = outpoints[0].tex.x; \n\
+      d.edges[ 1 ] = 1; \n\
+      d.edges[ 2 ] = 1; \n\
+      d.inside = 1; \n\
+      return d; \n\
+    } \n"
+#define HS_ATTR "[domain(\"tri\")] \n\
+    [partitioning(\"fractional_odd\")] \n\
+    [outputtopology(\"triangle_cw\")] \n\
+    [patchconstantfunc(\"HSPerPatchFunc\")] \n\
+    [outputcontrolpoints(3)] \n"
+#define HS_FUNC \
+    "PSSceneIn main(const uint id : SV_OutputControlPointID, \n\
+                    const InputPatch< PSSceneIn, 3 > points ) { \n\
+      return points[ id ]; \n\
+    } \n"
+#define HS_FUNC_NOOUT \
+    "void main(const uint id : SV_OutputControlPointID, \n\
+               const InputPatch< PSSceneIn, 3 > points ) { \n\
+    } \n"
+#define HS_FUNC_NOIN \
+    "PSSceneIn main( const uint id : SV_OutputControlPointID ) { \n\
+      return (PSSceneIn)0; \n\
+    } \n"
+#define DS_FUNC \
+    "[domain(\"tri\")] PSSceneIn main(const float3 bary : SV_DomainLocation, \n\
+                                      const OutputPatch<PSSceneIn, 3> patch, \n\
+                                      const HSPerPatchData perPatchData) { \n\
+      PSSceneIn v = patch[0]; \n\
+      v.pos = patch[0].pos * bary.x; \n\
+      v.pos += patch[1].pos * bary.y; \n\
+      v.pos += patch[2].pos * bary.z; \n\
+      return v; \n\
+    } \n"
+#define DS_FUNC_NOPC \
+    "[domain(\"tri\")] PSSceneIn main(const float3 bary : SV_DomainLocation, \n\
+                                      const OutputPatch<PSSceneIn, 3> patch) { \n\
+      PSSceneIn v = patch[0]; \n\
+      v.pos = patch[0].pos * bary.x; \n\
+      v.pos += patch[1].pos * bary.y; \n\
+      v.pos += patch[2].pos * bary.z; \n\
+      return v; \n\
+    } \n"
+
+TEST_F(ValidationTest, WhenProgramOutSigMissingThenFail) {
+  ReplaceContainerPartsCheckMsgs(
+    VERTEX_STRUCT1
+    PC_STRUCT1
+    PC_FUNC
+    HS_ATTR
+    HS_FUNC,
+
+    VERTEX_STRUCT1
+    PC_STRUCT1
+    PC_FUNC_NOOUT
+    HS_ATTR
+    HS_FUNC_NOOUT,
+
+    "hs_6_0",
+    {DFCC_InputSignature, DFCC_OutputSignature, DFCC_PatchConstantSignature},
+    {
+      "Container part 'Program Output Signature' does not match expected for module.",
+      "Validation failed."
+    }
+  );
+}
+
+TEST_F(ValidationTest, WhenProgramOutSigUnexpectedThenFail) {
+  ReplaceContainerPartsCheckMsgs(
+    VERTEX_STRUCT1
+    PC_STRUCT1
+    PC_FUNC_NOOUT
+    HS_ATTR
+    HS_FUNC_NOOUT,
+
+    VERTEX_STRUCT1
+    PC_STRUCT1
+    PC_FUNC
+    HS_ATTR
+    HS_FUNC,
+
+    "hs_6_0",
+    {DFCC_InputSignature, DFCC_OutputSignature, DFCC_PatchConstantSignature},
+    {
+      "Container part 'Program Output Signature' does not match expected for module.",
+      "Validation failed."
+    }
+  );
+}
+
+TEST_F(ValidationTest, WhenProgramSigMismatchThenFail) {
+  ReplaceContainerPartsCheckMsgs(
+    VERTEX_STRUCT1
+    PC_STRUCT1
+    PC_FUNC
+    HS_ATTR
+    HS_FUNC,
+
+    VERTEX_STRUCT2
+    PC_STRUCT2
+    PC_FUNC
+    HS_ATTR
+    HS_FUNC,
+
+    "hs_6_0",
+    {DFCC_InputSignature, DFCC_OutputSignature, DFCC_PatchConstantSignature},
+    {
+      "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 Patch Constant Signature' does not match expected for module.",
+      "Validation failed."
+    }
+  );
+}
+
+TEST_F(ValidationTest, WhenProgramInSigMissingThenFail) {
+  ReplaceContainerPartsCheckMsgs(
+    VERTEX_STRUCT1
+    PC_STRUCT1
+    PC_FUNC
+    HS_ATTR
+    HS_FUNC,
+
+    // Compiling the HS_FUNC_NOIN produces the following error
+    //error: validation errors
+    //HS input control point count must be [1..32].  0 specified
+    VERTEX_STRUCT1
+    PC_STRUCT1
+    PC_FUNC_NOIN
+    HS_ATTR
+    HS_FUNC_NOIN,
+    "hs_6_0",
+    {DFCC_InputSignature, DFCC_OutputSignature, DFCC_PatchConstantSignature},
+    {
+      "Container part 'Program Input Signature' does not match expected for module.",
+      "Validation failed."
+    }
+  );
+}
+
+TEST_F(ValidationTest, WhenProgramSigMismatchThenFail2) {
+  ReplaceContainerPartsCheckMsgs(
+    VERTEX_STRUCT1
+    PC_STRUCT1
+    DS_FUNC,
+
+    VERTEX_STRUCT2
+    PC_STRUCT2
+    DS_FUNC,
+
+    "ds_6_0",
+    {DFCC_InputSignature, DFCC_OutputSignature, DFCC_PatchConstantSignature},
+    {
+      "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 Patch Constant Signature' does not match expected for module.",
+      "Validation failed."
+    }
+  );
+}
+
+TEST_F(ValidationTest, WhenProgramPCSigMissingThenFail) {
+  ReplaceContainerPartsCheckMsgs(
+    VERTEX_STRUCT1
+    PC_STRUCT1
+    DS_FUNC,
+
+    VERTEX_STRUCT2
+    PC_STRUCT2
+    DS_FUNC_NOPC,
+
+    "ds_6_0",
+    {DFCC_InputSignature, DFCC_OutputSignature, DFCC_PatchConstantSignature},
+    {
+      "Container part 'Program Input Signature' does not match expected for module.",
+      "Container part 'Program Output Signature' does not match expected for module.",
+      "Missing part 'Program Patch Constant Signature' required by module.",
+      "Validation failed."
+    }
+  );
+}
+
+#undef VERTEX_STRUCT1
+#undef VERTEX_STRUCT2
+#undef PC_STRUCT1
+#undef PC_STRUCT2
+#undef PC_FUNC
+#undef PC_FUNC_NOOUT
+#undef PC_FUNC_NOIN
+#undef HS_ATTR
+#undef HS_FUNC
+#undef HS_FUNC_NOOUT
+#undef HS_FUNC_NOIN
+#undef DS_FUNC
+#undef DS_FUNC_NOPC
+
+TEST_F(ValidationTest, WhenPSVMismatchThenFail) {
+  ReplaceContainerPartsCheckMsgs(
+    "float c; [RootSignature ( \"RootConstants(b0, num32BitConstants = 1)\" )] float4 main() : semantic { return c; }",
+    "[RootSignature ( \"\" )] float4 main() : semantic { return 0; }",
+    "vs_6_0",
+    {DFCC_PipelineStateValidation},
+    {
+      "Container part 'Pipeline State Validation' does not match expected for module.",
+      "Validation failed."
+    }
+  );
+}
+
+TEST_F(ValidationTest, WhenFeatureInfoMismatchThenFail) {
+  ReplaceContainerPartsCheckMsgs(
+    "float4 main(uint2 foo : FOO) : SV_Target { return asdouble(foo.x, foo.y) * 2.0; }",
+    "float4 main() : SV_Target { return 0; }",
+    "ps_6_0",
+    {DFCC_FeatureInfo},
+    {
+      "Container part 'Feature Info' does not match expected for module.",
+      "Validation failed."
+    }
+  );
+}
+
 
 
 
 
 
 

+ 34 - 34
utils/hct/gen_intrin_main.txt

@@ -80,8 +80,8 @@
 namespace Intrinsics {
 namespace Intrinsics {
 
 
 int<4> [[rn]] D3DCOLORtoUBYTE4(in $match<0, 1> float<4> x) : d3dcolortoubyte4;
 int<4> [[rn]] D3DCOLORtoUBYTE4(in $match<0, 1> float<4> x) : d3dcolortoubyte4;
-uint [[]]  GetRenderTargetSampleCount() : rtsampleinfo;
-float<2> [[]] GetRenderTargetSamplePosition(in int s) : rtsamplepos;
+uint [[rn]]  GetRenderTargetSampleCount() : rtsampleinfo;
+float<2> [[rn]] GetRenderTargetSamplePosition(in int s) : rtsamplepos;
 void [[]]   abort();
 void [[]]   abort();
 $type1 [[rn]] abs(in numeric<> x);
 $type1 [[rn]] abs(in numeric<> x);
 $type1 [[rn]] acos(in float_like<> x);
 $type1 [[rn]] acos(in float_like<> x);
@@ -179,16 +179,16 @@ $match<0, 1> float_like [[rn]] noise(in float_like<c> x);
 $type1 [[rn]] normalize(in float_like<c> x);
 $type1 [[rn]] normalize(in float_like<c> x);
 $type1 [[rn]] pow(in float_like<> x, in $type1 y);
 $type1 [[rn]] pow(in float_like<> x, in $type1 y);
 // void printf(in string Format, ...);
 // void printf(in string Format, ...);
-void [[]] Process2DQuadTessFactorsAvg(in float<4> RawEdgeFactors, in float<2> InsideScale, out float<4> RoundedEdgeFactors, out float<2> RoundedInsideFactors, out float<2> UnroundedInsideFactors) : ptf_2dqavg;
-void [[]] Process2DQuadTessFactorsMax(in float<4> RawEdgeFactors, in float<2> InsideScale, out float<4> RoundedEdgeFactors, out float<2> RoundedInsideFactors, out float<2> UnroundedInsideFactors) : ptf_2dqmax;
-void [[]] Process2DQuadTessFactorsMin(in float<4> RawEdgeFactors, in float<2> InsideScale, out float<4> RoundedEdgeFactors, out float<2> RoundedInsideFactors, out float<2> UnroundedInsideFactors) : ptf_2dqmin;
-void [[]] ProcessIsolineTessFactors(in float<1> RawDetailFactor, in float<1> RawDensityFactor, out float<1> RoundedDetailFactorr, out float<1> RoundedDensityFactor) : ptf_i;
-void [[]] ProcessQuadTessFactorsAvg(in float<4> RawEdgeFactors, in float<1> InsideScale, out float<4> RoundedEdgeFactors, out float<2> RoundedInsideFactors, out float<2> UnroundedInsideFactors) : ptf_qavg;
-void [[]] ProcessQuadTessFactorsMax(in float<4> RawEdgeFactors, in float<1> InsideScale, out float<4> RoundedEdgeFactors, out float<2> RoundedInsideFactors, out float<2> UnroundedInsideFactors) : ptf_qmax;
-void [[]] ProcessQuadTessFactorsMin(in float<4> RawEdgeFactors, in float<1> InsideScale, out float<4> RoundedEdgeFactors, out float<2> RoundedInsideFactors, out float<2> UnroundedInsideFactors) : ptf_qmin;
-void [[]] ProcessTriTessFactorsAvg(in float<3> RawEdgeFactors, in float<1> InsideScale, out float<3> RoundedEdgeFactors, out float<1> RoundedInsideFactor, out float<1> UnroundedInsideFactor) : ptf_tmin;
-void [[]] ProcessTriTessFactorsMax(in float<3> RawEdgeFactors, in float<1> InsideScale, out float<3> RoundedEdgeFactors, out float<1> RoundedInsideFactor, out float<1> UnroundedInsideFactor) : ptf_tmax;
-void [[]] ProcessTriTessFactorsMin(in float<3> RawEdgeFactors, in float<1> InsideScale, out float<3> RoundedEdgeFactors, out float<1> RoundedInsideFactor, out float<1> UnroundedInsideFactor) : ptf_tavg;
+void [[rn]] Process2DQuadTessFactorsAvg(in float<4> RawEdgeFactors, in float<2> InsideScale, out float<4> RoundedEdgeFactors, out float<2> RoundedInsideFactors, out float<2> UnroundedInsideFactors) : ptf_2dqavg;
+void [[rn]] Process2DQuadTessFactorsMax(in float<4> RawEdgeFactors, in float<2> InsideScale, out float<4> RoundedEdgeFactors, out float<2> RoundedInsideFactors, out float<2> UnroundedInsideFactors) : ptf_2dqmax;
+void [[rn]] Process2DQuadTessFactorsMin(in float<4> RawEdgeFactors, in float<2> InsideScale, out float<4> RoundedEdgeFactors, out float<2> RoundedInsideFactors, out float<2> UnroundedInsideFactors) : ptf_2dqmin;
+void [[rn]] ProcessIsolineTessFactors(in float<1> RawDetailFactor, in float<1> RawDensityFactor, out float<1> RoundedDetailFactorr, out float<1> RoundedDensityFactor) : ptf_i;
+void [[rn]] ProcessQuadTessFactorsAvg(in float<4> RawEdgeFactors, in float<1> InsideScale, out float<4> RoundedEdgeFactors, out float<2> RoundedInsideFactors, out float<2> UnroundedInsideFactors) : ptf_qavg;
+void [[rn]] ProcessQuadTessFactorsMax(in float<4> RawEdgeFactors, in float<1> InsideScale, out float<4> RoundedEdgeFactors, out float<2> RoundedInsideFactors, out float<2> UnroundedInsideFactors) : ptf_qmax;
+void [[rn]] ProcessQuadTessFactorsMin(in float<4> RawEdgeFactors, in float<1> InsideScale, out float<4> RoundedEdgeFactors, out float<2> RoundedInsideFactors, out float<2> UnroundedInsideFactors) : ptf_qmin;
+void [[rn]] ProcessTriTessFactorsAvg(in float<3> RawEdgeFactors, in float<1> InsideScale, out float<3> RoundedEdgeFactors, out float<1> RoundedInsideFactor, out float<1> UnroundedInsideFactor) : ptf_tmin;
+void [[rn]] ProcessTriTessFactorsMax(in float<3> RawEdgeFactors, in float<1> InsideScale, out float<3> RoundedEdgeFactors, out float<1> RoundedInsideFactor, out float<1> UnroundedInsideFactor) : ptf_tmax;
+void [[rn]] ProcessTriTessFactorsMin(in float<3> RawEdgeFactors, in float<1> InsideScale, out float<3> RoundedEdgeFactors, out float<1> RoundedInsideFactor, out float<1> UnroundedInsideFactor) : ptf_tavg;
 $type1 [[rn]] radians(in float_like<> x);
 $type1 [[rn]] radians(in float_like<> x);
 $type1 [[rn]] rcp(in any_float<> x) : rcp_approx;
 $type1 [[rn]] rcp(in any_float<> x) : rcp_approx;
 $type1 [[rn]] reflect(in float_like<c> i, in $type1 n);
 $type1 [[rn]] reflect(in float_like<c> i, in $type1 n);
@@ -238,30 +238,30 @@ uint<c> [[rn]] AddUint64(in $match<1, 0> uint<c> a, in $match<2, 0> uint<c> b) :
 $type1 [[rn]] NonUniformResourceIndex(in any<> index) : nonuniform_resource_index;
 $type1 [[rn]] NonUniformResourceIndex(in any<> index) : nonuniform_resource_index;
 
 
 // Wave intrinsics.
 // Wave intrinsics.
-bool   [[rn]] WaveIsFirstLane();
+bool   [[]] WaveIsFirstLane();
 uint   [[rn]] WaveGetLaneIndex();
 uint   [[rn]] WaveGetLaneIndex();
 uint   [[rn]] WaveGetLaneCount();
 uint   [[rn]] WaveGetLaneCount();
-bool   [[rn]] WaveActiveAnyTrue(in bool cond);
-bool   [[rn]] WaveActiveAllTrue(in bool cond);
-$match<1, 0> bool<> [[rn]] WaveActiveAllEqual(in numeric<> value);
-uint<4> [[rn]] WaveActiveBallot(in bool cond);
-$type1 [[rn]] WaveReadLaneAt(in numeric<> value, in uint lane);
-$type1 [[rn]] WaveReadLaneFirst(in numeric<> value);
-uint   [[rn]] WaveActiveCountBits(in bool value);
-$type1 [[rn,unsigned_op=WaveActiveUSum]] WaveActiveSum(in numeric<> value);
-$type1 [[rn,unsigned_op=WaveActiveUProduct]] WaveActiveProduct(in numeric<> value);
-$type1 [[rn]] WaveActiveBitAnd(in uint_only<> value);
-$type1 [[rn]] WaveActiveBitOr(in uint_only<> value);
-$type1 [[rn]] WaveActiveBitXor(in uint_only<> value);
-$type1 [[rn,unsigned_op=WaveActiveUMin]] WaveActiveMin(in numeric<> value);
-$type1 [[rn,unsigned_op=WaveActiveUMax]] WaveActiveMax(in numeric<> value);
-uint   [[rn]] WavePrefixCountBits(in bool value);
-$type1 [[rn,unsigned_op=WavePrefixUSum]] WavePrefixSum(in numeric<> value);
-$type1 [[rn,unsigned_op=WavePrefixUProduct]] WavePrefixProduct(in numeric<> value);
-$type1 [[rn]] QuadReadLaneAt(in numeric<> value, in uint quadLane);
-$type1 [[rn]] QuadReadAcrossX(in numeric<> value);
-$type1 [[rn]] QuadReadAcrossY(in numeric<> value);
-$type1 [[rn]] QuadReadAcrossDiagonal(in numeric<> value);
+bool   [[]] WaveActiveAnyTrue(in bool cond);
+bool   [[]] WaveActiveAllTrue(in bool cond);
+$match<1, 0> bool<> [[]] WaveActiveAllEqual(in numeric<> value);
+uint<4> [[]] WaveActiveBallot(in bool cond);
+$type1 [[]] WaveReadLaneAt(in numeric<> value, in uint lane);
+$type1 [[]] WaveReadLaneFirst(in numeric<> value);
+uint   [[]] WaveActiveCountBits(in bool value);
+$type1 [[unsigned_op=WaveActiveUSum]] WaveActiveSum(in numeric<> value);
+$type1 [[unsigned_op=WaveActiveUProduct]] WaveActiveProduct(in numeric<> value);
+$type1 [[]] WaveActiveBitAnd(in uint_only<> value);
+$type1 [[]] WaveActiveBitOr(in uint_only<> value);
+$type1 [[]] WaveActiveBitXor(in uint_only<> value);
+$type1 [[unsigned_op=WaveActiveUMin]] WaveActiveMin(in numeric<> value);
+$type1 [[unsigned_op=WaveActiveUMax]] WaveActiveMax(in numeric<> value);
+uint   [[]] WavePrefixCountBits(in bool value);
+$type1 [[unsigned_op=WavePrefixUSum]] WavePrefixSum(in numeric<> value);
+$type1 [[unsigned_op=WavePrefixUProduct]] WavePrefixProduct(in numeric<> value);
+$type1 [[]] QuadReadLaneAt(in numeric<> value, in uint quadLane);
+$type1 [[]] QuadReadAcrossX(in numeric<> value);
+$type1 [[]] QuadReadAcrossY(in numeric<> value);
+$type1 [[]] QuadReadAcrossDiagonal(in numeric<> value);
 
 
 } namespace
 } namespace
 
 

+ 26 - 18
utils/hct/hctdb.py

@@ -894,46 +894,46 @@ class db_dxil(object):
             db_dxil_param(0, "i32", "", "result")])
             db_dxil_param(0, "i32", "", "result")])
         next_op_idx += 1
         next_op_idx += 1
 
 
-        self.add_dxil_op("CycleCounterLegacy", next_op_idx, "CycleCounterLegacy", "CycleCounterLegacy", "v", "rn", [
+        self.add_dxil_op("CycleCounterLegacy", next_op_idx, "CycleCounterLegacy", "CycleCounterLegacy", "v", "", [
             db_dxil_param(0, "twoi32", "", "result")])
             db_dxil_param(0, "twoi32", "", "result")])
         next_op_idx += 1
         next_op_idx += 1
             
             
         # Add wave intrinsics.
         # Add wave intrinsics.
-        self.add_dxil_op("WaveIsFirstLane", next_op_idx, "WaveIsFirstLane", "returns 1 for the first lane in the wave", "v", "ro", [
+        self.add_dxil_op("WaveIsFirstLane", next_op_idx, "WaveIsFirstLane", "returns 1 for the first lane in the wave", "v", "", [
             db_dxil_param(0, "i1", "", "operation result")])
             db_dxil_param(0, "i1", "", "operation result")])
         next_op_idx += 1
         next_op_idx += 1
-        self.add_dxil_op("WaveGetLaneIndex", next_op_idx, "WaveGetLaneIndex", "returns the index of the current lane in the wave", "v", "ro", [
+        self.add_dxil_op("WaveGetLaneIndex", next_op_idx, "WaveGetLaneIndex", "returns the index of the current lane in the wave", "v", "rn", [
             db_dxil_param(0, "i32", "", "operation result")])
             db_dxil_param(0, "i32", "", "operation result")])
         next_op_idx += 1
         next_op_idx += 1
-        self.add_dxil_op("WaveGetLaneCount", next_op_idx, "WaveGetLaneCount", "returns the number of lanes in the wave", "v", "ro", [
+        self.add_dxil_op("WaveGetLaneCount", next_op_idx, "WaveGetLaneCount", "returns the number of lanes in the wave", "v", "rn", [
             db_dxil_param(0, "i32", "", "operation result")])
             db_dxil_param(0, "i32", "", "operation result")])
         next_op_idx += 1
         next_op_idx += 1
-        self.add_dxil_op("WaveAnyTrue", next_op_idx, "WaveAnyTrue", "returns 1 if any of the lane evaluates the value to true", "v", "ro", [
+        self.add_dxil_op("WaveAnyTrue", next_op_idx, "WaveAnyTrue", "returns 1 if any of the lane evaluates the value to true", "v", "", [
             db_dxil_param(0, "i1", "", "operation result"),
             db_dxil_param(0, "i1", "", "operation result"),
             db_dxil_param(2, "i1", "cond", "condition to test")])
             db_dxil_param(2, "i1", "cond", "condition to test")])
         next_op_idx += 1
         next_op_idx += 1
-        self.add_dxil_op("WaveAllTrue", next_op_idx, "WaveAllTrue", "returns 1 if all the lanes evaluate the value to true", "v", "ro", [
+        self.add_dxil_op("WaveAllTrue", next_op_idx, "WaveAllTrue", "returns 1 if all the lanes evaluate the value to true", "v", "", [
             db_dxil_param(0, "i1", "", "operation result"),
             db_dxil_param(0, "i1", "", "operation result"),
             db_dxil_param(2, "i1", "cond", "condition to test")])
             db_dxil_param(2, "i1", "cond", "condition to test")])
         next_op_idx += 1
         next_op_idx += 1
-        self.add_dxil_op("WaveActiveAllEqual", next_op_idx, "WaveActiveAllEqual", "returns 1 if all the lanes have the same value", "hfd18wil", "ro", [
+        self.add_dxil_op("WaveActiveAllEqual", next_op_idx, "WaveActiveAllEqual", "returns 1 if all the lanes have the same value", "hfd18wil", "", [
             db_dxil_param(0, "i1", "", "operation result"),
             db_dxil_param(0, "i1", "", "operation result"),
             db_dxil_param(2, "$o", "value", "value to compare")])
             db_dxil_param(2, "$o", "value", "value to compare")])
         next_op_idx += 1
         next_op_idx += 1
-        self.add_dxil_op("WaveActiveBallot", next_op_idx, "WaveActiveBallot", "returns a struct with a bit set for each lane where the condition is true", "v", "ro", [
+        self.add_dxil_op("WaveActiveBallot", next_op_idx, "WaveActiveBallot", "returns a struct with a bit set for each lane where the condition is true", "v", "", [
             db_dxil_param(0, "$u4", "", "operation result"),
             db_dxil_param(0, "$u4", "", "operation result"),
             db_dxil_param(2, "i1", "cond", "condition to ballot on")])
             db_dxil_param(2, "i1", "cond", "condition to ballot on")])
         next_op_idx += 1
         next_op_idx += 1
-        self.add_dxil_op("WaveReadLaneAt", next_op_idx, "WaveReadLaneAt", "returns the value from the specified lane", "hfd18wil", "ro", [
+        self.add_dxil_op("WaveReadLaneAt", next_op_idx, "WaveReadLaneAt", "returns the value from the specified lane", "hfd18wil", "", [
             db_dxil_param(0, "$o", "", "operation result"),
             db_dxil_param(0, "$o", "", "operation result"),
             db_dxil_param(2, "$o", "value", "value to read"),
             db_dxil_param(2, "$o", "value", "value to read"),
             db_dxil_param(3, "i32", "lane", "lane index")])
             db_dxil_param(3, "i32", "lane", "lane index")])
         next_op_idx += 1
         next_op_idx += 1
-        self.add_dxil_op("WaveReadLaneFirst", next_op_idx, "WaveReadLaneFirst", "returns the value from the first lane", "hf18wil", "ro", [
+        self.add_dxil_op("WaveReadLaneFirst", next_op_idx, "WaveReadLaneFirst", "returns the value from the first lane", "hf18wil", "", [
             db_dxil_param(0, "$o", "", "operation result"),
             db_dxil_param(0, "$o", "", "operation result"),
             db_dxil_param(2, "$o", "value", "value to read")])
             db_dxil_param(2, "$o", "value", "value to read")])
         next_op_idx += 1
         next_op_idx += 1
-        self.add_dxil_op("WaveActiveOp", next_op_idx, "WaveActiveOp", "returns the result the operation across waves", "hfd18wil", "ro", [
+        self.add_dxil_op("WaveActiveOp", next_op_idx, "WaveActiveOp", "returns the result the operation across waves", "hfd18wil", "", [
             db_dxil_param(0, "$o", "", "operation result"),
             db_dxil_param(0, "$o", "", "operation result"),
             db_dxil_param(2, "$o", "value", "input value"),
             db_dxil_param(2, "$o", "value", "input value"),
             db_dxil_param(3, "i8", "op", "kind of operation to perform", enum_name="WaveOpKind", is_const=True),
             db_dxil_param(3, "i8", "op", "kind of operation to perform", enum_name="WaveOpKind", is_const=True),
@@ -947,7 +947,7 @@ class db_dxil(object):
             (1, "Product", "product of values"), 
             (1, "Product", "product of values"), 
             (2, "Min", "minimum value"), 
             (2, "Min", "minimum value"), 
             (3, "Max", "maximum value")])
             (3, "Max", "maximum value")])
-        self.add_dxil_op("WaveActiveBit", next_op_idx, "WaveActiveBit", "returns the result of the operation across all lanes", "8wil", "ro", [
+        self.add_dxil_op("WaveActiveBit", next_op_idx, "WaveActiveBit", "returns the result of the operation across all lanes", "8wil", "", [
             db_dxil_param(0, "$o", "", "operation result"),
             db_dxil_param(0, "$o", "", "operation result"),
             db_dxil_param(2, "$o", "value", "input value"),
             db_dxil_param(2, "$o", "value", "input value"),
             db_dxil_param(3, "i8", "op", "kind of operation to perform", enum_name="WaveBitOpKind", is_const=True)])
             db_dxil_param(3, "i8", "op", "kind of operation to perform", enum_name="WaveBitOpKind", is_const=True)])
@@ -956,13 +956,13 @@ class db_dxil(object):
             (0, "And", "bitwise and of values"), 
             (0, "And", "bitwise and of values"), 
             (1, "Or", "bitwise or of values"), 
             (1, "Or", "bitwise or of values"), 
             (2, "Xor", "bitwise xor of values")])
             (2, "Xor", "bitwise xor of values")])
-        self.add_dxil_op("WavePrefixOp", next_op_idx, "WavePrefixOp", "returns the result of the operation on prior lanes", "hfd8wil", "ro", [
+        self.add_dxil_op("WavePrefixOp", next_op_idx, "WavePrefixOp", "returns the result of the operation on prior lanes", "hfd8wil", "", [
             db_dxil_param(0, "$o", "", "operation result"),
             db_dxil_param(0, "$o", "", "operation result"),
             db_dxil_param(2, "$o", "value", "input value"),
             db_dxil_param(2, "$o", "value", "input value"),
             db_dxil_param(3, "i8", "op", "0=sum,1=product", enum_name="WaveOpKind", is_const=True),
             db_dxil_param(3, "i8", "op", "0=sum,1=product", enum_name="WaveOpKind", is_const=True),
             db_dxil_param(4, "i8", "sop", "sign of operands", enum_name="SignedOpKind", is_const=True)])
             db_dxil_param(4, "i8", "sop", "sign of operands", enum_name="SignedOpKind", is_const=True)])
         next_op_idx += 1
         next_op_idx += 1
-        self.add_dxil_op("QuadReadLaneAt", next_op_idx, "QuadReadLaneAt", "reads from a lane in the quad", "hfd18wil", "ro", [
+        self.add_dxil_op("QuadReadLaneAt", next_op_idx, "QuadReadLaneAt", "reads from a lane in the quad", "hfd18wil", "", [
             db_dxil_param(0, "$o", "", "operation result"),
             db_dxil_param(0, "$o", "", "operation result"),
             db_dxil_param(2, "$o", "value", "value to read"),
             db_dxil_param(2, "$o", "value", "value to read"),
             db_dxil_param(3, "u32", "quadLane", "lane to read from (0-4)", max_value = 3, is_const=True)])
             db_dxil_param(3, "u32", "quadLane", "lane to read from (0-4)", max_value = 3, is_const=True)])
@@ -971,7 +971,7 @@ class db_dxil(object):
             (0, "ReadAcrossX", "returns the value from the other lane in the quad in the horizontal direction"), 
             (0, "ReadAcrossX", "returns the value from the other lane in the quad in the horizontal direction"), 
             (1, "ReadAcrossY", "returns the value from the other lane in the quad in the vertical direction"),
             (1, "ReadAcrossY", "returns the value from the other lane in the quad in the vertical direction"),
             (2, "ReadAcrossDiagonal", "returns the value from the lane across the quad in horizontal and vertical direction")])
             (2, "ReadAcrossDiagonal", "returns the value from the lane across the quad in horizontal and vertical direction")])
-        self.add_dxil_op("QuadOp", next_op_idx, "QuadOp", "returns the result of a quad-level operation", "hfd8wil", "ro", [
+        self.add_dxil_op("QuadOp", next_op_idx, "QuadOp", "returns the result of a quad-level operation", "hfd8wil", "", [
             db_dxil_param(0, "$o", "", "operation result"),
             db_dxil_param(0, "$o", "", "operation result"),
             db_dxil_param(2, "$o", "value", "value for operation"),
             db_dxil_param(2, "$o", "value", "value for operation"),
             db_dxil_param(3, "i8", "op", "operation", enum_name = "QuadOpKind", is_const=True)])
             db_dxil_param(3, "i8", "op", "operation", enum_name = "QuadOpKind", is_const=True)])
@@ -1028,11 +1028,11 @@ class db_dxil(object):
             db_dxil_param(2, "d", "value", "double value to convert")])
             db_dxil_param(2, "d", "value", "double value to convert")])
         next_op_idx += 1
         next_op_idx += 1
 
 
-        self.add_dxil_op("WaveAllBitCount", next_op_idx, "WaveAllOp", "returns the count of bits set to 1 across the wave", "v", "ro", [
+        self.add_dxil_op("WaveAllBitCount", next_op_idx, "WaveAllOp", "returns the count of bits set to 1 across the wave", "v", "", [
             db_dxil_param(0, "i32", "", "operation result"),
             db_dxil_param(0, "i32", "", "operation result"),
             db_dxil_param(2, "i1", "value", "input value")])
             db_dxil_param(2, "i1", "value", "input value")])
         next_op_idx += 1
         next_op_idx += 1
-        self.add_dxil_op("WavePrefixBitCount", next_op_idx, "WavePrefixOp", "returns the count of bits set to 1 on prior lanes", "v", "ro", [
+        self.add_dxil_op("WavePrefixBitCount", next_op_idx, "WavePrefixOp", "returns the count of bits set to 1 on prior lanes", "v", "", [
             db_dxil_param(0, "i32", "", "operation result"),
             db_dxil_param(0, "i32", "", "operation result"),
             db_dxil_param(2, "i1", "value", "input value")])
             db_dxil_param(2, "i1", "value", "input value")])
         next_op_idx += 1
         next_op_idx += 1
@@ -1443,6 +1443,12 @@ class db_dxil(object):
     def build_valrules(self):
     def build_valrules(self):
         self.add_valrule_msg("Bitcode.Valid", "TODO - Module must be bitcode-valid", "Module bitcode is invalid")
         self.add_valrule_msg("Bitcode.Valid", "TODO - Module must be bitcode-valid", "Module bitcode is invalid")
 
 
+        self.add_valrule_msg("Container.PartMatches", "DXIL Container Parts must match Module", "Container part '%0' does not match expected for module.")
+        self.add_valrule_msg("Container.PartRepeated", "DXIL Container must have only one of each part type", "More than one container part '%0'.")
+        self.add_valrule_msg("Container.PartMissing", "DXIL Container requires certain parts, corresponding to module", "Missing part '%0' required by module.")
+        self.add_valrule_msg("Container.PartInvalid", "DXIL Container must not contain unknown parts", "Unknown part '%0' found in DXIL container.")
+        self.add_valrule_msg("Container.RootSignatureIncompatible", "Root Signature in DXIL Container must be compatible with shader", "Root Signature in DXIL container is not compatible with shader.")
+
         self.add_valrule("Meta.Required", "TODO - Required metadata missing")
         self.add_valrule("Meta.Required", "TODO - Required metadata missing")
         self.add_valrule_msg("Meta.Known", "Named metadata should be known", "Named metadata '%0' is unknown")
         self.add_valrule_msg("Meta.Known", "Named metadata should be known", "Named metadata '%0' is unknown")
         self.add_valrule("Meta.Used", "All metadata must be used by dxil")
         self.add_valrule("Meta.Used", "All metadata must be used by dxil")
@@ -1607,7 +1613,8 @@ class db_dxil(object):
         self.add_valrule("Sm.GSOutputVertexCountRange", "GS output vertex count must be [0..%0].  %1 specified")
         self.add_valrule("Sm.GSOutputVertexCountRange", "GS output vertex count must be [0..%0].  %1 specified")
         self.add_valrule("Sm.GSInstanceCountRange", "GS instance count must be [1..%0].  %1 specified")
         self.add_valrule("Sm.GSInstanceCountRange", "GS instance count must be [1..%0].  %1 specified")
         self.add_valrule("Sm.DSInputControlPointCountRange", "DS input control point count must be [0..%0].  %1 specified")
         self.add_valrule("Sm.DSInputControlPointCountRange", "DS input control point count must be [0..%0].  %1 specified")
-        self.add_valrule("Sm.HSInputControlPointCountRange", "HS input control point count must be [1..%0].  %1 specified")
+        self.add_valrule("Sm.HSInputControlPointCountRange", "HS input control point count must be [0..%0].  %1 specified")
+        self.add_valrule("Sm.ZeroHSInputControlPointWithInput", "When HS input control point count is 0, no input signature should exist")
         self.add_valrule("Sm.OutputControlPointCountRange", "output control point count must be [0..%0].  %1 specified")
         self.add_valrule("Sm.OutputControlPointCountRange", "output control point count must be [0..%0].  %1 specified")
         self.add_valrule("Sm.GSValidInputPrimitive", "GS input primitive unrecognized")
         self.add_valrule("Sm.GSValidInputPrimitive", "GS input primitive unrecognized")
         self.add_valrule("Sm.GSValidOutputPrimitiveTopology", "GS output primitive topology unrecognized")
         self.add_valrule("Sm.GSValidOutputPrimitiveTopology", "GS output primitive topology unrecognized")
@@ -1649,6 +1656,7 @@ class db_dxil(object):
         
         
         # Assign sensible category names and build up an enumeration description
         # Assign sensible category names and build up an enumeration description
         cat_names = {
         cat_names = {
+            "CONTAINER": "Container",
             "BITCODE": "Bitcode",
             "BITCODE": "Bitcode",
             "META": "Metadata",
             "META": "Metadata",
             "INSTR": "Instruction",
             "INSTR": "Instruction",

+ 2 - 2
utils/hct/hcttest.cmd

@@ -119,9 +119,9 @@ if "%TEST_CLANG%"=="1" (
   )
   )
 
 
   copy /y %HLSL_SRC_DIR%\utils\hct\smoke.hlsl %TEST_DIR%\smoke.hlsl
   copy /y %HLSL_SRC_DIR%\utils\hct\smoke.hlsl %TEST_DIR%\smoke.hlsl
-  call %HLSL_SRC_DIR%\utils\hct\hcttestcmds.cmd %TEST_DIR%
+  call %HLSL_SRC_DIR%\utils\hct\hcttestcmds.cmd %TEST_DIR% %HLSL_SRC_DIR%\tools\clang\test\HLSL
   if errorlevel 1 (
   if errorlevel 1 (
-    echo Failed - %HLSL_SRC_DIR%\utils\hct\hcttestcmds.cmd %TEST_DIR%
+    echo Failed - %HLSL_SRC_DIR%\utils\hct\hcttestcmds.cmd %TEST_DIR% %HLSL_SRC_DIR%\tools\clang\test\HLSL
     exit /b 1
     exit /b 1
   )
   )
 )
 )

+ 240 - 21
utils/hct/hcttestcmds.cmd

@@ -5,6 +5,11 @@ if "%1"=="" (
   exit /b 1
   exit /b 1
 )
 )
 
 
+if "%2"=="" (
+  echo Second argument to hcttestcmds should be the absolute path to tools\clang\test\HLSL
+  exit /b 1
+)
+
 echo Testing command line programs at %1 ...
 echo Testing command line programs at %1 ...
 
 
 setlocal
 setlocal
@@ -15,6 +20,28 @@ echo Smoke test for dxr command line program ...
 dxr.exe -remove-unused-globals smoke.hlsl -Emain 1> nul
 dxr.exe -remove-unused-globals smoke.hlsl -Emain 1> nul
 if %errorlevel% neq  0 (
 if %errorlevel% neq  0 (
   echo Failed - %CD%\dxr.exe -remove-unused-globals %CD%\smoke.hlsl -Emain
   echo Failed - %CD%\dxr.exe -remove-unused-globals %CD%\smoke.hlsl -Emain
+  call :cleanup 2>nul
+  exit /b 1
+)
+
+dxc.exe /T ps_6_0 smoke.hlsl /Fc smoke.hlsl.c 1>nul
+if %errorlevel% neq 0 (
+  echo Failed - %CD%\dxc.exe /T ps_6_0 smoke.hlsl /Fc %CD%\smoke.hlsl.c
+  call :cleanup 2>nul
+  exit /b 1
+)
+
+dxc.exe /T ps_6_0 smoke.hlsl /Zi /Fd smoke.hlsl.d 1>nul
+if %errorlevel% neq 0 (
+  echo Failed - %CD%\dxc.exe /T ps_6_0 smoke.hlsl /Zi /Fd %CD%\smoke.hlsl.d
+  call :cleanup 2>nul
+  exit /b 1
+)
+
+dxc.exe /T ps_6_0 smoke.hlsl /Fe smoke.hlsl.e 1>nul
+if %errorlevel% neq 0 (
+  echo Failed - %CD%\dxc.exe /T ps_6_0 smoke.hlsl /Fe %CD%\smoke.hlsl.e
+  call :cleanup 2>nul
   exit /b 1
   exit /b 1
 )
 )
 
 
@@ -22,95 +49,281 @@ echo Smoke test for dxc command line program ...
 dxc.exe /T ps_6_0 smoke.hlsl /Fh smoke.hlsl.h /Vn g_myvar 1> nul
 dxc.exe /T ps_6_0 smoke.hlsl /Fh smoke.hlsl.h /Vn g_myvar 1> nul
 if %errorlevel% neq 0 (
 if %errorlevel% neq 0 (
   echo Failed - %CD%\dxc.exe /T ps_6_0 %CD%\smoke.hlsl /Fh %CD%\smoke.hlsl.h /Vn g_myvar
   echo Failed - %CD%\dxc.exe /T ps_6_0 %CD%\smoke.hlsl /Fh %CD%\smoke.hlsl.h /Vn g_myvar
+  call :cleanup 2>nul
   exit /b 1
   exit /b 1
 )
 )
 findstr g_myvar %CD%\smoke.hlsl.h 1>nul
 findstr g_myvar %CD%\smoke.hlsl.h 1>nul
 if %errorlevel% neq 0 (
 if %errorlevel% neq 0 (
   echo Failed to find the variable g_myvar in %CD%\smoke.hlsl.h
   echo Failed to find the variable g_myvar in %CD%\smoke.hlsl.h
   echo Debug with start devenv /debugexe %CD%\dxc.exe /T ps_6_0 %CD%\smoke.hlsl /Fh %CD%\smoke.hlsl.h /Vn g_myvar
   echo Debug with start devenv /debugexe %CD%\dxc.exe /T ps_6_0 %CD%\smoke.hlsl /Fh %CD%\smoke.hlsl.h /Vn g_myvar
+  call :cleanup 2>nul
   exit /b 1
   exit /b 1
 )
 )
 findstr "0x44, 0x58" %CD%\smoke.hlsl.h 1>nul
 findstr "0x44, 0x58" %CD%\smoke.hlsl.h 1>nul
 if %errorlevel% neq 0 (
 if %errorlevel% neq 0 (
   echo Failed to find the bytecode for DXBC container in %CD%\smoke.hlsl.h
   echo Failed to find the bytecode for DXBC container in %CD%\smoke.hlsl.h
+  call :cleanup 2>nul
+  exit /b 1
+)
+
+dxc.exe smoke.hlsl /P preprocessed.hlsl 1>nul
+if %errorlevel% neq 0 (
+  echo Failed to preprocess smoke.hlsl
+  call :cleanup 2>nul
+  exit /b 1
+)
+
+dxc.exe /T ps_6_0 smoke.hlsl -force_rootsig_ver rootsig_1_0 1>nul
+if %errorlevel% neq 0 (
+  echo Failed to compile with forcing rootsignature rootsig_1_0
+  call :cleanup 2>nul
+  exit /b 1
+)
+
+dxc.exe /T ps_6_0 smoke.hlsl -force_rootsig_ver rootsig_1_1 1>nul
+if %errorlevel% neq 0 (
+  echo Failed to compile with forcing rootsignature rootsig_1_1
+  call :cleanup 2>nul
+  exit /b 1
+)
+
+dxc.exe /T ps_6_0 smoke.hlsl -force_rootsig_ver rootsig_2_0 2>nul
+if %errorlevel% equ 0 (
+  echo rootsig_2_0 is not supported but compilation passed
+  call :cleanup 2>nul
+  exit /b 1
+)
+
+dxc.exe /T ps_6_0 smoke.hlsl /HV 2016 1>nul
+if %errorlevel% neq 0 (
+  echo Failed to compile with HLSL version 2016
+  call :cleanup 2>nul
+  exit /b 1
+)
+
+dxc.exe /T ps_6_0 smoke.hlsl /HV 2015 2>nul
+if %errorlevel% equ 0 (
+  echo Unsupported HLSL version 2015 should fail but did not fail
+  call :cleanup 2>nul
   exit /b 1
   exit /b 1
 )
 )
 
 
 dxc.exe /T ps_6_0 smoke.hlsl /Zi /Fo smoke.cso 1> nul
 dxc.exe /T ps_6_0 smoke.hlsl /Zi /Fo smoke.cso 1> nul
 if %errorlevel% neq 0 (
 if %errorlevel% neq 0 (
-  echo Failed to compile to binary object from %CD%\smoke.hlsl.h
+  echo Failed to compile to binary object from %CD%\smoke.hlsl
+  call :cleanup 2>nul
   exit /b 1
   exit /b 1
 )
 )
+
+dxc.exe /T ps_6_0 smoke.hlsl /Zi /Fo smoke.cso /Cc /Ni /No /Lx 1> nul
+if %errorlevel% neq 0 (
+  echo Failed to compile to binary object from %CD%\smoke.hlsl with disassembly options
+  call :cleanup 2>nul
+  exit /b 1
+)
+
 dxc.exe -dumpbin smoke.cso 1> nul
 dxc.exe -dumpbin smoke.cso 1> nul
 if %errorlevel% neq 0 (
 if %errorlevel% neq 0 (
-  echo Failed to disassemble binary object from %CD%\smoke.hlsl.h
+  echo Failed to disassemble binary object from %CD%\smoke.hlsl
+  call :cleanup 2>nul
   exit /b 1
   exit /b 1
 )
 )
 
 
 dxc.exe smoke.cso /recompile 1>nul
 dxc.exe smoke.cso /recompile 1>nul
 if %errorlevel% neq 0 (
 if %errorlevel% neq 0 (
   echo Failed to recompile binary object compiled from %CD%\smoke.hlsl
   echo Failed to recompile binary object compiled from %CD%\smoke.hlsl
+  call :cleanup 2>nul
   exit /b 1
   exit /b 1
 )
 )
 
 
 dxc.exe smoke.cso /recompile /T ps_6_0 /E main 1>nul
 dxc.exe smoke.cso /recompile /T ps_6_0 /E main 1>nul
 if %errorlevel% neq 0 (
 if %errorlevel% neq 0 (
   echo Failed to recompile binary object with target ps_6_0 from %CD%\smoke.hlsl
   echo Failed to recompile binary object with target ps_6_0 from %CD%\smoke.hlsl
+  call :cleanup 2>nul
   exit /b 1
   exit /b 1
 )
 )
 
 
 dxc.exe smoke.hlsl /D "semantic = SV_Position" /T vs_6_0 /Zi /DDX12 /Fo smoke.cso 1> nul
 dxc.exe smoke.hlsl /D "semantic = SV_Position" /T vs_6_0 /Zi /DDX12 /Fo smoke.cso 1> nul
 if %errorlevel% neq 0 (
 if %errorlevel% neq 0 (
   echo Failed to compile smoke.hlsl with command line defines
   echo Failed to compile smoke.hlsl with command line defines
+  call :cleanup 2>nul
   exit /b 1
   exit /b 1
 )
 )
 
 
 dxc.exe smoke.cso /recompile 1> nul
 dxc.exe smoke.cso /recompile 1> nul
 if %errorlevel% neq 0 (
 if %errorlevel% neq 0 (
   echo Failed to recompile smoke.cso with command line defines
   echo Failed to recompile smoke.cso with command line defines
+  call :cleanup 2>nul
   exit /b 1
   exit /b 1
 )
 )
 
 
+
 dxc.exe smoke.cso /dumpbin /Qstrip_debug /Fo nodebug.cso 1>nul
 dxc.exe smoke.cso /dumpbin /Qstrip_debug /Fo nodebug.cso 1>nul
 if %errorlevel% neq 0 (
 if %errorlevel% neq 0 (
   echo Failed to strip debug part from DXIL container blob
   echo Failed to strip debug part from DXIL container blob
+  call :cleanup 2>nul
   exit /b 1
   exit /b 1
 )
 )
 
 
 dxc.exe smoke.cso /dumpbin /Qstrip_rootsignature /Fo norootsignature.cso 1>nul
 dxc.exe smoke.cso /dumpbin /Qstrip_rootsignature /Fo norootsignature.cso 1>nul
 if %errorlevel% neq 0 (
 if %errorlevel% neq 0 (
   echo Failed to strip rootsignature from DXIL container blob
   echo Failed to strip rootsignature from DXIL container blob
+  call :cleanup 2>nul
+  exit /b 1
+)
+
+dxc.exe smoke.cso /dumpbin /extractrootsignature /Fo rootsig.cso 1>nul
+if %errorlevel% neq 0 (
+  echo Failed to extract rootsignature from DXIL container blob
+  call :cleanup 2>nul
+  exit /b 1
+)
+
+dxc.exe norootsignature.cso /dumpbin /setrootsignature rootsig.cso /Fo smoke.cso 1>nul
+if %errorlevel% neq 0 (
+  echo Failed to setrootsignature to DXIL conatiner with no root signature
+  call :cleanup 2>nul
+  exit /b 1
+)
+
+dxc.exe "%2"\..\CodeGenHLSL\NonUniform.hlsl /T ps_6_0 /DDX12 /Fo NonUniform.cso 1>nul
+if %errorlevel% neq 0 (
+  echo Failed to compile NonUniform.hlsl
+  call :cleanup 2>nul
+  exit /b 1
+)
+
+dxc.exe NonUniform.cso /dumpbin /Qstrip_rootsignature /Fo NonUniformNoRootSig.cso 1>nul
+if %errorlevel% neq 0 (
+  echo Failed to strip rootsignature from DXIL container blob for NonUniform.cso
+  call :cleanup 2>nul
+  exit /b 1
+)
+
+dxc.exe NonUniform.cso /dumpbin /extractrootsignature /Fo NonUniformRootSig.cso 1>nul
+if %errorlevel% neq 0 (
+  echo Failed to extract rootsignature from DXIL container blob for NonUniform.cso
+  call :cleanup 2>nul
+  exit /b 1
+)
+
+dxc.exe smoke.cso /dumpbin /verifyrootsignature rootsig.cso 1>nul
+if %errorlevel% neq 0 (
+  echo Failed to verify root signature for somke.cso
+  call :cleanup 2>nul
+  exit /b 1
+)
+
+dxc.exe norootsignature.cso /dumpbin /verifyrootsignature rootsig.cso 1>nul
+if %errorlevel% neq 0 (
+  echo Failed to verify root signature for smoke.cso without root signature
+  call :cleanup 2>nul
+  exit /b 1
+)
+
+dxc.exe NonUniform.cso /dumpbin /verifyrootsignature NonUniformRootSig.cso 1>nul
+if %errorlevel% neq 0 (
+  echo Failed to verify root signature for NonUniform.cso
+  call :cleanup 2>nul
+  exit /b 1
+)
+
+dxc.exe NonUniformNoRootSig.cso /dumpbin /verifyrootsignature NonUniformRootSig.cso 1>nul
+if %errorlevel% neq 0 (
+  echo Failed to verify root signature for somke1.cso without root signature
+  call :cleanup 2>nul
+  exit /b 1
+)
+
+dxc.exe NonUniformNoRootSig.cso /dumpbin /verifyrootsignature rootsig.cso 2>nul
+if %errorlevel% equ 0 (
+  echo Verifying invalid root signature for NonUniformNoRootSig.cso should fail but passed
+  call :cleanup 2>nul
+  exit /b 1
+)
+
+dxc.exe norootsignature.cso /dumpbin /verifyrootsignature NonUniformRootSig.cso 2>nul
+if %errorlevel% equ 0 (
+  echo Verifying invalid root signature for norootsignature.cso should fail but passed
+  call :cleanup 2>nul
+  exit /b 1
+)
+
+dxc.exe smoke.cso /dumpbin /setrootsignature rootsig.cso /Fo smoke.cso 1>nul
+if %errorlevel% neq 0 (
+  echo Failed to setrootsignature to DXIL container that already contains root signature
+  call :cleanup 2>nul
+  exit /b 1
+)
+
+dxc.exe smoke.cso /dumpbin /setrootsignature NonUniformRootSig.cso /Fo smoke.cso 2>nul
+if %errorlevel% equ 0 (
+  echo setrootsignature of invalid root signature should fail but passed
+  call :cleanup 2>nul
+  exit /b 1
+)
+
+dxc.exe %2\..\CodeGenHLSL\Samples\MiniEngine\TextVS.hlsl /Tvs_6_0 /Zi /Fo TextVS.cso 1>nul
+if %errorlevel% neq 0 (
+  echo failed to compile %2\..\CodeGenHLSL\Samples\MiniEngine\TextVS.hlsl
+  call :cleanup 2>nul
+  exit /b 1
+)
+
+dxc.exe smoke.cso /dumpbin /verifyrootsignature TextVS.cso 1>nul
+if %errorlevel% neq 0 ( 
+  echo Verifying valid replacement of root signature failed
+  call :cleanup 2>nul
   exit /b 1
   exit /b 1
 )
 )
 
 
 echo private data > private.txt
 echo private data > private.txt
 dxc.exe smoke.cso /dumpbin /setprivate private.txt /Fo private.cso 1>nul
 dxc.exe smoke.cso /dumpbin /setprivate private.txt /Fo private.cso 1>nul
 if %errorlevel% neq 0 (
 if %errorlevel% neq 0 (
-  echo Failed to set private data from DXIL container blob
+  echo Failed to set private data to DXIL container with no private data
+  call :cleanup 2>nul
+  exit /b 1
+)
+
+dxc.exe private.cso /dumpbin /setprivate private.txt /Fo private.cso 1>nul
+if %errorlevel% neq 0 (
+  echo Failed to set private data to DXIL container that already contains private data
+  call :cleanup 2>nul
   exit /b 1
   exit /b 1
 )
 )
 
 
 dxc.exe private.cso /dumpbin /Qstrip_priv /Fo noprivate.cso 1>nul
 dxc.exe private.cso /dumpbin /Qstrip_priv /Fo noprivate.cso 1>nul
 if %errorlevel% neq 0 (
 if %errorlevel% neq 0 (
   echo Failed to strip private data from DXIL container blob
   echo Failed to strip private data from DXIL container blob
+  call :cleanup 2>nul
   exit /b 1
   exit /b 1
 )
 )
 
 
 dxc.exe private.cso /dumpbin /getprivate private1.txt 1>nul
 dxc.exe private.cso /dumpbin /getprivate private1.txt 1>nul
 if %errorlevel% neq 0 (
 if %errorlevel% neq 0 (
   echo Failed to get private data from DXIL container blob
   echo Failed to get private data from DXIL container blob
+  call :cleanup 2>nul
+  exit /b 1
+)
+
+findstr "private data" %CD%\private1.txt 1>nul
+if %errorlevel% neq 0 (
+  echo Failed to get private data content from DXIL container blob
+  call :cleanup 2>nul
   exit /b 1
   exit /b 1
 )
 )
 
 
 FC smoke.cso noprivate.cso 1>nul
 FC smoke.cso noprivate.cso 1>nul
 if %errorlevel% neq 0 (
 if %errorlevel% neq 0 (
   echo Appending and removing blob roundtrip failed.
   echo Appending and removing blob roundtrip failed.
+  call :cleanup 2>nul
   exit /b 1
   exit /b 1
 )
 )
 
 
-dxc.exe private.cso /Dumpbin /Qstrip_priv /Qstrip_debug /Qstrip_rootsignature /Fo noprivdebugroot.cso 1>nul
+dxc.exe private.cso /dumpbin /Qstrip_priv /Qstrip_debug /Qstrip_rootsignature /Fo noprivdebugroot.cso 1>nul
 if %errorlevel% neq 0 (
 if %errorlevel% neq 0 (
   echo Failed to extract multiple parts from DXIL container blob
   echo Failed to extract multiple parts from DXIL container blob
+  call :cleanup 2>nul
   exit /b 1
   exit /b 1
 )
 )
 
 
@@ -118,6 +331,7 @@ echo Smoke test for dxc.exe shader model upgrade...
 dxc.exe /T ps_5_0 smoke.hlsl 1> nul
 dxc.exe /T ps_5_0 smoke.hlsl 1> nul
 if %errorlevel% neq 0 (
 if %errorlevel% neq 0 (
   echo Failed shader model upgrade test - %CD%\dxc.exe /T ps_5_0 %CD%\smoke.hlsl
   echo Failed shader model upgrade test - %CD%\dxc.exe /T ps_5_0 %CD%\smoke.hlsl
+  call :cleanup 2>nul
   exit /b 1
   exit /b 1
 )
 )
 
 
@@ -125,64 +339,69 @@ echo Smoke test for dxa command line program ...
 dxa.exe smoke.cso -listfiles 1> nul
 dxa.exe smoke.cso -listfiles 1> nul
 if %errorlevel% neq 0 (
 if %errorlevel% neq 0 (
   echo Failed to list files from blob 
   echo Failed to list files from blob 
+  call :cleanup 2>nul
   exit /b 1
   exit /b 1
 )
 )
 
 
 dxa.exe smoke.cso -listparts 1> nul
 dxa.exe smoke.cso -listparts 1> nul
 if %errorlevel% neq 0 (
 if %errorlevel% neq 0 (
   echo Failed to list parts from blob
   echo Failed to list parts from blob
+  call :cleanup 2>nul
   exit /b 1
   exit /b 1
 )
 )
 
 
 dxa.exe smoke.cso -extractpart dbgmodule -o smoke.cso.ll 1>nul
 dxa.exe smoke.cso -extractpart dbgmodule -o smoke.cso.ll 1>nul
 if %errorlevel% neq 0 (
 if %errorlevel% neq 0 (
   echo Failed to extract DXIL part from the blob generated by %CD%\smoke.hlsl
   echo Failed to extract DXIL part from the blob generated by %CD%\smoke.hlsl
+  call :cleanup 2>nul
   exit /b 1
   exit /b 1
 )
 )
 
 
 dxa.exe smoke.cso.ll -listfiles 1> nul
 dxa.exe smoke.cso.ll -listfiles 1> nul
 if %errorlevel% neq 0 (
 if %errorlevel% neq 0 (
   echo Failed to list files from Dxil part with Dxil with Debug Info
   echo Failed to list files from Dxil part with Dxil with Debug Info
+  call :cleanup 2>nul
   exit /b 1
   exit /b 1
 )
 )
 
 
 dxa.exe smoke.cso.ll -extractfile * 1> nul
 dxa.exe smoke.cso.ll -extractfile * 1> nul
 if %errorlevel% neq 0 (
 if %errorlevel% neq 0 (
   echo Failed to extract files from Dxil part with Dxil with Debug Info
   echo Failed to extract files from Dxil part with Dxil with Debug Info
+  call :cleanup 2>nul
   exit /b 1
   exit /b 1
 )
 )
 
 
-echo Smoke test for dxopt ...
-dxopt.exe -passes | findstr inline 1>nul
-if %errorlevel% neq 0 (
-  echo Failed to find the inline pass via dxopt -passes
-  exit /b 1
-)
 dxa.exe smoke.cso -extractpart module -o smoke.cso.plain.ll 1>nul
 dxa.exe smoke.cso -extractpart module -o smoke.cso.plain.ll 1>nul
 if %errorlevel% neq 0 (
 if %errorlevel% neq 0 (
   echo Failed to extract plain module via dxa.exe smoke.cso -extractpart module -o smoke.cso.plain.ll
   echo Failed to extract plain module via dxa.exe smoke.cso -extractpart module -o smoke.cso.plain.ll
-  exit /b 1
-)
-dxopt.exe smoke.cso.plain.ll -o=smoke.cso.inlined.ll -inline
-if %errorlevel% neq 0 (
-  echo Failed to run an inline pass via dxopt.exe smoke.cso.ll -o=smoke.cso.inlined.ll -inline
-  exit /b 1
-)
-dxc.exe -dumpbin smoke.cso.inlined.ll 1>nul
-if %errorlevel% neq 0 (
-  echo Failed to dump the inlined file.
+  call :cleanup 2>nul
   exit /b 1
   exit /b 1
 )
 )
 
 
-rem Clean up.
+call :cleanup
+exit /b 0
+
+:cleanup
+del %CD%\preprocessed.hlsl
+del %CD%\smoke.hlsl.c
+del %CD%\smoke.hlsl.d
+del %CD%\smoke.hlsl.e
 del %CD%\smoke.hlsl.h
 del %CD%\smoke.hlsl.h
 del %CD%\smoke.cso
 del %CD%\smoke.cso
+del %CD%\NonUniform.cso
 del %CD%\private.cso
 del %CD%\private.cso
 del %CD%\private.txt
 del %CD%\private.txt
 del %CD%\private1.txt
 del %CD%\private1.txt
 del %CD%\noprivate.cso
 del %CD%\noprivate.cso
 del %CD%\nodebug.cso
 del %CD%\nodebug.cso
+del %CD%\rootsig.cso
+del %CD%\NonUniformRootSig.cso
 del %CD%\noprivdebugroot.cso
 del %CD%\noprivdebugroot.cso
 del %CD%\norootsignature.cso
 del %CD%\norootsignature.cso
+del %CD%\NonUniformNoRootSig.cso
+del %CD%\TextVS.cso
+del %CD%\smoke.cso.plain.ll
+del %CD%\smoke.cso.ll
 
 
 exit /b 0
 exit /b 0
+

+ 3 - 2
utils/hct/smoke.hlsl

@@ -1,12 +1,13 @@
+int g;
 #ifndef semantic
 #ifndef semantic
 #define semantic SV_Target
 #define semantic SV_Target
 #endif
 #endif
 #ifdef DX12
 #ifdef DX12
-#define RS ""
+#define RS "CBV(b0)"
 [RootSignature ( RS )]
 [RootSignature ( RS )]
 #endif
 #endif
 
 
 float4 main() : semantic
 float4 main() : semantic
 {
 {
-  return 0;
+  return g;
 }
 }

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio