Shaderkonstanten (HLSL)

Im Shadermodell 4 werden Shaderkonstanten in einer oder mehreren Pufferressourcen im Arbeitsspeicher gespeichert. Diese können in zwei Puffertypen organisiert werden: Konstantenpuffer (cbuffers) und Texturpuffer (tbuffers). Konstantenpuffer sind für die Verwendung konstanter Variablen optimiert, die durch den Zugriff mit niedrigerer Latenz und häufigere CPU-Aktualisierungen gekennzeichnet ist. Aus diesem Grund gelten zusätzliche Größen-, Layout- und Zugriffsbeschränkungen für diese Ressourcen. Auf Texturpuffer wird wie auf Texturen zugegriffen, und sie weisen eine bessere Leistung bei willkürlich indizierten Daten auf. Unabhängig vom verwendeten Ressourcentyp gibt es keine Beschränkung der Anzahl von Konstanten- oder Texturpuffern, die von einer Anwendung erstellt werden können.

Das Deklarieren eines Konstanten- oder Texturpuffers ähnelt einer Strukturdeklaration in C, wobei die Schlüsselwörter register und packoffset zusätzlich für das manuelle Zuweisen von Registern oder das Packen von Daten verwendet werden.

BufferTypeName [: register(b#)] { VariableDeclaration [: packoffset(c#.xyzw)]; ... };

Parameter

BufferType

[in] Puffertyp

BufferType Beschreibung
cbuffer Konstantenpuffer
tbuffer Texturpuffer

Name

[in] ASCII-Zeichenfolge mit einem eindeutigen Puffernamen

register(b#)

[in] Optionales Schlüsselwort, das zum manuellen Packen von Konstantendaten verwendet wird. Konstanten können ausschließlich in einem Konstantenpuffer in ein Register gepackt werden, wobei das Startregister durch die Registernummer (#) angegeben wird.

VariableDeclaration

[in] Variablendeklaration, die einer Strukturmemberdeklaration ähnelt. Dabei kann es sich mit Ausnahme einer Textur oder eines Samplerobjekts um einen beliebigen HLSL-Typ oder ein Effektobjekt handeln.

packoffset(c#.xyzw)

[in] Optionales Schlüsselwort, das zum manuellen Packen von Konstantendaten verwendet wird. Konstanten können in einen beliebigen Konstantenpuffer gepackt werden, wobei die Registernummer durch (#) angegeben wird. Das Packen von Unterkomponenten mithilfe von xyzw-Swizzling ist für Konstanten verfügbar, deren Größe in ein einzelnes Register passt. Dabei sollten keine Registergrenzen überschritten werden. Beispielsweise könnte eine float4-Struktur nicht in ein einzelnes Register gepackt werden, das mit der y-Komponente beginnt, da sie nicht in ein Register mit vier Komponenten passen würde.

Hinweise

Konstantenpuffer reduzieren die zum Aktualisieren von Shaderkonstanten erforderliche Bandbreite, indem Shaderkonstanten gruppiert und gleichzeitig committet werden können, anstatt jede Konstante über einzelne Aufrufe separat zu committen.

Ein Konstantenpuffer ist eine spezielle Pufferressource, auf die wie auf einen Puffer zugegriffen wird. Jeder Konstantenpuffer kann bis zu 4096 Vektoren enthalten, wobei jeder Vektor bis zu vier 32-Bit-Werte enthält. Sie können bis zu 14 Konstantenpuffer pro Pipelinephase binden. Zwei zusätzliche Slots sind für die interne Verwendung reserviert.

Ein Texturpuffer ist eine spezielle Pufferressource, auf die wie auf eine Textur zugegriffen wird. Der Texturzugriff kann im Vergleich zum Pufferzugriff eine bessere Leistung für willkürlich indizierte Daten aufweisen. Sie können bis zu 128 Texturpuffer pro Pipelinephase binden.

Eine Pufferressource ist so konzipiert, dass sie den Overhead für das Festlegen von Shaderkonstanten minimiert. Das Effektframework der ID3D10Effect-Schnittstelle verwaltet das Aktualisieren von Konstanten- und Texturpuffern. Sie können ebenfalls die Direct3D-API verwenden, um Puffer zu aktualisieren. Weitere Informationen finden Sie unter Kopieren von und Zugreifen auf Ressourcendaten (Direct3D 10). Eine Anwendung kann außerdem Daten aus einem anderen Puffer wie ein Render- oder Streamausgabeziel in einen Konstantenpuffer kopieren.

Weitere Informationen zur Verwendung von Konstantenpuffern in einer D3D10-Anwendung finden Sie unter Ressourcentypen (Direct3D 10) und Erstellen von Pufferressourcen (Direct3D 10).

Weitere Informationen zur Verwendung von Konstantenpuffern in einer D3D11-Anwendung finden Sie unter Einführung in Puffer in Direct3D 11 und Vorgehensweise beim Erstellen eines Konstantenpuffers.

Ein Konstantenpuffer erfordert keine Ansicht, um an die Pipeline gebunden zu werden. Ein Texturpuffer erfordert jedoch eine Ansicht und muss an einen Texturslot oder bei der Verwendung eines Effekts mit SetTextureBuffer gebunden werden.

Konstantendaten können auf zwei Arten gepackt werden: mithilfe der Schlüsselwörter register (DirectX HLSL) und packoffset (DirectX HLSL).

Unterschiede zwischen Direct3D 9 und Direct3D 10 und 11:

  • Bei der automatischen Zuweisung von Konstanten in Direct3D 9 wird kein Packen durchgeführt und stattdessen jeder Variablen eine Reihe von float4-Registern zugewiesen. Im Gegensatz dazu folgen HLSL-Konstantenvariablen den Packregeln in Direct3D 10 und 11.

Organisieren von Konstantenpuffern

Konstantenpuffer reduzieren die zum Aktualisieren von Shaderkonstanten erforderliche Bandbreite, indem Shaderkonstanten gruppiert und gleichzeitig committet werden können, anstatt jede Konstante über einzelne Aufrufe separat zu committen.

Die beste Möglichkeit zum effizienten Verwenden von Konstantenpuffern besteht darin, Shadervariablen basierend auf der Häufigkeit ihrer Aktualisierung in Konstantenpuffer zu organisieren. Auf diese Weise kann eine Anwendung die zum Aktualisieren von Shaderkonstanten erforderliche Bandbreite minimieren. Beispiel: Ein Shader kann zwei Konstantenpuffer deklarieren und die Daten basierend auf der Häufigkeit ihrer Aktualisierung organisieren. Daten, die pro Objekt aktualisiert werden müssen (z. B. eine Weltmatrix), werden in einen Konstantenpuffer gruppiert, der für jedes Objekt aktualisiert werden kann. Das unterscheidet sich von Daten, die eine Szene kennzeichnen und daher wahrscheinlich deutlich weniger häufig aktualisiert werden (beim Szenenwechsel).

cbuffer myObject
{       
    float4x4 matWorld;
    float3   vObjectPosition;
    int      arrayIndex;
}
 
cbuffer myScene
{
    float3   vSunPosition;
    float4x4 matView;
}
        

Standardkonstantenpuffer

Die beiden Standardkonstantenpuffer $Global und $Param sind verfügbar. Im globalen Bereich gesetzte Variablen werden implizit zum $Global-Konstantenpuffer (cbuffer) hinzugefügt, wobei die gleiche Packmethode wie bei cbuffers verwendet wird. Uniform-Parameter in der Parameterliste einer Funktion werden im $Param-Konstantenpuffer angezeigt, wenn ein Shader außerhalb des Effektframeworks kompiliert wird. Beim Kompilieren innerhalb des Effektframeworks müssen alle Uniform-Parameter in Variablen aufgelöst werden, die im globalen Bereich definiert sind.

Beispiele

Der folgende Texturpuffer ist Beispiel aus Skinning10 Sample und besteht aus einem Matrizenarray.

tbuffer tbAnimMatrices
{
    matrix g_mTexBoneWorld[MAX_BONE_MATRICES];
};
      

In dieser Beispieldeklaration wird ein Konstantenpuffer manuell zugewiesen, der auf einem bestimmten Register gestartet werden soll. Sie enthält außerdem bestimmte nach Unterkomponenten sortierte Element.

cbuffer MyBuffer : register(b3)
{
    float4 Element1 : packoffset(c0);
    float1 Element2 : packoffset(c1);
    float1 Element3 : packoffset(c1.y);
}
      

Shadermodell 4