基于GPU的粒子系统的粒子数目一般等于stream output的图元数,而stream output的统计信息可以通过ID3D10Query接口获取。步骤如下:
1.创建ID3D10Query查询对象
1ID3D10Query* pQuery;
2D3D10_QUERY_DESC queryDesc;
3queryDesc.Query = D3D10_QUERY_SO_STATISTICS;
4queryDesc.MiscFlags = 0;
5pD3DDevice->CreateQuery( &queryDesc, &pQuery );
2.在用DrawAuto()绘制粒子处设置查询的开始和结束标记:
1 pQuery->Begin();
2 pD3DDevice->DrawAuto(); // 绘制粒子
3 pQuery->End();
3. 获取Stream Output输出的图元个数:
1 D3D10_QUERY_DATA_SO_STATISTICS streamOutBufferSize;
2 if ( S_OK == pQuery->GetData( &streamOutBufferSize, pQuery->GetDataSize(), 0 ) ) // 错误产生的原因
3 {
4 mStreamOutParticleSize = (unsigned)streamOutBufferSize.NumPrimitivesWritten;
5 }
可是试验的时候,发现获取的粒子数目不正确。调试后发现
ID3D10Query::GetData()总返回S_FALSE,但极少数情况下也返回S_OK。参考文献1后明白,ID3D10Query接口是异步从GPU获取数据的,当GPU中繁忙或者查询的数据没有准备好,就会返回S_FALSE。正确的做法是:如果ID3D10Query::GetData()返回失败,则继续查询,直到成功为止。正确的完整代码如下:
1 // 创建ID3D10Query查询对象
2 ID3D10Query* pQuery;
3 D3D10_QUERY_DESC queryDesc;
4 queryDesc.Query = D3D10_QUERY_SO_STATISTICS;
5 queryDesc.MiscFlags = 0;
6 pD3DDevice->CreateQuery( &queryDesc, &pQuery );
7
8 // 设置查询的开始和结束标志
9 pQuery->Begin();
10 pD3DDevice->DrawAuto();
11 pQuery->End();
12
13 // 获取stream output输出的图元个数
14 D3D10_QUERY_DATA_SO_STATISTICS streamOutBufferSize;
15 while ( S_OK != pQuery->GetData( &streamOutBufferSize, pQuery->GetDataSize(), 0 ) ); // 不停循环,直到成功
16 mStreamOutParticleSize = (unsigned)streamOutBufferSize.NumPrimitivesWritten;
参考资料:
1. Get streaming output statistics: http://www.bennychen.cn/2009/07/get-streaming-output-statistics/