さて、定数バッファがパイプラインステージにバインドされて更新される方法を把握するのは大変です。DirectX11では、ステージごとに最大15個のシェーダー定数バッファーを使用でき、各バッファーには最大4096個の定数を保持できることを理解しています。ただし、定数バッファーと対話するために使用されるID3D11Buffer COMが、これらのバッファースロットを埋めるために使用されるメカニズム(またはハンドル)だけであるか、またはオブジェクトが実際に前後にプッシュされるバッファーデータの特定のインスタンスを参照するかどうかがわかりませんGPUとCPUの間。
このトピックに関する混乱は、2つの異なる定数バッファーを使用している問題の原因だと思います。
シェーダーコードの例を次に示します。
cbuffer PerFrame : register(b0) {
float4x4 view;
};
cbuffer PerObject : register(b1) {
float4x4 scale;
float4x4 rotation;
float4x4 translation;
};
コードの編成方法では、カメラはフレームごとの関連データの更新を処理し、GameObjectsはオブジェクトごとの独自のデータを更新します。両方のクラスには、これを行うために使用される独自のID3D11Bufferがあります(ハブアーキテクチャを使用しているため、1つのGameObjectクラスが、世界中のインスタンス化されたGameObjectsのレンダリングを処理します)。
問題は、スロットに応じて一度に1つしか更新できないことです。更新順序は、1つのバッファーが満たされ、もう1つのバッファーがゼロになると仮定しています。
これは基本的に私のコードです。両方のクラスは同一の更新ロジックを使用します。
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);
私の主な質問は-
- UpdateSubresource呼び出しで更新するには、ShaderBufferを設定またはバインドする必要がありますか?(つまり、パイプラインにある場合にのみ操作します)またはVSSetConstantBuffer呼び出しで送信されるデータのblobですか?(データのバインドと更新の順序は重要ではありません。パイプラインまたはCPUで何らかの方法で更新できます)
- バッファーを設定またはバインドするときに、スロット0を参照してPerFrameバッファーを更新し、スロット1を参照してPerObjectバッファーを更新する必要がありますか?私のコードでこの呼び出しを使用すると、すべてのバッファが上書きされる可能性がありますか?
- D3D11は、どのバッファーを更新またはマップするのかをどのようにして知るのですか?使用されているID3D11Buffer COMから知っていますか?
編集-
上記の例の定数バッファレジスタタグを変更しました。(b#)の代わりに(cb#)を使用すると、何らかの理由でバッファが正しく更新されないことがありました。元の構文をどこで取得したか、それがまったく有効かどうかはわかりませんが、それが私の主な問題のようです。