directx - Direct3D11 : "gradient instruction used in a loop with varying iteration, forcing loop to unroll", 警告:X3570

标签 directx direct3d hlsl

我正在使用 Direct3D 11 和 Visual Studio 2015 开发图形引擎。在用于主绘制调用的 HLSL 着色器中,我使用百分比更接近过滤对定向光源和点光源的阴影贴图进行采样,即,我对一个小的采样目标阴影贴图纹理元素周围的方形区域并对结果进行平均以获得柔和的阴影。现在,每次调用 ShadowMap_.Sample(...) 都会创建一个警告:“在具有不同迭代的循环中使用梯度指令,强制循环展开”(X3570)。我想解决这个问题,或者,如果不可能,请隐藏警告,因为它完全淹没了我的警告输出。

我尝试在线搜索错误消息,但找不到任何进一步的描述。我什至找不到梯度指令应该是什么的解释。我检查了 Microsoft 文档中是否有不同的采样器或采样函数,可以让我用 native 采样功能替换循环,但也没有找到类似的内容。这是我用于对点光源的阴影立方体贴图进行采样的函数:

float getPointShadowValue(in uint index, in float3 worldPosition)
{
    // (Half-)Radius for percentage closer filtering
    int hFilterRadius = 2;

    // Calculate the vector inside the cube that points to the fragment
    float3 fragToLight = worldPosition.xyz - pointEmitters_[index].position.xyz;

    // Calculate the depth of the current fragment
    float currentDepth = length(fragToLight);

    float sum = 0.0;
    for (float z = -hFilterRadius; z <= hFilterRadius; z++)
    {
        for (float y = -hFilterRadius; y <= hFilterRadius; y++)
        {
            for (float x = -hFilterRadius; x <= hFilterRadius; x++)
            {
                // Offset the currently targeted cube map texel and sample at that position
                float3 off = float3(x, y, z) * 0.05;
                float closestDepth = pointShadowMaps_.Sample(sampler_, float4(fragToLight + off, index)).x * farPlane_;
                sum += (currentDepth - 0.1 > closestDepth ? 1.0 : 0.0);
            }
        }
    }
    // Calculate the average and return the shadow value clamped to [0, 1]
    float shadow = sum / (pow(hFilterRadius * 2 + 1, 3));
    return min(shadow, 1.0);
}

代码仍然可以正常工作,但我收到了大量这些警告,并且不知道这是否会导致相关的性能影响。非常感谢有关该警告以及可以采取的措施的任何进一步信息。

提前致谢。

最佳答案

梯度函数都是纹理采样方法,它们自行决定所使用的mip级别,例如您使用的方法Sample。因此,他们在内部使用 ddx ( doc ) 和 ddy( doc )。片段在 GPU 上以 2x2 block 的形式进行计算,因此它们可以相互比较纹理坐标的差异。差异越大,使用的 mip-map 级别就越高。对于动态分支,此方法不再起作用,因为不能保证每个片段使用相同的计算路径,因此梯度函数在动态分支中不起作用。由于循环使用分支,编译器必须将它们设为静态才能使用梯度函数。这是通过在您的情况下展开来完成的,因为循环始终相同。编译器已经检测到它并编译循环,自动逐个编写所有步骤以生成非分支代码。使用[unroll]( doc ) 语句,您可以提示编译器这样做并抑制警告。

代码的另一种方法是使用不是梯度函数的采样方法,例如 SampleLevel ( doc ),您可以在其中传递所需的 mip-map-level (0 在您的情况是你的阴影贴图没有 mip-map-levels)并且 GPU 不需要确定它。据我所知,性能影响可以忽略不计,因为这种情况发生在一个非常低的水平上,大多数函数在 GPU 上处理得同样快,但也许你应该做自己的测试。

一个不适用于您的情况的补充,但获取文本元素的另一种非梯度方法是 Load ( doc ),以通过整数纹理元素索引直接获取特定纹理元素。

关于directx - Direct3D11 : "gradient instruction used in a loop with varying iteration, forcing loop to unroll", 警告:X3570,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56581141/

相关文章:

shader - 是否可以跳过像素着色器中的颜色输出?

silverlight - HLSL 色调变化算法

c++ - 将着色器与 directx 11 相结合

directx - 如何填充使用 D3DXCreateText 创建的 3D 网格?

directx - HLSL 中的多个光源

c++ - D3D11屏幕桌面复制到ID3D11Texture2D

graphics - 在 3D 图形库中对 I 型截面建模

c++ - DirectX11 - 几何着色器流输出流未定义

c++ - RAWINPUT - 如何获取鼠标滚轮数据

c++ - 空与零内存