|
@@ -1,6 +1,6 @@
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// //
|
|
-// ComputeViewIdState.cpp //
|
|
|
|
|
|
+// ComputeViewIdState.cpp //
|
|
// Copyright (C) Microsoft Corporation. All rights reserved. //
|
|
// Copyright (C) Microsoft Corporation. All rights reserved. //
|
|
// This file is distributed under the University of Illinois Open Source //
|
|
// This file is distributed under the University of Illinois Open Source //
|
|
// License. See LICENSE.TXT for details. //
|
|
// License. See LICENSE.TXT for details. //
|
|
@@ -49,65 +49,47 @@ const DxilViewIdState::InputsContributingToOutputType &DxilViewIdState::getInput
|
|
const DxilViewIdState::InputsContributingToOutputType &DxilViewIdState::getInputsContributingToPCOutputs() const { return m_InputsContributingToPCOutputs; }
|
|
const DxilViewIdState::InputsContributingToOutputType &DxilViewIdState::getInputsContributingToPCOutputs() const { return m_InputsContributingToPCOutputs; }
|
|
const DxilViewIdState::InputsContributingToOutputType &DxilViewIdState::getPCInputsContributingToOutputs() const { return m_PCInputsContributingToOutputs; }
|
|
const DxilViewIdState::InputsContributingToOutputType &DxilViewIdState::getPCInputsContributingToOutputs() const { return m_PCInputsContributingToOutputs; }
|
|
|
|
|
|
-void DxilViewIdState::Compute() {
|
|
|
|
- Clear();
|
|
|
|
-
|
|
|
|
- const ShaderModel *pSM = m_pModule->GetShaderModel();
|
|
|
|
- m_bUsesViewId = m_pModule->m_ShaderFlags.GetViewID();
|
|
|
|
-
|
|
|
|
- // 1. Traverse signature MD to determine max packed location.
|
|
|
|
- DetermineMaxPackedLocation(m_pModule->GetInputSignature(), &m_NumInputSigScalars, 1);
|
|
|
|
- DetermineMaxPackedLocation(m_pModule->GetOutputSignature(), &m_NumOutputSigScalars[0], pSM->IsGS() ? kNumStreams : 1);
|
|
|
|
- DetermineMaxPackedLocation(m_pModule->GetPatchConstantSignature(), &m_NumPCSigScalars, 1);
|
|
|
|
-
|
|
|
|
- // 2. Collect sets of functions reachable from main and pc entries.
|
|
|
|
- CallGraphAnalysis CGA;
|
|
|
|
- CallGraph CG = CGA.run(m_pModule->GetModule());
|
|
|
|
- m_Entry.pEntryFunc = m_pModule->GetEntryFunction();
|
|
|
|
- m_PCEntry.pEntryFunc = m_pModule->GetPatchConstantFunction();
|
|
|
|
- ComputeReachableFunctionsRec(CG, CG[m_Entry.pEntryFunc], m_Entry.Functions);
|
|
|
|
- if (m_PCEntry.pEntryFunc) {
|
|
|
|
- DXASSERT_NOMSG(pSM->IsHS());
|
|
|
|
- ComputeReachableFunctionsRec(CG, CG[m_PCEntry.pEntryFunc], m_PCEntry.Functions);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // 3. Determine shape components that are dynamically accesses and collect all sig outputs.
|
|
|
|
- AnalyzeFunctions(m_Entry);
|
|
|
|
- if (m_PCEntry.pEntryFunc) {
|
|
|
|
- AnalyzeFunctions(m_PCEntry);
|
|
|
|
- }
|
|
|
|
|
|
+namespace {
|
|
|
|
|
|
- // 4. Collect sets of values contributing to outputs.
|
|
|
|
- CollectValuesContributingToOutputs(m_Entry);
|
|
|
|
- if (m_PCEntry.pEntryFunc) {
|
|
|
|
- CollectValuesContributingToOutputs(m_PCEntry);
|
|
|
|
|
|
+void PrintOutputsDependentOnViewId(
|
|
|
|
+ llvm::raw_ostream &OS, llvm::StringRef SetName, unsigned NumOutputs,
|
|
|
|
+ const DxilViewIdState::OutputsDependentOnViewIdType
|
|
|
|
+ &OutputsDependentOnViewId) {
|
|
|
|
+ OS << SetName << " dependent on ViewId: { ";
|
|
|
|
+ bool bFirst = true;
|
|
|
|
+ for (unsigned i = 0; i < NumOutputs; i++) {
|
|
|
|
+ if (OutputsDependentOnViewId[i]) {
|
|
|
|
+ if (!bFirst)
|
|
|
|
+ OS << ", ";
|
|
|
|
+ OS << i;
|
|
|
|
+ bFirst = false;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
+ OS << " }\n";
|
|
|
|
+}
|
|
|
|
|
|
- // 5. Construct dependency sets.
|
|
|
|
- for (unsigned StreamId = 0; StreamId < (pSM->IsGS() ? kNumStreams : 1u); StreamId++) {
|
|
|
|
- CreateViewIdSets(m_Entry.ContributingInstructions[StreamId],
|
|
|
|
- m_OutputsDependentOnViewId[StreamId],
|
|
|
|
- m_InputsContributingToOutputs[StreamId], false);
|
|
|
|
- }
|
|
|
|
- if (pSM->IsHS()) {
|
|
|
|
- CreateViewIdSets(m_PCEntry.ContributingInstructions[0],
|
|
|
|
- m_PCOutputsDependentOnViewId,
|
|
|
|
- m_InputsContributingToPCOutputs, true);
|
|
|
|
- } else if (pSM->IsDS()) {
|
|
|
|
- OutputsDependentOnViewIdType OutputsDependentOnViewId;
|
|
|
|
- CreateViewIdSets(m_Entry.ContributingInstructions[0],
|
|
|
|
- OutputsDependentOnViewId,
|
|
|
|
- m_PCInputsContributingToOutputs, true);
|
|
|
|
- DXASSERT_NOMSG(OutputsDependentOnViewId == m_OutputsDependentOnViewId[0]);
|
|
|
|
|
|
+void PrintInputsContributingToOutputs(
|
|
|
|
+ llvm::raw_ostream &OS, llvm::StringRef InputSetName,
|
|
|
|
+ llvm::StringRef OutputSetName,
|
|
|
|
+ const DxilViewIdState::InputsContributingToOutputType
|
|
|
|
+ &InputsContributingToOutputs) {
|
|
|
|
+ OS << InputSetName << " contributing to computation of " << OutputSetName
|
|
|
|
+ << ":\n";
|
|
|
|
+ for (auto &it : InputsContributingToOutputs) {
|
|
|
|
+ unsigned outIdx = it.first;
|
|
|
|
+ auto &Inputs = it.second;
|
|
|
|
+ OS << "output " << outIdx << " depends on inputs: { ";
|
|
|
|
+ bool bFirst = true;
|
|
|
|
+ for (unsigned i : Inputs) {
|
|
|
|
+ if (!bFirst)
|
|
|
|
+ OS << ", ";
|
|
|
|
+ OS << i;
|
|
|
|
+ bFirst = false;
|
|
|
|
+ }
|
|
|
|
+ OS << " }\n";
|
|
}
|
|
}
|
|
-
|
|
|
|
- // 6. Update dynamically indexed input/output component masks.
|
|
|
|
- UpdateDynamicIndexUsageState();
|
|
|
|
-
|
|
|
|
-#if DXILVIEWID_DBG
|
|
|
|
- PrintSets(dbgs());
|
|
|
|
-#endif
|
|
|
|
}
|
|
}
|
|
|
|
+} // namespace
|
|
|
|
|
|
void DxilViewIdState::PrintSets(llvm::raw_ostream &OS) {
|
|
void DxilViewIdState::PrintSets(llvm::raw_ostream &OS) {
|
|
const ShaderModel *pSM = m_pModule->GetShaderModel();
|
|
const ShaderModel *pSM = m_pModule->GetShaderModel();
|
|
@@ -152,43 +134,7 @@ void DxilViewIdState::PrintSets(llvm::raw_ostream &OS) {
|
|
OS << "\n";
|
|
OS << "\n";
|
|
}
|
|
}
|
|
|
|
|
|
-void DxilViewIdState::PrintOutputsDependentOnViewId(llvm::raw_ostream &OS,
|
|
|
|
- llvm::StringRef SetName,
|
|
|
|
- unsigned NumOutputs,
|
|
|
|
- const OutputsDependentOnViewIdType &OutputsDependentOnViewId) {
|
|
|
|
- OS << SetName << " dependent on ViewId: { ";
|
|
|
|
- bool bFirst = true;
|
|
|
|
- for (unsigned i = 0; i < NumOutputs; i++) {
|
|
|
|
- if (OutputsDependentOnViewId[i]) {
|
|
|
|
- if (!bFirst) OS << ", ";
|
|
|
|
- OS << i;
|
|
|
|
- bFirst = false;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- OS << " }\n";
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-void DxilViewIdState::PrintInputsContributingToOutputs(llvm::raw_ostream &OS,
|
|
|
|
- llvm::StringRef InputSetName,
|
|
|
|
- llvm::StringRef OutputSetName,
|
|
|
|
- const InputsContributingToOutputType &InputsContributingToOutputs) {
|
|
|
|
- OS << InputSetName << " contributing to computation of " << OutputSetName << ":\n";
|
|
|
|
- for (auto &it : InputsContributingToOutputs) {
|
|
|
|
- unsigned outIdx = it.first;
|
|
|
|
- auto &Inputs = it.second;
|
|
|
|
- OS << "output " << outIdx << " depends on inputs: { ";
|
|
|
|
- bool bFirst = true;
|
|
|
|
- for (unsigned i : Inputs) {
|
|
|
|
- if (!bFirst) OS << ", ";
|
|
|
|
- OS << i;
|
|
|
|
- bFirst = false;
|
|
|
|
- }
|
|
|
|
- OS << " }\n";
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
void DxilViewIdState::Clear() {
|
|
void DxilViewIdState::Clear() {
|
|
- m_bUsesViewId = false;
|
|
|
|
m_NumInputSigScalars = 0;
|
|
m_NumInputSigScalars = 0;
|
|
for (unsigned i = 0; i < kNumStreams; i++) {
|
|
for (unsigned i = 0; i < kNumStreams; i++) {
|
|
m_NumOutputSigScalars[i] = 0;
|
|
m_NumOutputSigScalars[i] = 0;
|
|
@@ -196,602 +142,57 @@ void DxilViewIdState::Clear() {
|
|
m_InputsContributingToOutputs[i].clear();
|
|
m_InputsContributingToOutputs[i].clear();
|
|
}
|
|
}
|
|
m_NumPCSigScalars = 0;
|
|
m_NumPCSigScalars = 0;
|
|
- m_InpSigDynIdxElems.clear();
|
|
|
|
- m_OutSigDynIdxElems.clear();
|
|
|
|
- m_PCSigDynIdxElems.clear();
|
|
|
|
m_PCOutputsDependentOnViewId.reset();
|
|
m_PCOutputsDependentOnViewId.reset();
|
|
m_InputsContributingToPCOutputs.clear();
|
|
m_InputsContributingToPCOutputs.clear();
|
|
m_PCInputsContributingToOutputs.clear();
|
|
m_PCInputsContributingToOutputs.clear();
|
|
- m_Entry.Clear();
|
|
|
|
- m_PCEntry.Clear();
|
|
|
|
- m_FuncInfo.clear();
|
|
|
|
- m_ReachingDeclsCache.clear();
|
|
|
|
m_SerializedState.clear();
|
|
m_SerializedState.clear();
|
|
}
|
|
}
|
|
|
|
|
|
-void DxilViewIdState::EntryInfo::Clear() {
|
|
|
|
- pEntryFunc = nullptr;
|
|
|
|
- Functions.clear();
|
|
|
|
- Outputs.clear();
|
|
|
|
- for (unsigned i = 0; i < kNumStreams; i++)
|
|
|
|
- ContributingInstructions[i].clear();
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-void DxilViewIdState::FuncInfo::Clear() {
|
|
|
|
- Returns.clear();
|
|
|
|
- CtrlDep.Clear();
|
|
|
|
- pDomTree.reset();
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-void DxilViewIdState::DetermineMaxPackedLocation(DxilSignature &DxilSig,
|
|
|
|
- unsigned *pMaxSigLoc,
|
|
|
|
- unsigned NumStreams) {
|
|
|
|
- DXASSERT_NOMSG(NumStreams == 1 || NumStreams == kNumStreams);
|
|
|
|
-
|
|
|
|
- for (unsigned i = 0; i < NumStreams; i++) {
|
|
|
|
- pMaxSigLoc[i] = 0;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- for (auto &E : DxilSig.GetElements()) {
|
|
|
|
- if (E->GetStartRow() == Semantic::kUndefinedRow) continue;
|
|
|
|
-
|
|
|
|
- unsigned StreamId = E->GetOutputStream();
|
|
|
|
- unsigned endLoc = GetLinearIndex(*E, E->GetRows() - 1, E->GetCols() - 1);
|
|
|
|
- pMaxSigLoc[StreamId] = std::max(pMaxSigLoc[StreamId], endLoc + 1);
|
|
|
|
- E->GetCols();
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-void DxilViewIdState::ComputeReachableFunctionsRec(CallGraph &CG, CallGraphNode *pNode, FunctionSetType &FuncSet) {
|
|
|
|
- Function *F = pNode->getFunction();
|
|
|
|
- // Accumulate only functions with bodies.
|
|
|
|
- if (F->empty()) return;
|
|
|
|
- auto itIns = FuncSet.emplace(F);
|
|
|
|
- DXASSERT_NOMSG(itIns.second);
|
|
|
|
- (void)itIns;
|
|
|
|
- for (auto it = pNode->begin(), itEnd = pNode->end(); it != itEnd; ++it) {
|
|
|
|
- CallGraphNode *pSuccNode = it->second;
|
|
|
|
- ComputeReachableFunctionsRec(CG, pSuccNode, FuncSet);
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-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;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-void DxilViewIdState::AnalyzeFunctions(EntryInfo &Entry) {
|
|
|
|
- for (auto *F : Entry.Functions) {
|
|
|
|
- DXASSERT_NOMSG(!F->empty());
|
|
|
|
-
|
|
|
|
- auto itFI = m_FuncInfo.find(F);
|
|
|
|
- FuncInfo *pFuncInfo = nullptr;
|
|
|
|
- if (itFI != m_FuncInfo.end()) {
|
|
|
|
- pFuncInfo = itFI->second.get();
|
|
|
|
- } else {
|
|
|
|
- m_FuncInfo[F] = make_unique<FuncInfo>();
|
|
|
|
- pFuncInfo = m_FuncInfo[F].get();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- for (auto itBB = F->begin(), endBB = F->end(); itBB != endBB; ++itBB) {
|
|
|
|
- BasicBlock *BB = itBB;
|
|
|
|
-
|
|
|
|
- for (auto itInst = BB->begin(), endInst = BB->end(); itInst != endInst; ++itInst) {
|
|
|
|
- if (ReturnInst *RI = dyn_cast<ReturnInst>(itInst)) {
|
|
|
|
- pFuncInfo->Returns.emplace(RI);
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- CallInst *CI = dyn_cast<CallInst>(itInst);
|
|
|
|
- if (!CI) continue;
|
|
|
|
-
|
|
|
|
- DynamicallyIndexedElemsType *pDynIdxElems = nullptr;
|
|
|
|
- int row = Semantic::kUndefinedRow;
|
|
|
|
- unsigned id, col;
|
|
|
|
- if (DxilInst_LoadInput LI = DxilInst_LoadInput(CI)) {
|
|
|
|
- pDynIdxElems = &m_InpSigDynIdxElems;
|
|
|
|
- IFTBOOL(GetUnsignedVal(LI.get_inputSigId(), &id), DXC_E_GENERAL_INTERNAL_ERROR);
|
|
|
|
- GetUnsignedVal(LI.get_rowIndex(), (uint32_t*)&row);
|
|
|
|
- IFTBOOL(GetUnsignedVal(LI.get_colIndex(), &col), DXC_E_GENERAL_INTERNAL_ERROR);
|
|
|
|
- } else if (DxilInst_StoreOutput SO = DxilInst_StoreOutput(CI)) {
|
|
|
|
- pDynIdxElems = &m_OutSigDynIdxElems;
|
|
|
|
- IFTBOOL(GetUnsignedVal(SO.get_outputSigId(), &id), DXC_E_GENERAL_INTERNAL_ERROR);
|
|
|
|
- GetUnsignedVal(SO.get_rowIndex(), (uint32_t*)&row);
|
|
|
|
- IFTBOOL(GetUnsignedVal(SO.get_colIndex(), &col), DXC_E_GENERAL_INTERNAL_ERROR);
|
|
|
|
- Entry.Outputs.emplace(CI);
|
|
|
|
- } else if (DxilInst_LoadPatchConstant LPC = DxilInst_LoadPatchConstant(CI)) {
|
|
|
|
- if (m_pModule->GetShaderModel()->IsDS()) {
|
|
|
|
- pDynIdxElems = &m_PCSigDynIdxElems;
|
|
|
|
- IFTBOOL(GetUnsignedVal(LPC.get_inputSigId(), &id), DXC_E_GENERAL_INTERNAL_ERROR);
|
|
|
|
- GetUnsignedVal(LPC.get_row(), (uint32_t*)&row);
|
|
|
|
- IFTBOOL(GetUnsignedVal(LPC.get_col(), &col), DXC_E_GENERAL_INTERNAL_ERROR);
|
|
|
|
- } else {
|
|
|
|
- // Do nothing. This is an internal helper function for DXBC-2-DXIL converter.
|
|
|
|
- DXASSERT_NOMSG(m_pModule->GetShaderModel()->IsHS());
|
|
|
|
- }
|
|
|
|
- } else if (DxilInst_StorePatchConstant SPC = DxilInst_StorePatchConstant(CI)) {
|
|
|
|
- pDynIdxElems = &m_PCSigDynIdxElems;
|
|
|
|
- IFTBOOL(GetUnsignedVal(SPC.get_outputSigID(), &id), DXC_E_GENERAL_INTERNAL_ERROR);
|
|
|
|
- GetUnsignedVal(SPC.get_row(), (uint32_t*)&row);
|
|
|
|
- IFTBOOL(GetUnsignedVal(SPC.get_col(), &col), DXC_E_GENERAL_INTERNAL_ERROR);
|
|
|
|
- Entry.Outputs.emplace(CI);
|
|
|
|
- } else if (DxilInst_LoadOutputControlPoint LOCP = DxilInst_LoadOutputControlPoint(CI)) {
|
|
|
|
- if (m_pModule->GetShaderModel()->IsDS()) {
|
|
|
|
- pDynIdxElems = &m_InpSigDynIdxElems;
|
|
|
|
- IFTBOOL(GetUnsignedVal(LOCP.get_inputSigId(), &id), DXC_E_GENERAL_INTERNAL_ERROR);
|
|
|
|
- GetUnsignedVal(LOCP.get_row(), (uint32_t*)&row);
|
|
|
|
- IFTBOOL(GetUnsignedVal(LOCP.get_col(), &col), DXC_E_GENERAL_INTERNAL_ERROR);
|
|
|
|
- } else if (m_pModule->GetShaderModel()->IsHS()) {
|
|
|
|
- // Do nothings, as the information has been captured by the output signature of CP entry.
|
|
|
|
- } else {
|
|
|
|
- DXASSERT_NOMSG(false);
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Record dynamic index usage.
|
|
|
|
- if (pDynIdxElems && row == Semantic::kUndefinedRow) {
|
|
|
|
- (*pDynIdxElems)[id] |= (1 << col);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Compute dominator relation.
|
|
|
|
- pFuncInfo->pDomTree = make_unique<DominatorTreeBase<BasicBlock> >(false);
|
|
|
|
- pFuncInfo->pDomTree->recalculate(*F);
|
|
|
|
-#if DXILVIEWID_DBG
|
|
|
|
- pFuncInfo->pDomTree->print(dbgs());
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
- // Compute postdominator relation.
|
|
|
|
- DominatorTreeBase<BasicBlock> PDR(true);
|
|
|
|
- PDR.recalculate(*F);
|
|
|
|
-#if DXILVIEWID_DBG
|
|
|
|
- PDR.print(dbgs());
|
|
|
|
-#endif
|
|
|
|
- // Compute control dependence.
|
|
|
|
- pFuncInfo->CtrlDep.Compute(F, PDR);
|
|
|
|
-#if DXILVIEWID_DBG
|
|
|
|
- pFuncInfo->CtrlDep.print(dbgs());
|
|
|
|
-#endif
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-void DxilViewIdState::CollectValuesContributingToOutputs(EntryInfo &Entry) {
|
|
|
|
- for (auto *CI : Entry.Outputs) { // CI = call instruction
|
|
|
|
- DxilSignature *pDxilSig = nullptr;
|
|
|
|
- Value *pContributingValue = nullptr;
|
|
|
|
- unsigned id = (unsigned)-1;
|
|
|
|
- int startRow = Semantic::kUndefinedRow, endRow = Semantic::kUndefinedRow;
|
|
|
|
- unsigned col = (unsigned)-1;
|
|
|
|
- if (DxilInst_StoreOutput SO = DxilInst_StoreOutput(CI)) {
|
|
|
|
- pDxilSig = &m_pModule->GetOutputSignature();
|
|
|
|
- pContributingValue = SO.get_value();
|
|
|
|
- GetUnsignedVal(SO.get_outputSigId(), &id);
|
|
|
|
- GetUnsignedVal(SO.get_colIndex(), &col);
|
|
|
|
- GetUnsignedVal(SO.get_rowIndex(), (uint32_t*)&startRow);
|
|
|
|
- } else if (DxilInst_StorePatchConstant SPC = DxilInst_StorePatchConstant(CI)) {
|
|
|
|
- pDxilSig = &m_pModule->GetPatchConstantSignature();
|
|
|
|
- pContributingValue = SPC.get_value();
|
|
|
|
- GetUnsignedVal(SPC.get_outputSigID(), &id);
|
|
|
|
- GetUnsignedVal(SPC.get_row(), (uint32_t*)&startRow);
|
|
|
|
- GetUnsignedVal(SPC.get_col(), &col);
|
|
|
|
- } else {
|
|
|
|
- IFT(DXC_E_GENERAL_INTERNAL_ERROR);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- DxilSignatureElement &SigElem = pDxilSig->GetElement(id);
|
|
|
|
- if (!SigElem.IsAllocated())
|
|
|
|
- continue;
|
|
|
|
-
|
|
|
|
- unsigned StreamId = SigElem.GetOutputStream();
|
|
|
|
-
|
|
|
|
- if (startRow != Semantic::kUndefinedRow) {
|
|
|
|
- endRow = startRow;
|
|
|
|
- } else {
|
|
|
|
- // The entire column is affected by value.
|
|
|
|
- DXASSERT_NOMSG(SigElem.GetID() == id && SigElem.GetStartRow() != Semantic::kUndefinedRow);
|
|
|
|
- startRow = 0;
|
|
|
|
- endRow = SigElem.GetRows() - 1;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- InstructionSetType ContributingInstructionsAllRows;
|
|
|
|
- InstructionSetType *pContributingInstructions = &ContributingInstructionsAllRows;
|
|
|
|
- if (startRow == endRow) {
|
|
|
|
- // Scalar or indexable with known index.
|
|
|
|
- unsigned index = GetLinearIndex(SigElem, startRow, col);
|
|
|
|
- pContributingInstructions = &Entry.ContributingInstructions[StreamId][index];
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- CollectValuesContributingToOutputRec(Entry, pContributingValue, *pContributingInstructions);
|
|
|
|
-
|
|
|
|
- // Handle control dependence of this instruction BB.
|
|
|
|
- BasicBlock *pBB = CI->getParent();
|
|
|
|
- Function *F = pBB->getParent();
|
|
|
|
- FuncInfo *pFuncInfo = m_FuncInfo[F].get();
|
|
|
|
- const BasicBlockSet &CtrlDepSet = pFuncInfo->CtrlDep.GetCDBlocks(pBB);
|
|
|
|
- for (BasicBlock *B : CtrlDepSet) {
|
|
|
|
- CollectValuesContributingToOutputRec(Entry, B->getTerminator(), *pContributingInstructions);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (pContributingInstructions == &ContributingInstructionsAllRows) {
|
|
|
|
- // Write dynamically indexed output contributions to all rows.
|
|
|
|
- for (int row = startRow; row <= endRow; row++) {
|
|
|
|
- unsigned index = GetLinearIndex(SigElem, row, col);
|
|
|
|
- Entry.ContributingInstructions[StreamId][index].insert(ContributingInstructionsAllRows.begin(), ContributingInstructionsAllRows.end());
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-void DxilViewIdState::CollectValuesContributingToOutputRec(EntryInfo &Entry,
|
|
|
|
- Value *pContributingValue,
|
|
|
|
- InstructionSetType &ContributingInstructions) {
|
|
|
|
- if (dyn_cast<Argument>(pContributingValue)) {
|
|
|
|
- // This must be a leftover signature argument of an entry function.
|
|
|
|
- DXASSERT_NOMSG(Entry.pEntryFunc == m_pModule->GetEntryFunction() ||
|
|
|
|
- Entry.pEntryFunc == m_pModule->GetPatchConstantFunction());
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
|
|
+namespace {
|
|
|
|
|
|
- Instruction *pContributingInst = dyn_cast<Instruction>(pContributingValue);
|
|
|
|
- if (pContributingInst == nullptr) {
|
|
|
|
- // Can be literal constant, global decl, branch target.
|
|
|
|
- DXASSERT_NOMSG(isa<Constant>(pContributingValue) || isa<BasicBlock>(pContributingValue));
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
|
|
+unsigned RoundUpToUINT(unsigned x) { return (x + 31) / 32; }
|
|
|
|
|
|
- auto itInst = ContributingInstructions.emplace(pContributingInst);
|
|
|
|
- // Already visited instruction.
|
|
|
|
- if (!itInst.second) return;
|
|
|
|
-
|
|
|
|
- // Handle special cases.
|
|
|
|
- if (PHINode *phi = dyn_cast<PHINode>(pContributingInst)) {
|
|
|
|
- CollectPhiCFValuesContributingToOutputRec(phi, Entry, ContributingInstructions);
|
|
|
|
- } else if (isa<LoadInst>(pContributingInst) ||
|
|
|
|
- isa<AtomicCmpXchgInst>(pContributingInst) ||
|
|
|
|
- isa<AtomicRMWInst>(pContributingInst)) {
|
|
|
|
- Value *pPtrValue = pContributingInst->getOperand(0);
|
|
|
|
- DXASSERT_NOMSG(pPtrValue->getType()->isPointerTy());
|
|
|
|
- const ValueSetType &ReachingDecls = CollectReachingDecls(pPtrValue);
|
|
|
|
- DXASSERT_NOMSG(ReachingDecls.size() > 0);
|
|
|
|
- for (Value *pDeclValue : ReachingDecls) {
|
|
|
|
- const ValueSetType &Stores = CollectStores(pDeclValue);
|
|
|
|
- for (Value *V : Stores) {
|
|
|
|
- CollectValuesContributingToOutputRec(Entry, V, ContributingInstructions);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- } else if (CallInst *CI = dyn_cast<CallInst>(pContributingInst)) {
|
|
|
|
- if (!hlsl::OP::IsDxilOpFuncCallInst(CI)) {
|
|
|
|
- Function *F = CI->getCalledFunction();
|
|
|
|
- if (!F->empty()) {
|
|
|
|
- // Return value of a user function.
|
|
|
|
- if (Entry.Functions.find(F) != Entry.Functions.end()) {
|
|
|
|
- const FuncInfo &FI = *m_FuncInfo[F];
|
|
|
|
- for (ReturnInst *pRetInst : FI.Returns) {
|
|
|
|
- CollectValuesContributingToOutputRec(Entry, pRetInst, ContributingInstructions);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Handle instruction inputs.
|
|
|
|
- unsigned NumOps = pContributingInst->getNumOperands();
|
|
|
|
- for (unsigned i = 0; i < NumOps; i++) {
|
|
|
|
- Value *O = pContributingInst->getOperand(i);
|
|
|
|
- CollectValuesContributingToOutputRec(Entry, O, ContributingInstructions);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Handle control dependence of this instruction BB.
|
|
|
|
- BasicBlock *pBB = pContributingInst->getParent();
|
|
|
|
- Function *F = pBB->getParent();
|
|
|
|
- FuncInfo *pFuncInfo = m_FuncInfo[F].get();
|
|
|
|
- const BasicBlockSet &CtrlDepSet = pFuncInfo->CtrlDep.GetCDBlocks(pBB);
|
|
|
|
- for (BasicBlock *B : CtrlDepSet) {
|
|
|
|
- CollectValuesContributingToOutputRec(Entry, B->getTerminator(), ContributingInstructions);
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// Only process control-dependent basic blocks for constant operands of the phi-function.
|
|
|
|
-// An obvious "definition" point for a constant operand is the predecessor along corresponding edge.
|
|
|
|
-// However, this may be too conservative and, as such, pick up extra control dependent BBs.
|
|
|
|
-// A better "definition" point is the highest dominator where it is still legal to "insert" constant assignment.
|
|
|
|
-// In this context, "legal" means that only one value "leaves" the dominator and reaches Phi.
|
|
|
|
-void DxilViewIdState::CollectPhiCFValuesContributingToOutputRec(PHINode *pPhi,
|
|
|
|
- EntryInfo &Entry,
|
|
|
|
- InstructionSetType &ContributingInstructions) {
|
|
|
|
- Function *F = pPhi->getParent()->getParent();
|
|
|
|
- FuncInfo *pFuncInfo = m_FuncInfo[F].get();
|
|
|
|
- unordered_map<DomTreeNodeBase<BasicBlock> *, Value *> DomTreeMarkers;
|
|
|
|
-
|
|
|
|
- // Mark predecessors of each value, so that there is a legal "definition" point.
|
|
|
|
- for (unsigned i = 0; i < pPhi->getNumOperands(); i++) {
|
|
|
|
- Value *pValue = pPhi->getIncomingValue(i);
|
|
|
|
- BasicBlock *pBB = pPhi->getIncomingBlock(i);
|
|
|
|
- DomTreeNodeBase<BasicBlock> *pDomNode = pFuncInfo->pDomTree->getNode(pBB);
|
|
|
|
- auto it = DomTreeMarkers.emplace(pDomNode, pValue);
|
|
|
|
- DXASSERT_NOMSG(it.second || it.first->second == pValue); (void)it;
|
|
|
|
- }
|
|
|
|
- // Mark the dominator tree with "definition" values, walking up to the parent.
|
|
|
|
- for (unsigned i = 0; i < pPhi->getNumOperands(); i++) {
|
|
|
|
- Value *pValue = pPhi->getIncomingValue(i);
|
|
|
|
- BasicBlock *pDefBB = &F->getEntryBlock();
|
|
|
|
- if (Instruction *pDefInst = dyn_cast<Instruction>(pValue)) {
|
|
|
|
- pDefBB = pDefInst->getParent();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- BasicBlock *pBB = pPhi->getIncomingBlock(i);
|
|
|
|
- if (pBB == pDefBB) {
|
|
|
|
- continue; // we already handled the predecessor.
|
|
|
|
- }
|
|
|
|
- DomTreeNodeBase<BasicBlock> *pDomNode = pFuncInfo->pDomTree->getNode(pBB);
|
|
|
|
- pDomNode = pDomNode->getIDom();
|
|
|
|
- while (pDomNode) {
|
|
|
|
- auto it = DomTreeMarkers.emplace(pDomNode, pValue);
|
|
|
|
- if (!it.second) {
|
|
|
|
- if (it.first->second != pValue && it.first->second != nullptr) {
|
|
|
|
- if (!isa<Constant>(it.first->second) || !isa<Constant>(pValue)) {
|
|
|
|
- // Unless both are different constants, mark the "definition" point as illegal.
|
|
|
|
- it.first->second = nullptr;
|
|
|
|
- // If both are constants, leave the marker of the first one.
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Do not go higher than a legal definition point.
|
|
|
|
- pBB = pDomNode->getBlock();
|
|
|
|
- if (pBB == pDefBB)
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- pDomNode = pDomNode->getIDom();
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Handle control dependence for Constant arguments of Phi.
|
|
|
|
- for (unsigned i = 0; i < pPhi->getNumOperands(); i++) {
|
|
|
|
- Value *pValue = pPhi->getIncomingValue(i);
|
|
|
|
- if (!isa<Constant>(pValue))
|
|
|
|
- continue;
|
|
|
|
|
|
+void SerializeOutputsDependentOnViewId(
|
|
|
|
+ unsigned NumOutputs,
|
|
|
|
+ const DxilViewIdState::OutputsDependentOnViewIdType
|
|
|
|
+ &OutputsDependentOnViewId,
|
|
|
|
+ unsigned *&pData) {
|
|
|
|
+ unsigned NumOutUINTs = RoundUpToUINT(NumOutputs);
|
|
|
|
|
|
- // Determine the higher legal "definition" point.
|
|
|
|
- BasicBlock *pBB = pPhi->getIncomingBlock(i);
|
|
|
|
- DomTreeNodeBase<BasicBlock> *pDomNode = pFuncInfo->pDomTree->getNode(pBB);
|
|
|
|
- DomTreeNodeBase<BasicBlock> *pDefDomNode = pDomNode;
|
|
|
|
- while (pDomNode) {
|
|
|
|
- auto it = DomTreeMarkers.find(pDomNode);
|
|
|
|
- DXASSERT_NOMSG(it != DomTreeMarkers.end());
|
|
|
|
- if (it->second != pValue) {
|
|
|
|
- DXASSERT_NOMSG(it->second == nullptr || isa<Constant>(it->second));
|
|
|
|
- break;
|
|
|
|
|
|
+ // Serialize output dependence on ViewId.
|
|
|
|
+ for (unsigned i = 0; i < NumOutUINTs; i++) {
|
|
|
|
+ unsigned x = 0;
|
|
|
|
+ for (unsigned j = 0; j < std::min(32u, NumOutputs - 32u * i); j++) {
|
|
|
|
+ if (OutputsDependentOnViewId[i * 32 + j]) {
|
|
|
|
+ x |= (1u << j);
|
|
}
|
|
}
|
|
-
|
|
|
|
- pDefDomNode = pDomNode;
|
|
|
|
- pDomNode = pDomNode->getIDom();
|
|
|
|
}
|
|
}
|
|
-
|
|
|
|
- // Handle control dependence of this constant argument highest legal "definition" point.
|
|
|
|
- pBB = pDefDomNode->getBlock();
|
|
|
|
- const BasicBlockSet &CtrlDepSet = pFuncInfo->CtrlDep.GetCDBlocks(pBB);
|
|
|
|
- for (BasicBlock *B : CtrlDepSet) {
|
|
|
|
- CollectValuesContributingToOutputRec(Entry, B->getTerminator(), ContributingInstructions);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-const DxilViewIdState::ValueSetType &DxilViewIdState::CollectReachingDecls(Value *pValue) {
|
|
|
|
- auto it = m_ReachingDeclsCache.emplace(pValue, ValueSetType());
|
|
|
|
- if (it.second) {
|
|
|
|
- // We have not seen this value before.
|
|
|
|
- ValueSetType Visited;
|
|
|
|
- CollectReachingDeclsRec(pValue, it.first->second, Visited);
|
|
|
|
- }
|
|
|
|
- return it.first->second;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-void DxilViewIdState::CollectReachingDeclsRec(Value *pValue, ValueSetType &ReachingDecls, ValueSetType &Visited) {
|
|
|
|
- if (Visited.find(pValue) != Visited.end())
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- bool bInitialValue = Visited.size() == 0;
|
|
|
|
- Visited.emplace(pValue);
|
|
|
|
-
|
|
|
|
- if (!bInitialValue) {
|
|
|
|
- auto it = m_ReachingDeclsCache.find(pValue);
|
|
|
|
- if (it != m_ReachingDeclsCache.end()) {
|
|
|
|
- ReachingDecls.insert(it->second.begin(), it->second.end());
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (dyn_cast<GlobalVariable>(pValue)) {
|
|
|
|
- ReachingDecls.emplace(pValue);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (GetElementPtrInst *pGepInst = dyn_cast<GetElementPtrInst>(pValue)) {
|
|
|
|
- Value *pPtrValue = pGepInst->getPointerOperand();
|
|
|
|
- CollectReachingDeclsRec(pPtrValue, ReachingDecls, Visited);
|
|
|
|
- } else if (GEPOperator *pGepOp = dyn_cast<GEPOperator>(pValue)) {
|
|
|
|
- Value *pPtrValue = pGepOp->getPointerOperand();
|
|
|
|
- CollectReachingDeclsRec(pPtrValue, ReachingDecls, Visited);
|
|
|
|
- } else if (dyn_cast<AllocaInst>(pValue)) {
|
|
|
|
- ReachingDecls.emplace(pValue);
|
|
|
|
- } else if (PHINode *phi = dyn_cast<PHINode>(pValue)) {
|
|
|
|
- for (Value *pPtrValue : phi->operands()) {
|
|
|
|
- CollectReachingDeclsRec(pPtrValue, ReachingDecls, Visited);
|
|
|
|
- }
|
|
|
|
- } else if (SelectInst *SelI = dyn_cast<SelectInst>(pValue)) {
|
|
|
|
- CollectReachingDeclsRec(SelI->getTrueValue(), ReachingDecls, Visited);
|
|
|
|
- CollectReachingDeclsRec(SelI->getFalseValue(), ReachingDecls, Visited);
|
|
|
|
- } else if (dyn_cast<Argument>(pValue)) {
|
|
|
|
- ReachingDecls.emplace(pValue);
|
|
|
|
- } else {
|
|
|
|
- IFT(DXC_E_GENERAL_INTERNAL_ERROR);
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-const DxilViewIdState::ValueSetType &DxilViewIdState::CollectStores(llvm::Value *pValue) {
|
|
|
|
- auto it = m_StoresPerDeclCache.emplace(pValue, ValueSetType());
|
|
|
|
- if (it.second) {
|
|
|
|
- // We have not seen this value before.
|
|
|
|
- ValueSetType Visited;
|
|
|
|
- CollectStoresRec(pValue, it.first->second, Visited);
|
|
|
|
- }
|
|
|
|
- return it.first->second;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-void DxilViewIdState::CollectStoresRec(llvm::Value *pValue, ValueSetType &Stores, ValueSetType &Visited) {
|
|
|
|
- if (Visited.find(pValue) != Visited.end())
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- bool bInitialValue = Visited.size() == 0;
|
|
|
|
- Visited.emplace(pValue);
|
|
|
|
-
|
|
|
|
- if (!bInitialValue) {
|
|
|
|
- auto it = m_StoresPerDeclCache.find(pValue);
|
|
|
|
- if (it != m_StoresPerDeclCache.end()) {
|
|
|
|
- Stores.insert(it->second.begin(), it->second.end());
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (isa<LoadInst>(pValue)) {
|
|
|
|
- return;
|
|
|
|
- } else if (isa<StoreInst>(pValue) ||
|
|
|
|
- isa<AtomicCmpXchgInst>(pValue) ||
|
|
|
|
- isa<AtomicRMWInst>(pValue)) {
|
|
|
|
- Stores.emplace(pValue);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- for (auto *U : pValue->users()) {
|
|
|
|
- CollectStoresRec(U, Stores, Visited);
|
|
|
|
|
|
+ *pData++ = x;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-void DxilViewIdState::CreateViewIdSets(const std::unordered_map<unsigned, InstructionSetType> &ContributingInstructions,
|
|
|
|
- OutputsDependentOnViewIdType &OutputsDependentOnViewId,
|
|
|
|
- InputsContributingToOutputType &InputsContributingToOutputs,
|
|
|
|
- bool bPC) {
|
|
|
|
- const ShaderModel *pSM = m_pModule->GetShaderModel();
|
|
|
|
-
|
|
|
|
- for (auto &itOut : ContributingInstructions) {
|
|
|
|
- unsigned outIdx = itOut.first;
|
|
|
|
- for (Instruction *pInst : itOut.second) {
|
|
|
|
- // Set output dependence on ViewId.
|
|
|
|
- if (DxilInst_ViewID VID = DxilInst_ViewID(pInst)) {
|
|
|
|
- DXASSERT(m_bUsesViewId, "otherwise, DxilModule flag not set properly");
|
|
|
|
- OutputsDependentOnViewId[outIdx] = true;
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Start setting output dependence on inputs.
|
|
|
|
- DxilSignatureElement *pSigElem = nullptr;
|
|
|
|
- bool bLoadOutputCPInHS = false;
|
|
|
|
- unsigned inpId = (unsigned)-1;
|
|
|
|
- int startRow = Semantic::kUndefinedRow, endRow = Semantic::kUndefinedRow;
|
|
|
|
- unsigned col = (unsigned)-1;
|
|
|
|
- if (DxilInst_LoadInput LI = DxilInst_LoadInput(pInst)) {
|
|
|
|
- GetUnsignedVal(LI.get_inputSigId(), &inpId);
|
|
|
|
- GetUnsignedVal(LI.get_colIndex(), &col);
|
|
|
|
- GetUnsignedVal(LI.get_rowIndex(), (uint32_t*)&startRow);
|
|
|
|
- pSigElem = &m_pModule->GetInputSignature().GetElement(inpId);
|
|
|
|
- if (pSM->IsDS() && bPC) {
|
|
|
|
- pSigElem = nullptr;
|
|
|
|
- }
|
|
|
|
- } else if (DxilInst_LoadOutputControlPoint LOCP = DxilInst_LoadOutputControlPoint(pInst)) {
|
|
|
|
- GetUnsignedVal(LOCP.get_inputSigId(), &inpId);
|
|
|
|
- GetUnsignedVal(LOCP.get_col(), &col);
|
|
|
|
- GetUnsignedVal(LOCP.get_row(), (uint32_t*)&startRow);
|
|
|
|
- if (pSM->IsHS()) {
|
|
|
|
- pSigElem = &m_pModule->GetOutputSignature().GetElement(inpId);
|
|
|
|
- bLoadOutputCPInHS = true;
|
|
|
|
- } else if (pSM->IsDS()) {
|
|
|
|
- if (!bPC) {
|
|
|
|
- pSigElem = &m_pModule->GetInputSignature().GetElement(inpId);
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- DXASSERT_NOMSG(false);
|
|
|
|
- }
|
|
|
|
- } else if (DxilInst_LoadPatchConstant LPC = DxilInst_LoadPatchConstant(pInst)) {
|
|
|
|
- if (pSM->IsDS() && bPC) {
|
|
|
|
- GetUnsignedVal(LPC.get_inputSigId(), &inpId);
|
|
|
|
- GetUnsignedVal(LPC.get_col(), &col);
|
|
|
|
- GetUnsignedVal(LPC.get_row(), (uint32_t*)&startRow);
|
|
|
|
- pSigElem = &m_pModule->GetPatchConstantSignature().GetElement(inpId);
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Finalize setting output dependence on inputs.
|
|
|
|
- if (pSigElem && pSigElem->IsAllocated()) {
|
|
|
|
- if (startRow != Semantic::kUndefinedRow) {
|
|
|
|
- endRow = startRow;
|
|
|
|
- } else {
|
|
|
|
- // The entire column contributes to output.
|
|
|
|
- startRow = 0;
|
|
|
|
- endRow = pSigElem->GetRows() - 1;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- auto &ContributingInputs = InputsContributingToOutputs[outIdx];
|
|
|
|
- for (int row = startRow; row <= endRow; row++) {
|
|
|
|
- unsigned index = GetLinearIndex(*pSigElem, row, col);
|
|
|
|
- if (!bLoadOutputCPInHS) {
|
|
|
|
- ContributingInputs.emplace(index);
|
|
|
|
- } else {
|
|
|
|
- // This HS patch-constant output depends on an input value of LoadOutputControlPoint
|
|
|
|
- // that is the output value of the HS main (control-point) function.
|
|
|
|
- // Transitively update this (patch-constant) output dependence on main (control-point) output.
|
|
|
|
- DXASSERT_NOMSG(&OutputsDependentOnViewId == &m_PCOutputsDependentOnViewId);
|
|
|
|
- OutputsDependentOnViewId[outIdx] = OutputsDependentOnViewId[outIdx] || m_OutputsDependentOnViewId[0][index];
|
|
|
|
|
|
+void SerializeInputsContributingToOutput(
|
|
|
|
+ unsigned NumInputs, unsigned NumOutputs,
|
|
|
|
+ const DxilViewIdState::InputsContributingToOutputType
|
|
|
|
+ &InputsContributingToOutputs,
|
|
|
|
+ unsigned *&pData) {
|
|
|
|
+ unsigned NumOutUINTs = RoundUpToUINT(NumOutputs);
|
|
|
|
|
|
- const auto it = m_InputsContributingToOutputs[0].find(index);
|
|
|
|
- if (it != m_InputsContributingToOutputs[0].end()) {
|
|
|
|
- const std::set<unsigned> &LoadOutputCPInputsContributingToOutputs = it->second;
|
|
|
|
- ContributingInputs.insert(LoadOutputCPInputsContributingToOutputs.begin(),
|
|
|
|
- LoadOutputCPInputsContributingToOutputs.end());
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ // Serialize output dependence on inputs.
|
|
|
|
+ for (unsigned outputIdx = 0; outputIdx < NumOutputs; outputIdx++) {
|
|
|
|
+ auto it = InputsContributingToOutputs.find(outputIdx);
|
|
|
|
+ if (it != InputsContributingToOutputs.end()) {
|
|
|
|
+ for (unsigned inputIdx : it->second) {
|
|
|
|
+ unsigned w = outputIdx / 32;
|
|
|
|
+ unsigned b = outputIdx % 32;
|
|
|
|
+ pData[inputIdx * NumOutUINTs + w] |= (1u << b);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-}
|
|
|
|
-
|
|
|
|
-unsigned DxilViewIdState::GetLinearIndex(DxilSignatureElement &SigElem, int row, unsigned col) const {
|
|
|
|
- DXASSERT_NOMSG(row >= 0 && col < kNumComps && SigElem.GetStartRow() != Semantic::kUndefinedRow);
|
|
|
|
- unsigned idx = (((unsigned)row) + SigElem.GetStartRow())*kNumComps + col + SigElem.GetStartCol();
|
|
|
|
- DXASSERT_NOMSG(idx < kMaxSigScalars);
|
|
|
|
- return idx;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-void DxilViewIdState::UpdateDynamicIndexUsageState() const {
|
|
|
|
- UpdateDynamicIndexUsageStateForSig(m_pModule->GetInputSignature(), m_InpSigDynIdxElems);
|
|
|
|
- UpdateDynamicIndexUsageStateForSig(m_pModule->GetOutputSignature(), m_OutSigDynIdxElems);
|
|
|
|
- UpdateDynamicIndexUsageStateForSig(m_pModule->GetPatchConstantSignature(), m_PCSigDynIdxElems);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-void DxilViewIdState::UpdateDynamicIndexUsageStateForSig(DxilSignature &Sig,
|
|
|
|
- const DynamicallyIndexedElemsType &DynIdxElems) const {
|
|
|
|
- for (auto it : DynIdxElems) {
|
|
|
|
- unsigned id = it.first;
|
|
|
|
- unsigned mask = it.second;
|
|
|
|
- DxilSignatureElement &E = Sig.GetElement(id);
|
|
|
|
- E.SetDynIdxCompMask(mask);
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
|
|
|
|
-static unsigned RoundUpToUINT(unsigned x) {
|
|
|
|
- return (x + 31)/32;
|
|
|
|
|
|
+ pData += NumInputs * NumOutUINTs;
|
|
}
|
|
}
|
|
|
|
+} // namespace
|
|
|
|
|
|
void DxilViewIdState::Serialize() {
|
|
void DxilViewIdState::Serialize() {
|
|
const ShaderModel *pSM = m_pModule->GetShaderModel();
|
|
const ShaderModel *pSM = m_pModule->GetShaderModel();
|
|
@@ -799,31 +200,31 @@ void DxilViewIdState::Serialize() {
|
|
|
|
|
|
// Compute serialized state size in UINTs.
|
|
// Compute serialized state size in UINTs.
|
|
unsigned NumInputs = getNumInputSigScalars();
|
|
unsigned NumInputs = getNumInputSigScalars();
|
|
- unsigned NumStreams = pSM->IsGS()? kNumStreams : 1;
|
|
|
|
|
|
+ unsigned NumStreams = pSM->IsGS() ? kNumStreams : 1;
|
|
unsigned Size = 0;
|
|
unsigned Size = 0;
|
|
- Size += 1; // #Inputs.
|
|
|
|
|
|
+ Size += 1; // #Inputs.
|
|
for (unsigned StreamId = 0; StreamId < NumStreams; StreamId++) {
|
|
for (unsigned StreamId = 0; StreamId < NumStreams; StreamId++) {
|
|
- Size += 1; // #Outputs for stream StreamId.
|
|
|
|
|
|
+ Size += 1; // #Outputs for stream StreamId.
|
|
unsigned NumOutputs = getNumOutputSigScalars(StreamId);
|
|
unsigned NumOutputs = getNumOutputSigScalars(StreamId);
|
|
unsigned NumOutUINTs = RoundUpToUINT(NumOutputs);
|
|
unsigned NumOutUINTs = RoundUpToUINT(NumOutputs);
|
|
if (m_bUsesViewId) {
|
|
if (m_bUsesViewId) {
|
|
- Size += NumOutUINTs; // m_OutputsDependentOnViewId[StreamId]
|
|
|
|
|
|
+ Size += NumOutUINTs; // m_OutputsDependentOnViewId[StreamId]
|
|
}
|
|
}
|
|
- Size += NumInputs * NumOutUINTs; // m_InputsContributingToOutputs[StreamId]
|
|
|
|
|
|
+ Size += NumInputs * NumOutUINTs; // m_InputsContributingToOutputs[StreamId]
|
|
}
|
|
}
|
|
if (pSM->IsHS() || pSM->IsDS()) {
|
|
if (pSM->IsHS() || pSM->IsDS()) {
|
|
- Size += 1; // #PatchConstant.
|
|
|
|
|
|
+ Size += 1; // #PatchConstant.
|
|
unsigned NumPCs = getNumPCSigScalars();
|
|
unsigned NumPCs = getNumPCSigScalars();
|
|
unsigned NumPCUINTs = RoundUpToUINT(NumPCs);
|
|
unsigned NumPCUINTs = RoundUpToUINT(NumPCs);
|
|
if (pSM->IsHS()) {
|
|
if (pSM->IsHS()) {
|
|
if (m_bUsesViewId) {
|
|
if (m_bUsesViewId) {
|
|
- Size += NumPCUINTs; // m_PCOutputsDependentOnViewId
|
|
|
|
|
|
+ Size += NumPCUINTs; // m_PCOutputsDependentOnViewId
|
|
}
|
|
}
|
|
Size += NumInputs * NumPCUINTs; // m_InputsContributingToPCOutputs
|
|
Size += NumInputs * NumPCUINTs; // m_InputsContributingToPCOutputs
|
|
} else {
|
|
} else {
|
|
unsigned NumOutputs = getNumOutputSigScalars(0);
|
|
unsigned NumOutputs = getNumOutputSigScalars(0);
|
|
unsigned NumOutUINTs = RoundUpToUINT(NumOutputs);
|
|
unsigned NumOutUINTs = RoundUpToUINT(NumOutputs);
|
|
- Size += NumPCs * NumOutUINTs; // m_PCInputsContributingToOutputs
|
|
|
|
|
|
+ Size += NumPCs * NumOutUINTs; // m_PCInputsContributingToOutputs
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -837,21 +238,26 @@ void DxilViewIdState::Serialize() {
|
|
unsigned NumOutputs = getNumOutputSigScalars(StreamId);
|
|
unsigned NumOutputs = getNumOutputSigScalars(StreamId);
|
|
*pData++ = NumOutputs;
|
|
*pData++ = NumOutputs;
|
|
if (m_bUsesViewId) {
|
|
if (m_bUsesViewId) {
|
|
- SerializeOutputsDependentOnViewId(NumOutputs, m_OutputsDependentOnViewId[StreamId], pData);
|
|
|
|
|
|
+ SerializeOutputsDependentOnViewId(
|
|
|
|
+ NumOutputs, m_OutputsDependentOnViewId[StreamId], pData);
|
|
}
|
|
}
|
|
- SerializeInputsContributingToOutput(NumInputs, NumOutputs, m_InputsContributingToOutputs[StreamId], pData);
|
|
|
|
|
|
+ SerializeInputsContributingToOutput(
|
|
|
|
+ NumInputs, NumOutputs, m_InputsContributingToOutputs[StreamId], pData);
|
|
}
|
|
}
|
|
if (pSM->IsHS() || pSM->IsDS()) {
|
|
if (pSM->IsHS() || pSM->IsDS()) {
|
|
unsigned NumPCs = getNumPCSigScalars();
|
|
unsigned NumPCs = getNumPCSigScalars();
|
|
*pData++ = NumPCs;
|
|
*pData++ = NumPCs;
|
|
if (pSM->IsHS()) {
|
|
if (pSM->IsHS()) {
|
|
if (m_bUsesViewId) {
|
|
if (m_bUsesViewId) {
|
|
- SerializeOutputsDependentOnViewId(NumPCs, m_PCOutputsDependentOnViewId, pData);
|
|
|
|
|
|
+ SerializeOutputsDependentOnViewId(NumPCs, m_PCOutputsDependentOnViewId,
|
|
|
|
+ pData);
|
|
}
|
|
}
|
|
- SerializeInputsContributingToOutput(NumInputs, NumPCs, m_InputsContributingToPCOutputs, pData);
|
|
|
|
|
|
+ SerializeInputsContributingToOutput(
|
|
|
|
+ NumInputs, NumPCs, m_InputsContributingToPCOutputs, pData);
|
|
} else {
|
|
} else {
|
|
unsigned NumOutputs = getNumOutputSigScalars(0);
|
|
unsigned NumOutputs = getNumOutputSigScalars(0);
|
|
- SerializeInputsContributingToOutput(NumPCs, NumOutputs, m_PCInputsContributingToOutputs, pData);
|
|
|
|
|
|
+ SerializeInputsContributingToOutput(
|
|
|
|
+ NumPCs, NumOutputs, m_PCInputsContributingToOutputs, pData);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
DXASSERT_NOMSG(pData == (&m_SerializedState[0] + Size));
|
|
DXASSERT_NOMSG(pData == (&m_SerializedState[0] + Size));
|
|
@@ -867,44 +273,53 @@ const vector<unsigned> &DxilViewIdState::GetSerialized() const {
|
|
return m_SerializedState;
|
|
return m_SerializedState;
|
|
}
|
|
}
|
|
|
|
|
|
-void DxilViewIdState::SerializeOutputsDependentOnViewId(unsigned NumOutputs,
|
|
|
|
- const OutputsDependentOnViewIdType &OutputsDependentOnViewId,
|
|
|
|
- unsigned *&pData) {
|
|
|
|
|
|
+namespace {
|
|
|
|
+unsigned DeserializeOutputsDependentOnViewId(
|
|
|
|
+ unsigned NumOutputs,
|
|
|
|
+ DxilViewIdState::OutputsDependentOnViewIdType &OutputsDependentOnViewId,
|
|
|
|
+ const unsigned *pData, unsigned DataSize) {
|
|
unsigned NumOutUINTs = RoundUpToUINT(NumOutputs);
|
|
unsigned NumOutUINTs = RoundUpToUINT(NumOutputs);
|
|
|
|
+ IFTBOOL(NumOutUINTs <= DataSize, DXC_E_GENERAL_INTERNAL_ERROR);
|
|
|
|
|
|
- // Serialize output dependence on ViewId.
|
|
|
|
|
|
+ // Deserialize output dependence on ViewId.
|
|
for (unsigned i = 0; i < NumOutUINTs; i++) {
|
|
for (unsigned i = 0; i < NumOutUINTs; i++) {
|
|
- unsigned x = 0;
|
|
|
|
- for (unsigned j = 0; j < std::min(32u, NumOutputs - 32u*i); j++) {
|
|
|
|
- if (OutputsDependentOnViewId[i*32 + j]) {
|
|
|
|
- x |= (1u << j);
|
|
|
|
|
|
+ unsigned x = *pData++;
|
|
|
|
+ for (unsigned j = 0; j < std::min(32u, NumOutputs - 32u * i); j++) {
|
|
|
|
+ if (x & (1u << j)) {
|
|
|
|
+ OutputsDependentOnViewId[i * 32 + j] = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- *pData++ = x;
|
|
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ return NumOutUINTs;
|
|
}
|
|
}
|
|
|
|
|
|
-void DxilViewIdState::SerializeInputsContributingToOutput(unsigned NumInputs, unsigned NumOutputs,
|
|
|
|
- const InputsContributingToOutputType &InputsContributingToOutputs,
|
|
|
|
- unsigned *&pData) {
|
|
|
|
|
|
+unsigned DeserializeInputsContributingToOutput(
|
|
|
|
+ unsigned NumInputs, unsigned NumOutputs,
|
|
|
|
+ DxilViewIdState::InputsContributingToOutputType
|
|
|
|
+ &InputsContributingToOutputs,
|
|
|
|
+ const unsigned *pData, unsigned DataSize) {
|
|
unsigned NumOutUINTs = RoundUpToUINT(NumOutputs);
|
|
unsigned NumOutUINTs = RoundUpToUINT(NumOutputs);
|
|
|
|
+ unsigned Size = NumInputs * NumOutUINTs;
|
|
|
|
+ IFTBOOL(Size <= DataSize, DXC_E_GENERAL_INTERNAL_ERROR);
|
|
|
|
|
|
- // Serialize output dependence on inputs.
|
|
|
|
- for (unsigned outputIdx = 0; outputIdx < NumOutputs; outputIdx++) {
|
|
|
|
- auto it = InputsContributingToOutputs.find(outputIdx);
|
|
|
|
- if (it != InputsContributingToOutputs.end()) {
|
|
|
|
- for (unsigned inputIdx : it->second) {
|
|
|
|
- unsigned w = outputIdx / 32;
|
|
|
|
- unsigned b = outputIdx % 32;
|
|
|
|
- pData[inputIdx*NumOutUINTs + w] |= (1u << b);
|
|
|
|
|
|
+ // Deserialize output dependence on inputs.
|
|
|
|
+ for (unsigned inputIdx = 0; inputIdx < NumInputs; inputIdx++) {
|
|
|
|
+ for (unsigned outputIdx = 0; outputIdx < NumOutputs; outputIdx++) {
|
|
|
|
+ unsigned w = outputIdx / 32;
|
|
|
|
+ unsigned b = outputIdx % 32;
|
|
|
|
+ if (pData[inputIdx * NumOutUINTs + w] & (1u << b)) {
|
|
|
|
+ InputsContributingToOutputs[outputIdx].insert(inputIdx);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- pData += NumInputs * NumOutUINTs;
|
|
|
|
|
|
+ return Size;
|
|
}
|
|
}
|
|
|
|
+} // namespace
|
|
|
|
|
|
-void DxilViewIdState::Deserialize(const unsigned *pData, unsigned DataSizeInUINTs) {
|
|
|
|
|
|
+void DxilViewIdState::Deserialize(const unsigned *pData,
|
|
|
|
+ unsigned DataSizeInUINTs) {
|
|
Clear();
|
|
Clear();
|
|
m_SerializedState.resize(DataSizeInUINTs);
|
|
m_SerializedState.resize(DataSizeInUINTs);
|
|
memcpy(m_SerializedState.data(), pData, DataSizeInUINTs * sizeof(unsigned));
|
|
memcpy(m_SerializedState.data(), pData, DataSizeInUINTs * sizeof(unsigned));
|
|
@@ -913,125 +328,46 @@ void DxilViewIdState::Deserialize(const unsigned *pData, unsigned DataSizeInUINT
|
|
m_bUsesViewId = m_pModule->m_ShaderFlags.GetViewID();
|
|
m_bUsesViewId = m_pModule->m_ShaderFlags.GetViewID();
|
|
unsigned ConsumedUINTs = 0;
|
|
unsigned ConsumedUINTs = 0;
|
|
|
|
|
|
- IFTBOOL(DataSizeInUINTs-ConsumedUINTs >= 1, DXC_E_GENERAL_INTERNAL_ERROR);
|
|
|
|
|
|
+ IFTBOOL(DataSizeInUINTs - ConsumedUINTs >= 1, DXC_E_GENERAL_INTERNAL_ERROR);
|
|
unsigned NumInputs = pData[ConsumedUINTs++];
|
|
unsigned NumInputs = pData[ConsumedUINTs++];
|
|
m_NumInputSigScalars = NumInputs;
|
|
m_NumInputSigScalars = NumInputs;
|
|
|
|
|
|
- unsigned NumStreams = pSM->IsGS()? kNumStreams : 1;
|
|
|
|
|
|
+ unsigned NumStreams = pSM->IsGS() ? kNumStreams : 1;
|
|
for (unsigned StreamId = 0; StreamId < NumStreams; StreamId++) {
|
|
for (unsigned StreamId = 0; StreamId < NumStreams; StreamId++) {
|
|
- IFTBOOL(DataSizeInUINTs-ConsumedUINTs >= 1, DXC_E_GENERAL_INTERNAL_ERROR);
|
|
|
|
|
|
+ IFTBOOL(DataSizeInUINTs - ConsumedUINTs >= 1, DXC_E_GENERAL_INTERNAL_ERROR);
|
|
unsigned NumOutputs = pData[ConsumedUINTs++];
|
|
unsigned NumOutputs = pData[ConsumedUINTs++];
|
|
m_NumOutputSigScalars[StreamId] = NumOutputs;
|
|
m_NumOutputSigScalars[StreamId] = NumOutputs;
|
|
|
|
|
|
if (m_bUsesViewId) {
|
|
if (m_bUsesViewId) {
|
|
- ConsumedUINTs += DeserializeOutputsDependentOnViewId(NumOutputs,
|
|
|
|
- m_OutputsDependentOnViewId[StreamId],
|
|
|
|
- &pData[ConsumedUINTs],
|
|
|
|
- DataSizeInUINTs-ConsumedUINTs);
|
|
|
|
|
|
+ ConsumedUINTs += DeserializeOutputsDependentOnViewId(
|
|
|
|
+ NumOutputs, m_OutputsDependentOnViewId[StreamId],
|
|
|
|
+ &pData[ConsumedUINTs], DataSizeInUINTs - ConsumedUINTs);
|
|
}
|
|
}
|
|
- ConsumedUINTs += DeserializeInputsContributingToOutput(NumInputs, NumOutputs,
|
|
|
|
- m_InputsContributingToOutputs[StreamId],
|
|
|
|
- &pData[ConsumedUINTs],
|
|
|
|
- DataSizeInUINTs-ConsumedUINTs);
|
|
|
|
|
|
+ ConsumedUINTs += DeserializeInputsContributingToOutput(
|
|
|
|
+ NumInputs, NumOutputs, m_InputsContributingToOutputs[StreamId],
|
|
|
|
+ &pData[ConsumedUINTs], DataSizeInUINTs - ConsumedUINTs);
|
|
}
|
|
}
|
|
|
|
|
|
if (pSM->IsHS() || pSM->IsDS()) {
|
|
if (pSM->IsHS() || pSM->IsDS()) {
|
|
- IFTBOOL(DataSizeInUINTs-ConsumedUINTs >= 1, DXC_E_GENERAL_INTERNAL_ERROR);
|
|
|
|
|
|
+ IFTBOOL(DataSizeInUINTs - ConsumedUINTs >= 1, DXC_E_GENERAL_INTERNAL_ERROR);
|
|
unsigned NumPCs = pData[ConsumedUINTs++];
|
|
unsigned NumPCs = pData[ConsumedUINTs++];
|
|
m_NumPCSigScalars = NumPCs;
|
|
m_NumPCSigScalars = NumPCs;
|
|
if (pSM->IsHS()) {
|
|
if (pSM->IsHS()) {
|
|
if (m_bUsesViewId) {
|
|
if (m_bUsesViewId) {
|
|
- ConsumedUINTs += DeserializeOutputsDependentOnViewId(NumPCs,
|
|
|
|
- m_PCOutputsDependentOnViewId,
|
|
|
|
- &pData[ConsumedUINTs],
|
|
|
|
- DataSizeInUINTs-ConsumedUINTs);
|
|
|
|
|
|
+ ConsumedUINTs += DeserializeOutputsDependentOnViewId(
|
|
|
|
+ NumPCs, m_PCOutputsDependentOnViewId, &pData[ConsumedUINTs],
|
|
|
|
+ DataSizeInUINTs - ConsumedUINTs);
|
|
}
|
|
}
|
|
- ConsumedUINTs += DeserializeInputsContributingToOutput(NumInputs, NumPCs,
|
|
|
|
- m_InputsContributingToPCOutputs,
|
|
|
|
- &pData[ConsumedUINTs],
|
|
|
|
- DataSizeInUINTs-ConsumedUINTs);
|
|
|
|
|
|
+ ConsumedUINTs += DeserializeInputsContributingToOutput(
|
|
|
|
+ NumInputs, NumPCs, m_InputsContributingToPCOutputs,
|
|
|
|
+ &pData[ConsumedUINTs], DataSizeInUINTs - ConsumedUINTs);
|
|
} else {
|
|
} else {
|
|
unsigned NumOutputs = getNumOutputSigScalars(0);
|
|
unsigned NumOutputs = getNumOutputSigScalars(0);
|
|
- ConsumedUINTs += DeserializeInputsContributingToOutput(NumPCs, NumOutputs,
|
|
|
|
- m_PCInputsContributingToOutputs,
|
|
|
|
- &pData[ConsumedUINTs],
|
|
|
|
- DataSizeInUINTs-ConsumedUINTs);
|
|
|
|
|
|
+ ConsumedUINTs += DeserializeInputsContributingToOutput(
|
|
|
|
+ NumPCs, NumOutputs, m_PCInputsContributingToOutputs,
|
|
|
|
+ &pData[ConsumedUINTs], DataSizeInUINTs - ConsumedUINTs);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
DXASSERT_NOMSG(ConsumedUINTs == DataSizeInUINTs);
|
|
DXASSERT_NOMSG(ConsumedUINTs == DataSizeInUINTs);
|
|
}
|
|
}
|
|
-
|
|
|
|
-unsigned DxilViewIdState::DeserializeOutputsDependentOnViewId(unsigned NumOutputs,
|
|
|
|
- OutputsDependentOnViewIdType &OutputsDependentOnViewId,
|
|
|
|
- const unsigned *pData, unsigned DataSize) {
|
|
|
|
- unsigned NumOutUINTs = RoundUpToUINT(NumOutputs);
|
|
|
|
- IFTBOOL(NumOutUINTs <= DataSize, DXC_E_GENERAL_INTERNAL_ERROR);
|
|
|
|
-
|
|
|
|
- // Deserialize output dependence on ViewId.
|
|
|
|
- for (unsigned i = 0; i < NumOutUINTs; i++) {
|
|
|
|
- unsigned x = *pData++;
|
|
|
|
- for (unsigned j = 0; j < std::min(32u, NumOutputs - 32u*i); j++) {
|
|
|
|
- if (x & (1u << j)) {
|
|
|
|
- OutputsDependentOnViewId[i*32 + j] = true;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return NumOutUINTs;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-unsigned DxilViewIdState::DeserializeInputsContributingToOutput(unsigned NumInputs, unsigned NumOutputs,
|
|
|
|
- InputsContributingToOutputType &InputsContributingToOutputs,
|
|
|
|
- const unsigned *pData, unsigned DataSize) {
|
|
|
|
- unsigned NumOutUINTs = RoundUpToUINT(NumOutputs);
|
|
|
|
- unsigned Size = NumInputs * NumOutUINTs;
|
|
|
|
- IFTBOOL(Size <= DataSize, DXC_E_GENERAL_INTERNAL_ERROR);
|
|
|
|
-
|
|
|
|
- // Deserialize output dependence on inputs.
|
|
|
|
- for (unsigned inputIdx = 0; inputIdx < NumInputs; inputIdx++) {
|
|
|
|
- for (unsigned outputIdx = 0; outputIdx < NumOutputs; outputIdx++) {
|
|
|
|
- unsigned w = outputIdx / 32;
|
|
|
|
- unsigned b = outputIdx % 32;
|
|
|
|
- if (pData[inputIdx*NumOutUINTs + w] & (1u << b)) {
|
|
|
|
- InputsContributingToOutputs[outputIdx].insert(inputIdx);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return Size;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-char ComputeViewIdState::ID = 0;
|
|
|
|
-
|
|
|
|
-INITIALIZE_PASS_BEGIN(ComputeViewIdState, "viewid-state",
|
|
|
|
- "Compute information related to ViewID", true, true)
|
|
|
|
-INITIALIZE_PASS_END(ComputeViewIdState, "viewid-state",
|
|
|
|
- "Compute information related to ViewID", true, true)
|
|
|
|
-
|
|
|
|
-ComputeViewIdState::ComputeViewIdState() : ModulePass(ID) {
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-bool ComputeViewIdState::runOnModule(Module &M) {
|
|
|
|
- DxilModule &DxilModule = M.GetOrCreateDxilModule();
|
|
|
|
- const ShaderModel *pSM = DxilModule.GetShaderModel();
|
|
|
|
- if (!pSM->IsCS() && !pSM->IsLib()) {
|
|
|
|
- DxilViewIdState &ViewIdState = DxilModule.GetViewIdState();
|
|
|
|
- ViewIdState.Compute();
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- return false;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-void ComputeViewIdState::getAnalysisUsage(AnalysisUsage &AU) const {
|
|
|
|
- AU.setPreservesAll();
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-namespace llvm {
|
|
|
|
-
|
|
|
|
-ModulePass *createComputeViewIdStatePass() {
|
|
|
|
- return new ComputeViewIdState();
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-} // end of namespace llvm
|
|
|