Buffers de índice (Direct3D 9)

Os buffers de índice, representados pela interface IDirect3DIndexBuffer9, são buffers de memória que contêm dados de índice. Os dados de índice, ou índices, são deslocamentos inteiros em buffers de vértice usados para renderizar primitivos usando o método IDirect3DDevice9::DrawIndexedPrimitive.

Um buffer de vértices contém vértices. Portanto, você pode desenhar um buffer de vértice com ou sem primitivas indexadas. No entanto, como um buffer de índice contém índices, você não pode usar um buffer de índice sem um buffer de vértice correspondente. (Como uma nota lateral, IDirect3DDevice9::D rawIndexedPrimitiveUP e IDirect3DDevice9::D rawPrimitiveUP são os únicos métodos de desenho sem um índice ou um buffer de vértice.)

Descrição de buffer de índice

Um buffer de índice é descrito em termos de suas funcionalidades, como onde ele existe na memória, se suporta leitura e gravação, e o tipo e o número de índices que contém. Essas características são mantidas em uma estrutura D3DINDEXBUFFER_DESC.

Descrições de buffer de índice informam ao seu app como um buffer existente foi criado. Você fornece uma estrutura de descrição vazia para o sistema preencher com os recursos de um buffer de índice criado anteriormente.

  • O membro Format descreve o formato de superfície dos dados do buffer de índice.
  • O Type identifica o tipo de recurso do buffer de índice.
  • O membro da estrutura Usage contém sinalizadores de funcionalidade geral. O sinalizador D3DUSAGE_SOFTWAREPROCESSING indica que o buffer de índice deve ser usado com o processamento de vértices de software. A presença do sinalizador D3DUSAGE_WRITEONLY em Usage indica que a memória do buffer de índice é usada apenas para operações de gravação. Isso libera o driver para colocar os dados de índice no melhor local de memória para permitir processamento e renderização rápidos. Se o sinalizador D3DUSAGE_WRITEONLY não for usado, será menos provável que o driver coloque os dados em um local ineficiente para operações de leitura. Isso sacrifica a velocidade de processamento e renderização. Caso esse sinalizador não seja especificado, supõe-se que os aplicativos executem operações de leitura e gravação nos dados no buffer de índice.
  • Pool especifica a classe de memória alocada para o buffer de índice. O sinalizador D3DPOOL_SYSTEMMEM indica que o sistema criou o buffer de índice na memória do sistema.
  • O membro Size armazena o tamanho, em bytes, dos dados do buffer de vértice.
  • O último parâmetro pSharedHandle não é usado. Defina-o como NULL.

Requisitos de processamento de índice

O desempenho das operações de processamento de índice depende muito onde o buffer de índice existe na memória e qual tipo de dispositivo de renderização que está sendo usado. Os apps controlam a alocação de memória para buffers de índice quando eles são criados. Quando o sinalizador de memória D3DPOOL_SYSTEMMEM é definido, o buffer de índice é criado na memória do sistema. Quando o sinalizador de memória D3DPOOL_DEFAULT é usado, o driver de dispositivo determina onde a memória do buffer de índice é melhor alocada, geralmente chamada de memória ideal do driver. A memória ideal do driver pode ser memória de vídeo local, memória de vídeo não local ou memória do sistema.

Definir o sinalizador de comportamento D3DUSAGE_SOFTWAREPROCESSING ao chamar o método IDirect3DDevice9::CreateIndexBuffer especifica que o buffer de índice deve ser usado com o processamento de vértice do software. Esse sinalizador será necessário no processamento de vértice de modo misto (D3DCREATE_MIXED_VERTEXPROCESSING) quando o processamento de vértice de software for usado.

O aplicativo pode gravar índices diretamente em um buffer de índice alocado na memória ideal do driver. Essa técnica impede uma operação de cópia redundante mais tarde. Essa técnica não funciona bem se o app lê dados de um buffer de índice, pois operações de leitura feitas pelo host da memória ideal de driver podem ser muito lentas. Portanto, se seu app precisar ler durante o processamento ou gravar dados no buffer de modo irregular, um buffer de índice de memória do sistema é a melhor opção.

Observação

Sempre use D3DPOOL_DEFAULT, exceto quando não quiser usar memória de vídeo ou grandes quantidades de RAM bloqueada por página quando o driver estiver colocando buffers de vértice ou índice na memória AGP.

 

Criar um buffer de índice

Crie um objeto de buffer de índice chamando o método IDirect3DDevice9::CreateIndexBuffer, que aceita seis parâmetros.

  • O primeiro parâmetro especifica o tamanho do buffer de índice, em bytes.

  • O segundo parâmetro é um conjunto de controles de uso. Entre outras coisas, seu valor determina se os vértices referidos pelos índices são capazes de conter informações de recorte. Para melhorar o desempenho, especifique D3DUSAGE_DONOTCLIP quando o recorte não for necessário.

    O sinalizador D3DUSAGE_SOFTWAREPROCESSING pode ser definido quando o modo misto ou o processamento de vértice de software (D3DCREATE_MIXED_VERTEXPROCESSING / D3DCREATE_SOFTWARE_VERTEXPROCESSING) está habilitado para esse dispositivo. D3DUSAGE_SOFTWAREPROCESSING deve ser definido para buffers a serem usados com o processamento de vértice de software no modo misto, mas não deve ser definido para o melhor desempenho possível ao usar o processamento de índice de hardware no modo misto (D3DCREATE_HARDWARE_VERTEXPROCESSING). No entanto, definir D3DUSAGE_SOFTWAREPROCESSING será a única opção quando um único buffer for usado com processamento de vértice de hardware e software. D3DUSAGE_SOFTWAREPROCESSING é permitido para dispositivos mistos e de software.

    É possível forçar buffers de vértice e índice na memória do sistema especificando D3DPOOL_SYSTEMMEM, mesmo quando o processamento do índice está sendo feito no hardware. Essa é uma maneira de evitar quantidades excessivamente grandes de memória bloqueada por página quando um driver está colocando os buffers na memória AGP.

  • O terceiro parâmetro é o membro D3DFMT_INDEX16 ou D3DFMT_INDEX32 do tipo enumerado D3DFORMAT que especifica o tamanho de cada índice.

  • O quarto parâmetro é um membro do tipo enumerado D3DPOOL que informa ao sistema onde colocar o novo buffer de índice na memória.

  • O parâmetro final que IDirect3DDevice9::CreateIndexBuffer aceita é o endereço de uma variável que será preenchida com um ponteiro para a nova interface IDirect3DIndexBuffer9 do objeto de buffer de vértice, se a chamada for bem-sucedida.

O exemplo de código C++ a seguir mostra como a criação de um buffer de índice pode ser no código.

/*
 * For the purposes of this example, the d3dDevice variable is the 
 * address of an IDirect3DDevice9 interface exposed by a 
 * Direct3DDevice object, g_IB is a variable of type 
 * LPDIRECT3DINDEXBUFFER9.
 */

if( FAILED( d3dDevice->CreateIndexBuffer( 16384 *sizeof(WORD),
           D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, 
           &g_IB, NULL ) ) )
    return E_FAIL;

Acessar um buffer de índice

Os objetos de buffer de índice permitem que os aplicativos acessem diretamente a memória alocada para dados de índice. Você pode recuperar um ponteiro para a memória do buffer de índice chamando o método IDirect3DIndexBuffer9::Lock e, em seguida, acessando a memória conforme necessário para preencher o buffer com novos dados de índice ou para ler todos os dados que ele contém. O método Lock aceita quatro parâmetros. O primeiro, OffsetToLock, é o deslocamento nos dados do índice. O segundo parâmetro é o tamanho, medido em bytes, dos dados de índice. O terceiro parâmetro aceito pelo método IDirect3DIndexBuffer9::Lock, ppbData, será o endereço de um ponteiro BYTE preenchido com um ponteiro para os dados do índice, se a chamada for bem-sucedida.

O último parâmetro, Flags, informa ao sistema como a memória deve ser bloqueada. Você pode usá-lo para indicar como o aplicativo acessa os dados no buffer. Especifique constantes para o parâmetro Flags de acordo com a maneira como os dados de índice serão acessados pelo aplicativo. Isso permite que o driver bloqueie a memória e forneça o melhor desempenho de acordo com o tipo de acesso solicitado. Use o sinalizador D3DLOCK_READONLY se o aplicativo ler apenas da memória do buffer de índice. A inclusão do sinalizador permite que o Direct3D otimize seus procedimentos internos para melhorar a eficiência, já que o acesso à memória será somente leitura.

Depois de preencher ou ler os dados de índice, chame o método IDirect3DIndexBuffer9::Unlock, conforme mostrado no exemplo de código a seguir.

// This code example assumes the m_pIndexBuffer is a variable of type 
// LPDIRECT3DINDEXBUFFER9 and that g_Indices has been properly 
// initialized with indices.

// To fill the index buffer, you must lock the buffer to gain 
// access to the indices. This mechanism is required because index
// buffers may be in device memory.

VOID* pIndices;

if( FAILED( m_pIndexBuffer->Lock( 
      0,                 // Fill from start of the buffer
      sizeof(g_Indices), // Size of the data to load
      BYTE**)&pIndices,  // Returned index data
      0 ) ) )            // Send default flags to the lock
{
    SAFE_RELEASE(m_pIndexBuffer);
    return E_FAIL;
}

memcpy( pIndices, g_Indices, sizeof(g_Indices) );
m_pIndexBuffer->Unlock();

Observação

Se você criar um buffer de índice com o sinalizador D3DUSAGE_WRITEONLY, não use o sinalizador de bloqueio D3DLOCK_READONLY. Use o sinalizador D3DLOCK_READONLY se o aplicativo ler apenas da memória do buffer de índice. A inclusão do sinalizador permite que o Direct3D otimize seus procedimentos internos para melhorar a eficiência, já que o acesso à memória será somente leitura.

Para obter informações sobre como usar D3DLOCK_DISCARD ou D3DLOCK_NOOVERWRITE para o parâmetro Flags do método IDirect3DIndexBuffer9::Lock, confira Otimizações de desempenho (Direct3D 9).

 

Em C++, como você acessa diretamente a memória alocada para o buffer de índice, verifique se o aplicativo acessa corretamente a memória alocada. Caso contrário, você corre o risco de tornar essa memória inválida. Use o Stride do formato de índice que o aplicativo usa para mover de um índice no buffer alocado para outro.

Recupere informações sobre um buffer de índice chamando o método IDirect3DIndexBuffer9::GetDesc. Esse método preenche os membros da estrutura D3DINDEXBUFFER_DESC com informações sobre o buffer de índice.

Recursos do Direct3D

Renderização de buffers de vértice e índice (Direct3D 9)

Buffers de vértice (Direct3D 9)