2017-02-09 83 views
1

最近,我在我的引擎中實現了紋理加載。 但紋理有時會出現一些小毛病。使用動態索引時DirectX 12中奇怪的紋理毛刺

問題如下圖所示。 enter image description here

這與AMD R9 380 我也試圖執行對英特爾圖形HD 4600我的程序進行測試,但沒有繪製的。 (無幾何所示。)

我的shader代碼:

struct MaterialData 
{ 
    float4 gDiffuseAlbedo; 
    float3 gFresnelR0; 
    float gRoughness; 
    float4x4 gMatTransform; 
    uint gDiffuseMapIndex; 
    uint MaterialPad0; 
    uint MaterialPad1; 
    uint MaterialPad2; 
}; 
StructuredBuffer<MaterialData> gMaterialData : register(t1, space1); 

// texture array for dynamic indexing 
// gMaxNumOfTextures is set to 16 at now 
Texture2D gCommonTexture[gMaxNumOfTextures] : register(t3); 

// in my pixel shader: 
float4 diffuseAlbedoMap = gCommonTexture[matData.gDiffuseMapIndex].Sample(gsamAnisotropicWrap, pin.TexC) * matData.gDiffuseAlbedo; 

我已經仔細檢查所有matData.gDiffuseMapIndex,這是正確的。

我想盡一切辦法解決這個問題,但徒勞無功。 直到我修改我的代碼如下:

// in my pixel shader: 
float4 diffuseAlbedoMap = float4(0,0,0,0); 

uint realMatIndex; 
for(realMatIndex = 0;realMatIndex < gMaxNumOfTextures;realMatIndex++) 
    if(realMatIndex == matData.gDiffuseMapIndex) 
    { 
     diffuseAlbedoMap = gCommonTexture[matData.gDiffuseMapIndex].Sample(gsamAnisotropicWrap, pin.TexC) * matData.gDiffuseAlbedo; 
     break; 
    } 

這工作正常!

我R9 380

而且所有幾何圖形無毛刺是在HD 4600

但爲什麼正常顯示!?

爲什麼我需要使用for循環再次檢查索引以防止毛刺?

(如果我使用貼圖多,這可能無法有效地工作。)

什麼會導致這個問題?

我整晚都在想這個問題,但是我找不到答案。

謝謝!

完全Shader代碼: enter link description here

回答

0

您需要使用NonUniformIndex(matData.gDiffuseMapIndex)讓編譯器知道該指數是不均勻的,很明顯。

這是因爲在GCN硬件上,紋理描述符存儲在共享的標量寄存器中。內在的做你做的,一個循環,但通過屏蔽每個唯一索引找到的線程,直到所有線程完成,它更有效地一點點。

這當然是有效的,但如果你乘以非均勻的情況,你會以非常不理想的着色器結束。要改善這一點,唯一的方法就是不要使用內在因素,並保證指數在波動中是均勻的。例如,將不同的材質拆分爲ExecuteIndirect內部的單獨繪圖調用。

+1

謝謝!我應該學習一些GPU知識,而不是SDK。順便說一句,我可以問另一個問題嗎?在第1層硬件上(比如我的intel hd 4600),每個着色器階段所有描述符表中最大數量的Shader資源視圖最多隻能有128個。處理這個問題的最佳做法是什麼? –

+1

這意味着我只能使用128種不同的紋理(包括延遲渲染緩衝區)。我正在考慮將Texture2D更改爲Texture2DArray,並將具有相同分辨率的紋理放在一起。但這是一個很好的解決方案嗎?謝謝 –

+0

我的進步,如果你使用DX12,那麼你不關心英特爾GPU,這是不嚴重的。層1和描述符堆的概念是爲了支持不是無束的硬件。它會限制你達到最好的DX12 – galop1n