Condividi tramite


Creazione di risorse buffer (Direct3D 10)

La creazione di buffer richiede la definizione dei dati archiviati dal buffer, la fornitura di dati di inizializzazione e la configurazione di flag di utilizzo e binding appropriati. Per creare trame, vedere Creazione di risorse trama (Direct3D 10).

Creare un vertex buffer

I passaggi per la creazione di un buffer dei vertici sono i seguenti.

Creare una descrizione del buffer

Quando si crea un buffer dei vertici, viene usata una descrizione del buffer (vedere D3D10_BUFFER_DESC) per definire la modalità di organizzazione dei dati all'interno del buffer, il modo in cui la pipeline può accedere al buffer e come verrà usato il buffer.

Nell'esempio seguente viene illustrato come creare una descrizione del buffer per un singolo triangolo con vertici che contengono valori di posizione e colore.

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 questo esempio la descrizione del buffer viene inizializzata con quasi tutte le impostazioni predefinite per l'utilizzo, l'accesso alla CPU e i flag vari. Le altre impostazioni sono relative al flag di associazione che identifica la risorsa come solo un vertex buffer e le dimensioni del buffer.

I flag di accesso all'utilizzo e alla CPU sono importanti per le prestazioni. Questi due flag determinano la frequenza di accesso a una risorsa, il tipo di memoria in cui è possibile caricare la risorsa e il processore necessario per accedere alla risorsa. Utilizzo predefinito questa risorsa non verrà aggiornata molto spesso. L'impostazione dell'accesso della CPU su 0 significa che la CPU non dovrà leggere o scrivere la risorsa. In combinazione, questo significa che il runtime può caricare la risorsa nella memoria con prestazioni più elevate per la GPU perché la risorsa non richiede l'accesso alla CPU.

Come previsto, esiste un compromesso tra le migliori prestazioni e l'accessibilità in qualsiasi momento da entrambi i processori. Ad esempio, l'utilizzo predefinito senza accesso alla CPU significa che la risorsa può essere resa disponibile esclusivamente per la GPU. Ciò potrebbe includere il caricamento della risorsa in memoria non direttamente accessibile dalla CPU. La risorsa può essere modificata solo con UpdateSubresource.

Creare i dati di inizializzazione per il buffer

Un buffer è solo una raccolta di elementi e viene disposto come matrice 1D. Di conseguenza, l'inclinazione della memoria di sistema e il passo della sezione di memoria di sistema sono entrambi uguali; dimensioni della dichiarazione di dati dei vertici. Un'applicazione può fornire dati di inizializzazione quando viene creato un buffer usando una descrizione di sottorisorsa, che contiene un puntatore ai dati effettivi della risorsa e contiene informazioni sulle dimensioni e sul layout dei dati.

Qualsiasi buffer creato con utilizzo non modificabile (vedere D3D10_USAGE_IMMUTABLE) deve essere inizializzato in fase di creazione. I buffer che usano uno qualsiasi degli altri flag di utilizzo possono essere aggiornati dopo l'inizializzazione tramite CopyResource, CopySubresourceRegion e UpdateSubresource oppure accedendo alla memoria sottostante usando il metodo Map.

Creare il buffer

Usando la descrizione del buffer e i dati di inizializzazione (facoltativi) chiama CreateBuffer per creare un buffer dei vertici. Il frammento di codice seguente illustra come creare un buffer dei vertici da una matrice di dati dei vertici dichiarati dall'applicazione.

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] );

Creare un buffer di indice

La creazione di un buffer di indice è molto simile alla creazione di un buffer dei vertici; con due differenze. Un buffer di indice contiene solo dati a 16 bit o a 32 bit anziché l'ampia gamma di formati disponibili per un vertex buffer. Un buffer di indice richiede anche un flag di associazione index-buffer.

Nell'esempio seguente viene illustrato come creare un buffer di indice da una matrice di dati di indice.

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 );

Creare un buffer costante

Direct3D 10 introduce un buffer costante. Un buffer costante o un buffer costante shader è un buffer che contiene costanti shader. Di seguito è riportato un esempio di creazione di un buffer costante, tratto dall'esempio HLSLWithoutFX10.

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 );

Si noti che quando si usa l'interfaccia ID3D10Effect il processo di creazione, associazione e creazione di un buffer costante viene gestito dall'istanza dell'interfaccia ID3D10Effect. In tal caso è necessario ottenere la variabile solo dall'effetto con uno dei metodi GetVariable, ad esempio GetVariableByName e aggiornare la variabile con uno dei metodi SetVariable, ad esempio SetMatrix. Per un esempio dell'uso dell'interfaccia ID3D10Effect per gestire un buffer costante, vedere Esercitazione 7: Mapping delle trame e buffer costanti.

Risorse (Direct3D 10)