Búferes de índice (Direct3D 9)
Los búferes de índice, representados por la interfaz IDirect3DIndexBuffer9, son búferes de memoria que contienen datos de índice. Los datos de índice, o índices, son desplazamientos de enteros en búferes de vértices y se usan para representar primitivos mediante el método IDirect3DDevice9::DrawIndexedPrimitive.
Un búfer de vértices contiene vértices; por lo tanto, puede dibujar un búfer de vértices con o sin primitivos indizados. Sin embargo, como un búfer de índices contiene índices, no puede usar un búfer de índices sin un búfer de vértices correspondiente. (Como nota aparte, IDirect3DDevice9::DrawIndexedPrimitiveUP y IDirect3DDevice9::DrawPrimitiveUP son los únicos métodos de dibujado (draw) que dibujan sin un índice o un búfer de vértices).
Descripción del búfer de índices
Un búfer de índices se describe en términos de sus funcionalidades, como su ubicación en la memoria, si admite la lectura y escritura y el tipo y la cantidad de índices que puede contener. Estos rasgos se mantienen en una estructura D3DINDEXBUFFER_DESC.
Las descripciones del búfer de índices indican a la aplicación cómo se creó un búfer existente. Debe proporcionar una estructura de descripción vacía para que el sistema la rellene con las capacidades de un búfer de índices creado anteriormente.
- El miembro Format describe el formato de superficie de los datos del búfer de índice.
- El Type identifica el tipo de recurso del búfer de índice.
- El miembro de estructura Usage incluye flags de funcionalidad generales. La flag D3DUSAGE_SOFTWAREPROCESSING indica que el búfer de índice se va a usar con el procesamiento de vértices de software. La presencia de la flag D3DUSAGE_WRITEONLY en Usage indica que la memoria del búfer de índice solo se usa en las operaciones de escritura. Esto permite al controlador colocar los datos de índice en la mejor ubicación de memoria y así permitir un procesamiento y renderización rápidos. Si no se usa la flag D3DUSAGE_WRITEONLY, es menos probable que el controlador coloque los datos en una ubicación ineficaz para las operaciones de lectura. Esto sacrifica cierta velocidad de procesamiento y renderización. Si no se especifica esta flag, se supone que las aplicaciones realizan las operaciones de lectura y escritura en los datos del búfer de índice.
- Pool indica la clase de memoria asignada para el búfer de índice. La flag D3DPOOL_SYSTEMMEM indica que el sistema ha creado el búfer de índice en la memoria del sistema.
- El miembro Size almacena el tamaño, en bytes, de los datos del búfer de vértices.
- No se usa el último parámetro pSharedHandle. Páselo a NULL.
Requisitos de procesamiento de índices
El rendimiento de las operaciones de procesamiento de índices depende en gran medida de que el búfer de índices exista en la memoria y del tipo de dispositivo de representación que se usa. Las aplicaciones controlan la asignación de memoria para los búferes de índices cuando se crean. Cuando se crea la flag de memoria D3DPOOL_SYSTEMMEM, el búfer de índice se crea en la memoria del sistema. Cuando se usa la marca de memoria D3DPOOL_DEFAULT, el controlador de dispositivo determina dónde se asigna mejor la memoria del búfer de índice, a menudo denominada memoria óptima del controlador. La memoria óptima del controlador puede ser memoria de vídeo local, memoria de vídeo no local o memoria del sistema.
Crea la flag de uso D3DUSAGE_SOFTWAREPROCESSING al llamar al método IDirect3DDevice9::CreateIndexBuffer, se indica que el búfer de índice se usará con el procesamiento de vértices de software. Esta flag es necesaria en el procesamiento de vértices en modo mixto (D3DCREATE_MIXED_VERTEXPROCESSING) cuando se usa el procesamiento de vértices de software.
La aplicación puede escribir índices directamente en un búfer de índices asignado en la memoria óptima del controlador. Esta técnica impide que se haga una operación de copia redundante más adelante. Esta técnica no funciona bien si la aplicación vuelve a leer datos de un búfer de índices, ya que las operaciones de lectura que lleva a cabo el host de la memoria óptima para el controlador pueden ser muy lentas. Por lo tanto, si la aplicación tiene que leer durante el procesamiento o escribe datos en el búfer de forma errática, un búfer de índices de memoria del sistema es una elección mejor.
Nota:
Use siempre D3DPOOL_DEFAULT, excepto cuando no quiera usar memoria de vídeo o use grandes cantidades de RAM bloqueadas por páginas cuando el controlador coloca búferes de vértices o índices en la memoria AGP.
Creación de un búfer de índice
Cree un objeto de búfer de índice llamando al método IDirect3DDevice9::CreateIndexBuffer, que acepta seis parámetros.
El primer parámetro indica la longitud del búfer de índice, en bytes.
El segundo parámetro es un conjunto de controles de uso. Entre otras cosas, su valor determina si los vértices a los que hacen referencia los índices son capaces de contener la información del recorte. Para mejorar el rendimiento, indique D3DUSAGE_DONOTCLIP cuando no se necesite el recorte.
La flag D3DUSAGE_SOFTWAREPROCESSING se puede crear cuando el procesamiento de vértices de software o en modo mixto (D3DCREATE_MIXED_VERTEXPROCESSING o D3DCREATE_SOFTWARE_VERTEXPROCESSING) está habilitado en ese dispositivo. Debe crearse D3DUSAGE_SOFTWAREPROCESSING para que los búferes se usen con el procesamiento de vértices de software en modo mixto, pero no debe crearse para conseguir mejor rendimiento posible al usar el procesamiento de índices de hardware en modo mixto (D3DCREATE_HARDWARE_VERTEXPROCESSING). Sin embargo, crear D3DUSAGE_SOFTWAREPROCESSING es la única opción cuando se usa un solo búfer con el procesamiento de vértices de hardware y software. Se permite D3DUSAGE_SOFTWAREPROCESSING en dispositivos mixtos y de software.
Es posible forzar los búferes de vértices e índices en la memoria del sistema indicando D3DPOOL_SYSTEMMEM, aun cuando el procesamiento del índice se realiza en hardware. Esta es una manera de evitar grandes cantidades de memoria bloqueada por páginas cuando un controlador coloca estos búferes en memoria AGP.
El tercer parámetro es el miembro D3DFMT_INDEX16 o D3DFMT_INDEX32 del tipo enumerado D3DFORMAT que indica el tamaño de cada índice.
El cuarto parámetro es un miembro del tipo enumerado D3DPOOL que indica al sistema dónde colocar el nuevo búfer de índice en la memoria.
El parámetro final que IDirect3DDevice9::CreateIndexBuffer acepta es la dirección de una variable que se rellena con un puntero a la nueva interfaz IDirect3DIndexBuffer9 del objeto de búfer de vértices si la llamada se realiza correctamente.
En el siguiente ejemplo de código de C++, se muestra cómo se vería crear un búfer de índice en el 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;
Acceso a un búfer de índice
Los objetos de búfer de índice permiten que las aplicaciones accedan directamente a la memoria asignada para los datos de índice. Puede recuperar un puntero a la memoria del búfer de índice llamando al método IDirect3DIndexBuffer9::Lock y luego accediendo a la memoria si es necesario para rellenar el búfer con nuevos datos de índice o para leer los datos que contiene. El método Lock acepta cuatro parámetros. El primero, OffsetToLock, es el desplazamiento en los datos de índice. El segundo parámetro es el tamaño, calculado en bytes, de los datos de índice. El tercer parámetro aceptado por el método IDirect3DIndexBuffer9::Lock, ppbData, es la dirección de un puntero BYTE rellenado con un puntero a los datos de índice, si la llamada se realiza correctamente.
El último parámetro, Flags, indica al sistema cómo se debe bloquear la memoria. Puede usarlo para indicar de que forma la aplicación accede a los datos en el búfer. Indique las constantes en el parámetro Flags según la forma en que la aplicación vaya a tener acceso a los datos de índice. Esto permite al controlador bloquear la memoria y dar un mejor rendimiento según el tipo de acceso solicitado. Use la flag D3DLOCK_READONLY si la aplicación solo va a leer la memoria del búfer de índice. Al incluir esta flag, Direct3D es capaz de optimizar sus procedimientos internos para mejorar la eficacia, dado que el acceso a la memoria será de solo lectura.
Después de rellenar o leer los datos de índice, llame al método IDirect3DIndexBuffer9::Unlock, tal como se muestra en el ejemplo de código siguiente.
// 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:
Si crea un búfer de índice con la flag D3DUSAGE_WRITEONLY, no use la flag de bloqueo D3DLOCK_READONLY. Use la flag D3DLOCK_READONLY si la aplicación solo va a leer la memoria del búfer de índice. Al incluir esta flag, Direct3D es capaz de optimizar sus procedimientos internos para mejorar la eficacia, dado que el acceso a la memoria será de solo lectura.
Para obtener información sobre cómo usar D3DLOCK_DISCARD or D3DLOCK_NOOVERWRITE en el parámetro Flags del método IDirect3DIndexBuffer9::Lock, consulte Optimizaciones de rendimiento (Direct3D 9).
En C++, dado que accede directamente a la memoria asignada para el búfer de índice, asegúrese de que la aplicación accede correctamente a la memoria asignada. De lo contrario, corre el riesgo de renderizar esa memoria no válida. Use el progreso del formato de índice que usa la aplicación para pasar de un índice del búfer asignado a otro.
Recupere información sobre un búfer de índice llamando al método IDirect3DIndexBuffer9::GetDesc. Este método rellena los miembros de la estructura D3DINDEXBUFFER_DESC con información sobre el búfer de índice.
Temas relacionados