【问题标题】:Why won't this HLSL Pixel Shader compile when RWStructuredBuffer is referenced?当引用 RWStructuredBuffer 时,为什么这个 HLSL 像素着色器不能编译?
【发布时间】:2016-08-03 00:57:19
【问题描述】:

我正在使用 DirectX 12,尝试使用无人机进行渲染。这是我的像素着色器代码:

    struct PSInput
{
    float4 position : SV_POSITION;
    float4 color : COLOR;
};

struct FragmentDataStruct
{
    float4 color;
    float depth;
};

struct FragmentAndLinkStruct
{
    FragmentDataStruct fragmentData;
    uint nextFragment;
};

RWStructuredBuffer <FragmentAndLinkStruct> FLBuffer : register(u0);

RWByteAddressBuffer StartOffsetBuffer : register(u1);

float4 PSMain(PSInput input) : SV_TARGET
{
    input.color.x = float(FLBuffer[0].nextFragment);

    return input.color;
}

使用D3DCompileFromFile函数编译失败。

当我替换这一行时:

input.color.x = float(FLBuffer[0].nextFragment);

类似这样的:

FragmentAndLinkStruct otherThing;
otherThing.nextFragment = 1;
input.color.x = float(otherThing.nextFragment);

没有提到RWStructuredBuffer,那么它编译得很好并正确渲染。

我认为绑定数据没有任何问题(VS 图形调试器显示正确绑定的两个无人机)。不过,我认为这不会影响着色器的编译。

任何时候我引用FLBuffer 或StartOffsetBuffer,它都不会编译。

什么会导致这个问题?

【问题讨论】:

    标签: directx shader hlsl pixel-shader directx-12


    【解决方案1】:

    我在弄清楚如何读取编译器给出的错误后解决了这个问题。这里的问题是渲染目标输出使用了u0 着色器寄存器。

    为了找到这个,我通过使用下面的代码将D3DCompileFromFile 本身给出的错误读出为ID3DBlob*,将其转换为char* 数组,其中error 是ID3DBlob*:

    const char* error2 = static_cast<const char*>(error->GetBufferPointer());
    

    我在最后一行之后立即设置了一个断点,并简单地从 VS 的 locals 选项卡中读出了错误消息:

    error X4509: UAV registers live in the same name space as outputs, so they
    must be bound to at least u1, manual bind to slot u0 failed
    

    错误信息非常清晰简洁。很有帮助。

    更新后的代码:

    struct PSInput
    {
        float4 position : SV_POSITION;
        float4 color : COLOR;
    };
    
    struct FragmentDataStruct
    {
        float4 color;
        float depth;
    };
    
    struct FragmentAndLinkStruct
    {
        FragmentDataStruct fragmentData;
        uint nextFragment;
    };
    
    RWStructuredBuffer <FragmentAndLinkStruct> FLBuffer : register(u1);
    
    RWByteAddressBuffer StartOffsetBuffer : register(u2);
    
    float4 PSMain(PSInput input) : SV_TARGET
    {
        uint pixelCount = FLBuffer.IncrementCounter();
        input.color.x = float(pixelCount);
    
        return input.color;
    }
    

    请注意,编译器甚至不会查看对return 输出没有贡献的代码。我通过向PSMain 函数添加一些代码来测试这一点,该函数与FLBuffer 交互而不影响返回的input.color。看反汇编,所有多余的代码都被去掉了,没有编译。

    另外,由于我在工作时没有引用FLBuffer,所以它没有在输出着色器寄存器和我绑定的u0 着色器寄存器之间建立任何连接,所以没有出现问题。

    然后我必须假设它会在检查代码之前删除多余的代码,这在寻找效率时是有道理的。一旦它进行了完整性检查,它就会继续编译。

    希望这对以后学习 DirectX 或 HLSL 的人有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多