2017-02-09 81 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