Buffer di indice (Direct3D 9)

I buffer di indice, rappresentati dall'interfaccia IDirect3DIndexBuffer9 , sono buffer di memoria che contengono dati di indice. I dati di indice, o indici, sono offset integer in vertex buffer e vengono usati per eseguire il rendering di primitive usando il metodo IDirect3DDevice9::D rawIndexedPrimitive.

Un buffer vertici contiene vertici; pertanto, è possibile disegnare un buffer vertici con o senza primitive indicizzate. Tuttavia, poiché un buffer indice contiene indici, non è possibile usare un buffer indice senza un buffer vertici corrispondente. (Come nota laterale, IDirect3DDevice9::D rawIndexedPrimitiveUP e IDirect3DDevice9::D rawPrimitiveUP sono gli unici metodi di disegno che disegnano senza un indice o un vertex buffer.

Descrizione del buffer indice

Un buffer indice è descritto in termini di funzionalità, ad esempio la posizione in cui esiste in memoria, se supporta la lettura e la scrittura e il tipo e il numero di indici che può contenere. Questi tratti vengono mantenuti in una struttura D3DINDEXBUFFER_DESC.

Le descrizioni del buffer indice indicano all'applicazione come è stato creato un buffer esistente. Si fornisce una struttura di descrizione vuota per il sistema da riempire con le funzionalità di un buffer indice creato in precedenza.

  • Il membro Format descrive il formato di superficie dei dati del buffer di indice.
  • Il tipo identifica il tipo di risorsa del buffer di indice.
  • Il membro Della struttura Usage contiene flag di funzionalità generali. Il flag D3DUSAGE_SOFTWAREPROCESSING indica che il buffer di indice deve essere usato con l'elaborazione dei vertici software. La presenza del flag D3DUSAGE_WRITEONLY in Usage indica che la memoria del buffer di indice viene usata solo per le operazioni di scrittura. In questo modo il driver consente al driver di posizionare i dati dell'indice nella posizione di memoria migliore per consentire l'elaborazione e il rendering rapidi. Se il flag D3DUSAGE_WRITEONLY non viene usato, è meno probabile che il driver inserisca i dati in una posizione inefficiente per le operazioni di lettura. Questo sacrifica una certa velocità di elaborazione e rendering. Se questo flag non viene specificato, si presuppone che le applicazioni eseguano operazioni di lettura e scrittura sui dati nel buffer di indice.
  • Pool specifica la classe di memoria allocata per il buffer di indice. Il flag D3DPOOL_SYSTEMMEM indica che il sistema ha creato il buffer di indice nella memoria di sistema.
  • Il membro Size archivia le dimensioni, in byte, dei dati del vertex buffer.
  • L'ultimo parametro pSharedHandle non viene utilizzato. Impostarlo su NULL.

Requisiti di elaborazione dell'indice

Le prestazioni delle operazioni di elaborazione dell'indice dipendono principalmente dalla posizione in cui è presente il buffer indice in memoria e dal tipo di dispositivo di rendering in uso. Le applicazioni controllano l'allocazione di memoria per i buffer indice quando vengono creati. Quando viene impostato il flag di memoria D3DPOOL_SYSTEMMEM, il buffer di indice viene creato nella memoria di sistema. Quando viene usato il flag di memoria D3DPOOL_DEFAULT, il driver di dispositivo determina la posizione in cui la memoria per il buffer di indice viene allocata al meglio, spesso definita memoria ottimale del driver. La memoria ottimale del driver può essere la memoria video locale, la memoria video non locale o la memoria di sistema.

L'impostazione del flag di comportamento D3DUSAGE_SOFTWAREPROCESSING quando si chiama il metodo IDirect3DDevice9::CreateIndexBuffer specifica che il buffer di indice deve essere usato con l'elaborazione dei vertici software. Questo flag è necessario nell'elaborazione dei vertici in modalità mista (D3DCREATE_MIXED_VERTEXPROCESSING) quando viene usata l'elaborazione dei vertici software.

L'applicazione può scrivere direttamente indici in un buffer di indice allocato nella memoria ottimale del driver. Questa tecnica impedisce un'operazione di copia ridondante in un secondo momento. Questa tecnica non funziona correttamente se l'applicazione legge i dati da un buffer indice, perché le operazioni di lettura eseguite dall'host dalla memoria ottimale del driver possono essere molto lente. Pertanto, se l'applicazione deve leggere durante l'elaborazione o scrive i dati nel buffer in modo erratico, un buffer indice della memoria di sistema è una scelta migliore.

Nota

Usare sempre D3DPOOL_DEFAULT, tranne quando non si vuole usare la memoria video o usare grandi quantità di RAM bloccate a pagina quando il driver inserisce vertex o buffer di indice nella memoria AGP.

 

Creare un buffer di indice

Creare un oggetto buffer di indice chiamando il metodo IDirect3DDevice9::CreateIndexBuffer , che accetta sei parametri.

  • Il primo parametro specifica la lunghezza del buffer di indice, espressa in byte.

  • Il secondo parametro è un set di controlli di utilizzo. Tra le altre cose, il valore determina se i vertici a cui si fa riferimento dagli indici sono in grado di contenere informazioni di ritaglio. Per migliorare le prestazioni, specificare D3DUSAGE_DONOTCLIP quando il ritaglio non è necessario.

    Il flag D3DUSAGE_SOFTWAREPROCESSING può essere impostato quando l'elaborazione dei vertici software o in modalità mista (D3DCREATE_MIXED_VERTEXPROCESSING/D3DCREATE_SOFTWARE_VERTEXPROCESSING) è abilitata per il dispositivo. D3DUSAGE_SOFTWAREPROCESSING deve essere impostato affinché i buffer vengano usati con l'elaborazione dei vertici software in modalità mista, ma non devono essere impostati per ottenere prestazioni ottimali quando si usa l'elaborazione dell'indice hardware in modalità mista (D3DCREATE_HARDWARE_VERTEXPROCESSING). Tuttavia, l'impostazione D3DUSAGE_SOFTWAREPROCESSING è l'unica opzione quando viene usato un singolo buffer con elaborazione dei vertici hardware e software. D3DUSAGE_SOFTWAREPROCESSING è consentito per i dispositivi misti e software.

    È possibile forzare i vertex buffer e index buffer nella memoria di sistema specificando D3DPOOL_SYSTEMMEM, anche quando l'elaborazione dell'indice viene eseguita nell'hardware. Questo è un modo per evitare quantità eccessivamente elevate di memoria bloccata a pagina quando un driver inserisce questi buffer nella memoria AGP.

  • Il terzo parametro è il D3DFMT_INDEX16 o D3DFMT_INDEX32 membro del tipo enumerato D3DFORMAT che specifica le dimensioni di ogni indice.

  • Il quarto parametro è un membro del tipo enumerato D3DPOOL che indica al sistema dove inserire il nuovo buffer di indice in memoria.

  • Il parametro finale accettato da IDirect3DDevice9::CreateIndexBuffer è l'indirizzo di una variabile riempita con un puntatore alla nuova interfaccia IDirect3DIndexBuffer9 dell'oggetto vertex buffer, se la chiamata ha esito positivo.

Nell'esempio di codice C++ seguente viene illustrato l'aspetto della creazione di un buffer di indice nel codice.

/*
 * 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;

Accedere a un buffer di indice

Gli oggetti buffer dell'indice consentono alle applicazioni di accedere direttamente alla memoria allocata per i dati dell'indice. È possibile recuperare un puntatore alla memoria del buffer di indicizzazione chiamando il metodo IDirect3DIndexBuffer9::Lock e quindi accedendo alla memoria in base alle esigenze per riempire il buffer con nuovi dati di indice o per leggere i dati contenuti. Il metodo Lock accetta quattro parametri. Il primo, OffsetToLock, è l'offset nei dati dell'indice. Il secondo parametro è la dimensione, misurata in byte, dei dati dell'indice. Il terzo parametro accettato dal metodo IDirect3DIndexBuffer9::Lock , ppbData, è l'indirizzo di un puntatore BYTE riempito con un puntatore ai dati dell'indice, se la chiamata ha esito positivo.

L'ultimo parametro, Flags, indica al sistema come deve essere bloccata la memoria. È possibile usarlo per indicare come l'applicazione accede ai dati nel buffer. Specificare le costanti per il parametro Flags in base al modo in cui i dati dell'indice saranno accessibili dall'applicazione. In questo modo il driver può bloccare la memoria e offrire prestazioni ottimali in base al tipo di accesso richiesto. Usare D3DLOCK_READONLY flag se l'applicazione leggerà solo dalla memoria del buffer di indice. L'inclusione di questo flag consente a Direct3D di ottimizzare le procedure interne per migliorare l'efficienza, dato che l'accesso alla memoria sarà di sola lettura.

Dopo aver compilato o letto i dati dell'indice, chiamare il metodo IDirect3DIndexBuffer9::Unlock , come illustrato nell'esempio di codice seguente.

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

Nota

Se si crea un buffer di indice con il flag D3DUSAGE_WRITEONLY, non usare il flag di blocco D3DLOCK_READONLY. Usare il flag D3DLOCK_READONLY se l'applicazione leggerà solo dalla memoria del buffer di indice. L'inclusione di questo flag consente a Direct3D di ottimizzare le procedure interne per migliorare l'efficienza, dato che l'accesso alla memoria sarà di sola lettura.

Per informazioni sull'uso di D3DLOCK_DISCARD o D3DLOCK_NOOVERWRITE per il parametro Flags del metodo IDirect3DIndexBuffer9::Lock, vedere Ottimizzazioni delle prestazioni (Direct3D 9).

 

In C++, poiché si accede direttamente alla memoria allocata per il buffer di indice, assicurarsi che l'applicazione accesa correttamente alla memoria allocata. In caso contrario, si rischia di eseguire il rendering della memoria non valida. Usare lo stride del formato di indice usato dall'applicazione per passare da un indice nel buffer allocato a un altro.

Recuperare informazioni su un buffer di indice chiamando il metodo IDirect3DIndexBuffer9::GetDesc. Questo metodo riempie i membri della struttura D3DINDEXBUFFER_DESC con informazioni sul buffer di indice.

Risorse Direct3D

Rendering da vertex buffer e buffer di indice (Direct3D 9)

Vertex Buffers (Direct3D 9)