In Ordnung, es fällt mir schwer zu verstehen, wie konstante Puffer an eine Pipeline-Phase gebunden und aktualisiert werden. Ich verstehe, dass DirectX11 bis zu 15 Puffer mit Shader-Konstanten pro Stufe haben kann und jeder Puffer bis zu 4096 Konstanten enthalten kann. Ich verstehe jedoch nicht, ob die ID3D11-Puffer-COM, die zur Interaktion mit den konstanten Puffern verwendet wird, nur ein Mechanismus (oder ein Handle) ist, der zum Füllen dieser Pufferschlitze verwendet wird, oder ob das Objekt tatsächlich auf eine bestimmte Instanz von Pufferdaten verweist, die hin und her verschoben werden zwischen der GPU und der CPU.
Ich denke, meine Verwirrung in Bezug auf das Thema ist die Ursache für ein Problem, bei dem ich zwei verschiedene konstante Puffer verwende.
Hier ist ein Beispiel für Shader-Code.
cbuffer PerFrame : register(b0) {
float4x4 view;
};
cbuffer PerObject : register(b1) {
float4x4 scale;
float4x4 rotation;
float4x4 translation;
};
Wie mein Code organisiert ist, aktualisiert die Kamera die relevanten Pro-Frame-Daten und GameObjects aktualisiert ihre eigenen Pro-Objekt-Daten. Beide Klassen haben einen eigenen ID3D11-Puffer, der dazu verwendet wird. (Unter Verwendung einer Hub-Architektur übernimmt eine GameObject-Klasse das Rendern aller instanzierten GameObjects in der Welt.)
Das Problem ist, dass ich je nach Steckplatz immer nur eine Aktualisierung durchführen kann, und ich nehme an, dass in der Aktualisierungsreihenfolge ein Puffer gefüllt wird, während der andere Nullen aufweist.
Dies ist im Wesentlichen mein Code. Beide Klassen verwenden eine identische Aktualisierungslogik.
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);
Meine Hauptfragen sind -
- Muss ich den ShaderBuffer setzen oder binden, um ihn mit dem UpdateSubresource-Aufruf zu aktualisieren? (Das heißt, manipulieren Sie es nur, wenn es sich in der Pipeline befindet.) Oder handelt es sich um einen Datenblock, der mit dem VSSetConstantBuffer-Aufruf gesendet wird? (Das heißt, die Reihenfolge des Verbindens und Aktualisierens von Daten spielt keine Rolle, ich kann sie in der Pipeline oder irgendwie auf der CPU aktualisieren.)
- Muss ich beim Festlegen oder Binden des Puffers auf Steckplatz 0 verweisen, um den PerFrame-Puffer zu aktualisieren, und auf Steckplatz 1, um den PerObject-Puffer zu aktualisieren? Könnte eine Verwechslung mit diesem Aufruf in meinem Code dazu führen, dass alle Puffer überschrieben werden?
- Woher weiß D3D11, welchen Puffer ich aktualisieren oder zuordnen möchte? Kennt es den vom ID3D11Buffer verwendeten COM?
Bearbeiten -
Im obigen Beispiel wurden die Konstantenpufferregister-Tags geändert. Die Verwendung von (cb #) anstelle von (b #) hatte aus irgendeinem Grund Auswirkungen auf die Aktualisierung der Puffer. Ich bin mir nicht sicher, wo ich die ursprüngliche Syntax gefunden habe oder ob sie überhaupt gültig ist, aber es scheint mein Hauptproblem zu sein.