浏览代码

Add Sig element usage masks to metadata, compute in hlsl-dxilfinalize

Tex Riddell 6 年之前
父节点
当前提交
eea0c94c08

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

@@ -128,6 +128,7 @@ public:
   static const unsigned kDxilSignatureElementOutputStreamTag    = 0;
   static const unsigned kDxilSignatureElementOutputStreamTag    = 0;
   static const unsigned kHLSignatureElementGlobalSymbolTag      = 1;
   static const unsigned kHLSignatureElementGlobalSymbolTag      = 1;
   static const unsigned kDxilSignatureElementDynIdxCompMaskTag  = 2;
   static const unsigned kDxilSignatureElementDynIdxCompMaskTag  = 2;
+  static const unsigned kDxilSignatureElementUsageCompMaskTag   = 3;
 
 
   // Resources.
   // Resources.
   static const char kDxilResourcesMDName[];
   static const char kDxilResourcesMDName[];

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

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

+ 9 - 0
lib/DXIL/DxilMetadataHelper.cpp

@@ -2175,6 +2175,12 @@ void DxilExtraPropertyHelper::EmitSignatureElementProperties(const DxilSignature
     MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilSignatureElementDynIdxCompMaskTag, m_Ctx));
     MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilSignatureElementDynIdxCompMaskTag, m_Ctx));
     MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(SE.GetDynIdxCompMask(), m_Ctx));
     MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(SE.GetDynIdxCompMask(), m_Ctx));
   }
   }
+
+  if (SE.GetUsageMask() != 0 &&
+      DXIL::CompareVersions(m_ValMajor, m_ValMinor, 1, 5) >= 0) {
+    MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilSignatureElementUsageCompMaskTag, m_Ctx));
+    MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(SE.GetUsageMask(), m_Ctx));
+  }
 }
 }
 
 
 void DxilExtraPropertyHelper::LoadSignatureElementProperties(const MDOperand &MDO, DxilSignatureElement &SE) {
 void DxilExtraPropertyHelper::LoadSignatureElementProperties(const MDOperand &MDO, DxilSignatureElement &SE) {
@@ -2199,6 +2205,9 @@ void DxilExtraPropertyHelper::LoadSignatureElementProperties(const MDOperand &MD
     case DxilMDHelper::kDxilSignatureElementDynIdxCompMaskTag:
     case DxilMDHelper::kDxilSignatureElementDynIdxCompMaskTag:
       SE.SetDynIdxCompMask(DxilMDHelper::ConstMDToUint32(MDO));
       SE.SetDynIdxCompMask(DxilMDHelper::ConstMDToUint32(MDO));
       break;
       break;
+    case DxilMDHelper::kDxilSignatureElementUsageCompMaskTag:
+      SE.SetUsageMask(DxilMDHelper::ConstMDToUint32(MDO));
+      break;
     default:
     default:
       DXASSERT(false, "Unknown signature element tag");
       DXASSERT(false, "Unknown signature element tag");
     }
     }

+ 11 - 1
lib/DXIL/DxilSignatureElement.cpp

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

+ 21 - 6
lib/DxilContainer/DxilContainerAssembler.cpp

@@ -159,6 +159,10 @@ struct sort_sig {
   }
   }
 };
 };
 
 
+static uint8_t NegMask(uint8_t V) {
+  V ^= 0xF;
+  return V & 0xF;
+}
 
 
 class DxilProgramSignatureWriter : public DxilPartWriter {
 class DxilProgramSignatureWriter : public DxilPartWriter {
 private:
 private:
@@ -213,12 +217,23 @@ private:
     sig.Register = pElement->GetStartRow();
     sig.Register = pElement->GetStartRow();
 
 
     sig.Mask = pElement->GetColsAsMask();
     sig.Mask = pElement->GetColsAsMask();
-    // Only mark exist channel write for output.
-    // All channel not used for input.
-    if (!m_isInput)
-      sig.NeverWrites_Mask = ~(sig.Mask);
-    else
-      sig.AlwaysReads_Mask = 0;
+    if (m_bCompat_1_4) {
+      // Match what validator 1.4 and below expects
+      // Only mark exist channel write for output.
+      // All channel not used for input.
+      if (!m_isInput)
+        sig.NeverWrites_Mask = ~sig.Mask;
+      else
+        sig.AlwaysReads_Mask = 0;
+    } else {
+      unsigned UsageMask = pElement->GetUsageMask();
+      if (pElement->IsAllocated())
+        UsageMask <<= pElement->GetStartCol();
+      if (!m_isInput)
+        sig.NeverWrites_Mask = NegMask(UsageMask);
+      else
+        sig.AlwaysReads_Mask = UsageMask;
+    }
 
 
     sig.MinPrecision = m_useMinPrecision
     sig.MinPrecision = m_useMinPrecision
                            ? CompTypeToSigMinPrecision(pElement->GetCompType())
                            ? CompTypeToSigMinPrecision(pElement->GetCompType())

+ 74 - 0
lib/HLSL/DxilPreparePasses.cpp

@@ -17,6 +17,7 @@
 #include "dxc/DXIL/DxilTypeSystem.h"
 #include "dxc/DXIL/DxilTypeSystem.h"
 #include "dxc/DXIL/DxilUtil.h"
 #include "dxc/DXIL/DxilUtil.h"
 #include "dxc/DXIL/DxilFunctionProps.h"
 #include "dxc/DXIL/DxilFunctionProps.h"
+#include "dxc/DXIL/DxilInstructions.h"
 #include "llvm/IR/GetElementPtrTypeIterator.h"
 #include "llvm/IR/GetElementPtrTypeIterator.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/Instructions.h"
@@ -246,6 +247,74 @@ void CheckInBoundForTGSM(GlobalVariable &GV, const DataLayout &DL) {
   }
   }
 }
 }
 
 
+static bool GetUnsignedVal(Value *V, uint32_t *pValue) {
+  ConstantInt *CI = dyn_cast<ConstantInt>(V);
+  if (!CI) return false;
+  uint64_t u = CI->getZExtValue();
+  if (u > UINT32_MAX) return false;
+  *pValue = (uint32_t)u;
+  return true;
+}
+
+static uint8_t NegMask(uint8_t V) {
+  V ^= 0xF;
+  return V & 0xF;
+}
+
+static void MarkUsedSignatureElements(Function *F, DxilModule &DM) {
+  DXASSERT_NOMSG(F != nullptr);
+  // For every loadInput/storeOutput, update the corresponding ReadWriteMask.
+  // F is a pointer to a Function instance
+  for (llvm::inst_iterator I = llvm::inst_begin(F), E = llvm::inst_end(F); I != E; ++I) {
+    DxilInst_LoadInput LI(&*I);
+    DxilInst_StoreOutput SO(&*I);
+    DxilInst_LoadPatchConstant LPC(&*I);
+    DxilInst_StorePatchConstant SPC(&*I);
+    DxilSignature *pSig;
+    uint32_t col, row, sigId;
+    bool bDynIdx = false;
+    if (LI) {
+      if (!GetUnsignedVal(LI.get_inputSigId(), &sigId)) continue;
+      if (!GetUnsignedVal(LI.get_colIndex(), &col)) continue;
+      if (!GetUnsignedVal(LI.get_rowIndex(), &row)) bDynIdx = true;
+      pSig = &DM.GetInputSignature();
+    }
+    else if (SO) {
+      if (!GetUnsignedVal(SO.get_outputSigId(), &sigId)) continue;
+      if (!GetUnsignedVal(SO.get_colIndex(), &col)) continue;
+      if (!GetUnsignedVal(SO.get_rowIndex(), &row)) bDynIdx = true;
+      pSig = &DM.GetOutputSignature();
+    }
+    else if (SPC) {
+      if (!GetUnsignedVal(SPC.get_outputSigID(), &sigId)) continue;
+      if (!GetUnsignedVal(SPC.get_col(), &col)) continue;
+      if (!GetUnsignedVal(SPC.get_row(), &row)) bDynIdx = true;
+      pSig = &DM.GetPatchConstOrPrimSignature();
+    }
+    else if (LPC) {
+      if (!GetUnsignedVal(LPC.get_inputSigId(), &sigId)) continue;
+      if (!GetUnsignedVal(LPC.get_col(), &col)) continue;
+      if (!GetUnsignedVal(LPC.get_row(), &row)) bDynIdx = true;
+      pSig = &DM.GetPatchConstOrPrimSignature();
+    }
+    else {
+      continue;
+    }
+
+    // Consider being more fine-grained about masks.
+    // We report sometimes-read on input as always-read.
+    auto &El = pSig->GetElement(sigId);
+    unsigned UsageMask = El.GetUsageMask();
+    unsigned colBit = 1 << col;
+    if (!(colBit & UsageMask)) {
+      El.SetUsageMask(UsageMask | colBit);
+    }
+    if (bDynIdx && (El.GetDynIdxCompMask() & colBit) == 0) {
+      El.SetDynIdxCompMask(El.GetDynIdxCompMask() | colBit);
+    }
+  }
+}
+
 class DxilFinalizeModule : public ModulePass {
 class DxilFinalizeModule : public ModulePass {
 public:
 public:
   static char ID; // Pass identification, replacement for typeid
   static char ID; // Pass identification, replacement for typeid
@@ -293,6 +362,11 @@ public:
         if (ValMajor == 1 && ValMinor <= 1) {
         if (ValMajor == 1 && ValMinor <= 1) {
           patchValidation_1_1(M);
           patchValidation_1_1(M);
         }
         }
+
+        // Set used masks for signature elements
+        MarkUsedSignatureElements(DM.GetEntryFunction(), DM);
+        if (DM.GetShaderModel()->IsHS())
+          MarkUsedSignatureElements(DM.GetPatchConstantFunction(), DM);
       }
       }
 
 
       // Remove store undef output.
       // Remove store undef output.