Add a DescriptorType to GetDescriptors query

* This will be optional in many cases but for some situations might be required
  when type information is not implicitly available in the descriptor store.
  Generally it should always be available unless the descriptor store is being
  viewed 'blank' purely from its contents with no other context.
This commit is contained in:
baldurk
2025-05-07 14:50:12 +01:00
parent f896f8a2e2
commit ceb062b658
16 changed files with 156 additions and 71 deletions
+10 -1
View File
@@ -1475,6 +1475,8 @@ void DescriptorViewer::ViewD3D12State()
ranges[0].count = resourceDesc->descriptorCount;
ranges[0].descriptorSize = resourceDesc->descriptorByteSize;
ranges[0].offset = resourceDesc->firstDescriptorOffset;
// we are interpreting typeless descriptors, assume D3D12 can interpret it
ranges[0].type = DescriptorType::Unknown;
descriptors = r->GetDescriptors(resourceDesc->resourceId, ranges);
}
}
@@ -1487,6 +1489,8 @@ void DescriptorViewer::ViewD3D12State()
ranges[0].count = samplerDesc->descriptorCount;
ranges[0].descriptorSize = samplerDesc->descriptorByteSize;
ranges[0].offset = samplerDesc->firstDescriptorOffset;
// we are interpreting typeless descriptors, assume D3D12 can interpret it
ranges[0].type = DescriptorType::Unknown;
samplerDescriptors = r->GetSamplerDescriptors(samplerDesc->resourceId, ranges);
}
}
@@ -1525,6 +1529,8 @@ void DescriptorViewer::OnEventChanged(uint32_t eventId)
ranges[0].count = m_DescriptorStore.descriptorCount;
ranges[0].descriptorSize = descSize;
ranges[0].offset = m_DescriptorStore.firstDescriptorOffset;
// assume this descriptor store knows its type information and can interpret typeless descriptors
ranges[0].type = DescriptorType::Unknown;
rdcarray<Descriptor> descriptors = r->GetDescriptors(m_DescriptorStore.resourceId, ranges);
rdcarray<DescriptorLogicalLocation> locations =
@@ -1547,7 +1553,9 @@ void DescriptorViewer::OnEventChanged(uint32_t eventId)
idx++;
// combine contiguous ranges
if(!ranges.empty() && ranges.back().offset + ranges.back().count * descSize == i * descSize)
if(!ranges.empty() &&
ranges.back().offset + ranges.back().count * descSize == i * descSize &&
ranges.back().type == descriptors[i].type)
{
ranges.back().count++;
}
@@ -1557,6 +1565,7 @@ void DescriptorViewer::OnEventChanged(uint32_t eventId)
range.offset = m_DescriptorStore.firstDescriptorOffset + uint32_t(i * descSize);
range.descriptorSize = descSize;
range.count = 1;
range.type = descriptors[i].type;
ranges.push_back(range);
}
}
@@ -498,6 +498,8 @@ void D3D11PipelineStateViewer::OnEventChanged(uint32_t eventId)
range.offset = 0;
range.descriptorSize = state->descriptorByteSize;
range.count = state->descriptorCount;
// D3D11 doesn't need the descriptor type, it has internal type information
range.type = DescriptorType::Unknown;
rdcarray<DescriptorRange> ranges = {range};
@@ -528,15 +528,14 @@ void D3D12PipelineStateViewer::OnEventChanged(uint32_t eventId)
// if the last range is contiguous with this access, append this access as a new range to query
if(!ranges.empty() && ranges.back().descriptorSize == acc.byteSize &&
ranges.back().offset + ranges.back().descriptorSize == acc.byteOffset)
ranges.back().offset + ranges.back().descriptorSize == acc.byteOffset &&
ranges.back().type == acc.type)
{
ranges.back().count++;
continue;
}
DescriptorRange range;
range.offset = acc.byteOffset;
range.descriptorSize = acc.byteSize;
DescriptorRange range = acc;
ranges.push_back(range);
}
@@ -485,6 +485,8 @@ void GLPipelineStateViewer::OnEventChanged(uint32_t eventId)
range.offset = 0;
range.descriptorSize = state->descriptorByteSize;
range.count = state->descriptorCount;
// GL doesn't need the descriptor type, it has internal type information
range.type = DescriptorType::Unknown;
rdcarray<DescriptorRange> ranges = {range};
+5 -4
View File
@@ -170,7 +170,7 @@ struct AccessedResourceTag
{
}
AccessedResourceTag(ShaderDirectAccess acc, VarType t)
: resRef(acc), type(t), step(0), category(acc.category)
: resRef(acc), type(t), step(0), category(CategoryForDescriptorType(acc.type))
{
}
AccessedResourceTag(ShaderVariable var) : step(0), type(var.type)
@@ -181,7 +181,7 @@ struct AccessedResourceTag
{
resRef.directAccess = true;
resRef.access = var.GetDirectAccess();
category = resRef.access.category;
category = CategoryForDescriptorType(resRef.access.type);
}
else
{
@@ -2979,6 +2979,7 @@ QString ShaderViewer::stringRep(const ShaderVariable &var, uint32_t row)
ranges[0].count = 1;
ranges[0].descriptorSize = access.byteSize;
ranges[0].offset = access.byteOffset;
ranges[0].type = access.type;
rdcarray<DescriptorLogicalLocation> locations =
r->GetDescriptorLocations(access.descriptorStore, ranges);
@@ -5249,7 +5250,7 @@ RDTreeWidgetItem *ShaderViewer::makeAccessedResourceNode(const ShaderVariable &v
}
else
{
category = acc.category;
category = CategoryForDescriptorType(acc.type);
bindIdx = m_ReadOnlyResources.indexOf(acc);
}
if(category != DescriptorCategory::ReadOnlyResource)
@@ -5269,7 +5270,7 @@ RDTreeWidgetItem *ShaderViewer::makeAccessedResourceNode(const ShaderVariable &v
}
else
{
category = acc.category;
category = CategoryForDescriptorType(acc.type);
bindIdx = m_ReadWriteResources.indexOf(acc);
}
if(category != DescriptorCategory::ReadWriteResource)
+3 -4
View File
@@ -3294,15 +3294,14 @@ void TextureViewer::OnEventChanged(uint32_t eventId)
// if the last range is contiguous with this access, append this access as a new range to query
if(!ranges.empty() && ranges.back().descriptorSize == update.access.byteSize &&
ranges.back().offset + ranges.back().descriptorSize == update.access.byteOffset)
ranges.back().offset + ranges.back().descriptorSize == update.access.byteOffset &&
ranges.back().type == update.access.type)
{
ranges.back().count++;
continue;
}
DescriptorRange range;
range.offset = update.access.byteOffset;
range.descriptorSize = update.access.byteSize;
DescriptorRange range = update.access;
ranges.push_back(range);
}
+3 -4
View File
@@ -653,8 +653,8 @@ struct DescriptorAccess
}
bool operator==(const ShaderDirectAccess &o) const
{
return CategoryForDescriptorType(type) == o.category && descriptorStore == o.descriptorStore &&
byteOffset == o.byteOffset && byteSize == o.byteSize;
return type == o.type && descriptorStore == o.descriptorStore && byteOffset == o.byteOffset &&
byteSize == o.byteSize;
}
bool operator==(const DescriptorAccess &o) const
{
@@ -746,8 +746,7 @@ inline ShaderBindIndex::ShaderBindIndex(const DescriptorAccess &access)
}
inline ShaderDirectAccess::ShaderDirectAccess(const DescriptorAccess &access)
: ShaderDirectAccess(CategoryForDescriptorType(access.type), access.descriptorStore,
access.byteOffset, access.byteSize)
: ShaderDirectAccess(access.type, access.descriptorStore, access.byteOffset, access.byteSize)
{
}
+10 -1
View File
@@ -643,6 +643,7 @@ struct DescriptorRange
{
offset = access.byteOffset;
descriptorSize = access.byteSize;
type = access.type;
}
DOCUMENT("The offset in the descriptor storage where the descriptor range starts.");
@@ -651,11 +652,17 @@ struct DescriptorRange
uint32_t descriptorSize = 1;
DOCUMENT("The number of descriptors in this range.");
uint32_t count = 1;
DOCUMENT(R"(The type of descriptor in the descriptor range.
:type: DescriptorType
)");
DescriptorType type = DescriptorType::Unknown;
DOCUMENT("");
bool operator==(const DescriptorRange &o) const
{
return offset == o.offset && descriptorSize == o.descriptorSize && count == o.count;
return offset == o.offset && descriptorSize == o.descriptorSize && count == o.count &&
type == o.type;
}
bool operator<(const DescriptorRange &o) const
{
@@ -665,6 +672,8 @@ struct DescriptorRange
return descriptorSize < o.descriptorSize;
if(!(count == o.count))
return count < o.count;
if(!(type == o.type))
return type < o.type;
return false;
}
};
+12 -15
View File
@@ -136,7 +136,7 @@ struct ShaderDirectAccess
DOCUMENT("");
ShaderDirectAccess()
{
category = DescriptorCategory::Unknown;
type = DescriptorType::Unknown;
descriptorStore = ResourceId();
byteOffset = 0;
byteSize = 0;
@@ -144,20 +144,17 @@ struct ShaderDirectAccess
ShaderDirectAccess(const ShaderDirectAccess &) = default;
ShaderDirectAccess &operator=(const ShaderDirectAccess &) = default;
ShaderDirectAccess(DescriptorCategory category, ResourceId descriptorStore, uint32_t byteOffset,
ShaderDirectAccess(DescriptorType type, ResourceId descriptorStore, uint32_t byteOffset,
uint32_t byteSize)
: category(category),
descriptorStore(descriptorStore),
byteOffset(byteOffset),
byteSize(byteSize)
: type(type), descriptorStore(descriptorStore), byteOffset(byteOffset), byteSize(byteSize)
{
}
ShaderDirectAccess(const DescriptorAccess &access);
bool operator<(const ShaderDirectAccess &o) const
{
if(category != o.category)
return category < o.category;
if(type != o.type)
return type < o.type;
if(descriptorStore != o.descriptorStore)
return descriptorStore < o.descriptorStore;
if(byteOffset != o.byteOffset)
@@ -166,15 +163,15 @@ struct ShaderDirectAccess
}
bool operator==(const ShaderDirectAccess &o) const
{
return category == o.category && descriptorStore == o.descriptorStore &&
byteOffset == o.byteOffset && byteSize == o.byteSize;
return type == o.type && descriptorStore == o.descriptorStore && byteOffset == o.byteOffset &&
byteSize == o.byteSize;
}
DOCUMENT(R"(The category of the resource being accessed.
DOCUMENT(R"(The type of the resource being accessed.
:type: DescriptorCategory
:type: DescriptorType
)");
DescriptorCategory category;
DescriptorType type;
DOCUMENT(R"(The backing storage of the descriptor.
@@ -509,7 +506,7 @@ The :class:`ShaderDirectAccess` uniquely refers to a resource descriptor.
)");
inline void SetDirectAccess(const ShaderDirectAccess &access)
{
value.u32v[0] = (uint32_t)access.category;
value.u32v[0] = (uint32_t)access.type;
value.u32v[1] = access.byteOffset;
value.u32v[2] = access.byteSize;
// This marks the variable as ShaderDirectAccess and not ShaderBindIndex
@@ -532,7 +529,7 @@ The :class:`ShaderDirectAccess` uniquely refers to a resource descriptor.
{
ResourceId descriptorStore;
memcpy(&descriptorStore, &value.u64v[2], sizeof(descriptorStore));
return ShaderDirectAccess((DescriptorCategory)value.u64v[0], descriptorStore, value.u32v[1],
return ShaderDirectAccess((DescriptorType)value.u64v[0], descriptorStore, value.u32v[1],
value.u32v[2]);
}
+30 -14
View File
@@ -1109,19 +1109,18 @@ ResourceReferenceInfo D3D12APIWrapper::GetResourceReferenceInfo(const DXDebug::B
case D3D12DescriptorType::CBV:
{
resRefInfo.resClass = DXIL::ResourceClass::CBuffer;
resRefInfo.category = DescriptorCategory::ConstantBlock;
resRefInfo.type = VarType::ConstantBlock;
resRefInfo.descType = DescriptorType::ConstantBuffer;
resRefInfo.varType = VarType::ConstantBlock;
}
case D3D12DescriptorType::SRV:
{
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = desc.GetSRV();
ResourceId srvId = desc.GetResResourceId();
ID3D12Resource *pResource = rm->GetCurrentAs<ID3D12Resource>(srvId);
if(pResource)
{
resRefInfo.resClass = DXIL::ResourceClass::SRV;
resRefInfo.category = DescriptorCategory::ReadOnlyResource;
resRefInfo.type = VarType::ReadOnlyResource;
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = desc.GetSRV();
resRefInfo.varType = VarType::ReadOnlyResource;
if(srvDesc.ViewDimension == D3D12_SRV_DIMENSION_UNKNOWN)
srvDesc = MakeSRVDesc(pResource->GetDesc());
@@ -1145,20 +1144,37 @@ ResourceReferenceInfo D3D12APIWrapper::GetResourceReferenceInfo(const DXDebug::B
RDCERR("Unknown SRV resource at Descriptor Index %u", descriptorIndex);
return ResourceReferenceInfo();
}
if(srvDesc.ViewDimension == D3D12_SRV_DIMENSION_RAYTRACING_ACCELERATION_STRUCTURE)
resRefInfo.descType = DescriptorType::AccelerationStructure;
else if(srvDesc.ViewDimension == D3D12_SRV_DIMENSION_BUFFER &&
(srvDesc.Buffer.StructureByteStride > 0 || srvDesc.Format == DXGI_FORMAT_UNKNOWN))
resRefInfo.descType = DescriptorType::Buffer;
else if(srvDesc.ViewDimension == D3D12_SRV_DIMENSION_BUFFER)
resRefInfo.descType = DescriptorType::TypedBuffer;
else
resRefInfo.descType = DescriptorType::Image;
break;
}
case D3D12DescriptorType::UAV:
{
D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = desc.GetUAV();
resRefInfo.resClass = DXIL::ResourceClass::UAV;
resRefInfo.category = DescriptorCategory::ReadWriteResource;
resRefInfo.type = VarType::ReadWriteResource;
resRefInfo.varType = VarType::ReadWriteResource;
if(uavDesc.ViewDimension == D3D12_UAV_DIMENSION_BUFFER)
resRefInfo.descType = uavDesc.Format != DXGI_FORMAT_UNKNOWN
? DescriptorType::ReadWriteTypedBuffer
: DescriptorType::ReadWriteBuffer;
else
resRefInfo.descType = DescriptorType::ReadWriteImage;
break;
}
case D3D12DescriptorType::Sampler:
{
resRefInfo.resClass = DXIL::ResourceClass::Sampler;
resRefInfo.category = DescriptorCategory::Sampler;
resRefInfo.type = VarType::Sampler;
resRefInfo.descType = DescriptorType::Sampler;
resRefInfo.varType = VarType::Sampler;
D3D12_SAMPLER_DESC2 samplerDesc = desc.GetSampler();
// Don't think SAMPLER_MODE_MONO is supported in D3D12 (set for filter mode D3D10_FILTER_TEXT_1BIT)
resRefInfo.samplerData.samplerMode =
@@ -1172,7 +1188,7 @@ ResourceReferenceInfo D3D12APIWrapper::GetResourceReferenceInfo(const DXDebug::B
return resRefInfo;
}
ShaderDirectAccess D3D12APIWrapper::GetShaderDirectAccess(DescriptorCategory category,
ShaderDirectAccess D3D12APIWrapper::GetShaderDirectAccess(DescriptorType type,
const DXDebug::BindingSlot &slot)
{
const HeapDescriptorType heapType = slot.heapType;
@@ -1196,8 +1212,8 @@ ShaderDirectAccess D3D12APIWrapper::GetShaderDirectAccess(DescriptorCategory cat
{
if(heapType == HeapDescriptorType::Sampler)
{
RDCASSERTEQUAL(category, DescriptorCategory::Sampler);
return ShaderDirectAccess(category, rm->GetOriginalID(heapId), byteOffset, byteSize);
RDCASSERTEQUAL(CategoryForDescriptorType(type), DescriptorCategory::Sampler);
return ShaderDirectAccess(type, rm->GetOriginalID(heapId), byteOffset, byteSize);
}
}
else
@@ -1205,8 +1221,8 @@ ShaderDirectAccess D3D12APIWrapper::GetShaderDirectAccess(DescriptorCategory cat
RDCASSERT(heapDesc.Type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
if(heapType == HeapDescriptorType::CBV_SRV_UAV)
{
RDCASSERTNOTEQUAL(category, DescriptorCategory::Sampler);
return ShaderDirectAccess(category, rm->GetOriginalID(heapId), byteOffset, byteSize);
RDCASSERTNOTEQUAL(CategoryForDescriptorType(type), DescriptorCategory::Sampler);
return ShaderDirectAccess(type, rm->GetOriginalID(heapId), byteOffset, byteSize);
}
}
}
+1 -2
View File
@@ -61,8 +61,7 @@ public:
const DXBC::ShaderType shaderType, const char *opString);
ShaderVariable GetRenderTargetSampleInfo(const DXBC::ShaderType shaderType, const char *opString);
ResourceReferenceInfo GetResourceReferenceInfo(const DXDebug::BindingSlot &slot);
ShaderDirectAccess GetShaderDirectAccess(DescriptorCategory category,
const DXDebug::BindingSlot &slot);
ShaderDirectAccess GetShaderDirectAccess(DescriptorType type, const DXDebug::BindingSlot &slot);
private:
void FetchSRV(const D3D12Descriptor *resDescriptor, const BindingSlot &slot);
+64 -10
View File
@@ -1604,28 +1604,82 @@ void ResourceReferenceInfo::Create(const DXIL::ResourceReference *resRef, uint32
srvData.sampleCount = resRef->resourceBase.srvData.sampleCount;
srvData.compType = (DXDebug::ResourceRetType)ConvertComponentTypeToResourceRetType(
resRef->resourceBase.srvData.compType);
type = VarType::ReadOnlyResource;
category = DescriptorCategory::ReadOnlyResource;
varType = VarType::ReadOnlyResource;
switch(resRef->resourceBase.srvData.shape)
{
default:
RDCERR("Unexpected resource shape");
descType = DescriptorType::Unknown;
break;
case ResourceKind::Texture1D:
case ResourceKind::Texture2D:
case ResourceKind::Texture2DMS:
case ResourceKind::Texture3D:
case ResourceKind::TextureCube:
case ResourceKind::Texture1DArray:
case ResourceKind::Texture2DArray:
case ResourceKind::Texture2DMSArray:
case ResourceKind::TextureCubeArray:
case ResourceKind::FeedbackTexture2D:
case ResourceKind::FeedbackTexture2DArray: descType = DescriptorType::Image; break;
case ResourceKind::TypedBuffer:
case ResourceKind::TBuffer: descType = DescriptorType::TypedBuffer; break;
case ResourceKind::RawBuffer:
case ResourceKind::StructuredBuffer:
case ResourceKind::StructuredBufferWithCounter: descType = DescriptorType::Buffer; break;
case ResourceKind::RTAccelerationStructure:
descType = DescriptorType::AccelerationStructure;
break;
}
break;
}
case DXIL::ResourceClass::UAV:
{
type = VarType::ReadWriteResource;
category = DescriptorCategory::ReadWriteResource;
varType = VarType::ReadWriteResource;
switch(resRef->resourceBase.uavData.shape)
{
default:
RDCERR("Unexpected resource shape");
descType = DescriptorType::Unknown;
break;
case ResourceKind::Texture1D:
case ResourceKind::Texture2D:
case ResourceKind::Texture2DMS:
case ResourceKind::Texture3D:
case ResourceKind::TextureCube:
case ResourceKind::Texture1DArray:
case ResourceKind::Texture2DArray:
case ResourceKind::Texture2DMSArray:
case ResourceKind::TextureCubeArray:
case ResourceKind::FeedbackTexture2D:
case ResourceKind::FeedbackTexture2DArray: descType = DescriptorType::ReadWriteImage; break;
case ResourceKind::TypedBuffer:
case ResourceKind::TBuffer: descType = DescriptorType::ReadWriteTypedBuffer; break;
case ResourceKind::RawBuffer:
case ResourceKind::StructuredBuffer:
case ResourceKind::StructuredBufferWithCounter:
descType = DescriptorType::ReadWriteBuffer;
break;
case ResourceKind::RTAccelerationStructure:
descType = DescriptorType::AccelerationStructure;
break;
}
break;
}
case DXIL::ResourceClass::CBuffer:
{
type = VarType::ConstantBlock;
category = DescriptorCategory::ConstantBlock;
varType = VarType::ConstantBlock;
descType = DescriptorType::ConstantBuffer;
break;
}
case DXIL::ResourceClass::Sampler:
{
samplerData.samplerMode =
ConvertSamplerKindToSamplerMode(resRef->resourceBase.samplerData.samplerType);
type = VarType::Sampler;
category = DescriptorCategory::Sampler;
varType = VarType::Sampler;
descType = DescriptorType::Sampler;
break;
}
default: RDCERR("Unexpected resource class %s", ToStr(resClass).c_str()); break;
@@ -2420,11 +2474,11 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper,
RDCASSERT(m_DirectHeapAccessBindings.count(resultId) == 0);
m_DirectHeapAccessBindings[resultId] = resRefInfo;
ShaderDirectAccess access = apiWrapper->GetShaderDirectAccess(resRefInfo.category, slot);
ShaderDirectAccess access = apiWrapper->GetShaderDirectAccess(resRefInfo.descType, slot);
// Default to unannotated handle
ClearAnnotatedHandle(result);
rdcstr resName = m_Program.GetHandleAlias(result.name);
result.type = resRefInfo.type;
result.type = resRefInfo.varType;
result.name = resName;
result.SetDirectAccess(access);
break;
+3 -3
View File
@@ -138,8 +138,8 @@ struct ResourceReferenceInfo
DXIL::ResourceClass resClass;
BindingSlot binding;
DescriptorCategory category;
VarType type;
DescriptorType descType;
VarType varType;
struct SRVData
{
@@ -197,7 +197,7 @@ public:
virtual ShaderVariable GetRenderTargetSampleInfo(const DXBC::ShaderType shaderType,
const char *opString) = 0;
virtual ResourceReferenceInfo GetResourceReferenceInfo(const DXDebug::BindingSlot &slot) = 0;
virtual ShaderDirectAccess GetShaderDirectAccess(DescriptorCategory category,
virtual ShaderDirectAccess GetShaderDirectAccess(DescriptorType type,
const DXDebug::BindingSlot &slot) = 0;
};
+3 -4
View File
@@ -171,15 +171,14 @@ public:
// if the last range is contiguous with this access, append this access as a new range to query
if(!ranges.empty() && ranges.back().descriptorSize == acc.byteSize &&
ranges.back().offset + ranges.back().descriptorSize == acc.byteOffset)
ranges.back().offset + ranges.back().descriptorSize == acc.byteOffset &&
ranges.back().type == acc.type)
{
ranges.back().count++;
continue;
}
DescriptorRange range;
range.offset = acc.byteOffset;
range.descriptorSize = acc.byteSize;
DescriptorRange range = acc;
ranges.push_back(range);
}
+2 -1
View File
@@ -1059,8 +1059,9 @@ void DoSerialise(SerialiserType &ser, DescriptorRange &el)
SERIALISE_MEMBER(offset);
SERIALISE_MEMBER(descriptorSize);
SERIALISE_MEMBER(count);
SERIALISE_MEMBER(type);
SIZE_CHECK(12);
SIZE_CHECK(16);
}
template <typename SerialiserType>
+3 -4
View File
@@ -2327,15 +2327,14 @@ void ReplayController::FetchPipelineState(uint32_t eventId)
// if the last range is contiguous with this access, append this access as a new range to query
if(!ranges.empty() && ranges.back().descriptorSize == acc.byteSize &&
ranges.back().offset + ranges.back().descriptorSize == acc.byteOffset)
ranges.back().offset + ranges.back().descriptorSize == acc.byteOffset &&
ranges.back().type == acc.type)
{
ranges.back().count++;
continue;
}
DescriptorRange range;
range.offset = acc.byteOffset;
range.descriptorSize = acc.byteSize;
DescriptorRange range = acc;
ranges.push_back(range);
}