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 gli indici sono offset integer nei buffer dei vertici e vengono usati per eseguire il rendering delle primitive usando il metodo IDirect3DDevice9::D rawIndexedPrimitive .

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

Descrizione del buffer di indice

Un buffer di indice è descritto in termini di funzionalità, ad esempio 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 di indice indicano all'applicazione come è stato creato un buffer esistente. Specificare una struttura di descrizione vuota per il sistema per compilare le funzionalità di un buffer di indice creato in precedenza.

  • Il membro Format descrive il formato di superficie dei dati del buffer di indice.
  • Il tipo di risorsa identifica il tipo di risorsa del buffer di indice.
  • Il membro struttura Utilizzo 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 di D3DUSAGE_WRITEONLY in Utilizzo indica che la memoria del buffer di indice viene usata solo per le operazioni di scrittura. In questo modo il driver consente di inserire 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, il driver è meno probabile che i dati vengano inseriti in una posizione inefficiente per le operazioni di lettura. Ciò sacrifica una certa velocità di elaborazione e rendering. Se questo flag non è specificato, si presuppone che le applicazioni eseguano operazioni di lettura e scrittura sui dati nel buffer di indice.
  • Il 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 buffer dei vertici.
  • L'ultimo parametro pSharedHandle non viene usato. Impostarlo su NULL.

Requisiti di elaborazione degli indici

Le prestazioni delle operazioni di elaborazione dell'indice dipendono fortemente dalla posizione in cui esiste il buffer di indice in memoria e il tipo di dispositivo di rendering usato. Le applicazioni controllano l'allocazione della memoria per i buffer di 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 del dispositivo determina la posizione in cui la memoria per il buffer di indice è più adatta, spesso definita memoria ottimale del driver. La memoria ottimale del driver può essere memoria video locale, memoria video non locale o 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 del vertice software. Questo flag è necessario nell'elaborazione dei vertici in modalità mista (D3DCREATE_MIXED_VERTEXPROCESSING) quando viene usata l'elaborazione del vertice 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 di 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 di indice di memoria di sistema è una scelta migliore.

Nota

Usare sempre D3DPOOL_DEFAULT, tranne quando non si vuole usare memoria video o usare grandi quantità di RAM bloccate a pagina quando il driver inserisce i buffer di vertice o di indice in 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, 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 gli indici sono in grado di contenere informazioni di ritaglio. Per migliorare le prestazioni, specificare D3DUSAGE_DONOTCLIP quando il ritaglio non è obbligatorio.

    Il flag di D3DUSAGE_SOFTWAREPROCESSING può essere impostato quando l'elaborazione dei vertici software o modalità mista (D3DCREATE_MIXED_VERTEXPROCESSING/D3DCREATE_SOFTWARE_VERTEXPROCESSING) è abilitata per tale dispositivo. D3DUSAGE_SOFTWAREPROCESSING deve essere impostato per l'uso dei buffer con l'elaborazione dei vertici software in modalità mista, ma non deve essere impostato per le 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 l'elaborazione del vertice hardware e software. D3DUSAGE_SOFTWAREPROCESSING è consentito per i dispositivi misti e software.

    È possibile forzare i vertex e i buffer di indice 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.

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

Nell'esempio di codice C++ seguente viene illustrato ciò che potrebbe essere simile alla 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 di indice consentono alle applicazioni di accedere direttamente alla memoria allocata per i dati dell'indice. È possibile recuperare un puntatore alla memoria del buffer di indice 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. Ciò consente al driver di bloccare la memoria e fornire prestazioni ottimali in base al tipo di accesso richiesto. Usare D3DLOCK_READONLY flag se l'applicazione leggerà solo dalla memoria del buffer di indice. Incluso 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 di 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. Incluso 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 accinga 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 e buffer di indice (Direct3D 9)

Buffer vertex (Direct3D 9)