Erstellen von Pufferressourcen (Direct3D 10)

Zum Erstellen von Puffern müssen die Daten definiert werden, die der Puffer speichert, Initialisierungsdaten bereitstellen und geeignete Verwendungs- und Bindungskennzeichnungen einrichten. Informationen zum Erstellen von Texturen finden Sie unter Erstellen von Texturressourcen (Direct3D 10).

Erstellen eines Vertexpuffers

Die Schritte zum Erstellen eines Vertexpuffers lauten wie folgt.

Erstellen einer Pufferbeschreibung

Beim Erstellen eines Vertexpuffers wird eine Pufferbeschreibung (siehe D3D10_BUFFER_DESC) verwendet, um zu definieren, wie Daten innerhalb des Puffers organisiert werden, wie die Pipeline auf den Puffer zugreifen kann und wie der Puffer verwendet wird.

Im folgenden Beispiel wird veranschaulicht, wie Sie eine Pufferbeschreibung für ein einzelnes Dreieck mit Scheitelpunkten erstellen, die Position und Farbwerte enthalten.

struct SimpleVertex
{
    D3DXVECTOR3 Position;  
    D3DXVECTOR3 Color;  
};

    D3D10_BUFFER_DESC bufferDesc;
    bufferDesc.Usage            = D3D10_USAGE_DEFAULT;
    bufferDesc.ByteWidth        = sizeof( SimpleVertex ) * 3;
    bufferDesc.BindFlags        = D3D10_BIND_VERTEX_BUFFER;
    bufferDesc.CPUAccessFlags   = 0;
    bufferDesc.MiscFlags        = 0;

In diesem Beispiel wird die Pufferbeschreibung mit fast allen Standardeinstellungen für die Verwendung, den CPU-Zugriff und verschiedene Flags initialisiert. Die anderen Einstellungen gelten für das Bindungskennzeichnung , das die Ressource nur als Vertexpuffer und die Größe des Puffers identifiziert.

Die Verwendungs- und CPU-Zugriffskennzeichnungen sind für die Leistung wichtig. Diese beiden Flags bestimmen gemeinsam, wie oft auf eine Ressource zugegriffen wird, in welchen Speichertyp die Ressource geladen werden kann und in welchen Prozessor auf die Ressource zugreifen muss. Die Standardmäßige Verwendung dieser Ressource wird nicht sehr häufig aktualisiert. Das Festlegen des CPU-Zugriffs auf 0 bedeutet, dass die CPU weder die Ressource lesen noch schreiben muss. Dies bedeutet, dass die Laufzeit die Ressource in den leistungsstärksten Speicher für die GPU laden kann, da die Ressource keinen CPU-Zugriff erfordert.

Wie erwartet, gibt es einen Kompromiss zwischen der besten Leistung und der jederzeitigen Barrierefreiheit durch einen der Beiden Prozessor. Die Standardnutzung ohne CPU-Zugriff bedeutet beispielsweise, dass die Ressource ausschließlich der GPU zur Verfügung gestellt werden kann. Dies kann das Laden der Ressource in den Arbeitsspeicher umfassen, auf den nicht direkt von der CPU zugegriffen werden kann. Die Ressource konnte nur mit UpdateSubresource geändert werden.

Erstellen der Initialisierungsdaten für den Puffer

Ein Puffer ist nur eine Sammlung von Elementen und wird als 1D-Array angeordnet. Dies führt dazu, dass der Speicherabstand des Systems und das Systemspeichersegment-Pitch beide identisch sind. die Größe der Vertexdatendeklaration. Eine Anwendung kann Initialisierungsdaten bereitstellen, wenn ein Puffer mithilfe einer Unterressourcenbeschreibung erstellt wird, die einen Zeiger auf die tatsächlichen Ressourcendaten enthält und Informationen über die Größe und das Layout dieser Daten enthält.

Jeder Puffer, der mit unveränderlicher Verwendung erstellt wurde (siehe D3D10_USAGE_IMMUTABLE), muss zur Erstellungszeit initialisiert werden. Puffer, die eines der anderen Verwendungskennzeichnungen verwenden, können nach der Initialisierung mithilfe von CopyResource, CopySubresourceRegion und UpdateSubresource oder durch Zugriff auf den zugrunde liegenden Arbeitsspeicher mithilfe der Map-Methode aktualisiert werden.

Erstellen des Puffers

Verwenden der Pufferbeschreibung und der Initialisierungsdaten (optional) rufen CreateBuffer auf, um einen Vertexpuffer zu erstellen. Der folgende Codeausschnitt veranschaulicht das Erstellen eines Vertexpuffers aus einem Array von Vertexdaten, die von der Anwendung deklariert wurden.

struct SimpleVertexCombined
{
    D3DXVECTOR3 Pos;  
    D3DXVECTOR3 Col;  
};


ID3D10InputLayout* g_pVertexLayout = NULL;
ID3D10Buffer*      g_pVertexBuffer[2] = { NULL, NULL };
ID3D10Buffer*      g_pIndexBuffer = NULL;


SimpleVertexCombined verticesCombo[] =
{
    D3DXVECTOR3( 0.0f, 0.5f, 0.5f ),
    D3DXVECTOR3( 0.0f, 0.0f, 0.5f ),
    D3DXVECTOR3( 0.5f, -0.5f, 0.5f ),
    D3DXVECTOR3( 0.5f, 0.0f, 0.0f ),
    D3DXVECTOR3( -0.5f, -0.5f, 0.5f ),
    D3DXVECTOR3( 0.0f, 0.5f, 0.0f ),
};


    D3D10_BUFFER_DESC bufferDesc;
    bufferDesc.Usage            = D3D10_USAGE_DEFAULT;
    bufferDesc.ByteWidth        = sizeof( SimpleVertexCombined ) * 3;
    bufferDesc.BindFlags        = D3D10_BIND_VERTEX_BUFFER;
    bufferDesc.CPUAccessFlags   = 0;
    bufferDesc.MiscFlags        = 0;
    
    D3D10_SUBRESOURCE_DATA InitData;
    InitData.pSysMem = verticesCombo;
    InitData.SysMemPitch = 0;
    InitData.SysMemSlicePitch = 0;
    hr = g_pd3dDevice->CreateBuffer( &bufferDesc, &InitData, &g_pVertexBuffer[0] );

Erstellen eines Indexpuffers

Das Erstellen eines Indexpuffers ähnelt dem Erstellen eines Vertexpuffers. mit zwei Unterschieden. Ein Indexpuffer enthält nur 16-Bit- oder 32-Bit-Daten (anstelle der breiten Palette von Formaten, die für einen Vertexpuffer verfügbar sind. Ein Indexpuffer erfordert auch ein Indexpufferbindungsflagge.

Im folgenden Beispiel wird das Erstellen eines Indexpuffers aus einem Array von Indexdaten veranschaulicht.

ID3D10Buffer *g_pIndexBuffer = NULL;

    // Create indices
    unsigned int indices[] = { 0, 1, 2 };

    D3D10_BUFFER_DESC bufferDesc;
    bufferDesc.Usage           = D3D10_USAGE_DEFAULT;
    bufferDesc.ByteWidth       = sizeof( unsigned int ) * 3;
    bufferDesc.BindFlags       = D3D10_BIND_INDEX_BUFFER;
    bufferDesc.CPUAccessFlags  = 0;
    bufferDesc.MiscFlags       = 0;

    D3D10_SUBRESOURCE_DATA InitData;
    InitData.pSysMem = indices;
    InitData.SysMemPitch = 0;
    InitData.SysMemSlicePitch = 0;
    hr = g_pd3dDevice->CreateBuffer( &bufferDesc, &InitData, &g_pIndexBuffer );
    if( FAILED( hr ) )
        return hr;
  
    g_pd3dDevice->IASetIndexBuffer( g_pIndexBuffer, DXGI_FORMAT_R32_UINT, 0 );

Erstellen eines Konstantenpuffers

Direct3D 10 führt einen Konstantenpuffer ein. Ein Konstantenpuffer oder Shaderkonstantenpuffer ist ein Puffer, der Shaderkonstanten enthält. Hier ist ein Beispiel für das Erstellen eines Konstantenpuffers, der aus dem HLSLWithoutFX10-Beispiel stammt.

ID3D10Buffer*   g_pConstantBuffer10 = NULL;

struct VS_CONSTANT_BUFFER
{
    D3DXMATRIX mWorldViewProj;      //mWorldViewProj will probably be global to all shaders in a project.
                                    //It's a good idea not to move it around between shaders.
    D3DXVECTOR4 vSomeVectorThatMayBeNeededByASpecificShader;
    float fSomeFloatThatMayBeNeededByASpecificShader;
    float fTime;                    //fTime may also be global to all shaders in a project.
    float fSomeFloatThatMayBeNeededByASpecificShader2;
    float fSomeFloatThatMayBeNeededByASpecificShader3;
};

    D3D10_BUFFER_DESC cbDesc;
    cbDesc.ByteWidth = sizeof( VS_CONSTANT_BUFFER );
    cbDesc.Usage = D3D10_USAGE_DYNAMIC;
    cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
    cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
    cbDesc.MiscFlags = 0;
    hr = g_pd3dDevice->CreateBuffer( &cbDesc, NULL, &g_pConstantBuffer10 );
    if( FAILED( hr ) )
       return hr;

    g_pd3dDevice->VSSetConstantBuffers( 0, 1, g_pConstantBuffer10 );

Beachten Sie, dass bei Verwendung der ID3D10Effect Interface-Schnittstelle der Prozess zum Erstellen, Binden und Komitieren eines Konstantenpuffers von der ID3D10Effect-Schnittstelleninstanz behandelt wird. In diesem Fall ist es nur erforderlich, die Variable aus dem Effekt mit einer der GetVariable-Methoden wie GetVariableByName abzurufen und die Variable mit einer der SetVariable-Methoden wie SetMatrix zu aktualisieren. Ein Beispiel für die Verwendung der ID3D10Effect-Schnittstelle zum Verwalten eines Konstantenpuffers finden Sie im Lernprogramm 7: Texturzuordnung und Konstantenpuffer.

Ressourcen (Direct3D 10)