Muy bien, me está costando comprender cómo los buffers constantes están vinculados a una etapa de canalización y se actualizan. Entiendo que DirectX11 puede tener hasta 15 búferes de constante de sombreador por etapa y cada búfer puede contener hasta 4096 constantes. Sin embargo, no entiendo si el ID3D11Buffer COM utilizado para interactuar con los búferes constantes es solo un mecanismo (o identificador) utilizado para llenar estas ranuras de búfer o si el objeto realmente hace referencia a una instancia particular de datos de búfer que se empuja hacia adelante y hacia atrás entre la GPU y la CPU.
Creo que mi confusión sobre el tema es la causa de un problema que estoy teniendo usando dos buffers constantes diferentes.
Aquí hay un ejemplo de código de sombreador.
cbuffer PerFrame : register(b0) {
float4x4 view;
};
cbuffer PerObject : register(b1) {
float4x4 scale;
float4x4 rotation;
float4x4 translation;
};
La forma en que está organizado mi código, la cámara se encargará de actualizar los datos relevantes por fotograma y GameObjects actualizará sus propios datos por objeto. Ambas clases tienen su propio ID3D11Buffer que se usa para hacer esto (usando una arquitectura de concentrador, por lo que una clase de GameObject manejará la representación de todos los GameObjects instanciados en el mundo).
El problema es que solo puedo actualizar uno a la vez, dependiendo de la ranura y supongo que el orden de actualización se llena un búfer mientras que el otro se pone a cero.
Este es esencialmente mi código. Ambas clases usan una lógica de actualización idéntica.
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);
Mis preguntas principales son:
- ¿Debo configurar o vincular el ShaderBuffer para actualizarlo con la llamada UpdateSubresource? (Lo que significa manipularlo solo cuando está en la tubería) ¿O es un conjunto de datos que se enviarán con la llamada VSSetConstantBuffer? (Es decir, el orden de enlace y actualización de datos no importa, puedo actualizarlo en la tubería o de alguna manera en la CPU)
- Al configurar o vincular el búfer, ¿necesito hacer referencia a la ranura 0 para actualizar el búfer PerFrame y la ranura 1 para actualizar el búfer PerObject? ¿Podría algún tipo de confusión con esta llamada en mi código hacer que se sobrescriban todos los búferes?
- ¿Cómo sabe D3D11 qué búfer quiero actualizar o asignar? ¿Sabe por el ID3D11Buffer COM utilizado?
Editar -
Cambió las etiquetas de registro de búfer constante en el ejemplo anterior. El uso de (cb #) en lugar de (b #) estaba afectando a los buffers de actualizarse correctamente por alguna razón. No estoy seguro de dónde recogí la sintaxis original o si es válida, pero parece que fue mi principal problema.