|
@@ -323,109 +323,6 @@ void PatchLowerBoundOfCreateHandle(CallInst *handle, DxilModule &DM) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-static void PatchTBufferCreateHandle(CallInst *handle, DxilModule &DM, std::unordered_set<unsigned> &tbufferIDs) {
|
|
|
|
- DxilInst_CreateHandle createHandle(handle);
|
|
|
|
- DXASSERT_NOMSG(createHandle);
|
|
|
|
-
|
|
|
|
- DXIL::ResourceClass ResClass = static_cast<DXIL::ResourceClass>(createHandle.get_resourceClass_val());
|
|
|
|
- if (ResClass != DXIL::ResourceClass::CBuffer)
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- Value *resID = createHandle.get_rangeId();
|
|
|
|
- DXASSERT(isa<ConstantInt>(resID), "cannot handle dynamic resID for cbuffer CreateHandle");
|
|
|
|
- if (!isa<ConstantInt>(resID))
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- unsigned rangeId = cast<ConstantInt>(resID)->getLimitedValue();
|
|
|
|
- DxilResourceBase *res = &DM.GetCBuffer(rangeId);
|
|
|
|
-
|
|
|
|
- // For TBuffer, we need to switch resource type from CBuffer to SRV
|
|
|
|
- if (res->GetKind() == DXIL::ResourceKind::TBuffer) {
|
|
|
|
- // Track cbuffers IDs that are actually tbuffers
|
|
|
|
- tbufferIDs.insert(rangeId);
|
|
|
|
- hlsl::OP *hlslOP = DM.GetOP();
|
|
|
|
- llvm::LLVMContext &Ctx = DM.GetCtx();
|
|
|
|
-
|
|
|
|
- // Temporarily add SRV size to rangeID to guarantee unique new SRV ID
|
|
|
|
- Value *newRangeID = hlslOP->GetU32Const(rangeId + DM.GetSRVs().size());
|
|
|
|
- handle->setArgOperand(DXIL::OperandIndex::kCreateHandleResIDOpIdx,
|
|
|
|
- newRangeID);
|
|
|
|
- // switch create handle to SRV
|
|
|
|
- handle->setArgOperand(DXIL::OperandIndex::kCreateHandleResClassOpIdx,
|
|
|
|
- hlslOP->GetU8Const(
|
|
|
|
- static_cast<std::underlying_type<DxilResourceBase::Class>::type>(
|
|
|
|
- DXIL::ResourceClass::SRV)));
|
|
|
|
-
|
|
|
|
- Type *doubleTy = Type::getDoubleTy(Ctx);
|
|
|
|
- Type *i64Ty = Type::getInt64Ty(Ctx);
|
|
|
|
-
|
|
|
|
- // Replace corresponding cbuffer loads with typed buffer loads
|
|
|
|
- for (auto U = handle->user_begin(); U != handle->user_end(); ) {
|
|
|
|
- CallInst *I = cast<CallInst>(*(U++));
|
|
|
|
- DXASSERT(I && OP::IsDxilOpFuncCallInst(I), "otherwise unexpected user of CreateHandle value");
|
|
|
|
- DXIL::OpCode opcode = OP::GetDxilOpFuncCallInst(I);
|
|
|
|
- if (opcode == DXIL::OpCode::CBufferLoadLegacy) {
|
|
|
|
- DxilInst_CBufferLoadLegacy cbLoad(I);
|
|
|
|
-
|
|
|
|
- // Replace with appropriate buffer load instruction
|
|
|
|
- IRBuilder<> Builder(I);
|
|
|
|
- opcode = OP::OpCode::BufferLoad;
|
|
|
|
- Type *Ty = Type::getInt32Ty(Ctx);
|
|
|
|
- Function *BufLoad = hlslOP->GetOpFunc(opcode, Ty);
|
|
|
|
- Constant *opArg = hlslOP->GetU32Const((unsigned)opcode);
|
|
|
|
- Value *undefI = UndefValue::get(Type::getInt32Ty(Ctx));
|
|
|
|
- Value *offset = cbLoad.get_regIndex();
|
|
|
|
- CallInst* load = Builder.CreateCall(BufLoad, {opArg, handle, offset, undefI});
|
|
|
|
-
|
|
|
|
- // Find extractelement uses of cbuffer load and replace + generate bitcast as necessary
|
|
|
|
- for (auto LU = I->user_begin(); LU != I->user_end(); ) {
|
|
|
|
- ExtractValueInst *evInst = dyn_cast<ExtractValueInst>(*(LU++));
|
|
|
|
- DXASSERT(evInst && evInst->getNumIndices() == 1, "user of cbuffer load result should be extractvalue");
|
|
|
|
- uint64_t idx = evInst->getIndices()[0];
|
|
|
|
- Type *EltTy = evInst->getType();
|
|
|
|
- IRBuilder<> EEBuilder(evInst);
|
|
|
|
- Value *result = nullptr;
|
|
|
|
- if (EltTy != Ty) {
|
|
|
|
- // extract two values and DXIL::OpCode::MakeDouble or construct i64
|
|
|
|
- if ((EltTy == doubleTy) || (EltTy == i64Ty)) {
|
|
|
|
- DXASSERT(idx < 2, "64-bit component index out of range");
|
|
|
|
-
|
|
|
|
- // This assumes big endian order in tbuffer elements (is this correct?)
|
|
|
|
- Value *low = EEBuilder.CreateExtractValue(load, idx * 2);
|
|
|
|
- Value *high = EEBuilder.CreateExtractValue(load, idx * 2 + 1);
|
|
|
|
- if (EltTy == doubleTy) {
|
|
|
|
- opcode = OP::OpCode::MakeDouble;
|
|
|
|
- Function *MakeDouble = hlslOP->GetOpFunc(opcode, doubleTy);
|
|
|
|
- Constant *opArg = hlslOP->GetU32Const((unsigned)opcode);
|
|
|
|
- result = EEBuilder.CreateCall(MakeDouble, {opArg, low, high});
|
|
|
|
- } else {
|
|
|
|
- high = EEBuilder.CreateZExt(high, i64Ty);
|
|
|
|
- low = EEBuilder.CreateZExt(low, i64Ty);
|
|
|
|
- high = EEBuilder.CreateShl(high, hlslOP->GetU64Const(32));
|
|
|
|
- result = EEBuilder.CreateOr(high, low);
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- result = EEBuilder.CreateExtractValue(load, idx);
|
|
|
|
- result = EEBuilder.CreateBitCast(result, EltTy);
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- result = EEBuilder.CreateExtractValue(load, idx);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- evInst->replaceAllUsesWith(result);
|
|
|
|
- evInst->eraseFromParent();
|
|
|
|
- }
|
|
|
|
- } else if (opcode == DXIL::OpCode::CBufferLoad) {
|
|
|
|
- // TODO: Handle this, or prevent this for tbuffer
|
|
|
|
- DXASSERT(false, "otherwise CBufferLoad used for tbuffer rather than CBufferLoadLegacy");
|
|
|
|
- } else {
|
|
|
|
- DXASSERT(false, "otherwise unexpected user of CreateHandle value");
|
|
|
|
- }
|
|
|
|
- I->eraseFromParent();
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
}
|
|
}
|
|
|
|
|
|
void DxilCondenseResources::PatchCreateHandle(DxilModule &DM) {
|
|
void DxilCondenseResources::PatchCreateHandle(DxilModule &DM) {
|