如何使用信号量调度传输队列上的副本?



我的目标是使用vkCmdCopyBuffer的传输队列,该队列通过来自计算着色器队列的信号量发出信号。计算着色器运行在一个图形队列上,目的是向传输队列发出信号,以便将其复制到主机,同时也向渲染发出信号。我的目标是在与图形队列不同的队列上完成对主机的复制。

我目前得到的错误信息:

VULKAN>ERROR(violation): Validation ERROR: [UNASSIGNED-CoreValidation-DrawState-QueueForwardProgress] Object 0: handle = 0x301e6c0000000022, type = VK_OBJECT_TYPE_SEMAPHORE;对象1:handle = 0x21d51d0ac80, type = VK_OBJECT_TYPE_QUEUE;对象2:handle = 0x21d51d0ac80, type = VK_OBJECT_TYPE_QUEUE;| MessageID = 0xe825f293 | vkqueuessubmit (): psubmitted [0].pSignalSemaphores[1]正在发送VkQueue 0x21d51d0ac80[] (VkSemaphore 0x301e6c0000000022[]),该信号先前由VkQueue 0x21d51d0ac80[]发出,但此后没有任何队列等待。

计算着色器提交:

void Renderer::runCompute()
{
VkSemaphore waitSemaphores[]      = { mComputeReadySemaphore };
VkSemaphore signalSemaphores[]    = { mComputeFinishedSemaphoreGraphics, mComputeFinishedSemaphoreTransfer };
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT };
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
if (mHasDispatchedCompute) [[likely]]
{
submitInfo.waitSemaphoreCount = ARR_LEN(waitSemaphores);
submitInfo.pWaitSemaphores    = waitSemaphores;
submitInfo.pWaitDstStageMask  = waitStages;
}
else
{
mHasDispatchedCompute = true;
}
submitInfo.signalSemaphoreCount = ARR_LEN(signalSemaphores);
submitInfo.pSignalSemaphores    = signalSemaphores;
submitInfo.commandBufferCount   = 1;
submitInfo.pCommandBuffers      = &mComputeCommandBuffer;
if (vkQueueSubmit(mpGraphicsQueue, 1, &submitInfo, VK_NULL_HANDLE) != VK_SUCCESS)
throw std::runtime_error("Failed to submit command buffer!");
}

,传输队列提交:

void Renderer::runTransfer()
{
VkSemaphore waitSemaphores[]      = { mComputeFinishedSemaphoreTransfer };
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_ALL_COMMANDS_BIT };
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
if (mHasDispatchedTransfer) [[likely]]
{
submitInfo.waitSemaphoreCount = ARR_LEN(waitSemaphores);
submitInfo.pWaitSemaphores    = waitSemaphores;
submitInfo.pWaitDstStageMask  = waitStages;
}
else
{
mHasDispatchedTransfer = true;
}
submitInfo.commandBufferCount   = 1;
submitInfo.pCommandBuffers      = &mTransferCommandBuffer;
if (vkQueueSubmit(mpTransferQueue, 1, &submitInfo, mTransferReadFence) != VK_SUCCESS)
throw std::runtime_error("Failed to submit command buffer!");
}

在这里调用:

constexpr uint32_t SINGLE_FRAME_RENDERING = 0;
vkWaitForFences(mpLogicDevice, 1, &mTransferReadFence, VK_TRUE, UINT64_MAX);
updateFrame(SINGLE_FRAME_RENDERING);
vkResetFences(mpLogicDevice, 1, &mTransferReadFence);
runCompute();
runTransfer();
auto imageIndex = prepareFrame();
// Submit the command buffer
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
VkSemaphore waitSemaphores[]      = { mImageAvailableSemaphores[SINGLE_FRAME_RENDERING], mComputeFinishedSemaphoreGraphics };
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT };
submitInfo.waitSemaphoreCount     = ARR_LEN(waitSemaphores);
submitInfo.pWaitSemaphores        = waitSemaphores;
submitInfo.pWaitDstStageMask      = waitStages;
submitInfo.commandBufferCount     = 1;
submitInfo.pCommandBuffers        = &mGraphicsCommandBuffers[createCommandBuffersOnce() ? imageIndex : SINGLE_FRAME_RENDERING];
VkSemaphore signalSemaphores[]    = { mRenderFinishedSemaphores[SINGLE_FRAME_RENDERING], mComputeReadySemaphore };
submitInfo.signalSemaphoreCount   = ARR_LEN(signalSemaphores);
submitInfo.pSignalSemaphores      = signalSemaphores;
if (vkQueueSubmit(mpGraphicsQueue, 1, &submitInfo, mInFlightFences[SINGLE_FRAME_RENDERING]) != VK_SUCCESS)
throw std::runtime_error("Failed to submit draw command buffer!");
submitFrame(signalSemaphores, imageIndex);

其中updateFrame()是主机对缓冲区的操作,prepareFrame()是交换链图像采集,submitFrame()调用vkQueuePresentKHR()

if(mHasDispatchedTransfer)可以取消对信号量mComputeFinishedSemaphoreTransfer的等待,但是信号量在runCompute()中是无条件的。如果mHasDispatchedTransferfalse,这将导致信号量被重复发出而不需要等待。

最新更新