2
0
Эх сурвалжийг харах

RDAT: Fix shader stage and feature masks for ValVer 1.4 compat

Tex Riddell 6 жил өмнө
parent
commit
153edf8f5e

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

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

+ 9 - 0
lib/DXIL/DxilOperations.cpp

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

+ 15 - 2
lib/DxilContainer/DxilContainerAssembler.cpp

@@ -1023,6 +1023,8 @@ private:
   FunctionIndexMap m_FuncToResNameOffset; // list of resources used
   FunctionIndexMap m_FuncToDependencies;  // list of unresolved functions used
 
+  unsigned m_ValMajor, m_ValMinor;
+
   struct ShaderCompatInfo {
     ShaderCompatInfo()
       : minMajor(6), minMinor(0),
@@ -1042,7 +1044,9 @@ private:
         ShaderCompatInfo &info = m_FuncToShaderCompat[F];
         unsigned major, minor, mask;
         // bWithTranslation = true for library modules
-        OP::GetMinShaderModelAndMask(CI, /*bWithTranslation*/true, major, minor, mask);
+        OP::GetMinShaderModelAndMask(CI, /*bWithTranslation*/true,
+                                     m_ValMajor, m_ValMinor,
+                                     major, minor, mask);
         if (major > info.minMajor) {
           info.minMajor = major;
           info.minMinor = minor;
@@ -1145,6 +1149,12 @@ private:
   }
 
   void UpdateFunctionInfo(const DxilModule &DM) {
+    // We must select the appropriate shader mask for the validator version,
+    // so we don't set any bits the validator doesn't recognize.
+    unsigned ValidShaderMask = (1 << ((unsigned)DXIL::ShaderKind::Amplification + 1)) - 1;
+    if (DXIL::CompareVersions(m_ValMajor, m_ValMinor, 1, 5) < 0) {
+      ValidShaderMask = (1 << ((unsigned)DXIL::ShaderKind::Callable + 1)) - 1;
+    }
     for (auto &function : DM.GetModule()->getFunctionList()) {
       if (function.isDeclaration() && !function.isIntrinsic()) {
         if (OP::IsDxilOpFunc(&function)) {
@@ -1213,7 +1223,7 @@ private:
         }
         if ((DXIL::ShaderKind)shaderKind == DXIL::ShaderKind::Library) {
           // Init mask to all kinds for library functions
-          info.ShaderStageFlag = ((unsigned)1 << (unsigned)DXIL::ShaderKind::Invalid) - 1;
+          info.ShaderStageFlag = ValidShaderMask;
         } else {
           // Init mask to current kind for shader functions
           info.ShaderStageFlag = (unsigned)1 << shaderKind;
@@ -1330,6 +1340,9 @@ private:
 public:
   DxilRDATWriter(const DxilModule &module, uint32_t InfoVersion = 0)
       : m_RDATBuffer(), m_Parts(), m_FuncToResNameOffset() {
+    // Keep track of validator version so we can make a compatible RDAT
+    module.GetValidatorVersion(m_ValMajor, m_ValMinor);
+
     CreateParts();
     UpdateResourceInfo(module);
     UpdateFunctionInfo(module);