Add a query to determine logical identifiers for descriptors

* This is a consideration for any cases where binding numbers are relevant -
  primarily D3D11 and GL - where the offset into an arbitrary (and possibly
  fake) descriptor storage is not helpful but knowing the register binding
  definitely is.
* If someone wants to look at the raw descriptor contents without respect to a
  particular shader access they can use this query to determine a more useful
  'name' for any given descriptor. On D3D11 and GL this gives the register
  number, on Vulkan it gives the binding number (and array element). On D3D12 it
  just repeats the offset effectively.
This commit is contained in:
baldurk
2024-04-10 18:58:50 +01:00
parent b9787606ea
commit d88aad8fc2
22 changed files with 620 additions and 1 deletions
+1
View File
@@ -416,6 +416,7 @@ TEMPLATE_ARRAY_INSTANTIATE(rdcarray, DescriptorRange)
TEMPLATE_ARRAY_INSTANTIATE(rdcarray, Descriptor)
TEMPLATE_ARRAY_INSTANTIATE(rdcarray, SamplerDescriptor)
TEMPLATE_ARRAY_INSTANTIATE(rdcarray, DescriptorAccess)
TEMPLATE_ARRAY_INSTANTIATE(rdcarray, DescriptorLogicalLocation)
TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, Attachment)
TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, BindingElement)
TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, DescriptorBinding)
+105
View File
@@ -849,6 +849,111 @@ does not necessarily guarantee that the descriptor was accessed on the GPU durin
DECLARE_REFLECTION_STRUCT(DescriptorAccess);
DOCUMENT(R"(In many cases there may be a logical location or fixed binding point for a particular
descriptor which is not conveyed with a simple byte offset into a descriptor store.
This is particularly true for any descriptor stores that are not equivalent to a buffer of bytes
but actually have an API structure - for example D3D11 and GL with fixed binding points, or Vulkan
with descriptor sets.
In some cases on APIs with explicit descriptor storage this may convey information about virtualised
descriptors that are not explicitly backed with real storage.
This structure describes such a location queried for a given descriptor.
For example on D3D11 this would give the register number of the binding, and on GL it would give the
unit index. Both cases would be able to query the type and shader stage visibility of descriptors
that are not accessed or even bound.
On Vulkan this would give the set, binding, and visibility. In most cases this information will be
available for all descriptors but in some cases the type of descriptor may not be available if it
is unused and has not been initialised.
On D3D12 this would only give the index into the heap, as no other information is available purely
by the descriptor itself.
.. note::
This information may not be fully present on all APIs so the returned structures may be empty or
partially filled out, depending on what information is relevant per API.
)");
struct DescriptorLogicalLocation
{
DOCUMENT("");
DescriptorLogicalLocation() = default;
DescriptorLogicalLocation(const DescriptorLogicalLocation &) = default;
DescriptorLogicalLocation &operator=(const DescriptorLogicalLocation &) = default;
bool operator==(const DescriptorLogicalLocation &o) const
{
return fixedBindNumber == o.fixedBindNumber && stageMask == o.stageMask &&
category == o.category && logicalBindName == o.logicalBindName;
}
bool operator<(const DescriptorLogicalLocation &o) const
{
// note there are two different conflicting sorts that would be sensible here:
// stage > category > fixed bind would work best for D3D11/GL
// fixed bind first works better for Vulkan/D3D12.
//
// We assume users will access or sort D3D11/GL descriptors directly by binds if needed so are
// less likely to rely on this sort behaviour.
if(fixedBindNumber != o.fixedBindNumber)
return fixedBindNumber < o.fixedBindNumber;
if(stageMask != o.stageMask)
return stageMask < o.stageMask;
if(category != o.category)
return category < o.category;
if(logicalBindName != o.logicalBindName)
return logicalBindName < o.logicalBindName;
return false;
}
DOCUMENT(R"(The set of shader stages that this descriptor is intrinsically available to. This is
primarily relevant for D3D11 with its fixed per-stage register binding points.
Note this *only* shows if a descriptor itself can only ever be accessed by some shader stages by
definition, not if a descriptor is generally available but happened to only be accessed by one or
more stage. That information is available directly in the :class:`DescriptorAccess` itself.
:type: ShaderStageMask
)");
ShaderStageMask stageMask = ShaderStageMask::All;
DOCUMENT(R"(The general category of a descriptor stored. This may not be available for
uninitialised descriptors on all APIs.
:type: DescriptorCategory
)");
DescriptorCategory category = DescriptorCategory::Unknown;
DOCUMENT(R"(The fixed binding number for this descriptor. The interpretation of this is
API-specific and it is provided purely for informational purposes and has no bearing on how data
is accessed or described.
Generally speaking sorting by this number will give a reasonable ordering by binding if it exists.
.. note::
Because this number is API-specific, there is no guarantee that it will be unique across all
descriptors. It should be used only within contexts that can interpret it API-specifically, or
else for purely informational/non-semantic purposes like sorting.
:type: int
)");
uint32_t fixedBindNumber = 0;
DOCUMENT(R"(The logical binding name, as suitable for displaying to a user when displaying
the contents of a descriptor queried directly from a heap.
Depending on the API, this name may be identical or less specific than the one obtained from
shader reflection. Generally speaking it's preferred to use any information from shader reflection
first, and fall back to this name if no reflection information is available in the context.
:type: str
)");
rdcinflexiblestr logicalBindName;
};
DECLARE_REFLECTION_STRUCT(DescriptorLogicalLocation);
DOCUMENT("Information about a single constant buffer binding.");
struct BoundCBuffer
{
+10
View File
@@ -595,6 +595,16 @@ Multiple ranges within the store can be queried at once, and are returned in a c
)");
virtual rdcarray<DescriptorAccess> GetDescriptorAccess() = 0;
DOCUMENT(R"(Retrieve the logical locations for descriptors in a given descriptor store.
:param ResourceId descriptorStore: The descriptor store to be queried from.
:param List[DescriptorRange] ranges: The descriptor ranges to query.
:return: The descriptor logical locations.
:rtype: List[DescriptorLogicalLocation]
)");
virtual rdcarray<DescriptorLogicalLocation> GetDescriptorLocations(
ResourceId descriptorStore, const rdcarray<DescriptorRange> &ranges) = 0;
DOCUMENT(R"(Retrieve the list of possible disassembly targets for :meth:`DisassembleShader`. The
values are implementation dependent but will always include a default target first which is the
native disassembly of the shader. Further options may be available for additional diassembly views
+1 -1
View File
@@ -4771,7 +4771,7 @@ DOCUMENT(R"(A set of flags for ``ShaderStage`` stages
A shorthand version with flags set for all stages together.
)");
enum class ShaderStageMask : uint32_t
enum class ShaderStageMask : uint16_t
{
Unknown = 0,
Vertex = 1 << uint32_t(ShaderStage::Vertex),
+5
View File
@@ -280,6 +280,11 @@ public:
return ret;
}
rdcarray<DescriptorAccess> GetDescriptorAccess(uint32_t eventId) { return {}; }
rdcarray<DescriptorLogicalLocation> GetDescriptorLocations(ResourceId descriptorStore,
const rdcarray<DescriptorRange> &ranges)
{
return {};
}
DriverInformation GetDriverInfo()
{
DriverInformation ret = {};
+35
View File
@@ -101,6 +101,7 @@ rdcstr DoStringise(const ReplayProxyPacket &el)
STRINGISE_ENUM_NAMED(eReplayProxy_GetDescriptors, "GetDescriptors");
STRINGISE_ENUM_NAMED(eReplayProxy_GetSamplerDescriptors, "GetSamplerDescriptors");
STRINGISE_ENUM_NAMED(eReplayProxy_GetDescriptorAccess, "GetDescriptorAccess");
STRINGISE_ENUM_NAMED(eReplayProxy_GetDescriptorLocations, "GetDescriptorLocations");
}
END_ENUM_STRINGISE();
}
@@ -1938,6 +1939,39 @@ rdcarray<DescriptorAccess> ReplayProxy::GetDescriptorAccess(uint32_t eventId)
PROXY_FUNCTION(GetDescriptorAccess, eventId);
}
template <typename ParamSerialiser, typename ReturnSerialiser>
rdcarray<DescriptorLogicalLocation> ReplayProxy::Proxied_GetDescriptorLocations(
ParamSerialiser &paramser, ReturnSerialiser &retser, ResourceId descriptorStore,
const rdcarray<DescriptorRange> &ranges)
{
const ReplayProxyPacket expectedPacket = eReplayProxy_GetDescriptorLocations;
ReplayProxyPacket packet = eReplayProxy_GetDescriptorLocations;
rdcarray<DescriptorLogicalLocation> ret;
{
BEGIN_PARAMS();
SERIALISE_ELEMENT(descriptorStore);
SERIALISE_ELEMENT(ranges);
END_PARAMS();
}
{
REMOTE_EXECUTION();
if(paramser.IsReading() && !paramser.IsErrored() && !m_IsErrored)
ret = m_Remote->GetDescriptorLocations(descriptorStore, ranges);
}
SERIALISE_RETURN(ret);
return ret;
}
rdcarray<DescriptorLogicalLocation> ReplayProxy::GetDescriptorLocations(
ResourceId descriptorStore, const rdcarray<DescriptorRange> &ranges)
{
PROXY_FUNCTION(GetDescriptorLocations, descriptorStore, ranges);
}
template <typename ParamSerialiser, typename ReturnSerialiser>
void ReplayProxy::Proxied_ReplayLog(ParamSerialiser &paramser, ReturnSerialiser &retser,
uint32_t endEventID, ReplayLogType replayType)
@@ -3011,6 +3045,7 @@ bool ReplayProxy::Tick(int type)
case eReplayProxy_GetDescriptors: GetDescriptors(ResourceId(), {}); break;
case eReplayProxy_GetSamplerDescriptors: GetSamplerDescriptors(ResourceId(), {}); break;
case eReplayProxy_GetDescriptorAccess: GetDescriptorAccess(0); break;
case eReplayProxy_GetDescriptorLocations: GetDescriptorLocations(ResourceId(), {}); break;
case eReplayProxy_GetUsage: GetUsage(ResourceId()); break;
case eReplayProxy_GetLiveID: GetLiveID(ResourceId()); break;
case eReplayProxy_GetFrameRecord: GetFrameRecord(); break;
+3
View File
@@ -109,6 +109,7 @@ enum ReplayProxyPacket
eReplayProxy_GetDescriptors,
eReplayProxy_GetSamplerDescriptors,
eReplayProxy_GetDescriptorAccess,
eReplayProxy_GetDescriptorLocations,
};
DECLARE_REFLECTION_ENUM(ReplayProxyPacket);
@@ -487,6 +488,8 @@ public:
IMPLEMENT_FUNCTION_PROXIED(rdcarray<SamplerDescriptor>, GetSamplerDescriptors,
ResourceId descriptorStore, const rdcarray<DescriptorRange> &ranges);
IMPLEMENT_FUNCTION_PROXIED(rdcarray<DescriptorAccess>, GetDescriptorAccess, uint32_t eventId);
IMPLEMENT_FUNCTION_PROXIED(rdcarray<DescriptorLogicalLocation>, GetDescriptorLocations,
ResourceId descriptorStore, const rdcarray<DescriptorRange> &ranges);
IMPLEMENT_FUNCTION_PROXIED(rdcarray<uint32_t>, GetPassEvents, uint32_t eventId);
+58
View File
@@ -2003,6 +2003,64 @@ rdcarray<DescriptorAccess> D3D11Replay::GetDescriptorAccess(uint32_t eventId)
return ret;
}
rdcarray<DescriptorLogicalLocation> D3D11Replay::GetDescriptorLocations(
ResourceId descriptorStore, const rdcarray<DescriptorRange> &ranges)
{
rdcarray<DescriptorLogicalLocation> ret;
if(descriptorStore != m_pImmediateContext->GetDescriptorsID())
{
RDCERR("Descriptors query for invalid descriptor store on fixed bindings API (D3D11)");
return ret;
}
size_t count = 0;
for(const DescriptorRange &r : ranges)
count += r.count;
ret.resize(count);
size_t dst = 0;
for(const DescriptorRange &r : ranges)
{
uint32_t descriptorByteOffset = r.offset;
for(uint32_t i = 0; i < r.count; i++, dst++, descriptorByteOffset++)
{
DescriptorLogicalLocation &dstLoc = ret[dst];
D3D11DescriptorLocation srcLoc = DecodeD3D11DescriptorIndex(descriptorByteOffset);
dstLoc.stageMask = MaskForStage(srcLoc.stage);
char typePrefix = '?';
switch(srcLoc.type)
{
case D3D11DescriptorMapping::CBs:
typePrefix = 'b';
dstLoc.category = DescriptorCategory::ConstantBlock;
break;
case D3D11DescriptorMapping::Samplers:
typePrefix = 's';
dstLoc.category = DescriptorCategory::Sampler;
break;
case D3D11DescriptorMapping::SRVs:
typePrefix = 't';
dstLoc.category = DescriptorCategory::ReadOnlyResource;
break;
case D3D11DescriptorMapping::UAVs:
typePrefix = 'u';
dstLoc.category = DescriptorCategory::ReadWriteResource;
break;
case D3D11DescriptorMapping::Count:
case D3D11DescriptorMapping::Invalid: dstLoc.category = DescriptorCategory::Unknown; break;
}
dstLoc.fixedBindNumber = srcLoc.idx;
dstLoc.logicalBindName = StringFormat::Fmt("%c%u", typePrefix, srcLoc.idx);
}
}
return ret;
}
RDResult D3D11Replay::ReadLogInitialisation(RDCFile *rdc, bool storeStructuredBuffers)
{
return m_pDevice->ReadLogInitialisation(rdc, storeStructuredBuffers);
+2
View File
@@ -187,6 +187,8 @@ public:
rdcarray<SamplerDescriptor> GetSamplerDescriptors(ResourceId descriptorStore,
const rdcarray<DescriptorRange> &ranges);
rdcarray<DescriptorAccess> GetDescriptorAccess(uint32_t eventId);
rdcarray<DescriptorLogicalLocation> GetDescriptorLocations(ResourceId descriptorStore,
const rdcarray<DescriptorRange> &ranges);
void FreeTargetResource(ResourceId id);
void FreeCustomShader(ResourceId id);
+123
View File
@@ -2810,6 +2810,129 @@ rdcarray<DescriptorAccess> D3D12Replay::GetDescriptorAccess(uint32_t eventId)
return ret;
}
rdcarray<DescriptorLogicalLocation> D3D12Replay::GetDescriptorLocations(
ResourceId descriptorStore, const rdcarray<DescriptorRange> &ranges)
{
rdcarray<DescriptorLogicalLocation> ret;
D3D12ResourceManager *rm = m_pDevice->GetResourceManager();
ID3D12DeviceChild *res = rm->GetCurrentAs<ID3D12DeviceChild>(descriptorStore);
size_t count = 0;
for(const DescriptorRange &r : ranges)
count += r.count;
ret.resize(count);
// for sort keys we have the top 32-bits be the lower 32-bits of the store ResourceID, or 1 or 2
// for static samplers and root constants. Then the lower 32-bits are an index
if(WrappedID3D12RootSignature::IsAlloc(res))
{
WrappedID3D12RootSignature *sig = (WrappedID3D12RootSignature *)res;
size_t dst = 0;
for(const DescriptorRange &r : ranges)
{
uint32_t staticIdx = r.offset;
for(uint32_t i = 0; i < r.count; i++)
{
if(staticIdx >= sig->sig.StaticSamplers.size())
{
// silently drop out of bounds descriptor reads
}
else
{
ret[dst].fixedBindNumber = ~0U - 2048 + staticIdx;
ret[dst].stageMask = ToShaderStageMask(sig->sig.StaticSamplers[staticIdx].ShaderVisibility);
ret[dst].category = DescriptorCategory::Sampler;
ret[dst].logicalBindName = StringFormat::Fmt("Static #%u", staticIdx);
}
dst++;
staticIdx++;
}
}
return ret;
}
if(WrappedID3D12PipelineState::IsAlloc(res))
{
WrappedID3D12PipelineState *pipe = (WrappedID3D12PipelineState *)res;
WrappedID3D12RootSignature *sig =
(WrappedID3D12RootSignature *)(pipe->IsGraphics() ? pipe->graphics->pRootSignature
: pipe->compute->pRootSignature);
// root constants
size_t dst = 0;
for(const DescriptorRange &r : ranges)
{
uint32_t rootIndex = r.offset;
for(uint32_t i = 0; i < r.count; i++, rootIndex++, dst++)
{
const D3D12RootSignatureParameter &param = sig->sig.Parameters[rootIndex];
DescriptorLogicalLocation &l = ret[dst];
l.fixedBindNumber = ~0U - 2048 - 64 + rootIndex;
l.stageMask = ToShaderStageMask(param.ShaderVisibility);
if(param.ParameterType == D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS)
{
l.category = DescriptorCategory::ConstantBlock;
l.logicalBindName = StringFormat::Fmt("Consts #", rootIndex);
}
else if(param.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV)
{
l.category = DescriptorCategory::ConstantBlock;
l.logicalBindName = StringFormat::Fmt("Root CB #", rootIndex);
}
else if(param.ParameterType == D3D12_ROOT_PARAMETER_TYPE_SRV)
{
l.category = DescriptorCategory::ReadOnlyResource;
l.logicalBindName = StringFormat::Fmt("Root SRV #", rootIndex);
}
else if(param.ParameterType == D3D12_ROOT_PARAMETER_TYPE_UAV)
{
l.category = DescriptorCategory::ReadWriteResource;
l.logicalBindName = StringFormat::Fmt("Root UAV #", rootIndex);
}
}
}
return ret;
}
if(!WrappedID3D12DescriptorHeap::IsAlloc(res))
{
RDCERR("Invalid/unrecognised descriptor store %s", ToStr(descriptorStore).c_str());
return ret;
}
WrappedID3D12DescriptorHeap *heap = (WrappedID3D12DescriptorHeap *)res;
const bool sampler = (heap->GetDesc().Type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
size_t dst = 0;
for(const DescriptorRange &r : ranges)
{
uint32_t descriptorId = r.offset;
for(uint32_t i = 0; i < r.count; i++, dst++, descriptorId++)
{
// can't set anything except the "bind number" which we just set as the offset.
ret[dst].fixedBindNumber = descriptorId;
if(sampler)
ret[dst].logicalBindName = StringFormat::Fmt("SamplerDescriptorHeap[%u]", descriptorId);
else
ret[dst].logicalBindName = StringFormat::Fmt("ResourceDescriptorHeap[%u]", descriptorId);
}
}
return ret;
}
void D3D12Replay::RenderHighlightBox(float w, float h, float scale)
{
OutputWindow &outw = m_OutputWindows[m_CurrentOutputWindow];
+2
View File
@@ -143,6 +143,8 @@ public:
rdcarray<SamplerDescriptor> GetSamplerDescriptors(ResourceId descriptorStore,
const rdcarray<DescriptorRange> &ranges);
rdcarray<DescriptorAccess> GetDescriptorAccess(uint32_t eventId);
rdcarray<DescriptorLogicalLocation> GetDescriptorLocations(ResourceId descriptorStore,
const rdcarray<DescriptorRange> &ranges);
void FreeTargetResource(ResourceId id);
void FreeCustomShader(ResourceId id);
+110
View File
@@ -2865,6 +2865,116 @@ rdcarray<DescriptorAccess> GLReplay::GetDescriptorAccess(uint32_t eventId)
return m_Access;
}
rdcarray<DescriptorLogicalLocation> GLReplay::GetDescriptorLocations(
ResourceId descriptorStore, const rdcarray<DescriptorRange> &ranges)
{
rdcarray<DescriptorLogicalLocation> ret;
if(descriptorStore != m_pDriver->m_DescriptorsID)
{
RDCERR("Descriptors query for invalid descriptor store on fixed bindings API (OpenGL)");
return ret;
}
size_t count = 0;
for(const DescriptorRange &r : ranges)
count += r.count;
ret.resize(count);
size_t dst = 0;
for(const DescriptorRange &r : ranges)
{
uint32_t descriptorByteOffset = r.offset;
for(uint32_t i = 0; i < r.count; i++, dst++, descriptorByteOffset++)
{
DescriptorLogicalLocation &dstLoc = ret[dst];
GLDescriptorLocation srcLoc = DecodeGLDescriptorIndex(descriptorByteOffset);
const char *prefix = "Unknown";
dstLoc.stageMask = ShaderStageMask::All;
switch(srcLoc.type)
{
case GLDescriptorMapping::BareUniforms:
prefix = "Uniforms";
dstLoc.category = DescriptorCategory::ConstantBlock;
break;
case GLDescriptorMapping::UniformBinding:
prefix = "UBO";
dstLoc.category = DescriptorCategory::ConstantBlock;
break;
case GLDescriptorMapping::Tex1D:
prefix = "Tex1D";
dstLoc.category = DescriptorCategory::ReadOnlyResource;
break;
case GLDescriptorMapping::Tex2D:
prefix = "Tex2D";
dstLoc.category = DescriptorCategory::ReadOnlyResource;
break;
case GLDescriptorMapping::Tex3D:
prefix = "Tex3D";
dstLoc.category = DescriptorCategory::ReadOnlyResource;
break;
case GLDescriptorMapping::Tex1DArray:
prefix = "Tex1DArray";
dstLoc.category = DescriptorCategory::ReadOnlyResource;
break;
case GLDescriptorMapping::Tex2DArray:
prefix = "Tex2DArray";
dstLoc.category = DescriptorCategory::ReadOnlyResource;
break;
case GLDescriptorMapping::TexCubeArray:
prefix = "TexCubeArray";
dstLoc.category = DescriptorCategory::ReadOnlyResource;
break;
case GLDescriptorMapping::TexRect:
prefix = "TexRect";
dstLoc.category = DescriptorCategory::ReadOnlyResource;
break;
case GLDescriptorMapping::TexBuffer:
prefix = "TexBuffer";
dstLoc.category = DescriptorCategory::ReadOnlyResource;
break;
case GLDescriptorMapping::TexCube:
prefix = "TexCube";
dstLoc.category = DescriptorCategory::ReadOnlyResource;
break;
case GLDescriptorMapping::Tex2DMS:
prefix = "Tex2DMS";
dstLoc.category = DescriptorCategory::ReadOnlyResource;
break;
case GLDescriptorMapping::Tex2DMSArray:
prefix = "Tex2DMSArray";
dstLoc.category = DescriptorCategory::ReadOnlyResource;
break;
case GLDescriptorMapping::Images:
prefix = "Image";
dstLoc.category = DescriptorCategory::ReadWriteResource;
break;
case GLDescriptorMapping::AtomicCounter:
prefix = "Atomic";
dstLoc.category = DescriptorCategory::ReadWriteResource;
break;
case GLDescriptorMapping::ShaderStorage:
prefix = "SSBO";
dstLoc.category = DescriptorCategory::ReadWriteResource;
break;
case GLDescriptorMapping::Count:
case GLDescriptorMapping::Invalid: dstLoc.category = DescriptorCategory::Unknown; break;
}
dstLoc.fixedBindNumber = srcLoc.idx;
if(srcLoc.type == GLDescriptorMapping::BareUniforms)
dstLoc.logicalBindName =
StringFormat::Fmt("%s %s", prefix, ToStr(ShaderStage(srcLoc.idx)).c_str());
else
dstLoc.logicalBindName = StringFormat::Fmt("%s %u", prefix, srcLoc.idx);
}
}
return ret;
}
void GLReplay::OpenGLFillCBufferVariables(ResourceId shader, GLuint prog, bool bufferBacked,
rdcstr prefix, const rdcarray<ShaderConstant> &variables,
rdcarray<ShaderVariable> &outvars,
+2
View File
@@ -165,6 +165,8 @@ public:
rdcarray<SamplerDescriptor> GetSamplerDescriptors(ResourceId descriptorStore,
const rdcarray<DescriptorRange> &ranges);
rdcarray<DescriptorAccess> GetDescriptorAccess(uint32_t eventId);
rdcarray<DescriptorLogicalLocation> GetDescriptorLocations(ResourceId descriptorStore,
const rdcarray<DescriptorRange> &ranges);
void FreeTargetResource(ResourceId id);
RDResult ReadLogInitialisation(RDCFile *rdc, bool storeStructuredBuffers);
+7
View File
@@ -109,6 +109,13 @@ struct DescSetLayout
VkShaderStageFlags stageFlags : 31;
uint32_t variableSize : 1;
ResourceId *immutableSampler;
inline uint32_t GetDescriptorCount(uint32_t varDescriptorSize) const
{
if(variableSize)
return varDescriptorSize;
return descriptorCount;
}
};
rdcarray<Binding> bindings;
+122
View File
@@ -3007,6 +3007,128 @@ rdcarray<DescriptorAccess> VulkanReplay::GetDescriptorAccess(uint32_t eventId)
return ret;
}
rdcarray<DescriptorLogicalLocation> VulkanReplay::GetDescriptorLocations(
ResourceId descriptorStore, const rdcarray<DescriptorRange> &ranges)
{
rdcarray<DescriptorLogicalLocation> ret;
size_t count = 0;
for(const DescriptorRange &r : ranges)
count += r.count;
ret.resize(count);
// specialisation constants 'descriptor' stored in a pipeline
auto pipe = m_pDriver->m_CreationInfo.m_Pipeline.find(descriptorStore);
if(pipe != m_pDriver->m_CreationInfo.m_Pipeline.end())
{
// should only be one descriptor referred here, but just munge them all to be the same
for(DescriptorLogicalLocation &d : ret)
{
d.category = DescriptorCategory::ConstantBlock;
d.fixedBindNumber = ~0U - 2;
d.logicalBindName = "Specialization";
}
return ret;
}
VulkanResourceManager *rm = m_pDriver->GetResourceManager();
// push constants 'descriptor' stored in a command buffer
if(WrappedVkCommandBuffer::IsAlloc(rm->GetCurrentResource(descriptorStore)))
{
// should only be one descriptor referred here, but just munge them all to be the same
for(DescriptorLogicalLocation &d : ret)
{
d.category = DescriptorCategory::ConstantBlock;
d.fixedBindNumber = ~0U - 1;
d.logicalBindName = "Push constants";
}
return ret;
}
auto descit = m_pDriver->m_DescriptorSetState.find(descriptorStore);
if(descit == m_pDriver->m_DescriptorSetState.end())
{
RDCERR("Invalid/unrecognised descriptor store %s", ToStr(descriptorStore).c_str());
return ret;
}
const WrappedVulkan::DescriptorSetInfo &descState = descit->second;
uint32_t varDescCount = descState.data.variableDescriptorCount;
const DescSetLayout &descLayout = m_pDriver->m_CreationInfo.m_DescSetLayout[descState.layout];
size_t dst = 0;
for(const DescriptorRange &r : ranges)
{
uint32_t descriptorOffset = r.offset;
const DescSetLayout::Binding *bind = descLayout.bindings.data();
const DescSetLayout::Binding *firstBind = bind;
const DescSetLayout::Binding *lastBind = bind + descLayout.bindings.size();
for(uint32_t i = 0; i < r.count; i++, dst++, descriptorOffset++)
{
while(bind < lastBind &&
descLayout.inlineByteSize + bind->elemOffset + bind->GetDescriptorCount(varDescCount) <=
descriptorOffset)
bind++;
if(bind >= lastBind)
{
RDCERR("Ran off end of descriptor layout looking for matching offset");
break;
}
DescriptorLogicalLocation &d = ret[dst];
const DescriptorSetSlot *slot = descState.data.binds[0] + descriptorOffset;
switch(slot->type)
{
case DescriptorSlotType::Sampler: d.category = DescriptorCategory::Sampler; break;
case DescriptorSlotType::UniformBuffer:
case DescriptorSlotType::InlineBlock:
case DescriptorSlotType::UniformBufferDynamic:
case DescriptorSlotType::SampledImage:
case DescriptorSlotType::CombinedImageSampler:
case DescriptorSlotType::UniformTexelBuffer:
case DescriptorSlotType::InputAttachment:
case DescriptorSlotType::AccelerationStructure:
d.category = DescriptorCategory::ReadOnlyResource;
break;
case DescriptorSlotType::StorageBuffer:
case DescriptorSlotType::StorageBufferDynamic:
case DescriptorSlotType::StorageImage:
case DescriptorSlotType::StorageTexelBuffer:
d.category = DescriptorCategory::ReadWriteResource;
break;
case DescriptorSlotType::Unwritten:
case DescriptorSlotType::Count: d.category = DescriptorCategory::Unknown; break;
}
if(bind->stageFlags == VK_SHADER_STAGE_ALL)
d.stageMask = ShaderStageMask::All;
else
d.stageMask = (ShaderStageMask)bind->stageFlags;
// we only have one bind number, for simplicity, so we put the bind here and omit the array
// element entirely. Users that want to decode this are expected to either be aware of arrays
// and determine that contiguous identical bind numbers are arrays, or display with the
// logical name string below
d.fixedBindNumber = uint32_t(bind - firstBind);
if(bind->descriptorCount > 1 && bind->layoutDescType != VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK)
d.logicalBindName = StringFormat::Fmt("%zu[%u]", size_t(bind - firstBind),
descriptorOffset - bind->elemOffset);
else
d.logicalBindName = StringFormat::Fmt("%zu", size_t(bind - firstBind));
}
}
return ret;
}
void VulkanReplay::FillCBufferVariables(ResourceId pipeline, ResourceId shader, ShaderStage stage,
rdcstr entryPoint, uint32_t cbufSlot,
rdcarray<ShaderVariable> &outvars, const bytebuf &data)
+2
View File
@@ -354,6 +354,8 @@ public:
rdcarray<SamplerDescriptor> GetSamplerDescriptors(ResourceId descriptorStore,
const rdcarray<DescriptorRange> &ranges);
rdcarray<DescriptorAccess> GetDescriptorAccess(uint32_t eventId);
rdcarray<DescriptorLogicalLocation> GetDescriptorLocations(ResourceId descriptorStore,
const rdcarray<DescriptorRange> &ranges);
void FreeTargetResource(ResourceId id);
RDResult ReadLogInitialisation(RDCFile *rdc, bool storeStructuredBuffers);
+6
View File
@@ -170,6 +170,12 @@ rdcarray<DescriptorAccess> DummyDriver::GetDescriptorAccess(uint32_t eventId)
return {};
}
rdcarray<DescriptorLogicalLocation> DummyDriver::GetDescriptorLocations(
ResourceId descriptorStore, const rdcarray<DescriptorRange> &ranges)
{
return {};
}
FrameRecord DummyDriver::GetFrameRecord()
{
return m_FrameRecord;
+2
View File
@@ -65,6 +65,8 @@ public:
rdcarray<SamplerDescriptor> GetSamplerDescriptors(ResourceId descriptorStore,
const rdcarray<DescriptorRange> &ranges);
rdcarray<DescriptorAccess> GetDescriptorAccess(uint32_t eventId);
rdcarray<DescriptorLogicalLocation> GetDescriptorLocations(ResourceId descriptorStore,
const rdcarray<DescriptorRange> &ranges);
FrameRecord GetFrameRecord();
+12
View File
@@ -1138,6 +1138,17 @@ void DoSerialise(SerialiserType &ser, DescriptorAccess &el)
SIZE_CHECK(32);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, DescriptorLogicalLocation &el)
{
SERIALISE_MEMBER(stageMask);
SERIALISE_MEMBER(category);
SERIALISE_MEMBER(fixedBindNumber);
SERIALISE_MEMBER(logicalBindName);
SIZE_CHECK(16);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, StencilFace &el)
{
@@ -2604,6 +2615,7 @@ INSTANTIATE_SERIALISE_TYPE(DescriptorRange)
INSTANTIATE_SERIALISE_TYPE(Descriptor)
INSTANTIATE_SERIALISE_TYPE(SamplerDescriptor)
INSTANTIATE_SERIALISE_TYPE(DescriptorAccess)
INSTANTIATE_SERIALISE_TYPE(DescriptorLogicalLocation)
INSTANTIATE_SERIALISE_TYPE(D3D11Pipe::Layout)
INSTANTIATE_SERIALISE_TYPE(D3D11Pipe::InputAssembly)
INSTANTIATE_SERIALISE_TYPE(D3D11Pipe::View)
+8
View File
@@ -138,6 +138,14 @@ rdcarray<DescriptorAccess> ReplayController::GetDescriptorAccess()
return m_pDevice->GetDescriptorAccess(m_EventID);
}
rdcarray<DescriptorLogicalLocation> ReplayController::GetDescriptorLocations(
ResourceId descriptorStore, const rdcarray<DescriptorRange> &ranges)
{
CHECK_REPLAY_THREAD();
return m_pDevice->GetDescriptorLocations(m_pDevice->GetLiveID(descriptorStore), ranges);
}
rdcarray<SamplerDescriptor> ReplayController::GetSamplerDescriptors(
ResourceId descriptorStore, const rdcarray<DescriptorRange> &ranges)
{
+2
View File
@@ -155,6 +155,8 @@ public:
rdcarray<SamplerDescriptor> GetSamplerDescriptors(ResourceId descriptorStore,
const rdcarray<DescriptorRange> &ranges);
rdcarray<DescriptorAccess> GetDescriptorAccess();
rdcarray<DescriptorLogicalLocation> GetDescriptorLocations(ResourceId descriptorStore,
const rdcarray<DescriptorRange> &ranges);
rdcarray<rdcstr> GetDisassemblyTargets(bool withPipeline);
rdcstr DisassembleShader(ResourceId pipeline, const ShaderReflection *refl, const rdcstr &target);
+2
View File
@@ -167,6 +167,8 @@ public:
virtual rdcarray<SamplerDescriptor> GetSamplerDescriptors(
ResourceId descriptorStore, const rdcarray<DescriptorRange> &ranges) = 0;
virtual rdcarray<DescriptorAccess> GetDescriptorAccess(uint32_t eventId) = 0;
virtual rdcarray<DescriptorLogicalLocation> GetDescriptorLocations(
ResourceId descriptorStore, const rdcarray<DescriptorRange> &ranges) = 0;
virtual FrameRecord GetFrameRecord() = 0;