2

最近,我在我的引擎中实现了纹理加载。但是纹理有时会出现一些小故障。

问题如下图所示。 在此处输入图像描述

这是用 AMD R9 380 测试的。我也尝试在 Intel Graphic HD 4600 上执行我的程序,但它什么也没画。(没有显示几何形状。)

我的着色器代码:

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 循环再次检查索引以防止出现故障?

(如果我使用更多纹理,这可能无法有效地工作。)

什么会导致这个问题?

我整晚都在想这个问题,但我找不到答案。

谢谢!

完整的着色器代码: 在此处输入链接描述

4

1 回答 1

0

显然,您需要使用NonUniformIndex(matData.gDiffuseMapIndex)让编译器知道索引是非统一的。

这是因为在 GCN 硬件上,纹理描述符存储在跨波共享的标量寄存器中。内在函数做了你所做的,一个循环,但是通过在所有线程都完成之前根据找到的唯一索引屏蔽线程来更有效地执行它。

这当然可行,但是如果将非统一的情况相乘,您将得到一个非常非最佳的着色器。为了改善这一点,唯一的方法是不使用内在函数并保证指数在波浪中是一致的。例如,在 ExecuteIndirect 中将不同的材质拆分为单独的绘制调用。

于 2017-02-11T06:15:48.030 回答