关于多顶点类型和多着色器的基本问题
Fundamental questions about multiple vertex types and multiple shaders
我有两种类型的顶点,每种都有自己的顶点和片段着色器:
Vertex Type "A" => vertex shader "A" => fragment shader "A"
Vertex Type "B" => vertex shader "B" => fragment shader "B"
我需要将顶点和着色器分开,因为它们根本不同。
我知道我需要两个 graphicsPipelines,因为我有 4 个阶段(两个 vert,两个 frag)但它们不是按顺序应用的。使用单个管道我可以做到这一点:
VkPipelineShaderStageCreateInfo shaderStages[] = {
vertShaderStageCreateInfo,
fragShaderStageCreateInfo
};
graphicsPipelineCreateInfo.pStages = shaderStages;
这很明显是什么意思。但是我有 4 个着色器模块(着色器),因此有 4 个“阶段”,在一个管道上我只能定义一个“阶段序列”,如下所示:
Stage sequence: Stage 1 => Stage 2 => Stage 3 => Stage 4
这将是多通道渲染(我猜!)。
但我需要两个独立的舞台序列:
Stage sequence A: Stage 1 (vertex type A) => Stage 2 (vertex type A)
Stage sequence B: Stage 1 (vertex type B) => Stage 2 (vertex type B)
所以这就是为什么我需要两条管道,一个用于每个“顶点 type/shader 集”(A 和 B)。
QUESTION: Is this correct or am I misunderstanding pipelines?
现在,我必须使用两个管道(和 pipelinLayouts)记录命令缓冲区。在单管道方法中,我绑定管道、pipelineLayout、描述符和顶点:
void recordCommands(
VkPipeline& graphicsPipeline,
VkPipelineLayout& pipelineLayout,
VkBuffer& vertexBuffer)
{
vkCmdBeginRenderPass(...);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr);
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
vkCmdDraw(...);
vkCmdEndRenderPass(...);
}
我可以像这样在一个 drawcall 中绘制两条管道吗?
BEGIN RENDER PASS
BIND PIPELINE A, DESCRIPTORS, VERTEX_BUFFER A
DRAW A
BIND PIPELINE B, DESCRIPTORS, VERTEX_BUFFER B
DRAW B
END RENDER PASS
这可能吗?或者我是否必须在同一个命令缓冲区中注册两个 RENDER PASSES(这会是多通道渲染)吗?
或者更糟的是,我是否必须注册两个命令缓冲区,然后一个接一个地执行两个 VkSubmitInfo()?通过这样做,我是否必须等待第一个命令缓冲区结束('VkQueueWaitIdle' 或使用信号量),然后才能提交第二个命令缓冲区?或者我可以立即提交两个命令缓冲区(毕竟它被称为“队列”)?
老实说,我不明白您想象中的管道是如何工作的。它们只是状态,通过绑定改变,一次只能绑定一个管道。我不认为一个管道可以同时拥有多个顶点着色器——你只需要两个管道先绑定一个,然后用它绘制,然后再绑定第二个并绘制。一个管道定义了如何处理顶点和其他数据,从开始到像素(结束)。而且我不记得有什么可以阻止您在单个渲染通道内更改管道(除了成本,也许 - 更改状态有开销,尽管驱动程序应该能够优化一点 - vulkan 的工作方式有帮助)。此外,如果一个管道依赖于其他管道生成的数据(或者一个管道修改其他管道使用的数据,任何顺序),您将需要在它们之间设置一个屏障。
多通道渲染是指当你有多个渲染通道时,我认为如果你想在第二通道中使用第一通道的结果作为纹理,就可以使用它们。还有一些子通道,可以让你在一秒钟内使用第一个子通道的结果,但有一个限制,即你只能使用来自同一像素的数据。它们可能比单独的传递更有效...
此外,计算管道不能用于渲染过程。
我有两种类型的顶点,每种都有自己的顶点和片段着色器:
Vertex Type "A" => vertex shader "A" => fragment shader "A"
Vertex Type "B" => vertex shader "B" => fragment shader "B"
我需要将顶点和着色器分开,因为它们根本不同。
我知道我需要两个 graphicsPipelines,因为我有 4 个阶段(两个 vert,两个 frag)但它们不是按顺序应用的。使用单个管道我可以做到这一点:
VkPipelineShaderStageCreateInfo shaderStages[] = {
vertShaderStageCreateInfo,
fragShaderStageCreateInfo
};
graphicsPipelineCreateInfo.pStages = shaderStages;
这很明显是什么意思。但是我有 4 个着色器模块(着色器),因此有 4 个“阶段”,在一个管道上我只能定义一个“阶段序列”,如下所示:
Stage sequence: Stage 1 => Stage 2 => Stage 3 => Stage 4
这将是多通道渲染(我猜!)。
但我需要两个独立的舞台序列:
Stage sequence A: Stage 1 (vertex type A) => Stage 2 (vertex type A)
Stage sequence B: Stage 1 (vertex type B) => Stage 2 (vertex type B)
所以这就是为什么我需要两条管道,一个用于每个“顶点 type/shader 集”(A 和 B)。
QUESTION: Is this correct or am I misunderstanding pipelines?
现在,我必须使用两个管道(和 pipelinLayouts)记录命令缓冲区。在单管道方法中,我绑定管道、pipelineLayout、描述符和顶点:
void recordCommands(
VkPipeline& graphicsPipeline,
VkPipelineLayout& pipelineLayout,
VkBuffer& vertexBuffer)
{
vkCmdBeginRenderPass(...);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr);
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
vkCmdDraw(...);
vkCmdEndRenderPass(...);
}
我可以像这样在一个 drawcall 中绘制两条管道吗?
BEGIN RENDER PASS
BIND PIPELINE A, DESCRIPTORS, VERTEX_BUFFER A
DRAW A
BIND PIPELINE B, DESCRIPTORS, VERTEX_BUFFER B
DRAW B
END RENDER PASS
这可能吗?或者我是否必须在同一个命令缓冲区中注册两个 RENDER PASSES(这会是多通道渲染)吗?
或者更糟的是,我是否必须注册两个命令缓冲区,然后一个接一个地执行两个 VkSubmitInfo()?通过这样做,我是否必须等待第一个命令缓冲区结束('VkQueueWaitIdle' 或使用信号量),然后才能提交第二个命令缓冲区?或者我可以立即提交两个命令缓冲区(毕竟它被称为“队列”)?
老实说,我不明白您想象中的管道是如何工作的。它们只是状态,通过绑定改变,一次只能绑定一个管道。我不认为一个管道可以同时拥有多个顶点着色器——你只需要两个管道先绑定一个,然后用它绘制,然后再绑定第二个并绘制。一个管道定义了如何处理顶点和其他数据,从开始到像素(结束)。而且我不记得有什么可以阻止您在单个渲染通道内更改管道(除了成本,也许 - 更改状态有开销,尽管驱动程序应该能够优化一点 - vulkan 的工作方式有帮助)。此外,如果一个管道依赖于其他管道生成的数据(或者一个管道修改其他管道使用的数据,任何顺序),您将需要在它们之间设置一个屏障。
多通道渲染是指当你有多个渲染通道时,我认为如果你想在第二通道中使用第一通道的结果作为纹理,就可以使用它们。还有一些子通道,可以让你在一秒钟内使用第一个子通道的结果,但有一个限制,即你只能使用来自同一像素的数据。它们可能比单独的传递更有效...
此外,计算管道不能用于渲染过程。