Compartilhar via


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 e são usados para renderizar primitivos usando o método IDirect3DDevice9::D rawIndexedPrimitive .

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 observação lateral, IDirect3DDevice9::D rawIndexedPrimitiveUP e IDirect3DDevice9::D rawPrimitiveUP são os únicos métodos de desenho que desenham 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 Tipo identifica o tipo de recurso do buffer de índice.
  • O membro da estrutura Uso contém sinalizadores de funcionalidade gerais. O sinalizador D3DUSAGE_SOFTWAREPROCESSING indica que o buffer de índice deve ser usado com o processamento de vértice de software. A presença do sinalizador D3DUSAGE_WRITEONLY em Uso 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 habilitar o processamento e a renderização rápidos. Se o sinalizador D3DUSAGE_WRITEONLY não for usado, é menos provável que o driver coloque os dados em um local ineficiente para operações de leitura. Isso sacrifica alguma velocidade de processamento e renderização. Se esse sinalizador não for especificado, supõe-se que os aplicativos executem operações de leitura e gravação nos dados no buffer de índice.
  • O 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 do 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 de software. Esse sinalizador é necessário no processamento de vértice de modo misto (D3DCREATE_MIXED_VERTEXPROCESSING) quando o processamento de vértice de software é usado.

O app pode gravar diretamente índices em um buffer de índice alocado na memória ideal de 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 você não quiser usar memória de vídeo ou usar 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 comprimento 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 que estão sendo referenciados 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 processamento de vértice de software ou modo misto (D3DCREATE_MIXED_VERTEXPROCESSING/D3DCREATE_SOFTWARE_VERTEXPROCESSING) está habilitado para esse dispositivo. D3DUSAGE_SOFTWAREPROCESSING deve ser definido para buffers a serem usados com 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 é a única opção quando um único buffer é 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 de índice está sendo feito no hardware. Essa é uma maneira de evitar grandes quantidades de memória bloqueada por página quando um driver está colocando esses buffers na memória do AGP.

  • O terceiro parâmetro é o D3DFMT_INDEX16 ou D3DFMT_INDEX32 membro 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 na memória colocar o novo buffer de índice.

  • O parâmetro final que IDirect3DDevice9::CreateIndexBuffer aceita é o endereço de uma variável 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 pode ser a criação de um buffer de índice 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 indexar a memória do buffer chamando o método IDirect3DIndexBuffer9::Lock e acessando a memória conforme necessário para preencher o buffer com novos dados de índice ou para ler os dados que ele contém. O método Lock aceita quatro parâmetros. O primeiro, OffsetToLock, é o deslocamento para os dados de í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, é o endereço de um ponteiro BYTE preenchido com um ponteiro para os dados de í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 forma 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 dado o tipo de acesso solicitado. Use D3DLOCK_READONLY sinalizador se o aplicativo ler somente da memória do buffer de índice. A inclusão desse sinalizador permite que o Direct3D otimize seus procedimentos internos para melhorar a eficiência, dado 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 somente da memória do buffer de índice. A inclusão desse sinalizador permite que o Direct3D otimize seus procedimentos internos para melhorar a eficiência, dado 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 , consulte Otimizações de desempenho (Direct3D 9).

 

No 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 renderizar essa memória inválida. Use o passo a passo do formato de índice que seu 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)