【问题标题】:Fundamental questions about multiple vertex types and multiple shaders关于多个顶点类型和多个着色器的基本问题
【发布时间】:2021-05-02 12:56:42
【问题描述】:

我有两种类型的顶点,每种都有自己的顶点和片段着色器:

Vertex Type "A" => vertex shader "A" => fragment shader "A"
Vertex Type "B" => vertex shader "B" => fragment shader "B"

我需要将顶点和着色器分开,因为它们根本不同。

我知道我需要两个 graphicsPipelines,因为我有 4 个阶段(两个垂直,两个片段),但它们不是按顺序应用的。使用单个管道我可以做到这一点:

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)

这就是为什么我需要两条管道,一个用于每个“顶点类型/着色器集”(A 和 B)。

问题:这是正确的还是我误解了管道?

现在,我必须使用两个管道(和 pipelinLayouts)来记录命令缓冲区。在单管道方法中,我绑定了管道、管道布局、描述符和顶点:

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


    【解决方案1】:

    我真的不明白你想象管道是如何工作的。它们只是状态,通过绑定进行更改,一次只能绑定一个管道。我不认为一个管道可以同时拥有多个顶点着色器——你只有两个管道首先绑定一个,用它绘制,然后绑定第二个并绘制。一条管道定义了如何处理顶点和其他数据,从开始到像素(结束)。而且我不记得有什么会阻止您在单个渲染过程中更改管道(除了成本之外,也许-更改状态会产生开销,尽管驱动程序应该能够进行一些优化-vulkan 的工作原理会有所帮助)。此外,如果一个管道依赖于其他管道生成的数据(或者一个管道修改了其他管道使用的数据,任何顺序),您将需要在它们之间设置一个屏障。

    多通道渲染是指当您有多个渲染通道时,如果您想在第二通道中使用第一个通道的结果作为纹理,我认为使用它们。还有一些子通道,可让您在一秒钟内使用第一个子通道的结果,但限制是您只能使用来自同一像素的数据。它们可能比单独的传递更有效......

    另外,计算管道不能用于渲染通道。

    【讨论】:

    • 不错!我已经重构了代码(4 小时的工作),但现在我可以在单个命令缓冲区中绘制任意数量的管道!就像一个魅力,它对 CPU 方面的性能影响最小。不知道 GPU 方面,但我想这不是问题。
    猜你喜欢
    • 2017-12-13
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 2013-12-10
    • 2016-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多