Add a helper for running an action with proper barriers for feedback

This commit is contained in:
baldurk
2025-02-10 17:52:29 +00:00
parent 7369b8ad6c
commit 4ad2deb049
5 changed files with 91 additions and 120 deletions
+62 -1
View File
@@ -3652,6 +3652,67 @@ void VulkanReplay::PrepareStateForPatchedShader(
});
}
bool VulkanReplay::RunFeedbackAction(VkDeviceSize bufferSize, const ActionDescription *action,
VulkanRenderState &modifiedstate)
{
VkResult vkr = VK_SUCCESS;
VkDevice dev = m_Device;
VkCommandBuffer cmd = m_pDriver->GetNextCmd();
if(cmd == VK_NULL_HANDLE)
return false;
VkCommandBufferBeginInfo beginInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, NULL,
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT};
vkr = ObjDisp(dev)->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
CHECK_VKR(m_pDriver, vkr);
// fill destination buffer with 0s to ensure a baseline to then feedback against
ObjDisp(dev)->CmdFillBuffer(Unwrap(cmd), m_PatchedShaderFeedback.FeedbackBuffer.UnwrappedBuffer(),
0, bufferSize, 0);
VkBufferMemoryBarrier feedbackbufBarrier = {
VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
NULL,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_ACCESS_SHADER_WRITE_BIT,
VK_QUEUE_FAMILY_IGNORED,
VK_QUEUE_FAMILY_IGNORED,
m_PatchedShaderFeedback.FeedbackBuffer.UnwrappedBuffer(),
0,
bufferSize,
};
// wait for the above fill to finish.
DoPipelineBarrier(cmd, 1, &feedbackbufBarrier);
if(action->flags & ActionFlags::Dispatch)
{
modifiedstate.BindPipeline(m_pDriver, cmd, VulkanRenderState::BindCompute, true);
ObjDisp(cmd)->CmdDispatch(Unwrap(cmd), action->dispatchDimension[0],
action->dispatchDimension[1], action->dispatchDimension[2]);
}
else
{
modifiedstate.BeginRenderPassAndApplyState(m_pDriver, cmd, VulkanRenderState::BindGraphics,
false);
m_pDriver->ReplayDraw(cmd, *action);
modifiedstate.EndRenderPass(cmd);
}
vkr = ObjDisp(dev)->EndCommandBuffer(Unwrap(cmd));
CHECK_VKR(m_pDriver, vkr);
m_pDriver->SubmitCmds();
m_pDriver->FlushQ();
return true;
}
void VulkanDebugManager::CustomShaderRendering::Destroy(WrappedVulkan *driver)
{
driver->vkDestroyRenderPass(driver->GetDev(), TexRP, NULL);
@@ -3737,7 +3798,7 @@ void VulkanReplay::CreateResources()
m_StorageMode = BufferStorageMode::Descriptor;
}
m_BindlessFeedback.m_StorageMode = m_StorageMode;
m_PatchedShaderFeedback.m_StorageMode = m_StorageMode;
GpaVkContextOpenInfo context = {Unwrap(m_pDriver->GetInstance()), Unwrap(m_pDriver->GetPhysDev()),
Unwrap(m_pDriver->GetDev())};
+2 -2
View File
@@ -2153,7 +2153,7 @@ void VulkanReplay::SavePipelineState(uint32_t eventId)
&state.compute.descSets,
};
const VKDynamicShaderFeedback &usage = m_BindlessFeedback.Usage[eventId];
const VKDynamicShaderFeedback &usage = m_BindlessFeedback[eventId];
ret.shaderMessages = usage.messages;
@@ -2680,7 +2680,7 @@ rdcarray<DescriptorAccess> VulkanReplay::GetDescriptorAccess(uint32_t eventId)
access = DescriptorAccess();
}
const VKDynamicShaderFeedback &usage = m_BindlessFeedback.Usage[eventId];
const VKDynamicShaderFeedback &usage = m_BindlessFeedback[eventId];
if(usage.valid)
ret.append(usage.access);
+5 -2
View File
@@ -546,6 +546,9 @@ private:
rdcarray<uint32_t> &modSpirv, const VkSpecializationInfo *&specInfo)>
stagePatchCallback);
bool RunFeedbackAction(VkDeviceSize bufferSize, const ActionDescription *action,
VulkanRenderState &modifiedstate);
VulkanDebugManager *GetDebugManager();
VulkanResourceManager *GetResourceManager();
@@ -848,9 +851,9 @@ private:
BufferStorageMode m_StorageMode;
GPUBuffer FeedbackBuffer;
} m_PatchedShaderFeedback;
std::map<uint32_t, VKDynamicShaderFeedback> Usage;
} m_BindlessFeedback;
std::map<uint32_t, VKDynamicShaderFeedback> m_BindlessFeedback;
ShaderDebugData m_ShaderDebugData;
+12 -68
View File
@@ -1472,12 +1472,12 @@ void AnnotateShader(const ShaderReflection &refl, const SPIRVPatchData &patchDat
void VulkanReplay::ClearFeedbackCache()
{
m_BindlessFeedback.Usage.clear();
m_BindlessFeedback.clear();
}
bool VulkanReplay::FetchShaderFeedback(uint32_t eventId)
{
if(m_BindlessFeedback.Usage.find(eventId) != m_BindlessFeedback.Usage.end())
if(m_BindlessFeedback.find(eventId) != m_BindlessFeedback.end())
return false;
if(!Vulkan_BindlessFeedback())
@@ -1485,7 +1485,7 @@ bool VulkanReplay::FetchShaderFeedback(uint32_t eventId)
// create it here so we won't re-run any code if the event is re-selected. We'll mark it as valid
// if it actually has any data in it later.
VKDynamicShaderFeedback &result = m_BindlessFeedback.Usage[eventId];
VKDynamicShaderFeedback &result = m_BindlessFeedback[eventId];
const VulkanRenderState &state = m_pDriver->m_RenderState;
VulkanCreationInfo &creationInfo = m_pDriver->m_CreationInfo;
@@ -1680,13 +1680,7 @@ bool VulkanReplay::FetchShaderFeedback(uint32_t eventId)
}
}
// we go through the driver for all these creations since they need to be properly
// registered in order to be put in the partial replay state. Our patched shader is valid so we
// don't need to replay after doing the feedback execute
VkResult vkr = VK_SUCCESS;
VkDevice dev = m_Device;
m_BindlessFeedback.ResizeFeedbackBuffer(m_pDriver, feedbackData.feedbackStorageSize);
m_PatchedShaderFeedback.ResizeFeedbackBuffer(m_pDriver, feedbackData.feedbackStorageSize);
rdcarray<VkDescriptorSetLayoutBinding> newBindings = {
{
@@ -1712,7 +1706,8 @@ bool VulkanReplay::FetchShaderFeedback(uint32_t eventId)
return false;
if(!patchedBufferdata.descSets.empty())
m_BindlessFeedback.FeedbackBuffer.WriteDescriptor(Unwrap(patchedBufferdata.descSets[0]), 0, 0);
m_PatchedShaderFeedback.FeedbackBuffer.WriteDescriptor(Unwrap(patchedBufferdata.descSets[0]), 0,
0);
std::map<uint32_t, PrintfData> printfData[NumShaderStages];
@@ -1752,14 +1747,14 @@ bool VulkanReplay::FetchShaderFeedback(uint32_t eventId)
{
AnnotateShader<uint64_t>(*pipeInfo.shaders[idx].refl, *pipeInfo.shaders[idx].patchData,
ShaderStage(idx), entryName, feedbackData.offsetMap, maxSlot,
usePrimitiveID, m_BindlessFeedback.FeedbackBuffer.Address(),
usePrimitiveID, m_PatchedShaderFeedback.FeedbackBuffer.Address(),
m_StorageMode, usesMultiview, modSpirv, printfData[idx]);
}
else
{
AnnotateShader<uint32_t>(*pipeInfo.shaders[idx].refl, *pipeInfo.shaders[idx].patchData,
ShaderStage(idx), entryName, feedbackData.offsetMap, maxSlot,
usePrimitiveID, m_BindlessFeedback.FeedbackBuffer.Address(),
usePrimitiveID, m_PatchedShaderFeedback.FeedbackBuffer.Address(),
m_StorageMode, usesMultiview, modSpirv, printfData[idx]);
}
@@ -1768,65 +1763,14 @@ bool VulkanReplay::FetchShaderFeedback(uint32_t eventId)
return true;
};
PrepareStateForPatchedShader(patchedBufferdata, modifiedstate, result.compute, patchCallback);
{
VkCommandBuffer cmd = m_pDriver->GetNextCmd();
if(cmd == VK_NULL_HANDLE)
return false;
VkCommandBufferBeginInfo beginInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, NULL,
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT};
vkr = ObjDisp(dev)->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
CHECK_VKR(m_pDriver, vkr);
// fill destination buffer with 0s to ensure a baseline to then feedback against
ObjDisp(dev)->CmdFillBuffer(Unwrap(cmd), m_BindlessFeedback.FeedbackBuffer.UnwrappedBuffer(), 0,
feedbackData.feedbackStorageSize, 0);
VkBufferMemoryBarrier feedbackbufBarrier = {
VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
NULL,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_ACCESS_SHADER_WRITE_BIT,
VK_QUEUE_FAMILY_IGNORED,
VK_QUEUE_FAMILY_IGNORED,
m_BindlessFeedback.FeedbackBuffer.UnwrappedBuffer(),
0,
feedbackData.feedbackStorageSize,
};
// wait for the above fill to finish.
DoPipelineBarrier(cmd, 1, &feedbackbufBarrier);
if(result.compute)
{
modifiedstate.BindPipeline(m_pDriver, cmd, VulkanRenderState::BindCompute, true);
ObjDisp(cmd)->CmdDispatch(Unwrap(cmd), action->dispatchDimension[0],
action->dispatchDimension[1], action->dispatchDimension[2]);
}
else
{
modifiedstate.BeginRenderPassAndApplyState(m_pDriver, cmd, VulkanRenderState::BindGraphics,
false);
m_pDriver->ReplayDraw(cmd, *action);
modifiedstate.EndRenderPass(cmd);
}
vkr = ObjDisp(dev)->EndCommandBuffer(Unwrap(cmd));
CHECK_VKR(m_pDriver, vkr);
m_pDriver->SubmitCmds();
m_pDriver->FlushQ();
}
if(!RunFeedbackAction(feedbackData.feedbackStorageSize, action, modifiedstate))
return false;
bytebuf data;
GetDebugManager()->GetBufferData(m_BindlessFeedback.FeedbackBuffer, 0, 0, data);
GetDebugManager()->GetBufferData(m_PatchedShaderFeedback.FeedbackBuffer, 0, 0, data);
for(auto it = feedbackData.offsetMap.begin(); it != feedbackData.offsetMap.end(); ++it)
{
+10 -47
View File
@@ -3942,9 +3942,6 @@ ShaderDebugTrace *VulkanReplay::DebugPixel(uint32_t eventId, uint32_t x, uint32_
return new ShaderDebugTrace;
}
VkDevice dev = m_pDriver->GetDev();
VkResult vkr = VK_SUCCESS;
uint32_t sample = inputs.sample;
uint32_t primitive = inputs.primitive;
uint32_t view = inputs.view;
@@ -4125,7 +4122,7 @@ ShaderDebugTrace *VulkanReplay::DebugPixel(uint32_t eventId, uint32_t x, uint32_
feedbackStorageSize);
}
m_BindlessFeedback.ResizeFeedbackBuffer(m_pDriver, feedbackStorageSize);
m_PatchedShaderFeedback.ResizeFeedbackBuffer(m_pDriver, feedbackStorageSize);
struct SpecData
{
@@ -4168,9 +4165,10 @@ ShaderDebugTrace *VulkanReplay::DebugPixel(uint32_t eventId, uint32_t x, uint32_
}
if(!patchedBufferdata.descSets.empty())
m_BindlessFeedback.FeedbackBuffer.WriteDescriptor(Unwrap(patchedBufferdata.descSets[0]), 0, 0);
m_PatchedShaderFeedback.FeedbackBuffer.WriteDescriptor(Unwrap(patchedBufferdata.descSets[0]), 0,
0);
specData.bufferAddress = m_BindlessFeedback.FeedbackBuffer.Address();
specData.bufferAddress = m_PatchedShaderFeedback.FeedbackBuffer.Address();
if(specData.bufferAddress && Vulkan_Debug_ShaderDebugLogging())
{
RDCLOG("Got buffer address of %llu", specData.bufferAddress);
@@ -4249,53 +4247,18 @@ ShaderDebugTrace *VulkanReplay::DebugPixel(uint32_t eventId, uint32_t x, uint32_
PrepareStateForPatchedShader(patchedBufferdata, modifiedstate, false, patchCallback);
if(!RunFeedbackAction(feedbackStorageSize, action, modifiedstate))
{
VkCommandBuffer cmd = m_pDriver->GetNextCmd();
delete apiWrapper;
if(cmd == VK_NULL_HANDLE)
return new ShaderDebugTrace;
ShaderDebugTrace *ret = new ShaderDebugTrace;
ret->stage = ShaderStage::Pixel;
VkCommandBufferBeginInfo beginInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, NULL,
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT};
vkr = ObjDisp(dev)->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
CHECK_VKR(m_pDriver, vkr);
// fill destination buffer with 0s to ensure a baseline to then feedback against
ObjDisp(dev)->CmdFillBuffer(Unwrap(cmd), m_BindlessFeedback.FeedbackBuffer.UnwrappedBuffer(), 0,
feedbackStorageSize, 0);
VkBufferMemoryBarrier feedbackbufBarrier = {
VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
NULL,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_ACCESS_SHADER_WRITE_BIT,
VK_QUEUE_FAMILY_IGNORED,
VK_QUEUE_FAMILY_IGNORED,
m_BindlessFeedback.FeedbackBuffer.UnwrappedBuffer(),
0,
feedbackStorageSize,
};
// wait for the above fill to finish.
DoPipelineBarrier(cmd, 1, &feedbackbufBarrier);
modifiedstate.BeginRenderPassAndApplyState(m_pDriver, cmd, VulkanRenderState::BindGraphics,
false);
m_pDriver->ReplayDraw(cmd, *action);
modifiedstate.EndRenderPass(cmd);
vkr = ObjDisp(dev)->EndCommandBuffer(Unwrap(cmd));
CHECK_VKR(m_pDriver, vkr);
m_pDriver->SubmitCmds();
m_pDriver->FlushQ();
return ret;
}
bytebuf data;
GetDebugManager()->GetBufferData(m_BindlessFeedback.FeedbackBuffer, 0, 0, data);
GetDebugManager()->GetBufferData(m_PatchedShaderFeedback.FeedbackBuffer, 0, 0, data);
byte *base = data.data();
uint32_t numHits = ((uint32_t *)base)[0];