使用不同着色器程序的 DirectX 11 渲染管线

DirectX 11 Rendering Pipeline Using Different Shader Programs

我目前正在阅读 Practical Rendering and Computation with Direct3D 11。对于 DirectX/OpenGL 经验很少的人,我发现它提供了很多信息,并给了我一些很好的指导。一切都很有道理,而且看起来很简单(虽然,很沉重)。

然而,我目前正在阅读第 3 章(130 多页),我仍然对一件简单的事情感到困惑。

着色器程序,例如...如果您希望一些资源使用特定的着色器程序,而另一些资源使用其他一些着色器程序,该怎么办。或者,是否每个资源都得到相同的处理?此处的资源,请参考 vertex/index 数据,或 Texture1/2/3,或...如果我有一个正在渲染的模型并希望它在管道中使用特定的着色器程序。

显然必须有一些方法可以让一些输入沿着不同的路径进行不同的渲染结果。

但到目前为止,我还没有在书中看到它(也许我会再看 100 页)。

抱歉,如果这个问题已经出现在某个地方,不太确定如何构建 google 搜索类似的内容。

编辑:为清楚起见

假设我有一个名为 ShaderA_vs.hlsl 的顶点着色器,还有一个名为 ShaderB_vs.hlsl 的顶点着色器。现在,我加载了两个对象模型:ModelA 和 ModelB。我希望 ModelA 使用 ShaderA_vs,而 ModelB 使用 ShaderB_vs

GPU 着色器编程实际上有两种截然不同的途径:

可编程渲染

此模型是随 Direct3D 8.1 引入的,是 "Transform & Light" 部分和 "Texture blend cascade" 的旧固定功能遗留模型的演变。 顶点着色器是替换"Transform & Light"的着色器程序,像素着色器替换了"Texture blend cascade".

要渲染单个对象(点、线或三角形),您可以设置一个顶点着色器,每个点 运行 作为顶点缓冲区的原始数据提供一次(并且可能由索引索引)缓冲)。然后,硬件光栅化器为对象在 2D 屏幕上绘制时接触到的每个像素执行像素着色器。对于着色器和相关状态的特定组合,您可以一次绘制一个像素或 40 亿个三角形。

如果您想更改 任何 状态或着色器程序本身的任何方面,则必须提交新的绘图。您可以在每次绘制之间更改部分或全部状态,在某些情况下,您可能需要明确清除某些状态以避免来自调试层的验证警告。

Efficient state management across the whole scene is a challenge, so be sure to avoid assuming state, relying on default state you didn't set, and assuming states persist from frame-to-frame between Present calls.

即使在现代的 DirectX 管道中,硬件细分、几何着色器和基于物理的每像素照明的所有装饰都是对同一基本概念的扩展。

对于图形渲染,这通常是一个很好的概念模型,并且可以很好地映射到习惯于使用旧的 T&L + TextureBlending 模型思考的人。它还可以通过多种方式进行扩展,并在关键点非常有效地使用固定功能的硬件来完成在一般计算中昂贵的事情,如多边形扫描线转换、z 缓冲区深度剔除和 alpha 混合。

计算

人们已经使用以前的模型通过传统的可编程管线来做有趣的非图形的东西,你根本不关心光栅化或顶点着色器在做什么,你只需要在上面画一个大矩形整个渲染目标,然后你在像素着色器中做了一堆事情。然后,您将生成的渲染目标视为某种 'generic buffer'.

这里的问题是将问题映射到这个 "drawing but doing something else" 模型有点麻烦,这是我们得到 "Compute Shaders" 的地方(DirectX 称之为 DirectCompute)。在此模型中,您根本不使用顶点缓冲区、索引缓冲区、points/lines/triangles、光栅化器或纹理混合。您只是 运行 一个写出缓冲区的着色器。您可以直接通过 Dispatch.

控制着色器实例的数量 运行

顶点着色器、像素着色器、计算着色器等都可以做基本相同的事情,包括查找部分资源(纹理或被视为通用缓冲区),对它们进行计算,并将结果写入其他一些显存。由于隐含的输入,着色器的顶级调用有所不同,但仅此而已。

计算着色器可以做而其他着色器模型不能做的一件事是(有限地)通过少量共享内存与其他着色器实例通信。这打破了您从以前的模型中获得的极其强大的多线程优势,但使解决某些问题变得容易得多。在不造成重大停顿的情况下,这件事很难做到,您通常需要手动计算所有同步以获得有效结果。

I should mention that there's a third pathway which is what CUDA does, which is a system that hides all the low-level shader stuff and pretends to be C. It's still doing the same kind of thing as "compute" under the covers.