| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155 |
- ///////////////////////////////////////////////////////////////////////////////
- // //
- // DxilPatchShaderRecordBindings.cpp //
- // Copyright (C) Microsoft Corporation. All rights reserved. //
- // This file is distributed under the University of Illinois Open Source //
- // License. See LICENSE.TXT for details. //
- // //
- // Provides a pass used by the RayTracing Fallback Lyaer to add modify //
- // bindings to pull local root signature parameters from a global //
- // "shader table" buffer instead //
- // //
- ///////////////////////////////////////////////////////////////////////////////
- #include "dxc/HLSL/DxilGenerationPass.h"
- #include "dxc/HLSL/DxilFallbackLayerPass.h"
- #include "dxc/HLSL/DxilOperations.h"
- #include "dxc/HLSL/DxilSignatureElement.h"
- #include "dxc/HLSL/DxilFunctionProps.h"
- #include "dxc/HLSL/DxilModule.h"
- #include "dxc/Support/Global.h"
- #include "dxc/Support/Unicode.h"
- #include "dxc/HLSL/DxilTypeSystem.h"
- #include "dxc/HLSL/DxilConstants.h"
- #include "dxc/HLSL/DxilInstructions.h"
- #include "dxc/HLSL/DxilSpanAllocator.h"
- #include "dxc/HLSL/DxilRootSignature.h"
- #include "dxc/HLSL/DxilUtil.h"
- #include "llvm/Transforms/Utils/Cloning.h"
- #include "llvm/IR/Instructions.h"
- #include "llvm/IR/IntrinsicInst.h"
- #include "llvm/IR/InstIterator.h"
- #include "llvm/IR/Module.h"
- #include "llvm/IR/PassManager.h"
- #include "llvm/ADT/BitVector.h"
- #include "llvm/Pass.h"
- #include "llvm/Transforms/Utils/Local.h"
- #include "llvm/Transforms/Scalar.h"
- #include <memory>
- #include <unordered_set>
- #include <functional>
- #include <unordered_map>
- #include <array>
- struct D3D12_VERSIONED_ROOT_SIGNATURE_DESC;
- #include "DxilPatchShaderRecordBindingsShared.h"
- using namespace llvm;
- using namespace hlsl;
- bool operator==(const ViewKey &a, const ViewKey &b) {
- return memcmp(&a, &b, sizeof(a)) == 0;
- }
- const size_t SizeofD3D12GpuVA = sizeof(uint64_t);
- const size_t SizeofD3D12GpuDescriptorHandle = sizeof(uint64_t);
- Function *CloneFunction(Function *Orig,
- const llvm::Twine &Name,
- llvm::Module *llvmModule) {
- Function *F = Function::Create(Orig->getFunctionType(),
- GlobalValue::LinkageTypes::ExternalLinkage,
- Name, llvmModule);
- SmallVector<ReturnInst *, 2> Returns;
- ValueToValueMapTy vmap;
- // Map params.
- auto entryParamIt = F->arg_begin();
- for (Argument ¶m : Orig->args()) {
- vmap[¶m] = (entryParamIt++);
- }
- DxilModule &DM = llvmModule->GetOrCreateDxilModule();
- llvm::CloneFunctionInto(F, Orig, vmap, /*ModuleLevelChagnes*/ false, Returns);
- DM.GetTypeSystem().CopyFunctionAnnotation(F, Orig, DM.GetTypeSystem());
- if (DM.HasDxilFunctionProps(F)) {
- DM.CloneDxilEntryProps(Orig, F);
- }
- return F;
- }
- struct ShaderRecordEntry {
- DxilRootParameterType ParameterType;
- unsigned int RecordOffsetInBytes;
- unsigned int OffsetInDescriptors; // Only valid for descriptor tables
- static ShaderRecordEntry InvalidEntry() { return { (DxilRootParameterType)-1, (unsigned int)-1 }; }
- bool IsInvalid() { return (unsigned int)ParameterType == (unsigned int)-1; }
- };
- struct D3D12_VERSIONED_ROOT_SIGNATURE_DESC;
- class DxilPatchShaderRecordBindings : public ModulePass {
- public:
- static char ID; // Pass identification, replacement for typeid
- explicit DxilPatchShaderRecordBindings() : ModulePass(ID) {}
- const char *getPassName() const override { return "DXIL Patch Shader Record Binding"; }
- void applyOptions(PassOptions O) override;
- bool runOnModule(Module &M) override;
- private:
- void ValidateParameters();
- void AddInputBinding(Module &M);
- void PatchShaderBindings(Module &M);
- void InitializeViewTable();
- unsigned int AddSRVRawBuffer(Module &M, unsigned int registerIndex, unsigned int registerSpace, const std::string &bufferName);
- unsigned int AddHandle(Module &M, unsigned int baseRegisterIndex, unsigned int rangeSize, unsigned int registerSpace, DXIL::ResourceClass resClass, DXIL::ResourceKind resKind, const std::string &bufferName, llvm::Type *type = nullptr, unsigned int constantBufferSize = 0);
- unsigned int AddAliasedHandle(Module &M, unsigned int baseRegisterIndex, unsigned int registerSpace, DXIL::ResourceClass resClass, DXIL::ResourceKind resKind, const std::string &bufferName, llvm::Type *type);
- unsigned int AddCBufferAliasedHandle(Module &M, unsigned int baseRegisterIndex, unsigned int registerSpace, const std::string &bufferName);
- llvm::Value *CreateOffsetToShaderRecord(Module &M, IRBuilder<> &Builder, unsigned int RecordOffsetInBytes, llvm::Value *CbufferOffsetInBytes);
- llvm::Value *CreateShaderRecordBufferLoad(Module &M, IRBuilder<> &Builder, llvm::Value *ShaderRecordOffsetInBytes, llvm::Type* type);
- llvm::Value *CreateCBufferLoadOffsetInBytes(Module &M, IRBuilder<> &Builder, llvm::Instruction *instruction);
- llvm::Value *CreateCBufferLoadLegacy(Module &M, IRBuilder<> &Builder, llvm::Value *ResourceHandle, unsigned int RowToLoad = 0);
- llvm::Value *LoadShaderRecordData(Module &M, IRBuilder<> &Builder,
- llvm::Value *offsetToShaderRecord,
- unsigned int dataOffsetInShaderRecord);
- void PatchCreateHandleToUseDescriptorIndex(
- _In_ Module &M,
- _In_ IRBuilder<> &Builder,
- _In_ DXIL::ResourceKind &resourceKind,
- _In_ DXIL::ResourceClass &resourceClass,
- _In_ llvm::Type *resourceType,
- _In_ llvm::Value *descriptorIndex,
- _Inout_ DxilInst_CreateHandleForLib &createHandleInstr);
- bool GetHandleInfo(
- Module &M,
- DxilInst_CreateHandleForLib &createHandleStructForLib,
- _Out_ unsigned int &shaderRegister,
- _Out_ unsigned int ®isterSpace,
- _Out_ DXIL::ResourceKind &kind,
- _Out_ DXIL::ResourceClass &resClass,
- _Out_ llvm::Type *&resType);
- llvm::Value * GetAliasedDescriptorHeapHandle(Module &M, llvm::Type *, DXIL::ResourceClass resClass, DXIL::ResourceKind resKind);
- unsigned int GetConstantBufferOffsetToShaderRecord();
- bool IsCBufferLoad(llvm::Instruction *instruction);
- // Unlike the LLVM version of this function, this does not requires the InstructionToReplace and the ValueToReplaceWith to be the same instruction type
- static void ReplaceUsesOfWith(llvm::Instruction *InstructionToReplace, llvm::Value *ValueToReplaceWith);
- static ShaderRecordEntry FindRootSignatureDescriptor(const DxilVersionedRootSignatureDesc &rootSignatureDescriptor, unsigned int ShaderRecordIdentifierSizeInBytes, DXIL::ResourceClass resourceClass, unsigned int baseRegisterIndex, unsigned int registerSpace);
- // TODO: I would like to see these prefixed with m_
- llvm::Value *ShaderTableHandle = nullptr;
- llvm::Value *DispatchRaysConstantsHandle = nullptr;
- llvm::Value *BaseShaderRecordOffset = nullptr;
- static const unsigned int NumViewTypes = 4;
- struct ViewKeyHasher
- {
- public:
- std::size_t operator()(const ViewKey &x) const {
- return std::hash<unsigned int>()((unsigned int)x.ViewType) ^
- std::hash<unsigned int>()((unsigned int)x.StructuredStride);
- }
- };
- std::unordered_map<ViewKey, llvm::Value *, ViewKeyHasher>
- TypeToAliasedDescriptorHeap[NumViewTypes];
- llvm::Function *EntryPointFunction;
- ShaderInfo *pInputShaderInfo;
- DxilVersionedRootSignatureDesc *pRootSignatureDesc;
- DXIL::ShaderKind ShaderKind;
- };
- char DxilPatchShaderRecordBindings::ID = 0;
- // TODO: Find the right thing to do on failure
- void ThrowFailure() {
- throw std::exception();
- }
- // TODO: Stolen from Brandon's code, merge
- // Remove ELF mangling
- static inline std::string GetUnmangledName(StringRef name) {
- if (!name.startswith("\x1?"))
- return name;
- size_t pos = name.find("@@");
- if (pos == name.npos)
- return name;
- return name.substr(2, pos - 2);
- }
- static Function* getFunctionFromName(Module &M, const std::wstring& exportName) {
- for (auto F = M.begin(), E = M.end(); F != E; ++F) {
- std::wstring functionName = Unicode::UTF8ToUTF16StringOrThrow(GetUnmangledName(F->getName()).c_str());
- if (exportName == functionName) {
- return F;
- }
- }
- return nullptr;
- }
- ModulePass *llvm::createDxilPatchShaderRecordBindingsPass() {
- return new DxilPatchShaderRecordBindings();
- }
- INITIALIZE_PASS(DxilPatchShaderRecordBindings, "hlsl-dxil-patch-shader-record-bindings", "Patch shader record bindings to instead pull from the fallback provided bindings", false, false)
- void DxilPatchShaderRecordBindings::applyOptions(PassOptions O) {
- for (const auto & option : O) {
- if (0 == option.first.compare("root-signature")) {
- unsigned int cHexRadix = 16;
- pInputShaderInfo = (ShaderInfo*)strtoull(option.second.data(), nullptr, cHexRadix);
- pRootSignatureDesc = (DxilVersionedRootSignatureDesc*)pInputShaderInfo->pRootSignatureDesc;
- }
- }
- }
- void AddAnnoationsIfNeeded(DxilModule &DM, llvm::StructType *StructTy, const std::string &FieldName, unsigned int numFields = 1)
- {
- auto pAnnotation = DM.GetTypeSystem().GetStructAnnotation(StructTy);
- if (pAnnotation == nullptr)
- {
- pAnnotation = DM.GetTypeSystem().AddStructAnnotation(StructTy);
- pAnnotation->SetCBufferSize(sizeof(uint32_t) * numFields);
- for (unsigned int i = 0; i < numFields; i++)
- {
- pAnnotation->GetFieldAnnotation(i).SetCBufferOffset(sizeof(uint32_t) * i);
- pAnnotation->GetFieldAnnotation(i).SetCompType(hlsl::DXIL::ComponentType::I32);
- pAnnotation->GetFieldAnnotation(i).SetFieldName(FieldName + std::to_string(i));
- }
- }
- }
- unsigned int DxilPatchShaderRecordBindings::AddHandle(Module &M, unsigned int baseRegisterIndex, unsigned int rangeSize, unsigned int registerSpace, DXIL::ResourceClass resClass, DXIL::ResourceKind resKind, const std::string &bufferName, llvm::Type *type, unsigned int constantBufferSize) {
- LLVMContext & Ctx = M.getContext();
- DxilModule &DM = M.GetOrCreateDxilModule();
- // Set up a SRV with byte address buffer
- unsigned int resourceHandle;
- std::unique_ptr<DxilResource> pHandle;
- std::unique_ptr<DxilCBuffer> pCBuf;
- std::unique_ptr<DxilSampler> pSampler;
- DxilResourceBase *pBaseHandle;
- switch (resClass) {
- case DXIL::ResourceClass::SRV:
- resourceHandle = static_cast<unsigned int>(DM.GetSRVs().size());
- pHandle = llvm::make_unique<DxilResource>();
- pHandle->SetRW(false);
- pBaseHandle = pHandle.get();
- break;
- case DXIL::ResourceClass::UAV:
- resourceHandle = static_cast<unsigned int>(DM.GetUAVs().size());
- pHandle = llvm::make_unique<DxilResource>();
- pHandle->SetRW(true);
- pBaseHandle = pHandle.get();
- break;
- case DXIL::ResourceClass::CBuffer:
- resourceHandle = static_cast<unsigned int>(DM.GetCBuffers().size());
- pCBuf = llvm::make_unique<DxilCBuffer>();
- pCBuf->SetSize(constantBufferSize);
- pBaseHandle = pCBuf.get();
- break;
- case DXIL::ResourceClass::Sampler:
- resourceHandle = static_cast<unsigned int>(DM.GetSamplers().size());
- pSampler = llvm::make_unique<DxilSampler>();
- // TODO: Is this okay? What if one of the samplers in the table is a comparison sampler?
- pSampler->SetSamplerKind(DxilSampler::SamplerKind::Default);
- pBaseHandle = pSampler.get();
- break;
- }
- if (!type) {
- SmallVector<llvm::Type*, 1> Elements{ Type::getInt32Ty(Ctx) };
- std::string ByteAddressBufferName = "struct.ByteAddressBuffer";
- type = M.getTypeByName(ByteAddressBufferName);
- if (!type)
- {
- StructType *StructTy;
- type = StructTy = StructType::create(Elements, ByteAddressBufferName);
-
- AddAnnoationsIfNeeded(DM, StructTy, ByteAddressBufferName);
- }
- }
- GlobalVariable *GV = M.getGlobalVariable(bufferName);
- if (!GV) {
- GV = cast<GlobalVariable>(M.getOrInsertGlobal(bufferName, type));
- }
- pBaseHandle->SetGlobalName(bufferName.c_str());
- pBaseHandle->SetGlobalSymbol(GV);
- pBaseHandle->SetID(resourceHandle);
- pBaseHandle->SetSpaceID(registerSpace);
- pBaseHandle->SetLowerBound(baseRegisterIndex);
- pBaseHandle->SetRangeSize(rangeSize);
- pBaseHandle->SetKind(resKind);
- if (pHandle) {
- pHandle->SetGloballyCoherent(false);
- pHandle->SetHasCounter(false);
- pHandle->SetCompType(CompType::getF32()); // TODO: Need to handle all types
- }
- unsigned int ID;
- switch (resClass) {
- case DXIL::ResourceClass::SRV:
- ID = DM.AddSRV(std::move(pHandle));
- break;
- case DXIL::ResourceClass::UAV:
- ID = DM.AddUAV(std::move(pHandle));
- break;
- case DXIL::ResourceClass::CBuffer:
- ID = DM.AddCBuffer(std::move(pCBuf));
- break;
- case DXIL::ResourceClass::Sampler:
- ID = DM.AddSampler(std::move(pSampler));
- break;
- }
- assert(ID == resourceHandle);
- return ID;
- }
- unsigned int DxilPatchShaderRecordBindings::GetConstantBufferOffsetToShaderRecord()
- {
- switch (ShaderKind)
- {
- case DXIL::ShaderKind::ClosestHit:
- case DXIL::ShaderKind::AnyHit:
- case DXIL::ShaderKind::Intersection:
- return offsetof(DispatchRaysConstants, HitGroupShaderRecordStride);
- case DXIL::ShaderKind::Miss:
- return offsetof(DispatchRaysConstants, MissShaderRecordStride);
- default:
- ThrowFailure();
- return -1;
- }
- }
- unsigned int DxilPatchShaderRecordBindings::AddSRVRawBuffer(Module &M, unsigned int registerIndex, unsigned int registerSpace, const std::string &bufferName) {
- return AddHandle(M, registerIndex, 1, registerSpace, DXIL::ResourceClass::SRV, DXIL::ResourceKind::RawBuffer, bufferName);
- }
- llvm::Constant *GetArraySymbol(Module &M, const std::string &bufferName) {
- LLVMContext & Ctx = M.getContext();
- SmallVector<llvm::Type*, 1> Elements{ Type::getInt32Ty(Ctx) };
- llvm::StructType *StructTy = llvm::StructType::create(Elements, bufferName);
- llvm::ArrayType *ArrayTy = ArrayType::get(StructTy, -1);
- return UndefValue::get(ArrayTy->getPointerTo());
- }
- unsigned int DxilPatchShaderRecordBindings::AddCBufferAliasedHandle(Module &M, unsigned int baseRegisterIndex, unsigned int registerSpace, const std::string &bufferName) {
- const unsigned int maxConstantBufferSize = 4096 * 16;
- return AddHandle(M, baseRegisterIndex, UINT_MAX, registerSpace, DXIL::ResourceClass::CBuffer, DXIL::ResourceKind::CBuffer, bufferName, GetArraySymbol(M, bufferName)->getType(), maxConstantBufferSize);
- }
- unsigned int DxilPatchShaderRecordBindings::AddAliasedHandle(Module &M, unsigned int baseRegisterIndex, unsigned int registerSpace, DXIL::ResourceClass resClass, DXIL::ResourceKind resKind, const std::string &bufferName, llvm::Type *type) {
- return AddHandle(M, baseRegisterIndex, UINT_MAX, registerSpace, resClass, resKind, bufferName, type);
- }
- // TODO: Stolen from Brandon's code
- DXIL::ShaderKind GetRayShaderKindCopy(Function* F)
- {
- if (F->hasFnAttribute("exp-shader"))
- return DXIL::ShaderKind::RayGeneration;
- DxilModule& DM = F->getParent()->GetDxilModule();
- if (DM.HasDxilFunctionProps(F) && DM.GetDxilFunctionProps(F).IsRay())
- return DM.GetDxilFunctionProps(F).shaderKind;
- return DXIL::ShaderKind::Invalid;
- }
- static std::string ws2s(const std::wstring& wide)
- {
- return std::string(wide.begin(), wide.end());
- }
- bool DxilPatchShaderRecordBindings::runOnModule(Module &M) {
- DxilModule &DM = M.GetOrCreateDxilModule();
- EntryPointFunction = pInputShaderInfo->ExportName ? getFunctionFromName(M, pInputShaderInfo->ExportName) : DM.GetEntryFunction();
- ShaderKind = GetRayShaderKindCopy(EntryPointFunction);
- ValidateParameters();
- InitializeViewTable();
- PatchShaderBindings(M);
- DM.ReEmitDxilResources();
- return true;
- }
- void DxilPatchShaderRecordBindings::ValidateParameters() {
- if (!pInputShaderInfo || !pInputShaderInfo->pRootSignatureDesc) {
- throw std::exception();
- }
- }
- DxilResourceBase &GetResourceFromID(DxilModule &DM, DXIL::ResourceClass resClass, unsigned int id)
- {
- switch (resClass)
- {
- case DXIL::ResourceClass::CBuffer:
- return DM.GetCBuffer(id);
- break;
- case DXIL::ResourceClass::SRV:
- return DM.GetSRV(id);
- break;
- case DXIL::ResourceClass::UAV:
- return DM.GetUAV(id);
- break;
- case DXIL::ResourceClass::Sampler:
- return DM.GetSampler(id);
- break;
- default:
- ThrowFailure();
- return *(DxilResourceBase*)nullptr;
- }
- }
- unsigned int FindOrInsertViewIntoList(const ViewKey &key, ViewKey *pViewList, unsigned int &numViews, unsigned int maxViews)
- {
- unsigned int viewIndex = 0;
- for (; viewIndex < numViews; viewIndex++)
- {
- if (pViewList[viewIndex] == key)
- {
- break;
- }
- }
- if (viewIndex == numViews)
- {
- if (viewIndex >= maxViews) {
- ThrowFailure();
- }
- pViewList[viewIndex] = key;
- numViews++;
- }
- return viewIndex;
- }
- llvm::Value *DxilPatchShaderRecordBindings::GetAliasedDescriptorHeapHandle(Module &M, llvm::Type *type, DXIL::ResourceClass resClass, DXIL::ResourceKind resKind)
- {
- DxilModule &DM = M.GetOrCreateDxilModule();
- unsigned int resClassIndex = (unsigned int)resClass;
-
- ViewKey key = {};
- key.ViewType = (unsigned int)resKind;
- if (resKind == DXIL::ResourceKind::StructuredBuffer)
- {
- key.StructuredStride = type->getPrimitiveSizeInBits();
- } else if (resKind != DXIL::ResourceKind::RawBuffer)
- {
- auto containedType = type->getContainedType(0);
- // If it's a vector, get the type of just a single element
- if (containedType->getNumContainedTypes() > 0)
- {
- assert(containedType->getNumContainedTypes() <= 4);
- containedType = containedType->getContainedType(0);
- }
- key.SRVComponentType = (unsigned int)CompType::GetCompType(containedType).GetKind();
- }
- auto aliasedDescriptorHeapHandle = TypeToAliasedDescriptorHeap[resClassIndex].find(key);
- if (aliasedDescriptorHeapHandle == TypeToAliasedDescriptorHeap[resClassIndex].end())
- {
- unsigned int registerSpaceOffset = 0;
- std::string HandleName;
- if (resClass == DXIL::ResourceClass::SRV)
- {
- registerSpaceOffset = FindOrInsertViewIntoList(
- key,
- pInputShaderInfo->pSRVRegisterSpaceArray,
- *pInputShaderInfo->pNumSRVSpaces,
- FallbackLayerNumDescriptorHeapSpacesPerView);
- HandleName = std::string("SRVDescriptorHeapTable") +
- std::to_string(registerSpaceOffset);
- }
- else if (resClass == DXIL::ResourceClass::UAV)
- {
- registerSpaceOffset = FindOrInsertViewIntoList(
- key,
- pInputShaderInfo->pUAVRegisterSpaceArray,
- *pInputShaderInfo->pNumUAVSpaces,
- FallbackLayerNumDescriptorHeapSpacesPerView);
- if (registerSpaceOffset == 0)
- {
- // Using the descriptor heap declared by the fallback for handling emulated pointers,
- // make sure the name is an exact match
- assert(key.ViewType == (unsigned int)hlsl::DXIL::ResourceKind::RawBuffer);
- HandleName = "\01?DescriptorHeapBufferTable@@3PAURWByteAddressBuffer@@A";
- }
- else
- {
- HandleName = std::string("UAVDescriptorHeapTable") +
- std::to_string(registerSpaceOffset);
- }
- }
- else if (resClass == DXIL::ResourceClass::CBuffer)
- {
- HandleName = std::string("CBVDescriptorHeapTable");
- } else {
- HandleName = std::string("SamplerDescriptorHeapTable");
- }
- llvm::ArrayType *descriptorHeapType = ArrayType::get(type, 0);
- static unsigned int i = 0;
- unsigned int id = AddAliasedHandle(M, FallbackLayerDescriptorHeapTable, FallbackLayerRegisterSpace + FallbackLayerDescriptorHeapSpaceOffset + registerSpaceOffset, resClass, resKind, HandleName, descriptorHeapType);
-
- TypeToAliasedDescriptorHeap[resClassIndex][key] = GetResourceFromID(DM, resClass, id).GetGlobalSymbol();
- }
- return TypeToAliasedDescriptorHeap[resClassIndex][key];
- }
- void DxilPatchShaderRecordBindings::AddInputBinding(Module &M) {
- DxilModule &DM = M.GetOrCreateDxilModule();
- auto & EntryBlock = EntryPointFunction->getEntryBlock();
- auto & Instructions = EntryBlock.getInstList();
- std::string bufferName;
- unsigned int bufferRegister;
- switch (ShaderKind) {
- case DXIL::ShaderKind::AnyHit:
- case DXIL::ShaderKind::ClosestHit:
- case DXIL::ShaderKind::Intersection:
- bufferRegister = FallbackLayerHitGroupRecordByteAddressBufferRegister;
- bufferName = "\01?HitGroupShaderTable@@3UByteAddressBuffer@@A";
- break;
- case DXIL::ShaderKind::Miss:
- bufferRegister = FallbackLayerMissShaderRecordByteAddressBufferRegister;
- bufferName = "\01?MissShaderTable@@3UByteAddressBuffer@@A";
- break;
- case DXIL::ShaderKind::RayGeneration:
- bufferRegister = FallbackLayerRayGenShaderRecordByteAddressBufferRegister;
- bufferName = "\01?RayGenShaderTable@@3UByteAddressBuffer@@A";
- break;
- case DXIL::ShaderKind::Callable:
- bufferRegister = FallbackLayerCallableShaderRecordByteAddressBufferRegister;
- bufferName = "\01?CallableShaderTable@@3UByteAddressBuffer@@A";
- break;
- }
- unsigned int ShaderRecordID = AddSRVRawBuffer(M, bufferRegister, FallbackLayerRegisterSpace, bufferName);
- auto It = Instructions.begin();
- OP *HlslOP = DM.GetOP();
- LLVMContext & Ctx = M.getContext();
- IRBuilder<> Builder(It);
- {
- auto ShaderTableName = "ShaderTableHandle";
- llvm::Value *Symbol = DM.GetSRV(ShaderRecordID).GetGlobalSymbol();
- llvm::Value *Load = Builder.CreateLoad(Symbol, "LoadShaderTableHandle");
- Function *CreateHandleForLib = HlslOP->GetOpFunc(DXIL::OpCode::CreateHandleForLib, Load->getType());
- Constant *CreateHandleOpcodeArg = HlslOP->GetU32Const((unsigned)DXIL::OpCode::CreateHandleForLib);
- ShaderTableHandle = Builder.CreateCall(CreateHandleForLib, { CreateHandleOpcodeArg, Load }, ShaderTableName);
- }
- {
- auto CbufferName = "Constants";
- const unsigned int sizeOfConstantsInBytes = sizeof(DispatchRaysConstants);
- llvm::StructType *StructTy= M.getTypeByName(CbufferName);
- if (!StructTy)
- {
- const unsigned int numUintsInConstants = sizeOfConstantsInBytes / sizeof(unsigned int);
- SmallVector<llvm::Type*, numUintsInConstants> Elements(numUintsInConstants);
- for (unsigned int i = 0; i < numUintsInConstants; i++)
- {
- Elements[i] = Type::getInt32Ty(Ctx);
- }
- StructTy = llvm::StructType::create(Elements, CbufferName);
- AddAnnoationsIfNeeded(DM, StructTy, std::string(CbufferName), numUintsInConstants);
- }
- unsigned int handle = AddHandle(M, FallbackLayerDispatchConstantsRegister, 1, FallbackLayerRegisterSpace, DXIL::ResourceClass::CBuffer, DXIL::ResourceKind::CBuffer, CbufferName, StructTy, sizeOfConstantsInBytes);
- llvm::Value *Symbol = DM.GetCBuffer(handle).GetGlobalSymbol();
- llvm::Value *Load = Builder.CreateLoad(Symbol, "DispatchRaysConstants");
- Function *CreateHandleForLib = HlslOP->GetOpFunc(DXIL::OpCode::CreateHandleForLib, Load->getType());
- Constant *CreateHandleOpcodeArg = HlslOP->GetU32Const((unsigned)DXIL::OpCode::CreateHandleForLib);
- DispatchRaysConstantsHandle = Builder.CreateCall(CreateHandleForLib, { CreateHandleOpcodeArg, Load }, CbufferName);
- }
-
- // Raygen always reads from the start so no offset calculations needed
- if (ShaderKind != DXIL::ShaderKind::RayGeneration)
- {
- std::string ShaderRecordOffsetFuncName = "\x1?Fallback_ShaderRecordOffset@@YAIXZ";
- Function *ShaderRecordOffsetFunc = M.getFunction(ShaderRecordOffsetFuncName);
- if (!ShaderRecordOffsetFunc)
- {
- FunctionType *ShaderRecordOffsetFuncType = FunctionType::get(llvm::Type::getInt32Ty(Ctx), {}, false);
- ShaderRecordOffsetFunc = Function::Create(ShaderRecordOffsetFuncType, GlobalValue::LinkageTypes::ExternalLinkage, ShaderRecordOffsetFuncName, &M);
- }
- BaseShaderRecordOffset = Builder.CreateCall(ShaderRecordOffsetFunc, {}, "shaderRecordOffset");
- }
- else
- {
- BaseShaderRecordOffset = HlslOP->GetU32Const(0);
- }
- }
- llvm::Value *DxilPatchShaderRecordBindings::CreateOffsetToShaderRecord(Module &M, IRBuilder<> &Builder, unsigned int RecordOffsetInBytes, llvm::Value *CbufferOffsetInBytes) {
- DxilModule &DM = M.GetOrCreateDxilModule();
- OP *HlslOP = DM.GetOP();
- // Create handle for the newly-added constant buffer (which is achieved via a function call)
- auto AdddName = "ShaderRecordOffsetInBytes";
- Constant *ShaderRecordOffsetInBytes = HlslOP->GetU32Const(RecordOffsetInBytes); // Offset of constants in shader record buffer
- return Builder.CreateAdd(CbufferOffsetInBytes, ShaderRecordOffsetInBytes, AdddName);
- }
- llvm::Value *DxilPatchShaderRecordBindings::CreateCBufferLoadLegacy(Module &M, IRBuilder<> &Builder, llvm::Value *ResourceHandle, unsigned int RowToLoad) {
- DxilModule &DM = M.GetOrCreateDxilModule();
- OP *HlslOP = DM.GetOP();
- LLVMContext & Ctx = M.getContext();
- auto BufferLoadName = "ConstantBuffer";
- Function *BufferLoad = HlslOP->GetOpFunc(DXIL::OpCode::CBufferLoadLegacy, Type::getInt32Ty(Ctx));
- Constant *CBufferLoadOpcodeArg = HlslOP->GetU32Const((unsigned)DXIL::OpCode::CBufferLoadLegacy);
- Constant *RowToLoadConst = HlslOP->GetU32Const(RowToLoad);
- return Builder.CreateCall(BufferLoad, { CBufferLoadOpcodeArg, ResourceHandle, RowToLoadConst }, BufferLoadName);
- }
- llvm::Value *DxilPatchShaderRecordBindings::CreateShaderRecordBufferLoad(Module &M, IRBuilder<> &Builder, llvm::Value *ShaderRecordOffsetInBytes, llvm::Type* type) {
- DxilModule &DM = M.GetOrCreateDxilModule();
- OP *HlslOP = DM.GetOP();
- LLVMContext & Ctx = M.getContext();
- // Create handle for the newly-added constant buffer (which is achieved via a function call)
- auto BufferLoadName = "ShaderRecordBuffer";
- if (type->getNumContainedTypes() > 1)
- {
- // TODO: Buffer loads aren't legal with container types, check if this is the right wait to handle this
- type = type->getContainedType(0);
- }
- // TODO Do I need to check the result? Hopefully not
- Function *BufferLoad = HlslOP->GetOpFunc(DXIL::OpCode::BufferLoad, type);
- Constant *BufferLoadOpcodeArg = HlslOP->GetU32Const((unsigned)DXIL::OpCode::BufferLoad);
- Constant *Unused = UndefValue::get(llvm::Type::getInt32Ty(Ctx));
- return Builder.CreateCall(BufferLoad, { BufferLoadOpcodeArg, ShaderTableHandle, ShaderRecordOffsetInBytes, Unused }, BufferLoadName);
- }
- void DxilPatchShaderRecordBindings::ReplaceUsesOfWith(llvm::Instruction *InstructionToReplace, llvm::Value *ValueToReplaceWith) {
- for (auto UserIter = InstructionToReplace->user_begin(); UserIter != InstructionToReplace->user_end();) {
- // Increment the iterator before the replace since the replace alters the uses list
- auto userInstr = UserIter++;
- userInstr->replaceUsesOfWith(InstructionToReplace, ValueToReplaceWith);
- }
- InstructionToReplace->eraseFromParent();
- }
- llvm::Value *DxilPatchShaderRecordBindings::CreateCBufferLoadOffsetInBytes(Module &M, IRBuilder<> &Builder, llvm::Instruction *instruction) {
- DxilModule &DM = M.GetOrCreateDxilModule();
- OP *HlslOP = DM.GetOP();
- DxilInst_CBufferLoad cbufferLoad(instruction);
- DxilInst_CBufferLoadLegacy cbufferLoadLegacy(instruction);
- if (cbufferLoad) {
- return cbufferLoad.get_byteOffset();
- } else if (cbufferLoadLegacy) {
- Constant *LegacyMultiplier = HlslOP->GetU32Const(16);
- return Builder.CreateMul(cbufferLoadLegacy.get_regIndex(), LegacyMultiplier);
- } else {
- ThrowFailure();
- return nullptr;
- }
- }
- bool DxilPatchShaderRecordBindings::IsCBufferLoad(llvm::Instruction *instruction) {
- DxilInst_CBufferLoad cbufferLoad(instruction);
- DxilInst_CBufferLoadLegacy cbufferLoadLegacy(instruction);
- return cbufferLoad || cbufferLoadLegacy;
- }
- const unsigned int GetResolvedRangeID(DXIL::ResourceClass resClass, Value *rangeIdVal)
- {
- if (auto CI = dyn_cast<ConstantInt>(rangeIdVal))
- {
- return CI->getZExtValue();
- }
- else
- {
- assert(false);
- return 0;
- }
- }
- // TODO: This code is quite inefficient
- bool DxilPatchShaderRecordBindings::GetHandleInfo(
- Module &M,
- DxilInst_CreateHandleForLib &createHandleStructForLib,
- _Out_ unsigned int &shaderRegister,
- _Out_ unsigned int ®isterSpace,
- _Out_ DXIL::ResourceKind &kind,
- _Out_ DXIL::ResourceClass &resClass,
- _Out_ llvm::Type *&resType)
- {
- DxilModule &DM = M.GetOrCreateDxilModule();
- LoadInst *loadRangeId = cast<LoadInst>(createHandleStructForLib.get_Resource());
- Value *ResourceSymbol = loadRangeId->getPointerOperand();
- DXIL::ResourceClass resourceClasses[] = {
- DXIL::ResourceClass::CBuffer,
- DXIL::ResourceClass::SRV,
- DXIL::ResourceClass::UAV,
- DXIL::ResourceClass::Sampler
- };
- hlsl::DxilResourceBase *Resource = nullptr;
- for (auto &resourceClass : resourceClasses) {
-
- switch (resourceClass)
- {
- case DXIL::ResourceClass::CBuffer:
- {
- auto &cbuffers = DM.GetCBuffers();
- for (auto &cbuffer : cbuffers)
- {
- if (cbuffer->GetGlobalSymbol() == ResourceSymbol)
- {
- Resource = cbuffer.get();
- break;
- }
- }
- break;
- }
- case DXIL::ResourceClass::SRV:
- case DXIL::ResourceClass::UAV:
- {
- auto &viewList = resourceClass == DXIL::ResourceClass::SRV ? DM.GetSRVs() : DM.GetUAVs();
- for (auto &view : viewList)
- {
- if (view->GetGlobalSymbol() == ResourceSymbol)
- {
- Resource = view.get();
- break;
- }
- }
- break;
- }
- case DXIL::ResourceClass::Sampler:
- {
- auto &samplers = DM.GetSamplers();
- for (auto &sampler : samplers)
- {
- if (sampler->GetGlobalSymbol() == ResourceSymbol)
- {
- Resource = sampler.get();
- break;
- }
- }
- break;
- }
- }
- }
- if (Resource)
- {
- registerSpace = Resource->GetSpaceID();
- shaderRegister = Resource->GetLowerBound();
- kind = Resource->GetKind();
- resClass = Resource->GetClass();
- resType = cast<GlobalVariable>(Resource->GetGlobalSymbol())->getType()->getPointerElementType();
- }
- return Resource != nullptr;
- }
- llvm::Value *DxilPatchShaderRecordBindings::LoadShaderRecordData(
- Module &M,
- IRBuilder<> &Builder,
- llvm::Value *offsetToShaderRecord,
- unsigned int dataOffsetInShaderRecord)
- {
- DxilModule &DM = M.GetOrCreateDxilModule();
- LLVMContext &Ctx = M.getContext();
- OP *HlslOP = DM.GetOP();
- Constant *dataOffset =
- HlslOP->GetU32Const(dataOffsetInShaderRecord);
- Value *shaderTableOffsetToData = Builder.CreateAdd(dataOffset, offsetToShaderRecord);
- return CreateShaderRecordBufferLoad(M, Builder, shaderTableOffsetToData,
- llvm::Type::getInt32Ty(Ctx));
- }
- void DxilPatchShaderRecordBindings::PatchCreateHandleToUseDescriptorIndex(
- _In_ Module &M,
- _In_ IRBuilder<> &Builder,
- _In_ DXIL::ResourceKind &resourceKind,
- _In_ DXIL::ResourceClass &resourceClass,
- _In_ llvm::Type *resourceType,
- _In_ llvm::Value *descriptorIndex,
- _Inout_ DxilInst_CreateHandleForLib &createHandleInstr)
- {
- DxilModule &DM = M.GetOrCreateDxilModule();
- OP *HlslOP = DM.GetOP();
- llvm::Value *descriptorHeapSymbol = GetAliasedDescriptorHeapHandle(M, resourceType, resourceClass, resourceKind);
- llvm::Value *viewSymbol = Builder.CreateGEP(descriptorHeapSymbol, { HlslOP->GetU32Const(0), descriptorIndex }, "IndexIntoDH");
- DxilMDHelper::MarkNonUniform(cast<Instruction>(viewSymbol));
- llvm::Value *handle = Builder.CreateLoad(viewSymbol);
- auto callInst = cast<CallInst>(createHandleInstr.Instr);
- callInst->setCalledFunction(HlslOP->GetOpFunc(
- DXIL::OpCode::CreateHandleForLib,
- handle->getType()));
- createHandleInstr.set_Resource(handle);
- }
- void DxilPatchShaderRecordBindings::InitializeViewTable() {
- // The Fallback Layer declares a bindless raw buffer that spans the entire descriptor heap,
- // manually add it to the list of UAV register spaces used
- if (*pInputShaderInfo->pNumUAVSpaces == 0)
- {
- ViewKey key = { (unsigned int)hlsl::DXIL::ResourceKind::RawBuffer, 0 };
- unsigned int index = FindOrInsertViewIntoList(
- key,
- pInputShaderInfo->pUAVRegisterSpaceArray,
- *pInputShaderInfo->pNumUAVSpaces,
- FallbackLayerNumDescriptorHeapSpacesPerView);
- (void)index;
- assert(index == 0);
- }
- }
- void DxilPatchShaderRecordBindings::PatchShaderBindings(Module &M) {
- DxilModule &DM = M.GetOrCreateDxilModule();
- OP *HlslOP = DM.GetOP();
- // Don't erase instructions until the very end because it throws off the iterator
- std::vector<llvm::Instruction *> instructionsToRemove;
- for (BasicBlock &block : EntryPointFunction->getBasicBlockList()) {
- auto & Instructions = block.getInstList();
- auto It = Instructions.begin();
- for (auto &instr : Instructions) {
- DxilInst_CreateHandleForLib createHandleForLib(&instr);
- if (createHandleForLib) {
- DXIL::ResourceClass resourceClass;
- unsigned int registerSpace;
- unsigned int registerIndex;
- DXIL::ResourceKind kind;
- llvm::Type *resType;
- bool resourceIsResolved = true;
- resourceIsResolved = GetHandleInfo(M, createHandleForLib, registerIndex, registerSpace, kind, resourceClass, resType);
- if (!resourceIsResolved) continue; // TODO: This shouldn't actually be happening?
- ShaderRecordEntry shaderRecord = FindRootSignatureDescriptor(
- *pRootSignatureDesc,
- pInputShaderInfo->ShaderRecordIdentifierSizeInBytes,
- resourceClass,
- registerIndex,
- registerSpace);
- const bool IsBindingSpecifiedInLocalRootSignature = !shaderRecord.IsInvalid();
- if (IsBindingSpecifiedInLocalRootSignature) {
- if (!DispatchRaysConstantsHandle) {
- AddInputBinding(M);
- }
- switch (shaderRecord.ParameterType) {
- case DxilRootParameterType::Constants32Bit:
- {
- for (User *U : instr.users()) {
- llvm::Instruction *instruction = cast<CallInst>(U);
- if (IsCBufferLoad(instruction)) {
- llvm::Instruction *cbufferLoadInstr = instruction;
- IRBuilder<> Builder(cbufferLoadInstr);
- llvm::Value * cbufferOffsetInBytes = CreateCBufferLoadOffsetInBytes(M, Builder, cbufferLoadInstr);
- llvm::Value *LocalOffsetToRootConstant = CreateOffsetToShaderRecord(M, Builder, shaderRecord.RecordOffsetInBytes, cbufferOffsetInBytes);
- llvm::Value *GlobalOffsetToRootConstant = Builder.CreateAdd(LocalOffsetToRootConstant, BaseShaderRecordOffset);
- llvm::Value *srvBufferLoad = CreateShaderRecordBufferLoad(M, Builder, GlobalOffsetToRootConstant, cbufferLoadInstr->getType());
- ReplaceUsesOfWith(cbufferLoadInstr, srvBufferLoad);
- } else {
- ThrowFailure();
- }
- }
- instructionsToRemove.push_back(&instr);
- break;
- }
- case DxilRootParameterType::DescriptorTable:
- {
- IRBuilder<> Builder(&instr);
- llvm::Value *srvBufferLoad = LoadShaderRecordData(
- M,
- Builder,
- BaseShaderRecordOffset,
- shaderRecord.RecordOffsetInBytes);
- llvm::Value *DescriptorTableEntryLo = Builder.CreateExtractValue(srvBufferLoad, 0, "DescriptorTableHandleLo");
- unsigned int offsetToLoadInUints = offsetof(DispatchRaysConstants, SrvCbvUavDescriptorHeapStart) / sizeof(uint32_t);
- unsigned int uintsPerRow = 4;
- unsigned int rowToLoad = offsetToLoadInUints / uintsPerRow;
- unsigned int extractValueOffset = offsetToLoadInUints % uintsPerRow;
- llvm::Value *DescHeapConstants = CreateCBufferLoadLegacy(M, Builder, DispatchRaysConstantsHandle, rowToLoad);
- llvm::Value *DescriptorHeapStartAddressLo = Builder.CreateExtractValue(DescHeapConstants, extractValueOffset, "DescriptorHeapStartHandleLo");
- // TODO: The hi bits can only be ignored if the difference is guaranteed to be < 32 bytes. This is an unsafe assumption, particularly given
- // large descriptor sizes
- llvm::Value *DescriptorTableOffsetInBytes = Builder.CreateSub(DescriptorTableEntryLo, DescriptorHeapStartAddressLo, "TableOffsetInBytes");
- Constant *DescriptorSizeInBytes = HlslOP->GetU32Const(pInputShaderInfo->SrvCbvUavDescriptorSizeInBytes);
- llvm::Value * DescriptorTableStartIndex = Builder.CreateExactUDiv(DescriptorTableOffsetInBytes, DescriptorSizeInBytes, "TableStartIndex");
- Constant *RecordOffset = HlslOP->GetU32Const(shaderRecord.OffsetInDescriptors);
- llvm::Value * BaseDescriptorIndex = Builder.CreateAdd(DescriptorTableStartIndex, RecordOffset, "BaseDescriptorIndex");
- // TODO: Not supporting dynamic indexing yet, should be pulled from CreateHandleForLib
- // If dynamic indexing is being used, add the apps index on top of the calculated index
- llvm::Value * DynamicIndex = HlslOP->GetU32Const(0);
- llvm::Value * DescriptorIndex = Builder.CreateAdd(BaseDescriptorIndex, DynamicIndex, "DescriptorIndex");
- PatchCreateHandleToUseDescriptorIndex(
- M,
- Builder,
- kind,
- resourceClass,
- resType,
- DescriptorIndex,
- createHandleForLib);
- break;
- }
- case DxilRootParameterType::CBV:
- case DxilRootParameterType::SRV:
- case DxilRootParameterType::UAV: {
- IRBuilder<> Builder(&instr);
- llvm::Value *srvBufferLoad = LoadShaderRecordData(
- M,
- Builder,
- BaseShaderRecordOffset,
- shaderRecord.RecordOffsetInBytes);
- llvm::Value *DescriptorIndex = Builder.CreateExtractValue(
- srvBufferLoad, 1, "DescriptorHeapIndex");
- // TODO: Handle offset in bytes
- // llvm::Value *OffsetInBytes = Builder.CreateExtractValue(
- // srvBufferLoad, 0, "OffsetInBytes");
- PatchCreateHandleToUseDescriptorIndex(
- M,
- Builder,
- kind,
- resourceClass,
- resType,
- DescriptorIndex,
- createHandleForLib);
- break;
- }
- default:
- ThrowFailure();
- break;
- }
- }
- }
- }
- }
- for (auto instruction : instructionsToRemove) {
- instruction->eraseFromParent();
- }
- }
- bool IsParameterTypeCompatibleWithResourceClass(
- DXIL::ResourceClass resourceClass,
- DxilRootParameterType parameterType) {
- switch (parameterType) {
- case DxilRootParameterType::DescriptorTable:
- return true;
- case DxilRootParameterType::Constants32Bit:
- case DxilRootParameterType::CBV:
- return resourceClass == DXIL::ResourceClass::CBuffer;
- case DxilRootParameterType::SRV:
- return resourceClass == DXIL::ResourceClass::SRV;
- case DxilRootParameterType::UAV:
- return resourceClass == DXIL::ResourceClass::UAV;
- default:
- ThrowFailure();
- return false;
- }
- }
- DxilRootParameterType ConvertD3D12ParameterTypeToDxil(DxilRootParameterType parameter) {
- switch (parameter) {
- case DxilRootParameterType::Constants32Bit:
- return DxilRootParameterType::Constants32Bit;
- case DxilRootParameterType::DescriptorTable:
- return DxilRootParameterType::DescriptorTable;
- case DxilRootParameterType::CBV:
- return DxilRootParameterType::CBV;
- case DxilRootParameterType::SRV:
- return DxilRootParameterType::SRV;
- case DxilRootParameterType::UAV:
- return DxilRootParameterType::UAV;
- }
- assert(false);
- return (DxilRootParameterType)-1;
- }
- DXIL::ResourceClass ConvertD3D12RangeTypeToDxil(DxilDescriptorRangeType rangeType) {
- switch (rangeType) {
- case DxilDescriptorRangeType::SRV:
- return DXIL::ResourceClass::SRV;
- case DxilDescriptorRangeType::UAV:
- return DXIL::ResourceClass::UAV;
- case DxilDescriptorRangeType::CBV:
- return DXIL::ResourceClass::CBuffer;
- case DxilDescriptorRangeType::Sampler:
- return DXIL::ResourceClass::Sampler;
- }
- assert(false);
- return (DXIL::ResourceClass) - 1;
- }
- unsigned int GetParameterTypeAlignment(DxilRootParameterType parameterType) {
- switch (parameterType) {
- case DxilRootParameterType::DescriptorTable:
- return SizeofD3D12GpuDescriptorHandle;
- case DxilRootParameterType::Constants32Bit:
- return sizeof(uint32_t);
- case DxilRootParameterType::CBV: // fallthrough
- case DxilRootParameterType::SRV: // fallthrough
- case DxilRootParameterType::UAV:
- return SizeofD3D12GpuVA;
- default:
- return UINT_MAX;
- }
- }
- template <typename TD3D12_ROOT_SIGNATURE_DESC>
- ShaderRecordEntry FindRootSignatureDescriptorHelper(
- const TD3D12_ROOT_SIGNATURE_DESC &rootSignatureDescriptor,
- unsigned int ShaderRecordIdentifierSizeInBytes,
- DXIL::ResourceClass resourceClass, unsigned int baseRegisterIndex,
- unsigned int registerSpace) {
- // Automatically fail if it's looking for a fallback binding as these never
- // need to be patched
- if (registerSpace != FallbackLayerRegisterSpace) {
- unsigned int recordOffset = ShaderRecordIdentifierSizeInBytes;
- for (unsigned int rootParamIndex = 0;
- rootParamIndex < rootSignatureDescriptor.NumParameters;
- rootParamIndex++) {
- auto &rootParam = rootSignatureDescriptor.pParameters[rootParamIndex];
- auto dxilParamType =
- ConvertD3D12ParameterTypeToDxil(rootParam.ParameterType);
- #define ALIGN(alignment, num) (((num + alignment - 1) / alignment) * alignment)
- recordOffset = ALIGN(GetParameterTypeAlignment(rootParam.ParameterType),
- recordOffset);
- switch (rootParam.ParameterType) {
- case DxilRootParameterType::Constants32Bit:
- if (IsParameterTypeCompatibleWithResourceClass(resourceClass,
- dxilParamType) &&
- baseRegisterIndex == rootParam.Constants.ShaderRegister &&
- registerSpace == rootParam.Constants.RegisterSpace) {
- return {dxilParamType, recordOffset};
- }
- recordOffset += rootParam.Constants.Num32BitValues * sizeof(uint32_t);
- break;
- case DxilRootParameterType::DescriptorTable: {
- auto &descriptorTable = rootParam.DescriptorTable;
- unsigned int rangeOffsetInDescriptors = 0;
- for (unsigned int rangeIndex = 0;
- rangeIndex < descriptorTable.NumDescriptorRanges; rangeIndex++) {
- auto &range = descriptorTable.pDescriptorRanges[rangeIndex];
- if (range.OffsetInDescriptorsFromTableStart != -1) {
- rangeOffsetInDescriptors = range.OffsetInDescriptorsFromTableStart;
- }
- if (ConvertD3D12RangeTypeToDxil(range.RangeType) == resourceClass &&
- range.RegisterSpace == registerSpace &&
- range.BaseShaderRegister <= baseRegisterIndex &&
- range.BaseShaderRegister + range.NumDescriptors >
- baseRegisterIndex) {
- rangeOffsetInDescriptors +=
- baseRegisterIndex - range.BaseShaderRegister;
- return {dxilParamType, recordOffset, rangeOffsetInDescriptors};
- }
- rangeOffsetInDescriptors += range.NumDescriptors;
- }
- recordOffset += SizeofD3D12GpuDescriptorHandle;
- break;
- }
- case DxilRootParameterType::CBV:
- case DxilRootParameterType::SRV:
- case DxilRootParameterType::UAV:
- if (IsParameterTypeCompatibleWithResourceClass(resourceClass,
- dxilParamType) &&
- baseRegisterIndex == rootParam.Descriptor.ShaderRegister &&
- registerSpace == rootParam.Descriptor.RegisterSpace) {
- return {dxilParamType, recordOffset};
- }
- recordOffset += SizeofD3D12GpuVA;
- break;
- }
- }
- }
- return ShaderRecordEntry::InvalidEntry();
- }
- // TODO: Consider pre-calculating this into a map
- ShaderRecordEntry DxilPatchShaderRecordBindings::FindRootSignatureDescriptor(
- const DxilVersionedRootSignatureDesc &rootSignatureDescriptor,
- unsigned int ShaderRecordIdentifierSizeInBytes,
- DXIL::ResourceClass resourceClass,
- unsigned int baseRegisterIndex,
- unsigned int registerSpace) {
- switch (rootSignatureDescriptor.Version) {
- case DxilRootSignatureVersion::Version_1_0:
- return FindRootSignatureDescriptorHelper(rootSignatureDescriptor.Desc_1_0, ShaderRecordIdentifierSizeInBytes, resourceClass, baseRegisterIndex, registerSpace);
- case DxilRootSignatureVersion::Version_1_1:
- return FindRootSignatureDescriptorHelper(rootSignatureDescriptor.Desc_1_1, ShaderRecordIdentifierSizeInBytes, resourceClass, baseRegisterIndex, registerSpace);
- default:
- ThrowFailure();
- return ShaderRecordEntry::InvalidEntry();
- }
- }
|