关于D3D11管线绑定顶点缓冲区后Draw()调用的疑问
问题一解答
当顶点缓冲区A、B分别绑定到输入槽0和1时,ImmediateContext->Draw(VertexCount, StartVertexLocation)会同时使用两个缓冲区——前提是你的输入布局(Input Layout)已经定义了对应两个槽的顶点元素语义。
D3D11的Draw调用是基于输入布局匹配顶点缓冲区的:每个输入槽对应输入布局里的一组顶点元素,Draw会从每个绑定的、且被输入布局引用的缓冲区中,按指定的VertexCount和StartVertexLocation读取顶点数据,组合成完整的顶点属性供管线使用。
如果两个缓冲区大小不同,只要VertexCount + StartVertexLocation不超过任意一个被使用的缓冲区的顶点数量,就可以正常工作;如果超出,会触发设备错误(比如调试层报错或DXGI_ERROR_DEVICE_HUNG)。
问题二解答
如果输入槽0未绑定缓冲区,仅槽1绑定了B,Draw()不会使用B——除非你的输入布局完全只引用了输入槽1的顶点元素。
默认情况下,输入布局通常会关联输入槽0的元素(比如POSITION语义默认对应槽0),如果输入布局里没有定义任何引用槽1的元素,即使槽1绑定了缓冲区,管线也不会去读取它。只有当输入布局明确包含指向槽1的顶点元素时,Draw才会尝试从槽1读取数据;但如果此时槽0没有绑定缓冲区,而输入布局又需要槽0的数据,Draw调用会直接失败(调试层会报顶点缓冲区未绑定的错误)。
对用户原理解的纠正
你的理解存在部分偏差:Draw(N, ...)不是从每个绑定的缓冲区取N个顶点,而是根据输入布局的定义,从每个被输入布局引用的缓冲区中,按顶点顺序读取对应的数据,组合成N个完整的顶点(每个顶点包含输入布局里定义的所有属性)。
举个例子:如果输入布局定义了槽0的POSITION(3个float)和槽1的TEXCOORD(2个float),那么Draw(N, ...)会从槽0取N组POSITION数据,从槽1取N组TEXCOORD数据,每一组POSITION+TEXCOORD构成一个顶点,总共生成N个顶点供管线处理。
内容的提问来源于stack exchange,提问作者kppodd

