索引缓冲区 (Direct3D 9)

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

顶点缓冲区包含顶点;因此,你可以绘制包含或不包含索引基元的顶点缓冲区。 但是,由于索引缓冲区包含索引,因此不能使用没有对应顶点缓冲区的索引缓冲区。 (另请注意,IDirect3DDevice9::DrawIndexedPrimitiveUPIDirect3DDevice9::DrawPrimitiveUP 是唯一在没有索引或顶点缓冲区的情况下进行绘制的绘制方法。

索引缓冲区描述

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

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

  • Format 成员描述索引缓冲区数据的表面格式。
  • 类型标识索引缓冲区的资源类型。
  • Usage 结构成员包含一般功能标志。 D3DUSAGE_SOFTWAREPROCESSING 标志指示索引缓冲区用于软件顶点处理。 “使用情况”中存在 D3DUSAGE_WRITEONLY 标志表示索引缓冲区内存仅用于写入操作。 这样一来,驱动程序便可将索引数据置于最佳内存位置,以实现快速处理和呈现。 如果未使用 D3DUSAGE_WRITEONLY 标志,则驱动程序不太可能将数据置于不易于读取的位置。 这会影响处理和呈现速度。 如果未指定此标志,则假定应用程序对索引缓冲区中的数据执行读取和写入操作。
  • 池指定为索引缓冲区分配的内存类。 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)