Erste Schritte mit der Eingabeassemblerphase

Es sind einige Schritte erforderlich, um die Eingabeassemblerphase (IA) zu initialisieren. Sie müssen beispielsweise Pufferressourcen mit den von der Pipeline benötigten Vertexdaten erstellen, der IA-Phase mitteilen, wo die Puffer sind und welche Art von Daten sie enthalten, und den Typ der Grundtypen angeben, die aus den Daten zusammengesetzt werden sollen.

Die grundlegenden Schritte zum Einrichten der IA-Phase, die in der folgenden Tabelle dargestellt sind, werden in diesem Thema behandelt.

Schritt Beschreibung
Erstellen von Eingabepuffern Erstellen und Initialisieren von Eingabepuffern mit Eingabevertexdaten.
Erstellen des Input-Layout-Objekts Definieren Sie, wie die Vertexpufferdaten mithilfe eines Eingabelayoutobjekts in die IA-Phase gestreamt werden.
Binden von Objekten an die Eingabeassemblerphase Binden Sie die erstellten Objekte (Eingabepuffer und das Eingabelayoutobjekt) an die IA-Phase.
Angeben des Grundtyps Identifizieren Sie, wie die Scheitelpunkte in Grundtypen zusammengestellt werden.
Draw-Methoden aufrufen Senden Sie die an die IA-Phase gebundenen Daten über die Pipeline.

 

Nachdem Sie diese Schritte verstanden haben, fahren Sie mit der Verwendung von vom System generierten Werten fort.

Erstellen von Eingabepuffern

Es gibt zwei Arten von Eingabepuffern: Vertexpuffer und Indexpuffer. Vertexpuffer liefern Vertexdaten an die IA-Phase. Indexpuffer sind optional; sie stellen Indizes für Scheitelpunkte aus dem Vertexpuffer bereit. Sie können einen oder mehrere Vertexpuffer und optional einen Indexpuffer erstellen.

Nachdem Sie die Pufferressourcen erstellt haben, müssen Sie ein Input-Layout-Objekt erstellen, um das Datenlayout für die IA-Stufe zu beschreiben, und dann müssen Sie die Pufferressourcen an die IA-Stufe binden. Das Erstellen und Binden von Puffern ist nicht erforderlich, wenn die Shader keine Puffer verwenden. Ein Beispiel für einen einfachen Vertex- und Pixelshader, der ein einzelnes Dreieck zeichnet, finden Sie unter Verwenden der Eingabeassemblerphase ohne Puffer.

Hilfe zum Erstellen eines Vertexpuffers finden Sie unter Vorgehensweise: Erstellen eines Vertexpuffers. Hilfe zum Erstellen eines Indexpuffers finden Sie unter Vorgehensweise: Erstellen eines Indexpuffers.

Erstellen des Input-Layout-Objekts

Das Eingabe-Layoutobjekt kapselt den Eingabezustand der IA-Phase. Dazu gehört eine Beschreibung der Eingabedaten, die an die IA-Phase gebunden sind. Die Daten werden aus dem Arbeitsspeicher aus einem oder mehreren Vertexpuffern in die IA-Phase gestreamt. Die Beschreibung identifiziert die Eingabedaten, die von einem oder mehreren Vertex-Puffern gebunden werden, und gibt der Laufzeit die Möglichkeit, die Eingabedatentypen mit den Shader-Eingabeparametertypen zu vergleichen. Diese Typüberprüfung stellt nicht nur sicher, dass die Typen kompatibel sind, sondern auch, dass alle vom Shader benötigten Elemente in den Pufferressourcen verfügbar sind.

Ein Eingabe-Layoutobjekt wird aus einem Array von Eingabeelementbeschreibungen und einem Zeiger auf den kompilierten Shader erstellt (siehe ID3D11Device::CreateInputLayout). Das Array enthält ein oder mehrere Eingabeelemente; Jedes Eingabeelement beschreibt ein einzelnes Vertexdatenelement aus einem einzelnen Vertexpuffer. Der gesamte Satz von Eingabeelementbeschreibungen beschreibt alle Vertexdatenelemente aus allen Vertexpuffern, die an die IA-Phase gebunden werden.

In der folgenden Layoutbeschreibung wird ein einzelner Vertexpuffer beschrieben, der drei Vertexdatenelemente enthält:

D3D11_INPUT_ELEMENT_DESC layout[] =
{
    { L"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, 
          D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { L"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, 
          D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { L"NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 20, 
          D3D11_INPUT_PER_VERTEX_DATA, 0 },
};

Eine Beschreibung des Eingabeelements beschreibt jedes Element, das in einem einzelnen Scheitelpunkt in einem Vertexpuffer enthalten ist, einschließlich Größe, Typ, Position und Zweck. Jede Zeile identifiziert den Datentyp mithilfe der Semantik, des semantischen Indexes und des Datenformats. Eine Semantik ist eine Textzeichenfolge, die angibt, wie die Daten verwendet werden. In diesem Beispiel identifiziert die erste Zeile 3-Komponenten-Positionsdaten (z. B. xyz); die zweite Zeile identifiziert 2-Komponenten-Texturdaten (z. B. UV), und die dritte Zeile identifiziert normale Daten.

In diesem Beispiel einer Beschreibung eines Eingabeelements ist der semantische Index (der zweite Parameter) für alle drei Zeilen auf Null gesetzt. Der semantische Index hilft dabei, zwischen zwei Zeilen zu unterscheiden, die dieselbe Semantik verwenden. Da in diesem Beispiel keine ähnliche Semantik vorhanden ist, kann der semantische Index auf den Standardwert Null festgelegt werden.

Der dritte Parameter ist das Format. Das Format (siehe DXGI_FORMAT) gibt die Anzahl der Komponenten pro Element und den Datentyp an, der die Größe der Daten für jedes Element definiert. Das Format kann zum Zeitpunkt der Ressourcenerstellung vollständig eingegeben werden, oder Sie können eine Ressource mithilfe eines DXGI_FORMAT erstellen, das die Anzahl der Komponenten in einem Element identifiziert, aber den Datentyp nicht definiert.

Eingabeplätze

Die Daten geben die IA-Phase über Eingaben ein, die als Eingabeplätze bezeichnet werden, wie in der folgenden Abbildung dargestellt. Die IA-Phase verfügt über n Eingabeplätze, die für bis zu n Scheitelpunktpuffer ausgelegt sind, die Eingabedaten bereitstellen. Jeder Scheitelpunktpuffer muss einem anderen Steckplatz zugewiesen werden. Diese Informationen werden in der Eingabelayoutdeklaration gespeichert, wenn das Eingabelayoutobjekt erstellt wird. Sie können auch einen Offset vom Anfang jedes Puffers bis zum ersten zu lesenden Element im Puffer angeben.

illustration of the input slots for the ia stage

Die nächsten beiden Parameter sind der Eingabeplatz und der Eingabeoffset. Wenn Sie mehrere Puffer verwenden, können Sie diese an einen oder mehrere Eingabeplätze binden. Der Eingabeoffset ist die Anzahl der Bytes zwischen dem Anfang des Puffers und dem Anfang der Daten.

Erneutes Verwenden von Eingabe-Layoutobjekten

Jedes Eingabe-Layoutobjekt wird basierend auf einer Shadersignatur erstellt. Dadurch kann die API die Eingabe-Layoutobjektelemente anhand der Shadereingabesignatur überprüfen, um sicherzustellen, dass eine genaue Übereinstimmung mit Typen und Semantik vorhanden ist. Sie können ein einzelnes Eingabe-Layoutobjekt für viele Shader erstellen, solange alle Shadereingabesignaturen exakt übereinstimmen.

Binden von Objekten an die Eingabeassemblerphase

Nachdem Sie Vertexpufferressourcen und ein Eingabe-Layoutobjekt erstellt haben, können Sie diese an die IA-Phase binden, indem Sie ID3D11DeviceContext::IASetVertexBuffers und ID3D11DeviceContext::IASetInputLayout aufrufen. Das folgende Beispiel zeigt die Bindung eines einzelnen Vertexpuffers und eines Eingabe-Layoutobjekts an die IA-Phase:

UINT stride = sizeof( SimpleVertex );
UINT offset = 0;
g_pd3dDevice->IASetVertexBuffers( 
    0,                // the first input slot for binding
    1,                // the number of buffers in the array
    &g_pVertexBuffer, // the array of vertex buffers
    &stride,          // array of stride values, one for each buffer
    &offset );        // array of offset values, one for each buffer

// Set the input layout
g_pd3dDevice->IASetInputLayout( g_pVertexLayout );

Das Binden des Eingabe-Layoutobjekts erfordert nur einen Zeiger auf das Objekt.

Im vorherigen Beispiel ist ein einzelner Vertexpuffer gebunden. Mehrere Vertexpuffer können jedoch durch einen einzelnen Aufruf an ID3D11DeviceContext::IASetVertexBuffers gebunden werden, und der folgende Code zeigt einen solchen Aufruf zum Binden von drei Vertexpuffern:

UINT strides[3];
strides[0] = sizeof(SimpleVertex1);
strides[1] = sizeof(SimpleVertex2);
strides[2] = sizeof(SimpleVertex3);
UINT offsets[3] = { 0, 0, 0 };
g_pd3dDevice->IASetVertexBuffers( 
    0,                 //first input slot for binding
    3,                 //number of buffers in the array
    &g_pVertexBuffers, //array of three vertex buffers
    &strides,          //array of stride values, one for each buffer
    &offsets );        //array of offset values, one for each buffer

Ein Indexpuffer ist durch Aufrufen von ID3D11DeviceContext::IASetIndexBuffer an die IA-Phase gebunden.

Angeben des Grundtyps

Nachdem die Eingabepuffer gebunden wurden, muss der IA-Stufe mitgeteilt werden, wie die Scheitelpunkte zu Grundtypen zusammengesetzt werden sollen. Dazu wird der Grundtyp durch Aufrufen von ID3D11DeviceContext::IASetPrimitiveTopology angegeben. Der folgende Code ruft diese Funktion auf, um die Daten als Dreiecksliste ohne Adjazenz zu definieren:

g_pd3dDevice->IASetPrimitiveTopology( D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST );

Die restlichen Grundtypen werden in D3D_PRIMITIVE_TOPOLOGY aufgeführt.

Draw-Methoden aufrufen

Nachdem Eingaberessourcen an die Pipeline gebunden wurden, ruft eine Anwendung eine Draw-Methode auf, um Grundtypen zu rendern. Es gibt mehrere Draw-Methoden, die in der folgenden Tabelle dargestellt sind. Einige verwenden Indexpuffer, einige Instanzdaten und einige verwenden Daten aus der Streamingausgabestufe als Eingabe in die Eingabeassemblerphase.

Draw-Methoden Beschreibung
ID3D11DeviceContext::Draw Zeichnen Sie nicht indizierte, nicht instanziierte Grundtypen.
ID3D11DeviceContext::DrawInstanced Zeichnen Sie nicht indizierte, instanziierte Grundtypen.
ID3D11DeviceContext::DrawIndexed Zeichnen Sie indizierte, nicht instanziierte Grundtypen.
ID3D11DeviceContext::DrawIndexedInstanced Zeichnen Sie indizierte, instanziierte Grundtypen.
ID3D11DeviceContext::DrawAuto Zeichnen Sie nicht indizierte, nicht instanziierte Grundtypen aus Eingabedaten, die aus der Streamingausgabestufe stammen.

 

Jede Draw-Methode rendert einen einzelnen Topologietyp. Während des Renderings werden unvollständige Primitive (solche ohne genügend Scheitelpunkte, fehlende Indizes, partielle Primitive usw.) stillschweigend verworfen.

Eingabe-Assembler-Stufe