Browse Source

Copy ViewID state to PSV data and select PSV version based on validator (#291)

* Make validator version a first-class citizen of DxilModule

* Add validator version checks to DxilContainerAssembler
- eliminates need to check validator version in dxcompilerobj.cpp

* Copy dynamic index mask and ViewID state to PSV data
- Make const version of DxilViewIDState::GetSerialized() that just returns serialized state
Tex Riddell 8 years ago
parent
commit
c95244404a

+ 2 - 0
include/dxc/HLSL/ComputeViewIdState.h

@@ -61,7 +61,9 @@ public:
   const InputsContributingToOutputType &getPCInputsContributingToOutputs() const;
 
   void Compute();
+  void Serialize();
   const std::vector<unsigned> &GetSerialized();
+  const std::vector<unsigned> &GetSerialized() const;   // returns previously serialized data
   void Deserialize(const unsigned *pData, unsigned DataSize);
   void PrintSets(llvm::raw_ostream &OS);
 

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

@@ -423,7 +423,7 @@ public:
 DxilPartWriter *NewProgramSignatureWriter(const DxilModule &M, DXIL::SignatureKind Kind);
 DxilPartWriter *NewRootSignatureWriter(const RootSignatureHandle &S);
 DxilPartWriter *NewFeatureInfoWriter(const DxilModule &M);
-DxilPartWriter *NewPSVWriter(const DxilModule &M);
+DxilPartWriter *NewPSVWriter(const DxilModule &M, uint32_t PSVVersion = 0);
 
 class DxilContainerWriter : public DxilPartWriter  {
 public:
@@ -434,7 +434,7 @@ public:
 
 DxilContainerWriter *NewDxilContainerWriter();
 
-enum class SerializeDxilFlags {
+enum class SerializeDxilFlags : uint32_t {
   None = 0,                     // No flags defined.
   IncludeDebugInfoPart = 1,     // Include the debug info part in the container.
   IncludeDebugNamePart = 2,     // Include the debug name part in the container.
@@ -444,9 +444,16 @@ inline SerializeDxilFlags& operator |=(SerializeDxilFlags& l, const SerializeDxi
   l = static_cast<SerializeDxilFlags>(static_cast<int>(l) | static_cast<int>(r));
   return l;
 }
+inline SerializeDxilFlags& operator &=(SerializeDxilFlags& l, const SerializeDxilFlags& r) {
+  l = static_cast<SerializeDxilFlags>(static_cast<int>(l) & static_cast<int>(r));
+  return l;
+}
 inline int operator&(SerializeDxilFlags l, SerializeDxilFlags r) {
   return static_cast<int>(l) & static_cast<int>(r);
 }
+inline SerializeDxilFlags operator~(SerializeDxilFlags l) {
+  return static_cast<SerializeDxilFlags>(~static_cast<uint32_t>(l));
+}
 
 void SerializeDxilContainerForModule(hlsl::DxilModule *pModule,
                                      AbstractMemoryStream *pModuleBitcode,

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

@@ -188,6 +188,7 @@ public:
 
   // Validator version.
   static const char kDxilValidatorVersionMDName[];
+  // Validator version uses the same constants for fields as kDxilVersion*
 
   // Extended shader property tags.
   static const unsigned kDxilShaderFlagsTag     = 0;
@@ -257,6 +258,10 @@ public:
   void EmitDxilVersion(unsigned Major, unsigned Minor);
   void LoadDxilVersion(unsigned &Major, unsigned &Minor);
 
+  // Validator version.
+  void EmitValidatorVersion(unsigned Major, unsigned Minor);
+  void LoadValidatorVersion(unsigned &Major, unsigned &Minor);
+
   // Shader model.
   void EmitDxilShaderModel(const ShaderModel *pSM);
   void LoadDxilShaderModel(const ShaderModel *&pSM);

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

@@ -51,6 +51,14 @@ public:
   void SetShaderModel(const ShaderModel *pSM);
   const ShaderModel *GetShaderModel() const;
   void GetDxilVersion(unsigned &DxilMajor, unsigned &DxilMinor) const;
+  void SetValidatorVersion(unsigned ValMajor, unsigned ValMinor);
+  bool UpgradeValidatorVersion(unsigned ValMajor, unsigned ValMinor);
+  void GetValidatorVersion(unsigned &ValMajor, unsigned &ValMinor) const;
+
+  // Return true on success, requires valid shader model and CollectShaderFlags to have been set
+  bool GetMinValidatorVersion(unsigned &ValMajor, unsigned &ValMinor) const;
+  // Update validator version to minimum if higher than current (ex: after CollectShaderFlags)
+  bool UpgradeToMinValidatorVersion();
 
   // Entry functions.
   llvm::Function *GetEntryFunction();
@@ -106,6 +114,8 @@ public:
 
   // Remove Root Signature from module metadata
   void StripRootSignatureFromMetadata();
+  // Update validator version metadata to current setting
+  void UpdateValidatorVersionMetadata();
 
   // DXIL type system.
   DxilTypeSystem &GetTypeSystem();
@@ -116,6 +126,7 @@ public:
 
   // ViewId state.
   DxilViewIdState &GetViewIdState();
+  const DxilViewIdState &GetViewIdState() const;
 
   // DXIL metadata manipulation.
   /// Serialize DXIL in-memory form to metadata form.
@@ -288,6 +299,8 @@ private:
   const ShaderModel *m_pSM;
   unsigned m_DxilMajor;
   unsigned m_DxilMinor;
+  unsigned m_ValMajor;
+  unsigned m_ValMinor;
 
   std::unique_ptr<OP> m_pOP;
   size_t m_pUnused;

+ 14 - 12
include/dxc/HLSL/DxilPipelineStateValidation.h

@@ -449,10 +449,18 @@ public:
     if(!(pSize)) return false;
     if (initInfo.PSVVersion > 1) return false;
 
+    // Versioned structure sizes
+    m_uPSVRuntimeInfoSize = sizeof(PSVRuntimeInfo0);
+    m_uPSVResourceBindInfoSize = sizeof(PSVResourceBindInfo0);
+    m_uPSVSignatureElementSize = sizeof(PSVSignatureElement0);
+    if (initInfo.PSVVersion > 0) {
+      m_uPSVRuntimeInfoSize = sizeof(PSVRuntimeInfo1);
+    }
+
     // PSVVersion 0
-    uint32_t size = sizeof(PSVRuntimeInfo1) + sizeof(uint32_t) * 2;
+    uint32_t size = m_uPSVRuntimeInfoSize + sizeof(uint32_t) * 2;
     if (initInfo.ResourceCount) {
-      size += sizeof(uint32_t) + (sizeof(PSVResourceBindInfo0) * initInfo.ResourceCount);
+      size += sizeof(uint32_t) + (m_uPSVResourceBindInfoSize * initInfo.ResourceCount);
     }
 
     // PSVVersion 1
@@ -462,9 +470,9 @@ public:
       if (initInfo.SigInputElements || initInfo.SigOutputElements || initInfo.SigPatchConstantElements) {
         size += sizeof(uint32_t);   // PSVSignatureElement_size
       }
-      size += sizeof(PSVSignatureElement0) * initInfo.SigInputElements;
-      size += sizeof(PSVSignatureElement0) * initInfo.SigOutputElements;
-      size += sizeof(PSVSignatureElement0) * initInfo.SigPatchConstantElements;
+      size += m_uPSVSignatureElementSize * initInfo.SigInputElements;
+      size += m_uPSVSignatureElementSize * initInfo.SigOutputElements;
+      size += m_uPSVSignatureElementSize * initInfo.SigPatchConstantElements;
 
       if (initInfo.UsesViewID) {
         size += sizeof(uint32_t) * PSVComputeMaskDwordsFromVectors(initInfo.SigOutputVectors);
@@ -494,10 +502,6 @@ public:
 
     // PSVVersion 0
     memset(pBuffer, 0, size);
-    m_uPSVRuntimeInfoSize = sizeof(PSVRuntimeInfo0);
-    if (initInfo.PSVVersion > 0) {
-      m_uPSVRuntimeInfoSize = sizeof(PSVRuntimeInfo1);
-    }
     uint8_t* pCurBits = (uint8_t*)pBuffer;
     *(uint32_t*)pCurBits = m_uPSVRuntimeInfoSize;
     pCurBits += sizeof(uint32_t);
@@ -505,14 +509,13 @@ public:
     if (initInfo.PSVVersion > 0) {
       m_pPSVRuntimeInfo1 = (PSVRuntimeInfo1*)pCurBits;
     }
-    pCurBits += sizeof(PSVRuntimeInfo1);
+    pCurBits += m_uPSVRuntimeInfoSize;
 
     // Set resource info:
     m_uResourceCount = initInfo.ResourceCount;
     *(uint32_t*)pCurBits = m_uResourceCount;
     pCurBits += sizeof(uint32_t);
     if (m_uResourceCount > 0) {
-      m_uPSVResourceBindInfoSize = sizeof(PSVResourceBindInfo0);
       *(uint32_t*)pCurBits = m_uPSVResourceBindInfoSize;
       pCurBits += sizeof(uint32_t);
       m_pPSVResourceBindInfo = pCurBits;
@@ -547,7 +550,6 @@ public:
 
       // Dxil Signature Elements
       if (m_pPSVRuntimeInfo1->SigInputElements || m_pPSVRuntimeInfo1->SigOutputElements || m_pPSVRuntimeInfo1->SigPatchConstantElements) {
-        m_uPSVSignatureElementSize = sizeof(PSVSignatureElement0);
         *(uint32_t*)pCurBits = m_uPSVSignatureElementSize;
         pCurBits += sizeof(uint32_t);
       }

+ 1 - 1
include/dxc/HLSL/DxilShaderModel.h

@@ -44,7 +44,7 @@ public:
   unsigned GetMajor() const { return m_Major; }
   unsigned GetMinor() const { return m_Minor; }
   void GetDxilVersion(unsigned &DxilMajor, unsigned &DxilMinor) const;
-  uint32_t GetPSVVersion() const;
+  void GetMinValidatorVersion(unsigned &ValMajor, unsigned &ValMinor) const;
   bool IsSM50Plus() const   { return m_Major >= 5; }
   bool IsSM51Plus() const   { return m_Major > 5 || (m_Major == 5 && m_Minor >= 1); }
   bool IsSM60Plus() const   { return m_Major >= 6; }

+ 4 - 0
include/dxc/HLSL/HLModule.h

@@ -114,6 +114,8 @@ public:
   OP *GetOP() const;
   void SetShaderModel(const ShaderModel *pSM);
   const ShaderModel *GetShaderModel() const;
+  void SetValidatorVersion(unsigned ValMajor, unsigned ValMinor);
+  void GetValidatorVersion(unsigned &ValMajor, unsigned &ValMinor) const;
 
   // HLOptions
   void SetHLOptions(HLOptions &opts);
@@ -299,6 +301,8 @@ private:
   const ShaderModel *m_pSM;
   unsigned m_DxilMajor;
   unsigned m_DxilMinor;
+  unsigned m_ValMajor;
+  unsigned m_ValMinor;
   HLOptions m_Options;
   std::unique_ptr<OP> m_pOP;
   size_t m_pUnused;

+ 11 - 3
lib/HLSL/ComputeViewIdState.cpp

@@ -657,9 +657,9 @@ static unsigned RoundUpToUINT(unsigned x) {
   return (x + 31)/32;
 }
 
-const vector<unsigned> &DxilViewIdState::GetSerialized() {
+void DxilViewIdState::Serialize() {
   if (!m_SerializedState.empty())
-    return m_SerializedState;
+    return;
 
   const ShaderModel *pSM = m_pModule->GetShaderModel();
   unsigned NumOutUINTs = RoundUpToUINT(m_NumOutputSigScalars);
@@ -689,7 +689,13 @@ const vector<unsigned> &DxilViewIdState::GetSerialized() {
                m_OutputsDependentOnViewId, m_PCInputsContributingToOutputs, pData);
   }
   DXASSERT_NOMSG(pData == (&m_SerializedState[0] + Size));
-
+}
+const vector<unsigned> &DxilViewIdState::GetSerialized() {
+  if (m_SerializedState.empty())
+    Serialize();
+  return m_SerializedState;
+}
+const vector<unsigned> &DxilViewIdState::GetSerialized() const {
   return m_SerializedState;
 }
 
@@ -732,6 +738,8 @@ void DxilViewIdState::Serialize1(unsigned NumInputs, unsigned NumOutputs,
 
 void DxilViewIdState::Deserialize(const unsigned *pData, unsigned DataSize) {
   Clear();
+  m_SerializedState.resize(DataSize);
+  memcpy(m_SerializedState.data(), pData, DataSize * 4);
 
   const ShaderModel *pSM = m_pModule->GetShaderModel();
   unsigned ConsumedUINTs;

+ 49 - 10
lib/HLSL/DxilContainerAssembler.cpp

@@ -349,8 +349,8 @@ private:
     if (SE.GetKind() == DXIL::SemanticKind::Arbitrary && strlen(SE.GetName()) > 0) {
       E.SemanticName = (uint32_t)m_StringBuffer.size();
       StringRef Name(SE.GetName());
-      m_StringBuffer.append('\0', Name.size()+1);
-      memcpy(m_StringBuffer.data(), Name.data(), Name.size());
+      m_StringBuffer.append(Name.size()+1, '\0');
+      memcpy(m_StringBuffer.data() + E.SemanticName, Name.data(), Name.size());
     } else {
       // m_StringBuffer always starts with '\0' so offset 0 is empty string:
       E.SemanticName = 0;
@@ -374,7 +374,7 @@ private:
     }
     if (!match) {
       E.SemanticIndexes = m_SemanticIndexBuffer.size();
-      for (uint32_t row = 0; row < E.SemanticIndexes; row++) {
+      for (uint32_t row = 0; row < SemIdx.size(); row++) {
         m_SemanticIndexBuffer.push_back((uint32_t)SemIdx[row]);
       }
     }
@@ -395,15 +395,38 @@ private:
     E.DynamicMaskAndStream = (uint8_t)((SE.GetOutputStream() & 0x3) << 4);
 
     // TODO: Fill Dynamic Index Mask in!
-    //DXASSERT_NOMSG((SE.GetDynamicIndexMask() & ~0xF) == 0);
-    //E.DynamicMaskAndStream |= (SE.GetDynamicIndexMask()) & 0xF;
+    E.DynamicMaskAndStream |= (SE.GetDynIdxCompMask()) & 0xF;
+  }
+
+  const uint32_t *CopyViewIDState(const uint32_t *pSrc, const PSVComponentMasks &ViewIDMask, const PSVDependencyTable &IOTable) {
+    uint32_t InputScalars = *(pSrc++);
+    uint32_t OutputScalars = *(pSrc++);
+    unsigned MaskDwords = PSVComputeMaskDwordsFromVectors(PSVALIGN4(OutputScalars) / 4);
+    if (ViewIDMask.Masks) {
+      DXASSERT_NOMSG(!IOTable.Table || ViewIDMask.NumVectors == IOTable.OutputVectors);
+      memcpy(ViewIDMask.Masks, pSrc, 4 * MaskDwords);
+    }
+    pSrc += MaskDwords;
+    if (IOTable.Table && IOTable.InputVectors && IOTable.OutputVectors) {
+      DXASSERT_NOMSG((InputScalars <= IOTable.InputVectors * 4) && (IOTable.InputVectors * 4 - InputScalars < 4));
+      DXASSERT_NOMSG((OutputScalars <= IOTable.OutputVectors * 4) && (IOTable.OutputVectors * 4 - OutputScalars < 4));
+      memcpy(IOTable.Table, pSrc, 4 * MaskDwords * InputScalars);
+    }
+    pSrc += MaskDwords * InputScalars;
+    return pSrc;
   }
 
 public:
-  DxilPSVWriter(const DxilModule &module)
+  DxilPSVWriter(const DxilModule &module, uint32_t PSVVersion = 0)
   : m_Module(module),
-    m_PSVInitInfo(1)//module.GetShaderModel()->GetPSVVersion())
+    m_PSVInitInfo(PSVVersion)
   {
+    unsigned ValMajor, ValMinor;
+    m_Module.GetValidatorVersion(ValMajor, ValMinor);
+    // Allow PSVVersion to be upgraded
+    if (m_PSVInitInfo.PSVVersion < 1 && (ValMajor > 1 || (ValMajor == 1 && ValMinor >= 1)))
+      m_PSVInitInfo.PSVVersion = 1;
+
     UINT uCBuffers = m_Module.GetCBuffers().size();
     UINT uSamplers = m_Module.GetSamplers().size();
     UINT uSRVs = m_Module.GetSRVs().size();
@@ -623,7 +646,18 @@ public:
         memcpy(pPatchConstantElement, &m_SigPatchConstantElements[i], sizeof(PSVSignatureElement0));
       }
 
-      // TODO: Write ViewID Output masks and Input to Output dependency tables
+      // Gather ViewID dependency information
+      auto &viewState = m_Module.GetViewIdState().GetSerialized();
+      if (!viewState.empty()) {
+        const uint32_t *pSrc = viewState.data();
+        pSrc = CopyViewIDState(pSrc, m_PSV.GetViewIDOutputMasks(), m_PSV.GetInputToOutputTable());
+        if (m_Module.GetShaderModel()->IsHS()) {
+          pSrc = CopyViewIDState(pSrc, m_PSV.GetViewIDPCOutputMasks(), m_PSV.GetInputToPCOutputTable());
+        } else if (m_Module.GetShaderModel()->IsDS()) {
+          pSrc = CopyViewIDState(pSrc, PSVComponentMasks(), m_PSV.GetPCInputToOutputTable());
+        }
+        DXASSERT_NOMSG(viewState.data() + viewState.size() == pSrc);
+      }
     }
 
     ULONG cbWritten;
@@ -632,8 +666,8 @@ public:
   }
 };
 
-DxilPartWriter *hlsl::NewPSVWriter(const DxilModule &M) {
-  return new DxilPSVWriter(M);
+DxilPartWriter *hlsl::NewPSVWriter(const DxilModule &M, uint32_t PSVVersion) {
+  return new DxilPSVWriter(M, PSVVersion);
 }
 
 class DxilContainerWriter_impl : public DxilContainerWriter  {
@@ -745,6 +779,11 @@ void hlsl::SerializeDxilContainerForModule(DxilModule *pModule,
   DXASSERT_NOMSG(pModuleBitcode != nullptr);
   DXASSERT_NOMSG(pFinalStream != nullptr);
 
+  unsigned ValMajor, ValMinor;
+  pModule->GetValidatorVersion(ValMajor, ValMinor);
+  if (ValMajor == 1 && ValMinor == 0)
+    Flags &= ~SerializeDxilFlags::IncludeDebugNamePart;
+
   DxilProgramSignatureWriter inputSigWriter(pModule->GetInputSignature(),
                                             pModule->GetTessellatorDomain(),
                                             /*IsInput*/ true);

+ 8 - 0
lib/HLSL/DxilGenerationPass.cpp

@@ -105,6 +105,9 @@ void InitResource(const DxilResource *pSource, DxilResource *pDest) {
 
 void InitDxilModuleFromHLModule(HLModule &H, DxilModule &M, bool HasDebugInfo) {
   // Subsystems.
+  unsigned ValMajor, ValMinor;
+  H.GetValidatorVersion(ValMajor, ValMinor);
+  M.SetValidatorVersion(ValMajor, ValMinor);
   M.SetShaderModel(H.GetShaderModel());
 
   // Entry function.
@@ -231,6 +234,9 @@ void InitDxilModuleFromHLModule(HLModule &H, DxilModule &M, bool HasDebugInfo) {
   M.ResetOP(H.ReleaseOP());
   // Keep llvm used.
   M.EmitLLVMUsed();
+
+  // Update Validator Version
+  M.UpgradeToMinValidatorVersion();
 }
 
 class DxilGenerationPass : public ModulePass {
@@ -2996,6 +3002,8 @@ public:
       }
 
       DM.CollectShaderFlags(); // Update flags to reflect any changes.
+                               // Update Validator Version
+      DM.UpgradeToMinValidatorVersion();
       DM.EmitDxilMetadata();
       return true;
     }

+ 38 - 0
lib/HLSL/DxilMetadataHelper.cpp

@@ -108,6 +108,44 @@ void DxilMDHelper::LoadDxilVersion(unsigned &Major, unsigned &Minor) {
   Minor = ConstMDToUint32(pVersionMD->getOperand(kDxilVersionMinorIdx));
 }
 
+//
+// Validator version.
+//
+void DxilMDHelper::EmitValidatorVersion(unsigned Major, unsigned Minor) {
+  NamedMDNode *pDxilValidatorVersionMD = m_pModule->getNamedMetadata(kDxilValidatorVersionMDName);
+
+  // Allow re-writing the validator version, since this can be changed at later points.
+  if (pDxilValidatorVersionMD)
+    m_pModule->eraseNamedMetadata(pDxilValidatorVersionMD);
+
+  pDxilValidatorVersionMD = m_pModule->getOrInsertNamedMetadata(kDxilValidatorVersionMDName);
+
+  Metadata *MDVals[kDxilVersionNumFields];
+  MDVals[kDxilVersionMajorIdx] = Uint32ToConstMD(Major);
+  MDVals[kDxilVersionMinorIdx] = Uint32ToConstMD(Minor);
+
+  pDxilValidatorVersionMD->addOperand(MDNode::get(m_Ctx, MDVals));
+}
+
+void DxilMDHelper::LoadValidatorVersion(unsigned &Major, unsigned &Minor) {
+  NamedMDNode *pDxilValidatorVersionMD = m_pModule->getNamedMetadata(kDxilValidatorVersionMDName);
+
+  if (pDxilValidatorVersionMD == nullptr) {
+    // If no validator version metadata, assume 1.0
+    Major = 1;
+    Minor = 0;
+    return;
+  }
+
+  IFTBOOL(pDxilValidatorVersionMD->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
+
+  MDNode *pVersionMD = pDxilValidatorVersionMD->getOperand(0);
+  IFTBOOL(pVersionMD->getNumOperands() == kDxilVersionNumFields, DXC_E_INCORRECT_DXIL_METADATA);
+
+  Major = ConstMDToUint32(pVersionMD->getOperand(kDxilVersionMajorIdx));
+  Minor = ConstMDToUint32(pVersionMD->getOperand(kDxilVersionMinorIdx));
+}
+
 //
 // DXIL shader model.
 //

+ 49 - 1
lib/HLSL/DxilModule.cpp

@@ -68,6 +68,8 @@ DxilModule::DxilModule(Module *pModule)
 , m_pSM(nullptr)
 , m_DxilMajor(DXIL::kDxilMajor)
 , m_DxilMinor(DXIL::kDxilMinor)
+, m_ValMajor(1)
+, m_ValMinor(0)
 , m_InputPrimitive(DXIL::InputPrimitive::Undefined)
 , m_MaxVertexCount(0)
 , m_StreamPrimitiveTopology(DXIL::PrimitiveTopology::Undefined)
@@ -149,6 +151,42 @@ void DxilModule::GetDxilVersion(unsigned &DxilMajor, unsigned &DxilMinor) const
   DxilMinor = m_DxilMinor;
 }
 
+void DxilModule::SetValidatorVersion(unsigned ValMajor, unsigned ValMinor) {
+  m_ValMajor = ValMajor;
+  m_ValMinor = ValMinor;
+}
+
+bool DxilModule::UpgradeValidatorVersion(unsigned ValMajor, unsigned ValMinor) {
+  if (ValMajor > m_ValMajor || (ValMajor == m_ValMajor && ValMinor > m_ValMinor)) {
+    // Module requires higher validator version than previously set
+    SetValidatorVersion(ValMajor, ValMinor);
+    return true;
+  }
+  return false;
+}
+
+void DxilModule::GetValidatorVersion(unsigned &ValMajor, unsigned &ValMinor) const {
+  ValMajor = m_ValMajor;
+  ValMinor = m_ValMinor;
+}
+
+bool DxilModule::GetMinValidatorVersion(unsigned &ValMajor, unsigned &ValMinor) const {
+  if (!m_pSM)
+    return false;
+  m_pSM->GetMinValidatorVersion(ValMajor, ValMinor);
+  if (ValMajor == 1 && ValMinor == 0 && (m_ShaderFlags.GetFeatureInfo() & hlsl::ShaderFeatureInfo_ViewID))
+    ValMinor = 1;
+  return true;
+}
+
+bool DxilModule::UpgradeToMinValidatorVersion() {
+  unsigned ValMajor = 1, ValMinor = 0;
+  if (GetMinValidatorVersion(ValMajor, ValMinor)) {
+    return UpgradeValidatorVersion(ValMajor, ValMinor);
+  }
+  return false;
+}
+
 Function *DxilModule::GetEntryFunction() {
   return m_pEntryFunc;
 }
@@ -873,6 +911,10 @@ void DxilModule::StripRootSignatureFromMetadata() {
   }
 }
 
+void DxilModule::UpdateValidatorVersionMetadata() {
+  m_pMDHelper->EmitValidatorVersion(m_ValMajor, m_ValMinor);
+}
+
 void DxilModule::ResetInputSignature(DxilSignature *pValue) {
   m_InputSignature.reset(pValue);
 }
@@ -896,6 +938,9 @@ DxilTypeSystem &DxilModule::GetTypeSystem() {
 DxilViewIdState &DxilModule::GetViewIdState() {
   return *m_pViewIdState;
 }
+const DxilViewIdState &DxilModule::GetViewIdState() const {
+  return *m_pViewIdState;
+}
 
 void DxilModule::ResetTypeSystem(DxilTypeSystem *pValue) {
   m_pTypeSystem.reset(pValue);
@@ -947,6 +992,7 @@ vector<GlobalVariable* > &DxilModule::GetLLVMUsed() {
 // DXIL metadata serialization/deserialization.
 void DxilModule::EmitDxilMetadata() {
   m_pMDHelper->EmitDxilVersion(m_DxilMajor, m_DxilMinor);
+  m_pMDHelper->EmitValidatorVersion(m_ValMajor, m_ValMinor);
   m_pMDHelper->EmitDxilShaderModel(m_pSM);
 
   MDTuple *pMDSignatures = m_pMDHelper->EmitDxilSignatures(*m_InputSignature, 
@@ -955,7 +1001,8 @@ void DxilModule::EmitDxilMetadata() {
   MDTuple *pMDResources = EmitDxilResources();
   MDTuple *pMDProperties = EmitDxilShaderProperties();
   m_pMDHelper->EmitDxilTypeSystem(GetTypeSystem(), m_LLVMUsed);
-  if (!m_pSM->IsCS()) {
+  if (!m_pSM->IsCS() &&
+      (m_ValMajor > 1 || (m_ValMajor == 1 && m_ValMinor >= 1))) {
     m_pMDHelper->EmitDxilViewIdState(GetViewIdState());
   }
   EmitLLVMUsed();
@@ -975,6 +1022,7 @@ bool DxilModule::IsKnownNamedMetaData(llvm::NamedMDNode &Node) {
 
 void DxilModule::LoadDxilMetadata() {
   m_pMDHelper->LoadDxilVersion(m_DxilMajor, m_DxilMinor);
+  m_pMDHelper->LoadValidatorVersion(m_ValMajor, m_ValMinor);
   const ShaderModel *loadedModule;
   m_pMDHelper->LoadDxilShaderModel(loadedModule);
   SetShaderModel(loadedModule);

+ 9 - 5
lib/HLSL/DxilShaderModel.cpp

@@ -133,18 +133,22 @@ void ShaderModel::GetDxilVersion(unsigned &DxilMajor, unsigned &DxilMinor) const
   }
 }
 
-uint32_t ShaderModel::GetPSVVersion() const {
+void ShaderModel::GetMinValidatorVersion(unsigned &ValMajor, unsigned &ValMinor) const {
+  DXASSERT(IsValidForDxil(), "invalid shader model");
+  ValMajor = 1;
   switch (m_Minor) {
-  case 0: return 0;
-  case 1: return 1;
+  case 0:
+    ValMinor = 0;
+    break;
+  case 1:
+    ValMinor = 1;
+    break;
   default:
     DXASSERT(0, "IsValidForDxil() should have caught this.");
     break;
   }
-  return (unsigned)-1;
 }
 
-
 std::string ShaderModel::GetKindName() const {
   return std::string(m_pszName).substr(0, 2);
 }

+ 8 - 2
lib/HLSL/DxilValidation.cpp

@@ -4248,8 +4248,14 @@ bool VerifySignatureMatches(llvm::Module *pModule,
 static void VerifyPSVMatches(_In_ ValidationContext &ValCtx,
                              _In_reads_bytes_(PSVSize) const void *pPSVData,
                              _In_ uint32_t PSVSize) {
+  uint32_t PSVVersion = 1;  // This should be set to the newest version
+  unique_ptr<DxilPartWriter> pWriter(NewPSVWriter(ValCtx.DxilMod, PSVVersion));
+  // Try each version in case an earlier version matches module
+  while (PSVVersion && pWriter->size() != PSVSize) {
+    PSVVersion --;
+    pWriter.reset(NewPSVWriter(ValCtx.DxilMod, PSVVersion));
+  }
   // generate PSV data from module and memcmp
-  unique_ptr<DxilPartWriter> pWriter(NewPSVWriter(ValCtx.DxilMod));
   VerifyBlobPartMatches(ValCtx, "Pipeline State Validation", pWriter.get(), pPSVData, PSVSize);
 }
 
@@ -4494,7 +4500,7 @@ HRESULT ValidateDxilBitcode(
 
   DxilModule &dxilModule = pModule->GetDxilModule();
   if (!dxilModule.GetRootSignature().IsEmpty()) {
-    unique_ptr<DxilPartWriter> pWriter(NewPSVWriter(dxilModule));
+    unique_ptr<DxilPartWriter> pWriter(NewPSVWriter(dxilModule, 0));
     DXASSERT_NOMSG(pWriter->size());
     CComPtr<IMalloc> pMalloc;
     IFT(CoGetMalloc(1, &pMalloc));

+ 13 - 0
lib/HLSL/HLModule.cpp

@@ -80,6 +80,16 @@ LLVMContext &HLModule::GetCtx() const { return m_Ctx; }
 Module *HLModule::GetModule() const { return m_pModule; }
 OP *HLModule::GetOP() const { return m_pOP.get(); }
 
+void HLModule::SetValidatorVersion(unsigned ValMajor, unsigned ValMinor) {
+  m_ValMajor = ValMajor;
+  m_ValMinor = ValMinor;
+}
+
+void HLModule::GetValidatorVersion(unsigned &ValMajor, unsigned &ValMinor) const {
+  ValMajor = m_ValMajor;
+  ValMinor = m_ValMinor;
+}
+
 void HLModule::SetShaderModel(const ShaderModel *pSM) {
   DXASSERT(m_pSM == nullptr, "shader model must not change for the module");
   DXASSERT(pSM != nullptr && pSM->IsValidForDxil(), "shader model must be valid");
@@ -411,6 +421,7 @@ static const StringRef kHLDxilResourceTypeAnnotationMDName       = "dx.resource.
 // DXIL metadata serialization/deserialization.
 void HLModule::EmitHLMetadata() {
   m_pMDHelper->EmitDxilVersion(m_DxilMajor, m_DxilMinor);
+  m_pMDHelper->EmitValidatorVersion(m_ValMajor, m_ValMinor);
   m_pMDHelper->EmitDxilShaderModel(m_pSM);
 
   MDTuple *pMDSignatures = m_pMDHelper->EmitDxilSignatures(*m_InputSignature, 
@@ -483,6 +494,7 @@ void HLModule::EmitHLMetadata() {
 
 void HLModule::LoadHLMetadata() {
   m_pMDHelper->LoadDxilVersion(m_DxilMajor, m_DxilMinor);
+  m_pMDHelper->LoadValidatorVersion(m_ValMajor, m_ValMinor);
   m_pMDHelper->LoadDxilShaderModel(m_pSM);
   CreateSignatures(m_pSM, m_InputSignature, m_OutputSignature, m_PatchConstantSignature, m_RootSignature);
 
@@ -570,6 +582,7 @@ void HLModule::ClearHLMetadata(llvm::Module &M) {
         name == DxilMDHelper::kDxilRootSignatureMDName ||
         name == DxilMDHelper::kDxilResourcesMDName ||
         name == DxilMDHelper::kDxilTypeSystemMDName ||
+        name == DxilMDHelper::kDxilValidatorVersionMDName ||
         name == kHLDxilFunctionPropertiesMDName || // TODO: adjust to proper name
         name == kHLDxilResourceTypeAnnotationMDName ||
         name == kHLDxilOptionsMDName ||

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

@@ -308,7 +308,7 @@ CGMSHLSLRuntime::CGMSHLSLRuntime(CodeGenModule &CGM)
   }
   // TODO: add AllResourceBound.
   if (CGM.getCodeGenOpts().HLSLAvoidControlFlow && !CGM.getCodeGenOpts().HLSLAllResourcesBound) {
-    if (SM->GetMajor() >= 5 && SM->GetMinor() >= 1) {
+    if (SM->IsSM51Plus()) {
       DiagnosticsEngine &Diags = CGM.getDiags();
       unsigned DiagID =
           Diags.getCustomDiagID(DiagnosticsEngine::Error,
@@ -331,6 +331,8 @@ CGMSHLSLRuntime::CGMSHLSLRuntime(CodeGenModule &CGM)
   opts.PackingStrategy = CGM.getCodeGenOpts().HLSLSignaturePackingStrategy;
   m_pHLModule->SetHLOptions(opts);
 
+  m_pHLModule->SetValidatorVersion(CGM.getCodeGenOpts().HLSLValidatorMajorVer, CGM.getCodeGenOpts().HLSLValidatorMinorVer);
+
   m_bDebugInfo = CGM.getCodeGenOpts().getDebugInfo() == CodeGenOptions::FullDebugInfo;
 
   // set profile

+ 0 - 15
tools/clang/lib/CodeGen/CodeGenModule.cpp

@@ -3699,21 +3699,6 @@ void CodeGenModule::EmitVersionIdentMetadata() {
 
   llvm::Metadata *IdentNode[] = {llvm::MDString::get(Ctx, Version)};
   IdentMetadata->addOperand(llvm::MDNode::get(Ctx, IdentNode));
-
-  // HLSL Change Starts
-  if (getCodeGenOpts().HLSLValidatorMajorVer != 0 ||
-      getCodeGenOpts().HLSLValidatorMinorVer != 0) {
-    llvm::NamedMDNode *VerMetadata =
-        TheModule.getOrInsertNamedMetadata("dx.valver");
-    llvm::Metadata *VerValues[] = {
-        llvm::ValueAsMetadata::get(llvm::ConstantInt::get(
-            Ctx, llvm::APInt(32, getCodeGenOpts().HLSLValidatorMajorVer))),
-        llvm::ValueAsMetadata::get(llvm::ConstantInt::get(
-            Ctx, llvm::APInt(32, getCodeGenOpts().HLSLValidatorMinorVer)))};
-    llvm::MDTuple *VerNode = llvm::MDTuple::get(Ctx, VerValues);
-    VerMetadata->addOperand(VerNode);
-  }
-  // HLSL Change Ends
 }
 
 void CodeGenModule::EmitTargetMetadata() {

+ 23 - 0
tools/clang/tools/dxcompiler/dxcassembler.cpp

@@ -17,6 +17,7 @@
 #include "dxc/Support/FileIOHelper.h"
 #include "dxc/HLSL/DxilModule.h"
 #include "dxc/Support/dxcapi.impl.h"
+#include "dxillib.h"
 
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/IRReader/IRReader.h"
@@ -27,6 +28,9 @@
 using namespace llvm;
 using namespace hlsl;
 
+// This declaration is used for the locally-linked validator.
+HRESULT CreateDxcValidator(_In_ REFIID riid, _Out_ LPVOID *ppv);
+
 class DxcAssembler : public IDxcAssembler {
 private:
   DXC_MICROCOM_REF_FIELD(m_dwRef)      
@@ -115,6 +119,25 @@ HRESULT STDMETHODCALLTYPE DxcAssembler::AssembleToContainer(
       return S_OK;
     }
 
+    // Upgrade Validator Version if necessary:
+    {
+      CComPtr<IDxcValidator> pValidator;
+      if (DxilLibIsEnabled()) {
+        DxilLibCreateInstance(CLSID_DxcValidator, &pValidator);
+      }
+      if (pValidator == nullptr) {
+        CreateDxcValidator(IID_PPV_ARGS(&pValidator));
+      }
+      CComPtr<IDxcVersionInfo> pVersionInfo;
+      if (pValidator && SUCCEEDED(pValidator.QueryInterface(&pVersionInfo))) {
+        UINT32 majorVer, minorVer;
+        IFT(pVersionInfo->GetVersion(&majorVer, &minorVer));
+        if (program.UpgradeValidatorVersion(majorVer, minorVer)) {
+          program.UpdateValidatorVersionMetadata();
+        }
+      }
+    }
+
     WriteBitcodeToFile(M.get(), outStream);
     outStream.flush();
 

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

@@ -120,21 +120,6 @@ HRESULT RunInternalValidator(_In_ IDxcValidator *pValidator,
                              _In_ IDxcBlob *pShader, UINT32 Flags,
                              _In_ IDxcOperationResult **ppResult);
 
-static HRESULT GetValidatorVersion(IDxcValidator *pValidator, UINT32 *pMajor,
-                                   UINT32 *pMinor) {
-  CComPtr<IDxcVersionInfo> pVersionInfo;
-  IFR(pValidator->QueryInterface(&pVersionInfo));
-  IFR(pVersionInfo->GetVersion(pMajor, pMinor));
-  return S_OK;
-}
-
-static bool DoesValidatorSupportDebugNamePart(IDxcValidator *pValidator) {
-  UINT32 Major, Minor;
-  if (FAILED((GetValidatorVersion(pValidator, &Major, &Minor))))
-    return false;
-  return Major > 1 || (Major == 1 && Minor >= 1);
-}
-
 enum class HandleKind {
   Special = 0,
   File = 1,
@@ -2368,8 +2353,7 @@ public:
 
         SerializeDxilFlags SerializeFlags = SerializeDxilFlags::None;
         if (opts.DebugInfo) {
-          if (DoesValidatorSupportDebugNamePart(pValidator))
-            SerializeFlags = SerializeDxilFlags::IncludeDebugNamePart;
+          SerializeFlags = SerializeDxilFlags::IncludeDebugNamePart;
           // Unless we want to strip it right away, include it in the container.
           if (!opts.StripDebug || ppDebugBlob == nullptr) {
             SerializeFlags |= SerializeDxilFlags::IncludeDebugInfoPart;