mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-13 05:20:45 +00:00
Generate baked per-pipeline static descriptor access on D3D12
This commit is contained in:
@@ -2429,7 +2429,57 @@ rdcarray<SamplerDescriptor> D3D12Replay::GetSamplerDescriptors(ResourceId descri
|
||||
|
||||
rdcarray<DescriptorAccess> D3D12Replay::GetDescriptorAccess()
|
||||
{
|
||||
return {};
|
||||
const D3D12RenderState &rs = m_pDevice->GetQueue()->GetCommandData()->m_RenderState;
|
||||
|
||||
D3D12ResourceManager *rm = m_pDevice->GetResourceManager();
|
||||
|
||||
WrappedID3D12PipelineState *pipe = NULL;
|
||||
|
||||
if(rs.pipe != ResourceId())
|
||||
pipe = rm->GetCurrentAs<WrappedID3D12PipelineState>(rs.pipe);
|
||||
|
||||
rdcarray<DescriptorAccess> ret;
|
||||
|
||||
if(pipe)
|
||||
{
|
||||
pipe->ProcessDescriptorAccess();
|
||||
|
||||
ret = pipe->staticDescriptorAccess;
|
||||
|
||||
WrappedID3D12DescriptorHeap *resourceHeap = NULL;
|
||||
WrappedID3D12DescriptorHeap *samplerHeap = NULL;
|
||||
for(ResourceId id : rs.heaps)
|
||||
{
|
||||
WrappedID3D12DescriptorHeap *heap =
|
||||
(WrappedID3D12DescriptorHeap *)rm->GetCurrentAs<ID3D12DescriptorHeap>(id);
|
||||
D3D12_DESCRIPTOR_HEAP_DESC desc = heap->GetDesc();
|
||||
if(desc.Type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)
|
||||
resourceHeap = heap;
|
||||
else
|
||||
samplerHeap = heap;
|
||||
}
|
||||
|
||||
for(DescriptorAccess &access : ret)
|
||||
{
|
||||
if(access.type == DescriptorType::Sampler)
|
||||
access.descriptorStore =
|
||||
samplerHeap ? rm->GetOriginalID(samplerHeap->GetResourceID()) : ResourceId();
|
||||
else
|
||||
access.descriptorStore =
|
||||
resourceHeap ? rm->GetOriginalID(resourceHeap->GetResourceID()) : ResourceId();
|
||||
|
||||
uint32_t rootIndex = (uint32_t)access.byteSize;
|
||||
access.byteSize = 1;
|
||||
|
||||
// apply the per-parameter offset into the heap here
|
||||
if(pipe->IsGraphics())
|
||||
access.byteOffset += (uint32_t)rs.graphics.sigelems[rootIndex].offset;
|
||||
else
|
||||
access.byteOffset += (uint32_t)rs.compute.sigelems[rootIndex].offset;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void D3D12Replay::RenderHighlightBox(float w, float h, float scale)
|
||||
|
||||
@@ -661,6 +661,176 @@ void WrappedID3D12PipelineState::ShaderEntry::BuildReflection()
|
||||
m_Details->resourceId = GetResourceID();
|
||||
}
|
||||
|
||||
rdcpair<uint32_t, uint32_t> FindMatchingRootParameter(const D3D12RootSignature *sig,
|
||||
D3D12_SHADER_VISIBILITY visibility,
|
||||
D3D12_DESCRIPTOR_RANGE_TYPE rangeType,
|
||||
uint32_t space, uint32_t bind)
|
||||
{
|
||||
// search the root signature to find the matching entry and figure out the offset from the root binding
|
||||
for(uint32_t root = 0; root < sig->Parameters.size(); root++)
|
||||
{
|
||||
const D3D12RootSignatureParameter ¶m = sig->Parameters[root];
|
||||
|
||||
if(param.ShaderVisibility != visibility && param.ShaderVisibility != D3D12_SHADER_VISIBILITY_ALL)
|
||||
continue;
|
||||
|
||||
uint32_t descOffset = 0;
|
||||
for(const D3D12_DESCRIPTOR_RANGE1 &range : param.ranges)
|
||||
{
|
||||
uint32_t rangeOffset = range.OffsetInDescriptorsFromTableStart;
|
||||
if(range.OffsetInDescriptorsFromTableStart == D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)
|
||||
rangeOffset = descOffset;
|
||||
|
||||
if(range.RangeType == rangeType && range.RegisterSpace == space &&
|
||||
range.BaseShaderRegister <= bind &&
|
||||
(range.NumDescriptors == ~0U || bind < range.BaseShaderRegister + range.NumDescriptors))
|
||||
{
|
||||
return {root, rangeOffset + (bind - range.BaseShaderRegister)};
|
||||
}
|
||||
|
||||
descOffset = rangeOffset + range.NumDescriptors;
|
||||
}
|
||||
}
|
||||
|
||||
return {~0U, 0};
|
||||
}
|
||||
|
||||
void WrappedID3D12PipelineState::ProcessDescriptorAccess()
|
||||
{
|
||||
if(m_AccessProcessed)
|
||||
return;
|
||||
m_AccessProcessed = true;
|
||||
|
||||
const D3D12RootSignature *sig = NULL;
|
||||
if(graphics)
|
||||
sig = &((WrappedID3D12RootSignature *)graphics->pRootSignature)->sig;
|
||||
else if(compute)
|
||||
sig = &((WrappedID3D12RootSignature *)compute->pRootSignature)->sig;
|
||||
|
||||
for(ShaderEntry *shad : {VS(), HS(), DS(), GS(), PS(), AS(), MS(), CS()})
|
||||
{
|
||||
if(!shad)
|
||||
continue;
|
||||
|
||||
const ShaderReflection &refl = shad->GetDetails();
|
||||
const ShaderBindpointMapping &mapping = shad->GetMapping();
|
||||
|
||||
D3D12_SHADER_VISIBILITY visibility;
|
||||
switch(refl.stage)
|
||||
{
|
||||
case ShaderStage::Vertex: visibility = D3D12_SHADER_VISIBILITY_VERTEX; break;
|
||||
case ShaderStage::Hull: visibility = D3D12_SHADER_VISIBILITY_HULL; break;
|
||||
case ShaderStage::Domain: visibility = D3D12_SHADER_VISIBILITY_DOMAIN; break;
|
||||
case ShaderStage::Geometry: visibility = D3D12_SHADER_VISIBILITY_GEOMETRY; break;
|
||||
case ShaderStage::Pixel: visibility = D3D12_SHADER_VISIBILITY_PIXEL; break;
|
||||
case ShaderStage::Amplification: visibility = D3D12_SHADER_VISIBILITY_AMPLIFICATION; break;
|
||||
case ShaderStage::Mesh: visibility = D3D12_SHADER_VISIBILITY_MESH; break;
|
||||
default: visibility = D3D12_SHADER_VISIBILITY_ALL; break;
|
||||
}
|
||||
|
||||
DescriptorAccess access;
|
||||
access.stage = refl.stage;
|
||||
|
||||
// we will store the root signature element in byteSize to be decoded into descriptorStore later
|
||||
access.byteSize = 0;
|
||||
|
||||
staticDescriptorAccess.reserve(staticDescriptorAccess.size() + mapping.constantBlocks.size() +
|
||||
mapping.samplers.size() + mapping.readOnlyResources.size() +
|
||||
mapping.readWriteResources.size());
|
||||
|
||||
RDCASSERT(mapping.constantBlocks.size() < 0xffff, mapping.constantBlocks.size());
|
||||
for(uint16_t i = 0; i < mapping.constantBlocks.size(); i++)
|
||||
{
|
||||
const Bindpoint &bind = mapping.constantBlocks[i];
|
||||
|
||||
// arrayed descriptors will be handled with bindless feedback
|
||||
if(bind.arraySize > 1)
|
||||
continue;
|
||||
|
||||
access.staticallyUnused = !bind.used;
|
||||
access.type = DescriptorType::ConstantBuffer;
|
||||
access.index = i;
|
||||
rdctie(access.byteSize, access.byteOffset) =
|
||||
FindMatchingRootParameter(sig, visibility, D3D12_DESCRIPTOR_RANGE_TYPE_CBV,
|
||||
(uint32_t)bind.bindset, (uint32_t)bind.bind);
|
||||
|
||||
if(access.byteSize != ~0U)
|
||||
staticDescriptorAccess.push_back(access);
|
||||
}
|
||||
|
||||
RDCASSERT(mapping.samplers.size() < 0xffff, mapping.samplers.size());
|
||||
for(uint16_t i = 0; i < mapping.samplers.size(); i++)
|
||||
{
|
||||
const Bindpoint &bind = mapping.samplers[i];
|
||||
|
||||
// arrayed descriptors will be handled with bindless feedback
|
||||
if(bind.arraySize > 1)
|
||||
continue;
|
||||
|
||||
access.staticallyUnused = !bind.used;
|
||||
access.type = DescriptorType::Sampler;
|
||||
access.index = i;
|
||||
rdctie(access.byteSize, access.byteOffset) =
|
||||
FindMatchingRootParameter(sig, visibility, D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER,
|
||||
(uint32_t)bind.bindset, (uint32_t)bind.bind);
|
||||
|
||||
if(access.byteSize != ~0U)
|
||||
staticDescriptorAccess.push_back(access);
|
||||
}
|
||||
|
||||
RDCASSERT(mapping.readOnlyResources.size() < 0xffff, mapping.readOnlyResources.size());
|
||||
for(uint16_t i = 0; i < mapping.readOnlyResources.size(); i++)
|
||||
{
|
||||
const Bindpoint &bind = mapping.readOnlyResources[i];
|
||||
|
||||
// arrayed descriptors will be handled with bindless feedback
|
||||
if(bind.arraySize > 1)
|
||||
continue;
|
||||
|
||||
access.staticallyUnused = !bind.used;
|
||||
access.type = DescriptorType::Image;
|
||||
if(!refl.readOnlyResources[i].isTexture)
|
||||
access.type = (refl.readOnlyResources[i].variableType.baseType == VarType::UByte ||
|
||||
!refl.readOnlyResources[i].variableType.members.empty())
|
||||
? DescriptorType::Buffer
|
||||
: DescriptorType::TypedBuffer;
|
||||
access.index = i;
|
||||
rdctie(access.byteSize, access.byteOffset) =
|
||||
FindMatchingRootParameter(sig, visibility, D3D12_DESCRIPTOR_RANGE_TYPE_SRV,
|
||||
(uint32_t)bind.bindset, (uint32_t)bind.bind);
|
||||
|
||||
if(access.byteSize != ~0U)
|
||||
staticDescriptorAccess.push_back(access);
|
||||
}
|
||||
|
||||
RDCASSERT(mapping.readWriteResources.size() < 0xffff, mapping.readWriteResources.size());
|
||||
for(uint16_t i = 0; i < mapping.readWriteResources.size(); i++)
|
||||
{
|
||||
const Bindpoint &bind = mapping.readWriteResources[i];
|
||||
|
||||
// arrayed descriptors will be handled with bindless feedback
|
||||
if(bind.arraySize > 1)
|
||||
continue;
|
||||
|
||||
access.staticallyUnused = !bind.used;
|
||||
access.type = DescriptorType::ReadWriteImage;
|
||||
if(!refl.readWriteResources[i].isTexture)
|
||||
access.type = (refl.readWriteResources[i].variableType.baseType == VarType::UByte ||
|
||||
!refl.readWriteResources[i].variableType.members.empty())
|
||||
? DescriptorType::ReadWriteBuffer
|
||||
: DescriptorType::ReadWriteTypedBuffer;
|
||||
|
||||
access.index = i;
|
||||
rdctie(access.byteSize, access.byteOffset) =
|
||||
FindMatchingRootParameter(sig, visibility, D3D12_DESCRIPTOR_RANGE_TYPE_UAV,
|
||||
(uint32_t)bind.bindset, (uint32_t)bind.bind);
|
||||
|
||||
if(access.byteSize != ~0U)
|
||||
staticDescriptorAccess.push_back(access);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UINT GetPlaneForSubresource(ID3D12Resource *res, int Subresource)
|
||||
{
|
||||
D3D12_RESOURCE_DESC desc = res->GetDesc();
|
||||
|
||||
@@ -634,6 +634,9 @@ public:
|
||||
D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC *graphics = NULL;
|
||||
D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC *compute = NULL;
|
||||
|
||||
rdcarray<DescriptorAccess> staticDescriptorAccess;
|
||||
bool m_AccessProcessed = false;
|
||||
|
||||
void Fill(D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC &desc)
|
||||
{
|
||||
if(graphics)
|
||||
@@ -861,14 +864,14 @@ public:
|
||||
TypeEnum = Resource_PipelineState,
|
||||
};
|
||||
|
||||
ShaderEntry *VS() { return (ShaderEntry *)graphics->VS.pShaderBytecode; }
|
||||
ShaderEntry *HS() { return (ShaderEntry *)graphics->HS.pShaderBytecode; }
|
||||
ShaderEntry *DS() { return (ShaderEntry *)graphics->DS.pShaderBytecode; }
|
||||
ShaderEntry *GS() { return (ShaderEntry *)graphics->GS.pShaderBytecode; }
|
||||
ShaderEntry *PS() { return (ShaderEntry *)graphics->PS.pShaderBytecode; }
|
||||
ShaderEntry *AS() { return (ShaderEntry *)graphics->AS.pShaderBytecode; }
|
||||
ShaderEntry *MS() { return (ShaderEntry *)graphics->MS.pShaderBytecode; }
|
||||
ShaderEntry *CS() { return (ShaderEntry *)compute->CS.pShaderBytecode; }
|
||||
ShaderEntry *VS() { return graphics ? (ShaderEntry *)graphics->VS.pShaderBytecode : NULL; }
|
||||
ShaderEntry *HS() { return graphics ? (ShaderEntry *)graphics->HS.pShaderBytecode : NULL; }
|
||||
ShaderEntry *DS() { return graphics ? (ShaderEntry *)graphics->DS.pShaderBytecode : NULL; }
|
||||
ShaderEntry *GS() { return graphics ? (ShaderEntry *)graphics->GS.pShaderBytecode : NULL; }
|
||||
ShaderEntry *PS() { return graphics ? (ShaderEntry *)graphics->PS.pShaderBytecode : NULL; }
|
||||
ShaderEntry *AS() { return graphics ? (ShaderEntry *)graphics->AS.pShaderBytecode : NULL; }
|
||||
ShaderEntry *MS() { return graphics ? (ShaderEntry *)graphics->MS.pShaderBytecode : NULL; }
|
||||
ShaderEntry *CS() { return compute ? (ShaderEntry *)compute->CS.pShaderBytecode : NULL; }
|
||||
WrappedID3D12PipelineState(ID3D12PipelineState *real, WrappedID3D12Device *device)
|
||||
: WrappedDeviceChild12(real, device)
|
||||
{
|
||||
@@ -908,6 +911,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessDescriptorAccess();
|
||||
|
||||
//////////////////////////////
|
||||
// implement ID3D12PipelineState
|
||||
|
||||
|
||||
Reference in New Issue
Block a user