|
@@ -92,12 +92,6 @@ bool BuildRewriteMap(RemapEntryCollection &rewrites, DxilModule &DM) {
|
|
|
return !rewrites.empty();
|
|
|
}
|
|
|
|
|
|
-void ApplyRewriteMapOnResTable(RemapEntryCollection &rewrites, DxilModule &DM) {
|
|
|
- for (auto &entry : rewrites) {
|
|
|
- entry.second.Resource->SetID(entry.second.Index);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
} // namespace
|
|
|
|
|
|
class DxilResourceRegisterAllocator {
|
|
@@ -265,153 +259,6 @@ public:
|
|
|
}
|
|
|
};
|
|
|
|
|
|
-class DxilCondenseResources : public ModulePass {
|
|
|
-private:
|
|
|
- RemapEntryCollection m_rewrites;
|
|
|
-
|
|
|
-public:
|
|
|
- static char ID; // Pass identification, replacement for typeid
|
|
|
- explicit DxilCondenseResources() : ModulePass(ID) {}
|
|
|
-
|
|
|
- const char *getPassName() const override { return "DXIL Condense Resources"; }
|
|
|
-
|
|
|
- bool runOnModule(Module &M) override {
|
|
|
- DxilModule &DM = M.GetOrCreateDxilModule();
|
|
|
- // Skip lib.
|
|
|
- if (DM.GetShaderModel()->IsLib())
|
|
|
- return false;
|
|
|
-
|
|
|
- // Gather reserved resource registers while we still have
|
|
|
- // unused resources that might have explicit register assignments.
|
|
|
- DxilResourceRegisterAllocator ResourceRegisterAllocator;
|
|
|
- ResourceRegisterAllocator.GatherReservedRegisters(DM);
|
|
|
-
|
|
|
- // Remove unused resources.
|
|
|
- DM.RemoveUnusedResources();
|
|
|
-
|
|
|
- // Make sure all resource types are dense; build a map of rewrites.
|
|
|
- if (BuildRewriteMap(m_rewrites, DM)) {
|
|
|
- // Rewrite all instructions that refer to resources in the map.
|
|
|
- ApplyRewriteMap(DM);
|
|
|
- }
|
|
|
-
|
|
|
- bool hasResource = DM.GetCBuffers().size() ||
|
|
|
- DM.GetUAVs().size() || DM.GetSRVs().size() || DM.GetSamplers().size();
|
|
|
-
|
|
|
- if (hasResource) {
|
|
|
- if (!DM.GetShaderModel()->IsLib()) {
|
|
|
- ResourceRegisterAllocator.AllocateRegisters(DM);
|
|
|
- PatchCreateHandle(DM);
|
|
|
- }
|
|
|
- }
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- DxilResourceBase &GetFirstRewrite() const {
|
|
|
- DXASSERT_NOMSG(!m_rewrites.empty());
|
|
|
- return *m_rewrites.begin()->second.Resource;
|
|
|
- }
|
|
|
-
|
|
|
-private:
|
|
|
- void ApplyRewriteMap(DxilModule &DM);
|
|
|
- // Add lowbound to create handle range index.
|
|
|
- void PatchCreateHandle(DxilModule &DM);
|
|
|
-};
|
|
|
-
|
|
|
-void DxilCondenseResources::ApplyRewriteMap(DxilModule &DM) {
|
|
|
- for (Function &F : DM.GetModule()->functions()) {
|
|
|
- if (F.isDeclaration()) {
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- for (inst_iterator iter = inst_begin(F), E = inst_end(F); iter != E; ++iter) {
|
|
|
- llvm::Instruction &I = *iter;
|
|
|
- DxilInst_CreateHandle CH(&I);
|
|
|
- if (!CH)
|
|
|
- continue;
|
|
|
-
|
|
|
- ResourceID RId;
|
|
|
- RId.Class = (DXIL::ResourceClass)CH.get_resourceClass_val();
|
|
|
- RId.ID = (unsigned)llvm::dyn_cast<llvm::ConstantInt>(CH.get_rangeId())
|
|
|
- ->getZExtValue();
|
|
|
- RemapEntryCollection::iterator it = m_rewrites.find(RId);
|
|
|
- if (it == m_rewrites.end()) {
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- CallInst *CI = cast<CallInst>(&I);
|
|
|
- Value *newRangeID = DM.GetOP()->GetU32Const(it->second.Index);
|
|
|
- CI->setArgOperand(DXIL::OperandIndex::kCreateHandleResIDOpIdx,
|
|
|
- newRangeID);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- ApplyRewriteMapOnResTable(m_rewrites, DM);
|
|
|
-}
|
|
|
-
|
|
|
-namespace {
|
|
|
-
|
|
|
-void PatchLowerBoundOfCreateHandle(CallInst *handle, DxilModule &DM) {
|
|
|
- DxilInst_CreateHandle createHandle(handle);
|
|
|
- DXASSERT_NOMSG(createHandle);
|
|
|
-
|
|
|
- DXIL::ResourceClass ResClass =
|
|
|
- static_cast<DXIL::ResourceClass>(createHandle.get_resourceClass_val());
|
|
|
- // Dynamic rangeId is not supported - skip and let validation report the
|
|
|
- // error.
|
|
|
- if (!isa<ConstantInt>(createHandle.get_rangeId()))
|
|
|
- return;
|
|
|
-
|
|
|
- unsigned rangeId =
|
|
|
- cast<ConstantInt>(createHandle.get_rangeId())->getLimitedValue();
|
|
|
-
|
|
|
- DxilResourceBase *res = nullptr;
|
|
|
- switch (ResClass) {
|
|
|
- case DXIL::ResourceClass::SRV:
|
|
|
- res = &DM.GetSRV(rangeId);
|
|
|
- break;
|
|
|
- case DXIL::ResourceClass::UAV:
|
|
|
- res = &DM.GetUAV(rangeId);
|
|
|
- break;
|
|
|
- case DXIL::ResourceClass::CBuffer:
|
|
|
- res = &DM.GetCBuffer(rangeId);
|
|
|
- break;
|
|
|
- case DXIL::ResourceClass::Sampler:
|
|
|
- res = &DM.GetSampler(rangeId);
|
|
|
- break;
|
|
|
- default:
|
|
|
- DXASSERT(0, "invalid res class");
|
|
|
- return;
|
|
|
- }
|
|
|
- IRBuilder<> Builder(handle);
|
|
|
- unsigned lowBound = res->GetLowerBound();
|
|
|
- if (lowBound) {
|
|
|
- Value *Index = createHandle.get_index();
|
|
|
- if (ConstantInt *cIndex = dyn_cast<ConstantInt>(Index)) {
|
|
|
- unsigned newIdx = lowBound + cIndex->getLimitedValue();
|
|
|
- handle->setArgOperand(DXIL::OperandIndex::kCreateHandleResIndexOpIdx,
|
|
|
- Builder.getInt32(newIdx));
|
|
|
- } else {
|
|
|
- Value *newIdx = Builder.CreateAdd(Index, Builder.getInt32(lowBound));
|
|
|
- handle->setArgOperand(DXIL::OperandIndex::kCreateHandleResIndexOpIdx,
|
|
|
- newIdx);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-void DxilCondenseResources::PatchCreateHandle(DxilModule &DM) {
|
|
|
- Function *createHandle = DM.GetOP()->GetOpFunc(DXIL::OpCode::CreateHandle,
|
|
|
- Type::getVoidTy(DM.GetCtx()));
|
|
|
-
|
|
|
- for (User *U : createHandle->users()) {
|
|
|
- PatchLowerBoundOfCreateHandle(cast<CallInst>(U), DM);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-char DxilCondenseResources::ID = 0;
|
|
|
-
|
|
|
bool llvm::AreDxilResourcesDense(llvm::Module *M, hlsl::DxilResourceBase **ppNonDense) {
|
|
|
DxilModule &DM = M->GetOrCreateDxilModule();
|
|
|
RemapEntryCollection rewrites;
|
|
@@ -425,12 +272,6 @@ bool llvm::AreDxilResourcesDense(llvm::Module *M, hlsl::DxilResourceBase **ppNon
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-ModulePass *llvm::createDxilCondenseResourcesPass() {
|
|
|
- return new DxilCondenseResources();
|
|
|
-}
|
|
|
-
|
|
|
-INITIALIZE_PASS(DxilCondenseResources, "hlsl-dxil-condense", "DXIL Condense Resources", false, false)
|
|
|
-
|
|
|
static bool GetConstantLegalGepForSplitAlloca(GetElementPtrInst *gep, DxilValueCache *DVC, int64_t *ret) {
|
|
|
if (gep->getNumIndices() != 2) {
|
|
|
return false;
|