Performance Optimizations (Direct3D 9)

General Performance Tips

  • 尽量少用Clear : 尽量在原有的上面画。
  • 尽量少变换状态
  • 尽量用小的纹理
  • 尽量用front->back顺序画screen
  • 尽量用triangle而不是lists或fanarrange strips to reuse triangle vertices sooner, rather than later.
  • 尽量少用性能需求高的效果. 将其降级使用。
  • 经常 test 你应用程序的性能。
  • 尽量少交换vertex buffer
  • 尽量多用static vertex buffers
  • 尽量用一个大的static vertex buffer有不同的FVF为一个对象。而非多个。
  • 尽量用32bytes的整数倍, 进入vertex buffer, 否则选择尽量小的格式。
  • 尽量用定点索引。
  • 尽量在同一时间清理depth buffer 和 stencil buffer

Databases and Culling

为对象建造一个可靠的数据库 是 D3D杰出表现的关键。 这比 优化 光栅化和硬件更重要。

你应该保持用尽量少的多边形。使用多边形时一定要保证不会牺牲以后的效率。记住最快的多边形是不去画。

Batching Primitives

将相同状态的Primitive打包,一起渲染。

举例: 一个对象 包含2种纹理。 把素有no.1纹理的点 batch and render. 再把no.2纹理的点batch and render.

Lighting Tips

光的使用,要涉及每个顶点计算。

  • 尽量少的光源。使用整体级别增量,而非增加光源。例如使用环境光。
  • 平行光,比点光,聚光灯,有更高的效率。因为平行光是固定的,不需要为每点计算。
  • 聚光灯,比电光,有更高的效率。
  • 镜面光,是双倍性能消耗。只有当必须的时候才用。默认是关闭D3DRS_SPECULARENABLE. 当设置了纹理时, 必须把镜面光设置为0, 只把材料的颜色设置为0,0,0是不成的。

Texture Size

纹理映射很依赖于内存速度。这里有一些最大化你cache速度的方法。

  • 纹理要小。小纹理更可能被缓存于CPU的2级缓存中。
  • 尽量用方纹理。256*256是最快的。

Using Dynamic Vertex and Index Buffers

当 图像处理器 在使用vertex buffer时, 锁住vertex buffer, 这显然有效率问题。

必须等到 图像处理 完所有定点, 才能返回到 应用程序, 这有明显的延迟。

--------------------------

动态定点缓存 可以带来性能提高。

应用程序必须调用Lock加适当的flags。

D3DLOCKDISCARD使应用程序不必保持old vertex或old index 的buffer.

如果graphic processor仍在使用这些buffer, 当lock被调用时(有人也要进入, 使用buffer.),一个指向新内存区域的指针被返回, 来替代老的buffer指针。

这允许graphics processor能继续使用旧的数据, 同时应用程序把数据放在新buffer中一份。

这不会带来额外的内存维护;当old buffer用完之后, 会被自动释放或重新利用。

注意: lock buffer with D3DLOCK_DISCARD总是丢失整个buffer, 如果你在冲掉缓存时(后来进入lock的行为), 设置了起始点和偏移量,这将使其他定点丢失。

---------------------------------

这里有一种情况, 应用程序 每次lock时, 需要存储的data是较小的,

例如, 增加4个点精灵去渲染。

D3DLOCK_NOOVERWRITE使得应用程序不会覆盖 正在使用的 动态缓存。

后者调用lock时, 会返回一个指向old data的指针, 允许应用程序 在没有使用的vertex or index区域 增加新的data。 应用程序 不应该 修改vertices or index, 当在执行draw操作graphics processor可能正在使用这些定点时。

应用程序 应该在新buffer完全接收完后, 并在graphics processor使用完后, 完全被丢掉。

----------------------------------

异步查询机制有助于 判断定点是否仍被graphics processor使用。

发行一个D3DQUERYTYPE_EVENT的查询, 在所有DrawPrimitive完成后。

当GetData返回S_OK时, 说明graphics processor没有再使用buffer.

lock buffer 带 D3DLOCK_DISCARD或没有flags的方式,总能保证使用的vertex buffer是最新的, 但是使用lock 不带 flags的方式 会产生性能问题。 

其他API不保证 graphics processor 已经完成对vertices的使用BeginScene, EndScene, Present.

    // USAGE STYLE 1
// Discard the entire vertex buffer and refill with thousands of vertices.
// Might contain multiple objects and/or require multiple DrawPrimitive
// calls separated by state changes, etc.

// Determine the size of data to be moved into the vertex buffer.
UINT nSizeOfData = nNumberOfVertices * m_nVertexStride;

// Discard and refill the used portion of the vertex buffer.
CONST DWORD dwLockFlags = D3DLOCK_DISCARD;

// Lock the vertex buffer.
BYTE* pBytes;
if( FAILED( m_pVertexBuffer->Lock( 0, 0, &pBytes, dwLockFlags ) ) )
return false;

// Copy the vertices into the vertex buffer.
memcpy( pBytes, pVertices, nSizeOfData );      //因为使用完后,
m_pVertexBuffer->Unlock();

// Render the primitives.
m_pDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, nNumberOfVertices/3)



posted on 2011-10-03 23:48  oleeceo  阅读(336)  评论(0编辑  收藏  举报

导航