多线程着色通过 Vulkan
Multithreaded shading pass Vulkan
我目前正在 Vulkan 中使用多线程实现基本的延迟渲染器。由于我的 G-Buffer 应该具有与最终图像相同的分辨率,因此我想在具有多个子通道的单个渲染通道中完成,根据幻灯片 44(第 138 页)上的 this 演示。它说:
- vkCmdBeginCommandBuffer
- vkCmdBeginRenderPass
- vkCmdExecuteCommands
- vkCmdNextSubpass
- vkCmdExecuteCommands
- vkCmdEndRenderPass
- vkCmdEndCommandBuffer
我知道在第一个子通道中,您迭代场景图并为每个 entity/mesh 记录一个辅助命令缓冲区。我不明白的是您应该如何使用辅助命令缓冲区进行着色处理。您是否以某种方式将屏幕分成多个部分并在单独的线程中渲染每个部分,或者只为整个第二个子通道记录一个辅助命令缓冲区?
What I don't get is how you are supposed to do the shading pass with secondary command buffers.
着色通道(可能是第二个子通道)可能会将第一个子通道创建的 G 缓冲区作为 输入附件。然后它将使用来自 G 缓冲区的数据 + 来自一组灯光(或您的延迟着色器试图延迟的任何内容)的数据绘制到相同大小的屏幕大小的四边形。
您link 的演示文稿试图从第 13 页(标记为 "Page 107")开始暗示这种结构样式。
第一步是让它发挥作用。使用例如这个SW example。那么下一步将其优化为单个渲染通道应该更容易。
对我来说,正如您所说,您可能需要为 "building g-buffer subpass" 对命令缓冲区进行多线程处理。然而对于着色通道,它必须取决于你是如何做的。对我来说(再一次),你不需要多线程处理你的着色子通道。但是,您必须考虑到您可以拥有一个 "by region dependency".
所以,我鼓励你这样做。
在开始 RenderPass 之前,使用 Compute Shader 将所有灯光映射到屏幕上(这里有一种 "quad" 的数组)。
我所说的喷溅是指这种事情。你有一个点光源(例如),这个想法是计算受光影响的屏幕 space 中的四边形。这样你就有了 4 个顶点(代表一个四边形),你可以将它们放入 SSBO 中,你可以将它用作着色子通道中的顶点缓冲区。
现在开始渲染过程。
- 如果需要MT场景图渲染。并执行 vkCmdExecuteCommands();
- NextSubpass
- 使用您从较早的计算着色器创建的 "array of quads"(不要忘记 VK_SUBPASS_EXTERNAL 依赖项)。
- NextSubpass 等等
然而,你说
you iterate the scene graph and record one secondary commandbuffer for each entity/mesh.
我不确定我是否真的理解你的意思,但如果你打算为一个网格设置一个辅助命令缓冲区,我真的建议你改变你的做法。您必须使用批处理。假设您要绘制 64000 个不同的网格。例如,您可以创建 64 个命令缓冲区(您在 4 个线程上分派)并且每个命令缓冲区有 1000 个网格要绘制。 (数字是随机抽取的,因此请分析您的应用程序)。
所以为了回答你关于着色子通道的问题,我不会使用命令缓冲区或者只使用很少的命令缓冲区(根据灯光的种类(准时,定向))
我目前正在 Vulkan 中使用多线程实现基本的延迟渲染器。由于我的 G-Buffer 应该具有与最终图像相同的分辨率,因此我想在具有多个子通道的单个渲染通道中完成,根据幻灯片 44(第 138 页)上的 this 演示。它说:
- vkCmdBeginCommandBuffer
- vkCmdBeginRenderPass
- vkCmdExecuteCommands
- vkCmdNextSubpass
- vkCmdExecuteCommands
- vkCmdEndRenderPass
- vkCmdEndCommandBuffer
我知道在第一个子通道中,您迭代场景图并为每个 entity/mesh 记录一个辅助命令缓冲区。我不明白的是您应该如何使用辅助命令缓冲区进行着色处理。您是否以某种方式将屏幕分成多个部分并在单独的线程中渲染每个部分,或者只为整个第二个子通道记录一个辅助命令缓冲区?
What I don't get is how you are supposed to do the shading pass with secondary command buffers.
着色通道(可能是第二个子通道)可能会将第一个子通道创建的 G 缓冲区作为 输入附件。然后它将使用来自 G 缓冲区的数据 + 来自一组灯光(或您的延迟着色器试图延迟的任何内容)的数据绘制到相同大小的屏幕大小的四边形。
您link 的演示文稿试图从第 13 页(标记为 "Page 107")开始暗示这种结构样式。
第一步是让它发挥作用。使用例如这个SW example。那么下一步将其优化为单个渲染通道应该更容易。
对我来说,正如您所说,您可能需要为 "building g-buffer subpass" 对命令缓冲区进行多线程处理。然而对于着色通道,它必须取决于你是如何做的。对我来说(再一次),你不需要多线程处理你的着色子通道。但是,您必须考虑到您可以拥有一个 "by region dependency".
所以,我鼓励你这样做。 在开始 RenderPass 之前,使用 Compute Shader 将所有灯光映射到屏幕上(这里有一种 "quad" 的数组)。
我所说的喷溅是指这种事情。你有一个点光源(例如),这个想法是计算受光影响的屏幕 space 中的四边形。这样你就有了 4 个顶点(代表一个四边形),你可以将它们放入 SSBO 中,你可以将它用作着色子通道中的顶点缓冲区。
现在开始渲染过程。
- 如果需要MT场景图渲染。并执行 vkCmdExecuteCommands();
- NextSubpass
- 使用您从较早的计算着色器创建的 "array of quads"(不要忘记 VK_SUBPASS_EXTERNAL 依赖项)。
- NextSubpass 等等
然而,你说
you iterate the scene graph and record one secondary commandbuffer for each entity/mesh.
我不确定我是否真的理解你的意思,但如果你打算为一个网格设置一个辅助命令缓冲区,我真的建议你改变你的做法。您必须使用批处理。假设您要绘制 64000 个不同的网格。例如,您可以创建 64 个命令缓冲区(您在 4 个线程上分派)并且每个命令缓冲区有 1000 个网格要绘制。 (数字是随机抽取的,因此请分析您的应用程序)。
所以为了回答你关于着色子通道的问题,我不会使用命令缓冲区或者只使用很少的命令缓冲区(根据灯光的种类(准时,定向))