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 associaçã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 do 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 dentro do 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 associação que identifica o recurso apenas como um buffer de vértice e o tamanho do buffer.

O uso e os sinalizadores de acesso à CPU são importantes para o desempenho. Esses dois sinalizadores juntos determinam com que frequência um recurso é acessado, em que tipo de memória o recurso pode ser carregado e em qual processador precisa 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. Feito em combinação, isso significa que o runtime pode carregar o recurso na memória de maior desempenho para a GPU, pois o recurso não requer acesso à CPU.

Conforme 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 o carregamento do recurso na memória não diretamente acessível pela CPU. O recurso só pôde 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 tom de memória do sistema e a 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 sub-fonte, 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 é opcional) chamam CreateBuffer para criar um buffer de vértice. O snippet de código a seguir demonstra como criar um buffer de vértice 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

A criação de 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 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 associaçã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, extraído 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, associação e confirmação de um buffer constante é tratado pela instância da Interface ID3D10Effect . Nesse caso, é apenas um nescesário 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)