HansKristian-Work / vkd3d-proton

Fork of VKD3D. Development branches for Proton's Direct3D 12 implementation.
GNU Lesser General Public License v2.1
1.76k stars 184 forks source link

test_shader_io_mismatch seems to use xfb incorrectly #1938

Open hakzsam opened 4 months ago

hakzsam commented 4 months ago
d3d12: ======== test_shader_io_mismatch begin ========
d3d12: ../src/compiler/nir/nir_gather_xfb_info.c:104: add_var_xfb_outputs: Assertion `xfb->buffer_to_stream[buffer] == var->data.stream' failed.
Aborted (core dumped)
#version 450
layout(triangles) in;
layout(max_vertices = 3, points) out;

layout(xfb_buffer = 0, xfb_stride = 64, stream = 1) out gl_PerVertex
{
    layout(xfb_offset = 0) vec4 gl_Position;
};

invariant gl_Position;

layout(location = 1) in vec3 ARG[3];
layout(location = 2) in vec2 ARG_1[3];
layout(location = 3) in uvec4 ARG_2[3];
layout(location = 1, xfb_buffer = 0, xfb_stride = 64, xfb_offset = 16) out vec3 ARG_3;
layout(location = 2, xfb_buffer = 0, xfb_stride = 64, xfb_offset = 28) flat out uvec4 ARG_2_1;
layout(location = 4, xfb_buffer = 1, xfb_stride = 64, xfb_offset = 0, stream = 1) out vec2 ARG_1_1;

void main()
{
    uint _44;
    _44 = 0u;
    for (;;)
    {
        gl_Position.x = gl_in[_44].gl_Position.x;
        gl_Position.y = gl_in[_44].gl_Position.y;
        gl_Position.z = gl_in[_44].gl_Position.z;
        gl_Position.w = gl_in[_44].gl_Position.w;
        ARG_3.x = ARG[_44].x;
        ARG_3.y = ARG[_44].y;
        ARG_3.z = ARG[_44].z;
        ARG_2_1.x = ARG_2[_44].x;
        ARG_2_1.y = ARG_2[_44].y;
        ARG_2_1.z = ARG_2[_44].z;
        ARG_2_1.w = ARG_2[_44].w;
        EmitStreamVertex(int(0u));
        uint _45 = _44 + 1u;
        if (_45 == 3u)
        {
            break;
        }
        else
        {
            _44 = _45;
        }
    }
    gl_Position.x = gl_in[0u].gl_Position.x;
    gl_Position.y = gl_in[0u].gl_Position.y;
    gl_Position.z = gl_in[0u].gl_Position.z;
    gl_Position.w = gl_in[0u].gl_Position.w;
    ARG_1_1.x = ARG_1[0u].x;
    ARG_1_1.y = ARG_1[0u].y;
    EmitStreamVertex(int(1u));
}

The Vulkan spec says:

"VUID-StandaloneSpirv-Stream-04694
If any variables or block members in the output interface of the entry point being compiled are decorated with Stream, then all variables belonging to the same XfbBuffer must specify the same Stream value"

I think it's a test bug.

doitsujin commented 4 months ago

The test should be correct, this looks more like an actual xfb bug since the test deliberately declares multiple variables in different streams as SV_Position and our shader compilers don't seem to handle that. This is perfectly legal in D3D12.

hakzsam commented 4 months ago

But it doesn't seem legal in VK.

doitsujin commented 4 months ago

Again, the problem is that we have multiple SV_Position variables that our compilers map to a single one. The correct fix here is to only map the one for the rasterized stream to gl_Position and keep the other ones separate, same for all other potential system values.