无法与渲染并行获取和呈现? [英] Impossible to acquire and present in parallel with rendering?

查看:27
本文介绍了无法与渲染并行获取和呈现?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意:我正在自学 Vulkan,对现代 OpenGL 知之甚少.

Note: I'm self-learning Vulkan with little knowledge of modern OpenGL.

阅读 Vulkan 规范,我可以看到非常好的信号量,允许命令缓冲区和交换链同步.以下是我所理解的一种简单(但我认为效率低下)的做事方式:

Reading the Vulkan specifications, I can see very nice semaphores that allow the command buffer and the swapchain to synchronize. Here's what I understand to be a simple (yet I think inefficient) way of doing things:

  1. 使用vkAcquireNextImageKHR获取图像,信号sem_post_acq
  2. 构建命令缓冲区(或使用预构建):
    • 图像屏障使图像远离VK_IMAGE_LAYOUT_UNDEFINED
    • 渲染
    • 将图像转换为VK_IMAGE_LAYOUT_PRESENT_SRC_KHR的图像屏障
  1. Get image with vkAcquireNextImageKHR, signalling sem_post_acq
  2. Build command buffer (or use pre-built) with:
    • Image barrier to transition image away from VK_IMAGE_LAYOUT_UNDEFINED
    • render
    • Image barrier to transition image to VK_IMAGE_LAYOUT_PRESENT_SRC_KHR

这里的问题是命令缓冲区中的图像屏障必须知道它们正在转换哪个图像,这意味着 vkAcquireNextImageKHR 必须在知道如何构建命令缓冲区(或哪个预构建命令缓冲区以提交).但是 vkAcquireNextImageKHR 可能会睡很多(因为演示引擎很忙并且没有免费图像).另一方面,提交命令缓冲区本身成本很高,更重要的是,片段之前的所有阶段都可以运行,而无需知道最终结果将呈现到哪个图像.

The problem here is that the image barriers in the command buffer must know which image they are transitioning, which means that vkAcquireNextImageKHR must return before one knows how to build the command buffer (or which pre-built command buffer to submit). But vkAcquireNextImageKHR could potentially sleep a lot (because the presentation engine is busy and there are no free images). On the other hand, the submission of the command buffer is costly itself, and more importantly, all stages before fragment can run without having any knowledge of which image the final result will be rendered to.

理论上,在我看来,类似以下的方案将允许更高程度的并行性:

Theoretically, it seems to me that a scheme like the following would allow a higher degree of parallelism:

  1. 构建命令缓冲区(或使用预构建):
    • 图像屏障使图像远离VK_IMAGE_LAYOUT_UNDEFINED
    • 渲染
    • 将图像转换为VK_IMAGE_LAYOUT_PRESENT_SRC_KHR的图像屏障

理论上,这将允许管道一直执行到片段着色器,同时我们等待 vkAcquireNextImageKHR.这不起作用的唯一原因是既不可能告诉命令缓冲区此图像将在稍后确定(通过适当的同步),也不可能向呈现引擎询问特定图像.

Which would, again theoretically, allow the pipeline to execute all the way up to the fragment shader, while we wait for vkAcquireNextImageKHR. The only reason this doesn't work is that it is neither possible to tell the command buffer that this image will be determined later (with proper synchronization), nor is it possible to ask the presentation engine for a specific image.

我的第一个问题是:我的分析是否正确?如果是这样,这样的优化在 Vulkan 中根本不可能吗?为什么不呢?

My first question is: is my analysis correct? If so, is such an optimization not possible in Vulkan at all and why not?

我的第二个问题是:如果您可以告诉 vkAcquireNextImageKHR 您想要获取哪个特定图像,并自己遍历它们,会不会更有意义?这样,您就可以提前知道要请求哪个图像,并相应地构建和提交您的命令缓冲区.

My second question is: wouldn't it have made more sense if you could tell vkAcquireNextImageKHR which particular image you want to acquire, and iterate through them yourself? That way, you could know in advance which image you are going to ask for, and build and submit your command buffer accordingly.

推荐答案

就像 Nicol 所说的那样,您可以独立于将渲染到哪个图像来记录辅助.

Like Nicol said you can record secondaries independent of which image it will be rendering to.

但是,您可以更进一步,提前记录所有 swpachain 图像的命令缓冲区,然后从获取的图像中选择正确的提交.

However you can take it a step further and record command buffers for all swpachain images in advance and select the correct one to submit from the image acquired.

这种类型的重用确实需要考虑一些额外的因素,因为使用的所有内存范围都被烘焙到命令缓冲区中.但在许多情况下,所需的渲染命令实际上不会将一帧更改为下一帧,只是使用了一点点数据.

This type of reuse does take some extra consideration into account because all memory ranges used are baked into the command buffer. But in many situations the required render commands don't actually change frame one frame to the next, only a little bit of the data used.

所以这样一个帧的顺序是:

So the sequence of such a frame would be:

vkAcquireNextImageKHR(vk.dev, vk.swap, 0, vk.acquire, VK_NULL_HANDLE, &vk.image_ind);
vkWaitForFences(vk.dev, 1, &vk.fences[vk.image_ind], true, ~0);

engine_update_render_data(vk.mapped_staging[vk.image_ind]);

VkSubmitInfo submit = build_submit(vk.acquire, vk.rend_cmd[vk.image_ind], vk.present);
vkQueueSubmit(vk.rend_queue, 1, &submit, vk.fences[vk.image_ind]);

VkPresentInfoKHR present = build_present(vk.present, vk.swap, vk.image_ind);
vkQueuePresentKHR(vk.queue, &present);

当然,这不允许条件渲染,但 gpu 通常足够快,允许在帧外渲染某些几何图形而没有任何明显的延迟.因此,在玩家到达必须显示新几何体的加载区域之前,您可以保持这些命令缓冲区处于活动状态.

Granted this does not allow for conditional rendering but the gpu is in general fast enough to allow some geometry to be rendered out of frame without any noticeable delays. So until the player reaches a loading zone where new geometry has to be displayed you can keep those command buffers alive.

这篇关于无法与渲染并行获取和呈现?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆