2013-06-18 20 views
1

我一直在嘗試實現基於計算着色器的粒子系統。跨越多個着色器使用的無人機計數器指數?

我有一個計算着色器,它使用帶有D3D11_BUFFER_UAV_FLAG_COUNTER標記的無人機構建粒子的結構化緩衝區。

當我添加到這個緩衝區時,我檢查這個粒子是否有任何複雜的行爲,我想過濾並在單獨的計算着色器中執行。例如,如果粒子想要執行衝突檢測,我將其索引添加到另一個結構化緩衝區,同樣也使用D3D11_BUFFER_UAV_FLAG_COUNTER標誌。

然後,我運行第二個計算着色器,該着色器處理所有索引,並將碰撞檢測應用於這些粒子。

但是,在第二個計算着色器中,我估計大約5%的索引是錯誤的 - 它們屬於其他粒子,不支持碰撞檢測。

這裏的計算着色器代碼perfroms名單建設:

// append to destination buffer 
uint dstIndex = g_dstParticles.IncrementCounter(); 
g_dstParticles[ dstIndex ] = particle; 

// add to behaviour lists 
if (params.flags & EMITTER_FLAG_COLLISION) 
{ 
    uint behaviourIndex = g_behaviourCollisionIndices.IncrementCounter(); 
    g_behaviourCollisionIndices[ behaviourIndex ] = dstIndex; 
} 

如果我打出了「添加到行爲清單」位到一個單獨的計算着色器,並運行它的粒子列表被創建後,一切正常。不過我認爲我不應該這樣做 - 這是浪費帶寬再次通過所有粒子。

我懷疑IncrementCounter實際上不能保證返回一個唯一的索引進入無人機,並且有一些聰明的優化繼續,這意味着索引只在其使用的計算着色器內有效。將它傳遞給第二個計算着色器是無效的。

任何人都可以給出具體的答案,這裏發生了什麼?如果我有一種方法可以保留與我的核心更新相同的計算着色器中的過濾功能嗎?

謝謝!

回答

1

IncrementCounter是一個原子操作,所以(驅動程序/硬件錯誤儘管)將返回一個唯一值給調用它的每個線程。

你有沒有想過使用Append/Consume緩衝區來達到這個目的,因爲它是爲它設計的?第一遍簡單地將複雜的碰撞粒子附加到AppendStructuredBuffer,第二遍消耗來自同一個緩衝區,但使用ConsumeStructuredBuffer視圖。計算的第二次運行將需要使用DispatchIndirect,因此您只需要爲列表中的數字運行儘可能多的線程組(CPU不知道的東西)。

通常的建議適用,但是,您是否嘗試過D3D11調試層並在參考設備上運行它以確保它不是驅動程序問題?

+0

感謝您的信息 - 這幾乎是我的想法。我在其他2個圖形供應商的硬件上測試了代碼,發現它在這些硬件上工作得很好,所以它一定是我測試的硬件/驅動程序的問題。我已經向他們提交了一個錯誤報告和repro案例。 – Hybrid