mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-24 15:36:33 +00:00
Fetch vulkan dynamic feedback directly as descriptor accesses
This commit is contained in:
@@ -2891,118 +2891,8 @@ rdcarray<DescriptorAccess> VulkanReplay::GetDescriptorAccess(uint32_t eventId)
|
||||
|
||||
const VKDynamicShaderFeedback &usage = m_BindlessFeedback.Usage[eventId];
|
||||
|
||||
// decode dynamic usage by reverse looking up shader bindpoint mappings. This is a temporary
|
||||
// measure, once the old style bindings reporting are removed we can refactor the shader feedback
|
||||
// to provide our data more directly in the format we want
|
||||
if(usage.valid)
|
||||
{
|
||||
ResourceId pipeline = usage.compute ? state.compute.pipeline : state.graphics.pipeline;
|
||||
const VulkanCreationInfo::Pipeline &pipeInfo = m_pDriver->m_CreationInfo.m_Pipeline[pipeline];
|
||||
const rdcarray<ResourceId> &descSetLayouts = pipeInfo.descSetLayouts;
|
||||
const rdcarray<VulkanStatePipeline::DescriptorAndOffsets> &descSets =
|
||||
usage.compute ? state.compute.descSets : state.graphics.descSets;
|
||||
for(const BindpointIndex &bind : usage.used)
|
||||
{
|
||||
if(bind.bindset >= descSetLayouts.count() || bind.bindset >= descSets.count())
|
||||
{
|
||||
RDCERR("Out-of-bounds descriptor set referenced in dynamic usage");
|
||||
continue;
|
||||
}
|
||||
|
||||
const DescSetLayout &setLayoutInfo =
|
||||
m_pDriver->m_CreationInfo.m_DescSetLayout[descSetLayouts[bind.bindset]];
|
||||
const DescSetLayout::Binding &bindInfo = setLayoutInfo.bindings[bind.bind];
|
||||
|
||||
DescriptorAccess access;
|
||||
|
||||
if(bind.bind >=
|
||||
m_pDriver->m_DescriptorSetState[descSets[bind.bindset].descSet].data.binds.count())
|
||||
{
|
||||
RDCERR("Out-of-bounds binding referenced in dynamic usage in set %u", bind.bindset);
|
||||
continue;
|
||||
}
|
||||
|
||||
// once we refactor the shader feedback this type will be provided directly by the access
|
||||
switch(m_pDriver->m_DescriptorSetState[descSets[bind.bindset].descSet]
|
||||
.data.binds[bind.bind][bind.arrayIndex]
|
||||
.type)
|
||||
{
|
||||
case DescriptorSlotType::Unwritten:
|
||||
default:
|
||||
RDCERR("Unexpected current descriptor type referenced");
|
||||
access.type = DescriptorType::Unknown;
|
||||
break;
|
||||
case DescriptorSlotType::Sampler: access.type = DescriptorType::Sampler; break;
|
||||
case DescriptorSlotType::CombinedImageSampler:
|
||||
access.type = DescriptorType::ImageSampler;
|
||||
break;
|
||||
case DescriptorSlotType::SampledImage: access.type = DescriptorType::Image; break;
|
||||
case DescriptorSlotType::StorageImage: access.type = DescriptorType::ReadWriteImage; break;
|
||||
case DescriptorSlotType::UniformTexelBuffer:
|
||||
access.type = DescriptorType::TypedBuffer;
|
||||
break;
|
||||
case DescriptorSlotType::StorageTexelBuffer:
|
||||
access.type = DescriptorType::ReadWriteTypedBuffer;
|
||||
break;
|
||||
case DescriptorSlotType::UniformBuffer: access.type = DescriptorType::ConstantBuffer; break;
|
||||
case DescriptorSlotType::StorageBuffer:
|
||||
access.type = DescriptorType::ReadWriteBuffer;
|
||||
break;
|
||||
case DescriptorSlotType::UniformBufferDynamic:
|
||||
access.type = DescriptorType::ConstantBuffer;
|
||||
break;
|
||||
case DescriptorSlotType::StorageBufferDynamic:
|
||||
access.type = DescriptorType::ReadWriteBuffer;
|
||||
break;
|
||||
case DescriptorSlotType::InputAttachment: access.type = DescriptorType::Image; break;
|
||||
case DescriptorSlotType::InlineBlock: access.type = DescriptorType::ConstantBuffer; break;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
// this could have come from any stage, so we just find the first match
|
||||
for(size_t s = 0; !found && s < NumShaderStages; s++)
|
||||
{
|
||||
// only look at candidate stages
|
||||
if((usage.compute && (ShaderStage)s != ShaderStage::Compute) ||
|
||||
(!usage.compute && (ShaderStage)s == ShaderStage::Compute))
|
||||
continue;
|
||||
|
||||
if(!pipeInfo.shaders[s].refl)
|
||||
continue;
|
||||
|
||||
for(const rdcarray<Bindpoint> &iface : {
|
||||
pipeInfo.shaders[s].mapping->constantBlocks,
|
||||
pipeInfo.shaders[s].mapping->samplers,
|
||||
pipeInfo.shaders[s].mapping->readOnlyResources,
|
||||
pipeInfo.shaders[s].mapping->readWriteResources,
|
||||
})
|
||||
{
|
||||
access.index = 0;
|
||||
for(const Bindpoint &searchBind : iface)
|
||||
{
|
||||
if(searchBind == bind)
|
||||
{
|
||||
access.stage = pipeInfo.shaders[s].stage;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
access.index++;
|
||||
}
|
||||
|
||||
if(found)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
access.arrayElement = bind.arrayIndex;
|
||||
|
||||
access.descriptorStore = rm->GetOriginalID(descSets[bind.bindset].descSet);
|
||||
access.byteOffset = bindInfo.elemOffset + setLayoutInfo.inlineByteSize + bind.arrayIndex;
|
||||
access.byteSize = 1;
|
||||
|
||||
ret.push_back(access);
|
||||
}
|
||||
}
|
||||
ret.append(usage.access);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -256,6 +256,7 @@ struct VKDynamicShaderFeedback
|
||||
{
|
||||
bool compute = false, valid = false;
|
||||
rdcarray<BindpointIndex> used;
|
||||
rdcarray<DescriptorAccess> access;
|
||||
rdcarray<ShaderMessage> messages;
|
||||
};
|
||||
|
||||
|
||||
@@ -45,10 +45,37 @@ RDOC_EXTERN_CONFIG(bool, Vulkan_Debug_DisableBufferDeviceAddress);
|
||||
|
||||
static const uint32_t ShaderStageHeaderBitShift = 28U;
|
||||
|
||||
struct feedbackData
|
||||
struct BindKey
|
||||
{
|
||||
bool operator<(const BindKey &o) const
|
||||
{
|
||||
if(stage != o.stage)
|
||||
return stage < o.stage;
|
||||
return index < o.index;
|
||||
}
|
||||
|
||||
bool operator!=(const BindKey &o) const { return !operator==(o); }
|
||||
bool operator==(const BindKey &o) const { return stage == o.stage && index == o.index; }
|
||||
|
||||
ShaderStage stage;
|
||||
ShaderBindIndex index;
|
||||
|
||||
// unused as key, here for convenience when looking up bindings
|
||||
uint32_t arraySize;
|
||||
};
|
||||
|
||||
struct BindData
|
||||
{
|
||||
uint64_t offset;
|
||||
uint32_t numEntries;
|
||||
|
||||
DescriptorAccess access;
|
||||
};
|
||||
|
||||
struct BindlessFeedbackData
|
||||
{
|
||||
std::map<BindKey, BindData> offsetMap;
|
||||
uint32_t feedbackStorageSize = 0;
|
||||
};
|
||||
|
||||
struct PrintfData
|
||||
@@ -348,7 +375,7 @@ void OffsetBindingsToMatch(rdcarray<uint32_t> &modSpirv)
|
||||
|
||||
template <typename uintvulkanmax_t>
|
||||
void AnnotateShader(const ShaderReflection &refl, const SPIRVPatchData &patchData, ShaderStage stage,
|
||||
const char *entryName, const std::map<rdcspv::Binding, feedbackData> &offsetMap,
|
||||
const char *entryName, const std::map<BindKey, BindData> &offsetMap,
|
||||
uint32_t maxSlot, bool usePrimitiveID, VkDeviceAddress addr,
|
||||
bool bufferAddressKHR, bool usesMultiview, rdcarray<uint32_t> &modSpirv,
|
||||
std::map<uint32_t, PrintfData> &printfData)
|
||||
@@ -435,11 +462,34 @@ void AnnotateShader(const ShaderReflection &refl, const SPIRVPatchData &patchDat
|
||||
var.storage != rdcspv::StorageClass::StorageBuffer)
|
||||
continue;
|
||||
|
||||
// get this variable's binding info
|
||||
rdcspv::Binding bind = editor.GetBinding(var.id);
|
||||
// figure out which interface this variable is in to make our key
|
||||
BindKey key = {};
|
||||
key.stage = refl.stage;
|
||||
|
||||
int32_t idx = -1;
|
||||
if((idx = patchData.cblockInterface.indexOf(var.id)) >= 0)
|
||||
{
|
||||
key.index.category = DescriptorCategory::ConstantBlock;
|
||||
key.index.index = (uint32_t)idx;
|
||||
}
|
||||
else if((idx = patchData.samplerInterface.indexOf(var.id)) >= 0)
|
||||
{
|
||||
key.index.category = DescriptorCategory::Sampler;
|
||||
key.index.index = (uint32_t)idx;
|
||||
}
|
||||
else if((idx = patchData.roInterface.indexOf(var.id)) >= 0)
|
||||
{
|
||||
key.index.category = DescriptorCategory::ReadOnlyResource;
|
||||
key.index.index = (uint32_t)idx;
|
||||
}
|
||||
else if((idx = patchData.rwInterface.indexOf(var.id)) >= 0)
|
||||
{
|
||||
key.index.category = DescriptorCategory::ReadWriteResource;
|
||||
key.index.index = (uint32_t)idx;
|
||||
}
|
||||
|
||||
// if this is one of the bindings we care about
|
||||
auto it = offsetMap.find(bind);
|
||||
auto it = offsetMap.find(key);
|
||||
if(it != offsetMap.end())
|
||||
{
|
||||
// store the offset for this variable so we watch for access chains and know where to store to
|
||||
@@ -448,18 +498,21 @@ void AnnotateShader(const ShaderReflection &refl, const SPIRVPatchData &patchDat
|
||||
rdcspv::Id id = varLookup[var.id] =
|
||||
editor.AddConstantImmediate<uintvulkanmax_t>(uintvulkanmax_t(it->second.offset));
|
||||
|
||||
editor.SetName(id, StringFormat::Fmt("__feedbackOffset_set%u_bind%u", it->first.set,
|
||||
it->first.binding));
|
||||
editor.SetName(
|
||||
id, StringFormat::Fmt("__feedbackOffset_%s_%u", ToStr(it->first.index.category).c_str(),
|
||||
it->first.index.index));
|
||||
}
|
||||
else
|
||||
{
|
||||
// check that the offset fits in 32-bit word, convert byte offset to uint32 index
|
||||
uint64_t index = it->second.offset / 4;
|
||||
RDCASSERT(index < 0xFFFFFFFFULL, bind.set, bind.binding, it->second.offset);
|
||||
RDCASSERT(index < 0xFFFFFFFFULL, it->first.index.category, it->first.index.index,
|
||||
it->second.offset);
|
||||
rdcspv::Id id = varLookup[var.id] = editor.AddConstantImmediate<uint32_t>(uint32_t(index));
|
||||
|
||||
editor.SetName(
|
||||
id, StringFormat::Fmt("__feedbackIndex_set%u_bind%u", it->first.set, it->first.binding));
|
||||
id, StringFormat::Fmt("__feedbackOffset_%s_%u", ToStr(it->first.index.category).c_str(),
|
||||
it->first.index.index));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1578,10 +1631,6 @@ bool VulkanReplay::FetchShaderFeedback(uint32_t eventId)
|
||||
|
||||
const VulkanCreationInfo::Pipeline &pipeInfo = creationInfo.m_Pipeline[pipe.pipeline];
|
||||
|
||||
VkDeviceSize feedbackStorageSize = 0;
|
||||
|
||||
std::map<rdcspv::Binding, feedbackData> offsetMap;
|
||||
|
||||
bool usesPrintf = false;
|
||||
|
||||
VkGraphicsPipelineCreateInfo graphicsInfo = {};
|
||||
@@ -1619,88 +1668,126 @@ bool VulkanReplay::FetchShaderFeedback(uint32_t eventId)
|
||||
}
|
||||
}
|
||||
|
||||
BindlessFeedbackData feedbackData;
|
||||
|
||||
if(usesPrintf)
|
||||
{
|
||||
// reserve some space at the start for an atomic offset counter then the buffer size, and an
|
||||
// overflow section for any clamped messages
|
||||
feedbackStorageSize += 16 + Vulkan_Debug_PrintfBufferSize() + 1024;
|
||||
feedbackData.feedbackStorageSize += 16 + Vulkan_Debug_PrintfBufferSize() + 1024;
|
||||
}
|
||||
|
||||
ResourceId pipeLayouts[] = {pipeInfo.vertLayout, pipeInfo.fragLayout};
|
||||
if(result.compute)
|
||||
ShaderReflection *stageRefls[NumShaderStages] = {};
|
||||
|
||||
{
|
||||
pipeLayouts[0] = pipeInfo.compLayout;
|
||||
pipeLayouts[1] = ResourceId();
|
||||
}
|
||||
|
||||
if(pipeInfo.vertLayout == pipeInfo.fragLayout)
|
||||
pipeLayouts[1] = ResourceId();
|
||||
|
||||
for(size_t i = 0; i < ARRAY_COUNT(pipeLayouts); i++)
|
||||
{
|
||||
if(pipeLayouts[i] == ResourceId())
|
||||
continue;
|
||||
|
||||
const rdcarray<VulkanStatePipeline::DescriptorAndOffsets> &descSets =
|
||||
(result.compute ? state.compute.descSets : state.graphics.descSets);
|
||||
|
||||
rdcspv::Binding key;
|
||||
|
||||
rdcarray<const DescSetLayout *> descLayouts;
|
||||
for(size_t set = 0; set < pipeInfo.descSetLayouts.size(); set++)
|
||||
{
|
||||
key.set = (uint32_t)set;
|
||||
descLayouts.push_back(&creationInfo.m_DescSetLayout[pipeInfo.descSetLayouts[set]]);
|
||||
|
||||
const DescSetLayout &layout = creationInfo.m_DescSetLayout[pipeInfo.descSetLayouts[set]];
|
||||
auto processBinding = [this, &descLayouts, &descSets, &feedbackData](
|
||||
ShaderStage stage, DescriptorType type, uint16_t index,
|
||||
uint32_t bindset, uint32_t bind, uint32_t arraySize) {
|
||||
// only process array bindings
|
||||
if(arraySize <= 1)
|
||||
return;
|
||||
|
||||
for(size_t binding = 0; binding < layout.bindings.size(); binding++)
|
||||
BindKey key;
|
||||
key.stage = stage;
|
||||
key.arraySize = arraySize;
|
||||
key.index.category = CategoryForDescriptorType(type);
|
||||
key.index.index = index;
|
||||
key.index.arrayElement = 0;
|
||||
|
||||
if(bindset >= descLayouts.size() || !descLayouts[bindset] || bindset > descSets.size() ||
|
||||
descSets[bindset].descSet == ResourceId())
|
||||
{
|
||||
const DescSetLayout::Binding &bindData = layout.bindings[binding];
|
||||
|
||||
// skip empty bindings
|
||||
if(bindData.layoutDescType == VK_DESCRIPTOR_TYPE_MAX_ENUM)
|
||||
continue;
|
||||
|
||||
// only process array bindings
|
||||
if(bindData.descriptorCount > 1 &&
|
||||
bindData.layoutDescType != VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK)
|
||||
{
|
||||
uint32_t descriptorCount = bindData.descriptorCount;
|
||||
if(bindData.variableSize)
|
||||
{
|
||||
if(set < descSets.size())
|
||||
{
|
||||
ResourceId descSet = descSets[set].descSet;
|
||||
if(descSet != ResourceId())
|
||||
{
|
||||
auto it = m_pDriver->m_DescriptorSetState.find(descSet);
|
||||
if(it != m_pDriver->m_DescriptorSetState.end())
|
||||
descriptorCount = it->second.data.variableDescriptorCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
key.binding = (uint32_t)binding;
|
||||
|
||||
offsetMap[key] = {feedbackStorageSize, descriptorCount};
|
||||
|
||||
feedbackStorageSize += descriptorCount * sizeof(uint32_t);
|
||||
}
|
||||
RDCERR("Invalid set %u referenced by %s shader", bindset, ToStr(key.stage).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
ResourceId descSet = descSets[bindset].descSet;
|
||||
|
||||
if(bind >= descLayouts[bindset]->bindings.size())
|
||||
{
|
||||
RDCERR("Invalid binding %u in set %u referenced by %s shader", bind, bindset,
|
||||
ToStr(key.stage).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if(descLayouts[bindset]->bindings[bind].variableSize)
|
||||
{
|
||||
auto it = m_pDriver->m_DescriptorSetState.find(descSet);
|
||||
if(it != m_pDriver->m_DescriptorSetState.end())
|
||||
arraySize = it->second.data.variableDescriptorCount;
|
||||
}
|
||||
else if(arraySize == ~0U)
|
||||
{
|
||||
// if the array was unbounded, clamp it to the size of the descriptor set
|
||||
arraySize = descLayouts[bindset]->bindings[bind].descriptorCount;
|
||||
}
|
||||
|
||||
DescriptorAccess access;
|
||||
access.stage = key.stage;
|
||||
access.type = type;
|
||||
access.index = index;
|
||||
access.descriptorStore = m_pDriver->GetResourceManager()->GetOriginalID(descSet);
|
||||
access.byteOffset =
|
||||
descLayouts[bindset]->bindings[bind].elemOffset + descLayouts[bindset]->inlineByteSize;
|
||||
access.byteSize = 1;
|
||||
|
||||
feedbackData.offsetMap[key] = {feedbackData.feedbackStorageSize, arraySize, access};
|
||||
|
||||
feedbackData.feedbackStorageSize += arraySize * sizeof(uint32_t);
|
||||
};
|
||||
|
||||
for(const VulkanCreationInfo::Pipeline::Shader &sh : pipeInfo.shaders)
|
||||
{
|
||||
if(!sh.refl)
|
||||
continue;
|
||||
|
||||
stageRefls[(uint32_t)sh.refl->stage] = sh.refl;
|
||||
|
||||
for(uint32_t i = 0; i < sh.refl->constantBlocks.size(); i++)
|
||||
processBinding(sh.refl->stage, DescriptorType::ConstantBuffer, i & 0xffff,
|
||||
sh.refl->constantBlocks[i].fixedBindSetOrSpace,
|
||||
sh.refl->constantBlocks[i].fixedBindNumber,
|
||||
sh.refl->constantBlocks[i].bindArraySize);
|
||||
|
||||
for(uint32_t i = 0; i < sh.refl->samplers.size(); i++)
|
||||
processBinding(sh.refl->stage, DescriptorType::Sampler, i & 0xffff,
|
||||
sh.refl->samplers[i].fixedBindSetOrSpace,
|
||||
sh.refl->samplers[i].fixedBindNumber, sh.refl->samplers[i].bindArraySize);
|
||||
|
||||
for(uint32_t i = 0; i < sh.refl->readOnlyResources.size(); i++)
|
||||
processBinding(sh.refl->stage, sh.refl->readOnlyResources[i].descriptorType, i & 0xffff,
|
||||
sh.refl->readOnlyResources[i].fixedBindSetOrSpace,
|
||||
sh.refl->readOnlyResources[i].fixedBindNumber,
|
||||
sh.refl->readOnlyResources[i].bindArraySize);
|
||||
|
||||
for(uint32_t i = 0; i < sh.refl->readWriteResources.size(); i++)
|
||||
processBinding(sh.refl->stage, sh.refl->readWriteResources[i].descriptorType, i & 0xffff,
|
||||
sh.refl->readWriteResources[i].fixedBindSetOrSpace,
|
||||
sh.refl->readWriteResources[i].fixedBindNumber,
|
||||
sh.refl->readWriteResources[i].bindArraySize);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t maxSlot = uint32_t(feedbackStorageSize / sizeof(uint32_t));
|
||||
uint32_t maxSlot = uint32_t(feedbackData.feedbackStorageSize / sizeof(uint32_t));
|
||||
|
||||
// add some extra padding just in case of out-of-bounds writes
|
||||
feedbackStorageSize += 128;
|
||||
feedbackData.feedbackStorageSize += 128;
|
||||
|
||||
// if we don't have any array descriptors or printf's to feedback then just return now
|
||||
if(offsetMap.empty() && !usesPrintf)
|
||||
if(feedbackData.offsetMap.empty() && !usesPrintf)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!m_pDriver->GetDeviceEnabledFeatures().shaderInt64 && feedbackStorageSize > 0xffff0000U)
|
||||
if(!m_pDriver->GetDeviceEnabledFeatures().shaderInt64 &&
|
||||
feedbackData.feedbackStorageSize > 0xffff0000U)
|
||||
{
|
||||
RDCLOG(
|
||||
"Feedback buffer is too large for 32-bit addressed maths, and device doesn't support "
|
||||
@@ -1724,7 +1811,7 @@ bool VulkanReplay::FetchShaderFeedback(uint32_t eventId)
|
||||
VkResult vkr = VK_SUCCESS;
|
||||
VkDevice dev = m_Device;
|
||||
|
||||
if(feedbackStorageSize > m_BindlessFeedback.FeedbackBuffer.sz)
|
||||
if(feedbackData.feedbackStorageSize > m_BindlessFeedback.FeedbackBuffer.sz)
|
||||
{
|
||||
uint32_t flags = GPUBuffer::eGPUBufferGPULocal | GPUBuffer::eGPUBufferSSBO;
|
||||
|
||||
@@ -1732,7 +1819,8 @@ bool VulkanReplay::FetchShaderFeedback(uint32_t eventId)
|
||||
flags |= GPUBuffer::eGPUBufferAddressable;
|
||||
|
||||
m_BindlessFeedback.FeedbackBuffer.Destroy();
|
||||
m_BindlessFeedback.FeedbackBuffer.Create(m_pDriver, dev, feedbackStorageSize, 1, flags);
|
||||
m_BindlessFeedback.FeedbackBuffer.Create(m_pDriver, dev, feedbackData.feedbackStorageSize, 1,
|
||||
flags);
|
||||
}
|
||||
|
||||
VkDeviceAddress bufferAddress = 0;
|
||||
@@ -1853,16 +1941,16 @@ bool VulkanReplay::FetchShaderFeedback(uint32_t eventId)
|
||||
if(m_pDriver->GetDeviceEnabledFeatures().shaderInt64)
|
||||
{
|
||||
AnnotateShader<uint64_t>(*pipeInfo.shaders[5].refl, *pipeInfo.shaders[5].patchData,
|
||||
ShaderStage(StageIndex(stage.stage)), stage.pName, offsetMap,
|
||||
maxSlot, false, bufferAddress, useBufferAddressKHR, false, modSpirv,
|
||||
printfData[5]);
|
||||
ShaderStage(StageIndex(stage.stage)), stage.pName,
|
||||
feedbackData.offsetMap, maxSlot, false, bufferAddress,
|
||||
useBufferAddressKHR, false, modSpirv, printfData[5]);
|
||||
}
|
||||
else
|
||||
{
|
||||
AnnotateShader<uint32_t>(*pipeInfo.shaders[5].refl, *pipeInfo.shaders[5].patchData,
|
||||
ShaderStage(StageIndex(stage.stage)), stage.pName, offsetMap,
|
||||
maxSlot, false, bufferAddress, useBufferAddressKHR, false, modSpirv,
|
||||
printfData[5]);
|
||||
ShaderStage(StageIndex(stage.stage)), stage.pName,
|
||||
feedbackData.offsetMap, maxSlot, false, bufferAddress,
|
||||
useBufferAddressKHR, false, modSpirv, printfData[5]);
|
||||
}
|
||||
|
||||
if(!Vulkan_Debug_FeedbackDumpDirPath().empty())
|
||||
@@ -1946,16 +2034,16 @@ bool VulkanReplay::FetchShaderFeedback(uint32_t eventId)
|
||||
else if(m_pDriver->GetDeviceEnabledFeatures().shaderInt64)
|
||||
{
|
||||
AnnotateShader<uint64_t>(*pipeInfo.shaders[idx].refl, *pipeInfo.shaders[idx].patchData,
|
||||
ShaderStage(StageIndex(stage.stage)), stage.pName, offsetMap,
|
||||
maxSlot, usePrimitiveID, bufferAddress, useBufferAddressKHR,
|
||||
usesMultiview, modSpirv, printfData[idx]);
|
||||
ShaderStage(StageIndex(stage.stage)), stage.pName,
|
||||
feedbackData.offsetMap, maxSlot, usePrimitiveID, bufferAddress,
|
||||
useBufferAddressKHR, usesMultiview, modSpirv, printfData[idx]);
|
||||
}
|
||||
else
|
||||
{
|
||||
AnnotateShader<uint32_t>(*pipeInfo.shaders[idx].refl, *pipeInfo.shaders[idx].patchData,
|
||||
ShaderStage(StageIndex(stage.stage)), stage.pName, offsetMap,
|
||||
maxSlot, usePrimitiveID, bufferAddress, useBufferAddressKHR,
|
||||
usesMultiview, modSpirv, printfData[idx]);
|
||||
ShaderStage(StageIndex(stage.stage)), stage.pName,
|
||||
feedbackData.offsetMap, maxSlot, usePrimitiveID, bufferAddress,
|
||||
useBufferAddressKHR, usesMultiview, modSpirv, printfData[idx]);
|
||||
}
|
||||
|
||||
if(!Vulkan_Debug_FeedbackDumpDirPath().empty())
|
||||
@@ -2025,7 +2113,7 @@ bool VulkanReplay::FetchShaderFeedback(uint32_t eventId)
|
||||
|
||||
// fill destination buffer with 0s to ensure a baseline to then feedback against
|
||||
ObjDisp(dev)->CmdFillBuffer(Unwrap(cmd), Unwrap(m_BindlessFeedback.FeedbackBuffer.buf), 0,
|
||||
feedbackStorageSize, 0);
|
||||
feedbackData.feedbackStorageSize, 0);
|
||||
|
||||
VkBufferMemoryBarrier feedbackbufBarrier = {
|
||||
VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
|
||||
@@ -2036,7 +2124,7 @@ bool VulkanReplay::FetchShaderFeedback(uint32_t eventId)
|
||||
VK_QUEUE_FAMILY_IGNORED,
|
||||
Unwrap(m_BindlessFeedback.FeedbackBuffer.buf),
|
||||
0,
|
||||
feedbackStorageSize,
|
||||
feedbackData.feedbackStorageSize,
|
||||
};
|
||||
|
||||
// wait for the above fill to finish.
|
||||
@@ -2069,22 +2157,51 @@ bool VulkanReplay::FetchShaderFeedback(uint32_t eventId)
|
||||
bytebuf data;
|
||||
GetBufferData(GetResID(m_BindlessFeedback.FeedbackBuffer.buf), 0, 0, data);
|
||||
|
||||
for(auto it = offsetMap.begin(); it != offsetMap.end(); ++it)
|
||||
for(auto it = feedbackData.offsetMap.begin(); it != feedbackData.offsetMap.end(); ++it)
|
||||
{
|
||||
uint32_t *feedbackData = (uint32_t *)(data.data() + it->second.offset);
|
||||
uint32_t *readbackData = (uint32_t *)(data.data() + it->second.offset);
|
||||
|
||||
BindpointIndex used;
|
||||
used.bindset = it->first.set;
|
||||
used.bind = it->first.binding;
|
||||
|
||||
ShaderReflection *refl = stageRefls[(uint32_t)it->first.stage];
|
||||
if(refl)
|
||||
{
|
||||
if(it->first.index.category == DescriptorCategory::ConstantBlock)
|
||||
{
|
||||
used.bindset = refl->constantBlocks[it->first.index.index].fixedBindSetOrSpace;
|
||||
used.bind = refl->constantBlocks[it->first.index.index].fixedBindNumber;
|
||||
}
|
||||
else if(it->first.index.category == DescriptorCategory::Sampler)
|
||||
{
|
||||
used.bindset = refl->samplers[it->first.index.index].fixedBindSetOrSpace;
|
||||
used.bind = refl->samplers[it->first.index.index].fixedBindNumber;
|
||||
}
|
||||
else if(it->first.index.category == DescriptorCategory::ReadOnlyResource)
|
||||
{
|
||||
used.bindset = refl->readOnlyResources[it->first.index.index].fixedBindSetOrSpace;
|
||||
used.bind = refl->readOnlyResources[it->first.index.index].fixedBindNumber;
|
||||
}
|
||||
else if(it->first.index.category == DescriptorCategory::ReadWriteResource)
|
||||
{
|
||||
used.bindset = refl->readWriteResources[it->first.index.index].fixedBindSetOrSpace;
|
||||
used.bind = refl->readWriteResources[it->first.index.index].fixedBindNumber;
|
||||
}
|
||||
}
|
||||
|
||||
DescriptorAccess access = it->second.access;
|
||||
|
||||
for(uint32_t i = 0; i < it->second.numEntries; i++)
|
||||
{
|
||||
if(feedbackData[i])
|
||||
if(readbackData[i])
|
||||
{
|
||||
used.arrayIndex = i;
|
||||
access.arrayElement = i;
|
||||
|
||||
result.used.push_back(used);
|
||||
result.access.push_back(access);
|
||||
}
|
||||
|
||||
access.byteOffset++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user