我在这里不太明白。:https://github.com/SaschaWillems/Vulkan/blob/master/examples/computeshader/computeshader.cpp
void draw()
{
VulkanExampleBase::prepareFrame();
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer];
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
VulkanExampleBase::submitFrame();
// Submit compute commands
// Use a fence to ensure that compute command buffer has finished executin before using it again
vkWaitForFences(device, 1, &compute.fence, VK_TRUE, UINT64_MAX);
vkResetFences(device, 1, &compute.fence);
VkSubmitInfo computeSubmitInfo = vks::initializers::submitInfo();
computeSubmitInfo.commandBufferCount = 1;
computeSubmitInfo.pCommandBuffers = &compute.commandBuffer;
VK_CHECK_RESULT(vkQueueSubmit(compute.queue, 1, &computeSubmitInfo, compute.fence));
}drawCmdBufferscurrentBuffer运行在compute.commandBuffer之前,但是消费者drawCmdBufferscurrentBuffer需要生产者compute.commandBuffer生成的textureComputeTarget。
在下面的代码中,只有第一个帧被呈现,而正确的图片没有得到textureComputeTarget,所以它是用蓝色背景呈现的。
void draw()
{
VulkanExampleBase::prepareFrame();
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer];
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
VulkanExampleBase::submitFrame();
// Submit compute commands
// Use a fence to ensure that compute command buffer has finished executin before using it again
vkWaitForFences(device, 1, &compute.fence, VK_TRUE, UINT64_MAX);
vkResetFences(device, 1, &compute.fence);
VkSubmitInfo computeSubmitInfo = vks::initializers::submitInfo();
computeSubmitInfo.commandBufferCount = 1;
computeSubmitInfo.pCommandBuffers = &compute.commandBuffer;
VK_CHECK_RESULT(vkQueueSubmit(compute.queue, 1, &computeSubmitInfo, compute.fence));
sleep(1000) // <-------- Wait
}调用vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)时执行
VkImageMemoryBarrier imageMemoryBarrier = {};
imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
// We won't be changing the layout of the image
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
imageMemoryBarrier.image = textureComputeTarget.image;
imageMemoryBarrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
imageMemoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
vkCmdPipelineBarrier(
drawCmdBuffers[i],
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_FLAGS_NONE,
0, nullptr,
0, nullptr,
1, &imageMemoryBarrier);
vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);在第6.6节中,管道屏障vkCmdPipelineBarrier是一个同步命令,它在提交给相同队列的命令之间或在相同子传递中的命令之间插入依赖项。
void draw()
{
printf("%p, %p\n", queue, compute.queue);
VulkanExampleBase::prepareFrame();
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer];
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
VulkanExampleBase::submitFrame();
// Submit compute commands
// Use a fence to ensure that compute command buffer has finished executin before using it again
vkWaitForFences(device, 1, &compute.fence, VK_TRUE, UINT64_MAX);
vkResetFences(device, 1, &compute.fence);
VkSubmitInfo computeSubmitInfo = vks::initializers::submitInfo();
computeSubmitInfo.commandBufferCount = 1;
computeSubmitInfo.pCommandBuffers = &compute.commandBuffer;
VK_CHECK_RESULT(vkQueueSubmit(compute.queue, 1, &computeSubmitInfo, compute.fence));
sleep(1000);
}打印结果: 0x6000039c4a20,0x6000039c4a20当前队列和compute.queue是相同的queue.But,上面的代码可能会生成不同的队列。
发布于 2019-11-12 14:32:38
不知道,这是个例子。作者可能对第一帧中发生的事情并不十分担心。它只需延迟一个帧即可绘制。在抽签之前交换计算也需要付出一定的努力。
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,但是这个阶段以前还没有执行过,为什么管道没有卡住?是否因为以前没有管道,所以没有必要等待?因为这不是管道和依赖关系的工作方式。vkCmdPipelineBarrier确保在屏障到达(并完成)之前队列中的任何命令\操作至少在到达dstStage后记录的任何命令\op之前的srcStage阶段(即COMPUTE)。
即使以前没有记录命令,这种依赖也是可以满足的。也就是说,根据"nothing“的定义,还没有任何尚未达到COMPUTE阶段的命令。
VkImageMemoryBarrier可以在多个队列中同步吗?是的,在信号灯的帮助下。
对于VK_SHARING_MODE_EXCLUSIVE和不同的队列族,它被称为队列族所有权转移 (QFOT)。
否则,信号量已经执行内存依赖,并且不需要VkImageMemoryBarrier。
vkCmdPipelineBarrier是一个同步命令,它在提交到同一个队列的命令之间或在同一子传递的命令之间插入依赖项。为什么使用“或”,为什么不使用“和”?vkCmdPipelineBarrier不是在子传递之外,而是通过队列中前后记录的命令形成依赖关系。
或者vkCmdPipelineBarrier位于子通道中,在这种情况下,它被称为“子传递自相关性”,并且它的范围仅限于该子通道(以及其他限制)。
https://stackoverflow.com/questions/58817866
复制相似问题