首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >vulkan: VkImageMemoryBarrier

vulkan: VkImageMemoryBarrier
EN

Stack Overflow用户
提问于 2019-11-12 11:33:22
回答 1查看 586关注 0票数 0

我在这里不太明白。:https://github.com/SaschaWillems/Vulkan/blob/master/examples/computeshader/computeshader.cpp

代码语言:javascript
复制
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。

  1. 我不明白为什么drawCmdBufferscurrentBuffer在compute.commandBuffer之前被调用。

在下面的代码中,只有第一个帧被呈现,而正确的图片没有得到textureComputeTarget,所以它是用蓝色背景呈现的。

代码语言:javascript
复制
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)时执行

代码语言:javascript
复制
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);

  1. 等待VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,但是这个阶段以前还没有执行过,为什么管道没有卡住?是否因为以前没有管道,所以没有必要等待?

在第6.6节中,管道屏障vkCmdPipelineBarrier是一个同步命令,它在提交给相同队列的命令之间或在相同子传递中的命令之间插入依赖项。

代码语言:javascript
复制
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,上面的代码可能会生成不同的队列。

  1. VkImageMemoryBarrier可以在多个队列中同步吗?
  2. vkCmdPipelineBarrier是一个同步命令,它在提交到同一个队列的命令之间插入依赖项,在同一子传递中的命令之间插入。为什么使用,为什么不使用
EN

回答 1

Stack Overflow用户

发布于 2019-11-12 14:32:38

  1. 我不明白为什么drawCmdBufferscurrentBuffer在compute.commandBuffer之前被调用。

不知道,这是个例子。作者可能对第一帧中发生的事情并不十分担心。它只需延迟一个帧即可绘制。在抽签之前交换计算也需要付出一定的努力。

  1. 等待VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,但是这个阶段以前还没有执行过,为什么管道没有卡住?是否因为以前没有管道,所以没有必要等待?

因为这不是管道和依赖关系的工作方式。vkCmdPipelineBarrier确保在屏障到达(并完成)之前队列中的任何命令\操作至少在到达dstStage后记录的任何命令\op之前的srcStage阶段(即COMPUTE)。

即使以前没有记录命令,这种依赖也是可以满足的。也就是说,根据"nothing“的定义,还没有任何尚未达到COMPUTE阶段的命令。

  1. VkImageMemoryBarrier可以在多个队列中同步吗?

是的,在信号灯的帮助下。

对于VK_SHARING_MODE_EXCLUSIVE和不同的队列族,它被称为队列族所有权转移 (QFOT)。

否则,信号量已经执行内存依赖,并且不需要VkImageMemoryBarrier

  1. vkCmdPipelineBarrier是一个同步命令,它在提交到同一个队列的命令之间或在同一子传递的命令之间插入依赖项。为什么使用“或”,为什么不使用“和”?

vkCmdPipelineBarrier不是在子传递之外,而是通过队列中前后记录的命令形成依赖关系。

或者vkCmdPipelineBarrier位于子通道中,在这种情况下,它被称为“子传递自相关性”,并且它的范围仅限于该子通道(以及其他限制)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58817866

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档