Criando recursos de buffer (Direct3D 10)

A criação de buffers requer a definição dos dados que o buffer armazenará, o fornecimento de dados de inicialização e a configuração de sinalizadores de uso e vinculação apropriados. Para criar texturas, consulte Criando recursos de textura (Direct3D 10).

Criar um buffer de vértice

As etapas para criar um buffer de vértice são as seguintes.

Criar uma descrição de buffer

Ao criar um buffer de vértice, uma descrição do buffer (consulte D3D10_BUFFER_DESC) é usada para definir como os dados são organizados no buffer, como o pipeline pode acessar o buffer e como o buffer será usado.

O exemplo a seguir demonstra como criar uma descrição de buffer para um único triângulo com vértices que contêm valores de posição e cor.

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;

Neste exemplo, a descrição do buffer é inicializada com quase todas as configurações padrão para uso, acesso à CPU e sinalizadores diversos. As outras configurações são para o sinalizador de ligação, que identifica o recurso apenas como um buffer de vértice, e o tamanho do buffer.

Os sinalizadores de uso e acesso à CPU são importantes para o desempenho. Esses dois sinalizadores juntos determinam a frequência com que um recurso é acessado, em que tipo de memória o recurso pode ser carregado e qual processador precisa para acessar o recurso. Uso padrão Esse recurso não será atualizado com muita frequência. Definir o acesso à CPU como 0 significa que a CPU não precisará ler ou gravar o recurso. Tomado em combinação, isso significa que o tempo de execução pode carregar o recurso na memória de melhor desempenho para a GPU, uma vez que o recurso não requer acesso à CPU.

Como esperado, há uma compensação entre o melhor desempenho e a acessibilidade a qualquer momento por qualquer processador. Por exemplo, o uso padrão sem acesso à CPU significa que o recurso pode ser disponibilizado exclusivamente para a GPU. Isso pode incluir carregar o recurso na memória não diretamente acessível pela CPU. O recurso só pode ser modificado com UpdateSubresource.

Criar os dados de inicialização para o buffer

Um buffer é apenas uma coleção de elementos e é disposto como uma matriz 1D. Como resultado, o pitch da memória do sistema e o pitch da fatia de memória do sistema são os mesmos; O tamanho da declaração de dados de vértice. Um aplicativo pode fornecer dados de inicialização quando um buffer é criado usando uma descrição de subrecurso, que contém um ponteiro para os dados reais do recurso e contém informações sobre o tamanho e o layout desses dados.

Qualquer buffer criado com uso imutável (consulte D3D10_USAGE_IMMUTABLE) deve ser inicializado no momento da criação. Os buffers que usam qualquer um dos outros sinalizadores de uso podem ser atualizados após a inicialização usando CopyResource, CopySubresourceRegion e UpdateSubresource ou acessando sua memória subjacente usando o método Map.

Criar o buffer

Usando a descrição do buffer e os dados de inicialização (que são opcionais), chame CreateBuffer para criar um buffer de vértice. O trecho de código a seguir demonstra como criar um buffer de vértice a partir de uma matriz de dados de vértice declarada pelo aplicativo.

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

Criar um buffer de índice

Criar um buffer de índice é muito semelhante à criação de um buffer de vértice; com duas diferenças. Um buffer de índice contém apenas dados de 16 bits ou 32 bits (em vez da ampla gama de formatos disponíveis para um buffer de vértice. Um buffer de índice também requer um sinalizador de ligação de buffer de índice.

O exemplo a seguir demonstra como criar um buffer de índice a partir de uma matriz de dados de índice.

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

Criar um buffer constante

O Direct3D 10 introduz um buffer constante. Um buffer constante, ou buffer constante de sombreador, é um buffer que contém constantes de sombreador. Aqui está um exemplo de criação de um buffer constante, retirado do exemplo 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 );

Observe que, ao usar a interface ID3D10Effect Interface, o processo de criação, vinculação e confirmação de um buffer constante é manipulado pela instância ID3D10Effect Interface. Nesse caso, é necessário apenas obter a variável do efeito com um dos métodos GetVariable como GetVariableByName e atualizar a variável com um dos métodos SetVariable como SetMatrix. Para obter um exemplo de como usar a Interface ID3D10Effect para gerenciar um buffer constante, consulte Tutorial 7: Mapeamento de textura e buffers constantes.

Recursos (Direct3D 10)