索引缓冲区 (Direct3D 9)

索引缓冲区(由 IDirect3DIndexBuffer9 接口表示)是包含索引数据的内存缓冲区。 索引数据(或索引)是顶点缓冲区的整数偏移量,用于使用 IDirect3DDevice9::D rawIndexedPrimitive 方法呈现基元。

顶点缓冲区包含顶点;因此,你可以绘制包含或不包含索引基元的顶点缓冲区。 但是,由于索引缓冲区包含索引,因此不能使用没有对应顶点缓冲区的索引缓冲区。 (作为旁注, IDirect3DDevice9::D rawIndexedPrimitiveUPIDirect3DDevice9::D rawPrimitiveUP 是唯一在没有索引或顶点缓冲区的情况下绘制的绘图方法。)

索引缓冲区描述

索引缓冲区在功能方面进行描述,例如其存在于内存中的位置、其是否支持读取和写入以及其能够包含的索引的类型和数量。 这些特征保存在 D3DINDEXBUFFER_DESC 结构中。

索引缓冲区描述用于告知应用程序现有的缓冲区是如何创建的。 你提供一个空描述结构,以便系统填充之前创建的索引缓冲区的能力。

  • Format 成员描述索引缓冲区数据的表面格式。
  • Type 标识索引缓冲区的资源类型。
  • Usage 结构成员包含常规功能标志。 D3DUSAGE_SOFTWAREPROCESSING标志指示索引缓冲区将用于软件顶点处理。 Usage 中存在 D3DUSAGE_WRITEONLY 标志表示索引缓冲区内存仅用于写入操作。 这样,驱动程序即可将索引数据放在最佳内存位置,以实现快速处理和呈现。 如果未使用 D3DUSAGE_WRITEONLY 标志,则驱动程序不太可能将数据放在读取操作效率低下的位置。 这牺牲了一些处理和呈现速度。 如果未指定此标志,则假定应用程序对索引缓冲区中的数据执行读取和写入操作。
  • Pool 指定为索引缓冲区分配的内存类。 D3DPOOL_SYSTEMMEM标志指示系统在系统内存中创建索引缓冲区。
  • Size 成员存储顶点缓冲区数据的大小(以字节为单位)。
  • 不使用最后一个参数 pSharedHandle。 将其设置为 NULL

索引处理要求

索引处理操作的性能很大程度上取决于索引缓冲区存在于内存中的位置,以及所用的是何种类型的渲染设备。 应用程序在创建索引缓冲区时控制其内存分配。 设置D3DPOOL_SYSTEMMEM内存标志时,在系统内存中创建索引缓冲区。 使用D3DPOOL_DEFAULT内存标志时,设备驱动程序将确定索引缓冲区内存的最佳分配位置,通常称为驱动程序最佳内存。 驱动程序最佳内存可以是本地视频内存、非本地视频内存或系统内存。

在调用 IDirect3DDevice9::CreateIndexBuffer 方法时设置D3DUSAGE_SOFTWAREPROCESSING行为标志将指定索引缓冲区用于软件顶点处理。 在使用软件顶点处理时,混合模式顶点处理 (D3DCREATE_MIXED_VERTEXPROCESSING) 需要此标志。

应用程序可以直接将索引写入到在驱动程序优化存储器中分配的索引缓冲区。 这种技术可以避免后来进行冗余的复制操作。 如果你的应用程序从索引缓冲区读回数据,则此技术无法正常工作,因为宿主从驱动程序优化存储器执行读取操作可能会非常缓慢。 因此,如果你的应用程序需要在处理期间读取或将数据不规律地写入缓冲区,则系统内存索引缓冲区是更好的选择。

注意

始终使用 D3DPOOL_DEFAULT,除非你不想使用视频内存,或者在驱动程序将顶点或索引缓冲区放入 AGP 内存时使用大量页锁定 RAM。

 

创建索引缓冲区

通过调用 IDirect3DDevice9::CreateIndexBuffer 方法创建索引缓冲区对象,该方法接受六个参数。

  • 第一个参数指定索引缓冲区长度(以字节为单位)。

  • 第二个参数是一组使用控件。 除其他事项外,其值确定索引所引用的顶点是否能够包含剪辑信息。 若要提高性能,请在不需要剪裁时指定D3DUSAGE_DONOTCLIP。

    当为该设备启用混合模式或软件顶点处理 (D3DCREATE_MIXED_VERTEXPROCESSING/D3DCREATE_SOFTWARE_VERTEXPROCESSING) 时,可以设置D3DUSAGE_SOFTWAREPROCESSING标志。 对于要在混合模式下的软件顶点处理配合使用的缓冲区,必须设置D3DUSAGE_SOFTWAREPROCESSING,但在混合模式下 (D3DCREATE_HARDWARE_VERTEXPROCESSING) 使用硬件索引处理时,不应设置该缓冲区以获得最佳性能。 但是,当单个缓冲区同时用于硬件和软件顶点处理时,设置D3DUSAGE_SOFTWAREPROCESSING是唯一的选择。 混合设备和软件设备允许D3DUSAGE_SOFTWAREPROCESSING。

    即使索引处理是在硬件中完成的,也可以通过指定D3DPOOL_SYSTEMMEM将顶点和索引缓冲区强制进入系统内存。 这是一种在驱动程序将这些缓冲区放入 AGP 内存时避免页面锁定内存过大的方法。

  • 第三个参数是指定每个索引大小的 D3DFORMAT 枚举类型的D3DFMT_INDEX16或D3DFMT_INDEX32成员。

  • 第四个参数是 D3DPOOL 枚举类型的成员,该类型告知系统在内存中放置新索引缓冲区的位置。

  • IDirect3DDevice9::CreateIndexBuffer 接受的最后一个参数是变量的地址,该变量使用指向顶点缓冲区对象的新 IDirect3DIndexBuffer9 接口的指针填充(如果调用成功)。

以下 C++ 代码示例演示创建索引缓冲区在代码中的外观。

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

访问索引缓冲区

索引缓冲区对象使应用程序能够直接访问为索引数据分配的内存。 可以通过调用 IDirect3DIndexBuffer9::Lock 方法检索指向索引缓冲区内存的指针,然后根据需要访问内存以使用新的索引数据填充缓冲区或读取其包含的任何数据。 Lock 方法接受四个参数。 第一个 是 OffsetToLock,是索引数据的偏移量。 第二个参数是索引数据的大小(以字节为单位)。 如果调用成功, IDirect3DIndexBuffer9::Lock 方法 ppbData 接受的第三个参数是用指向索引数据的指针填充的 BYTE 指针的地址。

最后一个参数 Flags 告知系统应如何锁定内存。 可以使用它来指示应用程序如何访问缓冲区中的数据。 根据应用程序访问索引数据的方式为 Flags 参数指定常量。 这样,驱动程序就可以锁定内存,并在给定请求的访问类型的情况下提供最佳性能。 如果应用程序将仅从索引缓冲区内存中读取,请使用 D3DLOCK_READONLY 标志。 如果包含此标志,Direct3D 可以优化其内部过程以提高效率,因为对内存的访问将是只读的。

填充或读取索引数据后,调用 IDirect3DIndexBuffer9::Unlock 方法,如以下代码示例所示。

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

注意

如果使用 D3DUSAGE_WRITEONLY 标志创建索引缓冲区,请不要使用D3DLOCK_READONLY锁定标志。 如果应用程序将仅从索引缓冲区内存中读取,请使用 D3DLOCK_READONLY 标志。 如果包含此标志,Direct3D 可以优化其内部过程以提高效率,因为对内存的访问将是只读的。

有关为 IDirect3DIndexBuffer9::Lock 方法的 Flags 参数使用 D3DLOCK_DISCARD 或D3DLOCK_NOOVERWRITE的信息,请参阅性能优化 (Direct3D 9)

 

在 C++ 中,由于直接访问为索引缓冲区分配的内存,因此请确保应用程序正确访问分配的内存。 否则,存在使内存无效的风险。 使用应用程序用于从分配缓冲区中的一个索引移动到另一个索引的索引格式的步幅。

通过调用 IDirect3DIndexBuffer9::GetDesc 方法检索有关索引缓冲区的信息。 此方法使用有关索引缓冲区的信息填充 D3DINDEXBUFFER_DESC 结构的成员。

Direct3D 资源

从顶点缓冲区和索引缓冲区呈现 (Direct3D 9)

顶点缓冲区 (Direct3D 9)