[vertex shader]
void main(float4 pos : POSITION, out float2 color_xy : COLOR0,
        out float2 color_zw : COLOR1, out float4 position : SV_POSITION)
{
    position = pos;
    color_xy = float2(0.25, 0.5);
    color_zw = float2(0.75, 1.0);
}

[pixel shader]
float4 main(float2 color_xy : COLOR0, float2 color_zw : COLOR1) : SV_TARGET
{
    return float4(color_xy, color_zw);
}

[test]
draw quad
probe(320, 240) rgba(0.25, 0.5, 0.75, 1.0)

% Test handling of arrays in interface blocks

[require]
shader model >= 4.0
shader model < 6.0

[input layout]

[vertex shader]
// Rules:
// 1. Arrays always start on .x
// 2. When placing a scalar or vector, search through the allocated slots for space *vertically*
//    (So check if you can place at o1.y, then o2.y, o3.y before o1.z, o2.z, etc.)
// 3. Elements with different interpolation cannot share a slot.
// 4. The first field of a struct is always aligned.
struct data
{
    float4 position : SV_Position; // Should be placed in o0
    float  array1[2] : ARRAY1;     // Should be placed in o1.x, o2.x
    float3 array3[1] : ARRAY3;     // Should be placed in o3.xyz
    float  array4[2] : ARRAY4;     // Should be placed in o4.x, o5.x
    nointerpolation float ndata : NDATA; // Should be placed in o6.x
    uint   udata : UDATA;                // Should be placed in o6.y
    float4 data1 : DATA1;          // Should be placed in o7.xyzw
    float3 data2 : DATA2;          // Should be placed in o1.yzw
    float2 data3 : DATA3;          // Should be placed in o2.yz
    float  data4 : DATA4;          // Should be placed in o4.y
    float2 data5 : DATA5;          // Should be placed in o5.yz
    float2 data6 : DATA6;          // Should be placed in o4.zw
    float  data7 : DATA7;          // Should be placed in o2.w
    float2 data8 : DATA8;          // Should be placed in o8.xy
    float  data9 : DATA9;          // Should be placed in o8.z (not o3.w)
    float  data10 : DATA10;        // Should be placed in o3.w
};

void main(uint id : SV_VertexID, out data output)
{
    output.position = float4(id & 1 ? 3 : -1, id & 2 ? -3 : 1, 0, 1);
    output.array1[0] = 1.0;
    output.array1[1] = 2.0;
    output.array3[0] = float3(3.0, 4.0, 5.0);
    output.array4[0] = 6.0;
    output.array4[1] = 7.0;
    output.data1 = float4(8.0, 9.0, 10.0, 11.0);
    output.data2 = float3(12.0, 13.0, 14.0);
    output.data3 = float2(15.0, 16.0);
    output.data4 = 17.0;
    output.data5 = float2(18.0, 19.0);
    output.data6 = float2(20.0, 21.0);
    output.data7 = 22.0;
    output.data8 = float2(23.0, 24.0);
    output.data9 = 25.0;
    output.data10 = 26.0;
    output.ndata = 27.0;
    output.udata = 28;
}

[pixel shader]
struct data
{
    float4 position : SV_Position; // v0.xyzw
    float  array1 : ARRAY1;        // v1.x
    float3 data2  : DATA2;         // v1.yzw
    float  array2 : ARRAY2;        // v2.x
    float2 data3  : DATA3;         // v2.yz
    float  data7  : DATA7;         // v2.w
    float3 array3 : ARRAY3;        // v3.xyz
    float  data10 : DATA10;        // v3.w
    float  array4 : ARRAY4;        // v4.x
    float  data4  : DATA4;         // v4.y
    float2 data6  : DATA6;         // v4.zw
    float  array5 : ARRAY5;        // v5.x
    float2 data5  : DATA5;         // v5.yz
    nointerpolation float ndata : NDATA; // v6.x
    uint   udata : UDATA;          // v6.y
    float4 data1 : DATA1;          // v7.xyzw
    float2 data8 : DATA8;          // v8.xy
    float  data9 : DATA9;          // v8.z
};

float4 main(data input) : SV_Target
{
    switch (int(input.position.x))
    {
        case 1: return float4(input.array1, input.data2);
        case 2: return float4(input.array2, input.data3, input.data7);
        case 3: return float4(input.array3, input.data10);
        case 4: return float4(input.array4, input.data4, input.data6);
        case 5: return float4(input.array5, input.data5, 0);
        case 6: return float4(input.ndata, input.udata, 0, 0);
        case 7: return input.data1;
        case 8: return float4(input.data8, input.data9, 0);
        default: return 0;
    }
}

[test]
clear rtv 0 -1.0 -1.0 -1.0 -1.0
todo(msl) draw triangle list 3
probe (0, 0) rgba ( 0.0,  0.0,  0.0,  0.0)
probe (1, 0) rgba ( 1.0, 12.0, 13.0, 14.0)
probe (2, 0) rgba ( 2.0, 15.0, 16.0, 22.0)
probe (3, 0) rgba ( 3.0,  4.0,  5.0, 26.0)
probe (4, 0) rgba ( 6.0, 17.0, 20.0, 21.0)
probe (5, 0) rgba ( 7.0, 18.0, 19.0,  0.0)
probe (6, 0) rgba (27.0, 28.0,  0.0,  0.0)
probe (7, 0) rgba ( 8.0,  9.0, 10.0, 11.0)
probe (8, 0) rgba (23.0, 24.0, 25.0,  0.0)

[require]
shader model >= 3.0

[input layout]
0 r32g32-float POSITION

[vb 0]
-1.0 -1.0
-1.0 3.0
3.0 -1.0

[vertex shader]
void main(float2 in_pos : POSITION, out float4 pos : SV_Position, out float4 color : COLOR)
{
    pos = float4(in_pos, 0.0f, 1.0f);
    color = float4(1.0f, 2.0f, 3.0f, 4.0f);
}

[pixel shader]
% The point of this test is to check that signature masks are handled correctly
% when they are not contiguous, so we attempt reading only component .xw from
% `color'. This happens when the shader is compiled by native, but not by us,
% currently, so it's not very useful for the moment. I'm leaving it anyway
% so that it either becomes useful when our HLSL compiler becomes more optimized
% or can be eventually rewritten in assembly/bytecode when the shader runner
% supports that.
float4 main(float4 pos : SV_Position, float4 color : COLOR) : SV_Target
{
    return float4(color.x, 10.0f, 11.0f, color.w);
}

[test]
todo(msl) draw triangle list 3
probe (0, 0) rgba(1.0, 10.0, 11.0, 4.0)