基于GPU的粒子系統的粒子數目一般等于stream output的圖元數,而stream output的統計信息可以通過ID3D10Query接口獲取。步驟如下:
1.創建ID3D10Query查詢對象
1
ID3D10Query* pQuery;
2
D3D10_QUERY_DESC queryDesc;
3
queryDesc.Query = D3D10_QUERY_SO_STATISTICS;
4
queryDesc.MiscFlags = 0;
5
pD3DDevice->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/