2

我正在使用 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 图形调试器显示正确绑定的两个无人机)。不过,我认为这不会影响着色器的编译。

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

什么会导致这个问题?

4

1 回答 1

0

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

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

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 的人有所帮助。

于 2016-08-03T04:44:57.150 回答