好吧,我很难理解常量缓冲区如何绑定到流水线阶段并进行更新。我知道DirectX11每阶段最多可以有15个着色器常量缓冲区,每个缓冲区最多可以容纳4096个常量。但是,我不明白用于与常量缓冲区交互的ID3D11Buffer COM是否只是用于填充这些缓冲区插槽的机制(或句柄),还是该对象是否实际引用了来回推送的缓冲区数据的特定实例?在GPU和CPU之间。
我认为我对该主题的困惑是导致我使用两个不同的常量缓冲区的问题的原因。
这是一些示例着色器代码。
cbuffer PerFrame : register(b0) {
float4x4 view;
};
cbuffer PerObject : register(b1) {
float4x4 scale;
float4x4 rotation;
float4x4 translation;
};
我的代码的组织方式,相机将处理更新相关的每帧数据,而GameObjects将更新其自己的每对象数据。这两个类都有自己的ID3D11Buffer来执行此操作(使用集线器体系结构,因此一个GameObject类将处理世界上所有实例GameObject的呈现)。
问题是我一次只能更新一个,具体取决于插槽,并且我假设一个缓冲区被填充,而另一个缓冲区被填充为零的更新顺序。
这本质上是我的代码。这两个类使用相同的更新逻辑。
static PerObjectShaderBuffer _updatedBuffer; // PerFrameShaderBuffer if Camera class
_updatedBuffer.scale = _rScale;
_updatedBuffer.rotation = _rRotation;
_updatedBuffer.translation = _rTranslation;
pDeviceContext->UpdateSubresource(pShaderBuffer, 0 , 0, &_updatedBuffer, 0, 0);
pDeviceContext->VSSetShader(pVShader->GetShaderPtr(), 0, 0);
pDeviceContext->PSSetShader(pPShader->GetShaderPtr(), 0, 0);
pDeviceContext->VSSetConstantBuffers(1, 1, &pShaderBuffer);
pDeviceContext->IASetVertexBuffers(0, 1, &pVertexBuffer, &vStride, &_offset );
pDeviceContext->IASetPrimitiveTopology(topologyType);
pDeviceContext->Draw(bufSize, 0);
我的主要问题是-
- 我是否需要设置或绑定ShaderBuffer以便通过UpdateSubresource调用对其进行更新?(意味着仅当它在管道中时才对其进行操作)还是它是将通过VSSetConstantBuffer调用发送的数据块?(意味着绑定和更新数据的顺序无关紧要,我可以在管道中或以某种方式在cpu上对其进行更新)
- 在设置或绑定缓冲区时,是否需要引用插槽0来更新PerFrame缓冲区,并引用插槽1来更新PerObject缓冲区?我的代码中对此调用的某种混淆是否会导致所有缓冲区被覆盖?
- D3D11如何知道我要更新或映射哪个缓冲区?从使用的ID3D11Buffer COM知道吗?
编辑-
在上面的示例中更改了常量缓冲寄存器标签。由于某些原因,使用(cb#)而不是(b#)正在影响缓冲区正确更新。不知道我在哪里选择了原始语法,或者它是否完全有效,但这似乎是我的主要问题。