[require]
shader model >= 6.0
wave-ops
format r32g32b32a32-float uav-load
format r32g32b32a32-uint uav-load

[uav 0]
format r32g32b32a32-float
size (buffer, 4)

3.5 1.0 4.0 2.5
3.5 1.0 4.0 2.5
3.5 1.5 4.0 2.5
3.5 1.0 4.5 2.5

[uav 1]
format r32g32b32a32-uint
size (buffer, 8)

0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0

[compute shader]
RWBuffer<float4> u0;
RWBuffer<uint4> u1;

    [numthreads(4, 1, 1)]
void main(uint id : SV_GroupIndex)
{
    bool4 b = WaveActiveAllEqual(u0[id]);
    u1[id] = uint4(b.x, b.y, b.z, b.w);
}

[test]
dispatch 4 1 1
probe uav 1 (0) u32(1, 0, 0, 1)
probe uav 1 (1) u32(1, 0, 0, 1)
probe uav 1 (2) u32(1, 0, 0, 1)
probe uav 1 (3) u32(1, 0, 0, 1)


[compute shader]
RWBuffer<float4> u0;
RWBuffer<uint4> u1;

    [numthreads(4, 1, 1)]
void main(uint id : SV_GroupIndex)
{
    bool any = u0[id].y == 1.5f;
    bool all = u0[id].x == 3.5f;
    bool none = u0[id].z == 3.0f;
    u1[id] = uint4(WaveActiveAnyTrue(any), WaveActiveAnyTrue(all), WaveActiveAnyTrue(none), 0);
    u1[4 + id] = uint4(WaveActiveAllTrue(any), WaveActiveAllTrue(all), WaveActiveAllTrue(none), 0);
}

[test]
dispatch 4 1 1
probe uav 1 (0) u32(1, 1, 0, 0)
probe uav 1 (1) u32(1, 1, 0, 0)
probe uav 1 (2) u32(1, 1, 0, 0)
probe uav 1 (3) u32(1, 1, 0, 0)
probe uav 1 (4) u32(0, 1, 0, 0)
probe uav 1 (5) u32(0, 1, 0, 0)
probe uav 1 (6) u32(0, 1, 0, 0)
probe uav 1 (7) u32(0, 1, 0, 0)


[compute shader]
RWBuffer<float4> u0;
RWBuffer<uint4> u1;

    [numthreads(4, 1, 1)]
void main(uint id : SV_GroupIndex)
{
    bool b = u0[id].y < 1.5;
    u1[id] = WaveActiveBallot(b);
}

[test]
dispatch 4 1 1
probe uav 1 (0) u32(0xb, 0, 0, 0)


[uav 1]
format r32g32b32a32-float
size (buffer, 8)

0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0

[compute shader]
RWBuffer<float4> u0;
RWBuffer<float4> u1;

    [numthreads(4, 1, 1)]
void main(uint id : SV_GroupIndex)
{
    float4 f = u0[id] + u0[id ^ 1];
    u1[id] = WaveReadLaneFirst(f);
    u1[4 + id] = WaveReadLaneAt(f, 3);
}

[test]
dispatch 4 1 1
probe uav 1 (0) rgba (7.0, 2.0, 8.0, 5.0)
probe uav 1 (1) rgba (7.0, 2.0, 8.0, 5.0)
probe uav 1 (2) rgba (7.0, 2.0, 8.0, 5.0)
probe uav 1 (3) rgba (7.0, 2.0, 8.0, 5.0)
probe uav 1 (4) rgba (7.0, 2.5, 8.5, 5.0)
probe uav 1 (5) rgba (7.0, 2.5, 8.5, 5.0)
probe uav 1 (6) rgba (7.0, 2.5, 8.5, 5.0)
probe uav 1 (7) rgba (7.0, 2.5, 8.5, 5.0)


[compute shader]
RWBuffer<float4> u0;
RWBuffer<float4> u1;

    [numthreads(4, 1, 1)]
void main(uint id : SV_GroupIndex)
{
    u1[id] = WaveActiveSum(u0[id]);
}

[test]
dispatch 4 1 1
probe uav 1 (0) rgba (14.0, 4.5, 16.5, 10.0)
probe uav 1 (1) rgba (14.0, 4.5, 16.5, 10.0)
probe uav 1 (2) rgba (14.0, 4.5, 16.5, 10.0)
probe uav 1 (3) rgba (14.0, 4.5, 16.5, 10.0)


[compute shader]
RWBuffer<float4> u0;
RWBuffer<float4> u1;

    [numthreads(4, 1, 1)]
void main(uint id : SV_GroupIndex)
{
    u1[id] = WaveActiveProduct(u0[id]);
}

[test]
dispatch 4 1 1
probe uav 1 (0) rgba (150.0625, 1.5, 288.0, 39.0625)
probe uav 1 (1) rgba (150.0625, 1.5, 288.0, 39.0625)
probe uav 1 (2) rgba (150.0625, 1.5, 288.0, 39.0625)
probe uav 1 (3) rgba (150.0625, 1.5, 288.0, 39.0625)


[compute shader]
RWBuffer<float4> u0;
RWBuffer<float4> u1;

    [numthreads(4, 1, 1)]
void main(uint id : SV_GroupIndex)
{
    u1[id] = WaveActiveMin(u0[id]);
}

[test]
dispatch 4 1 1
probe uav 1 (0) rgba (3.5, 1.0, 4.0, 2.5)
probe uav 1 (1) rgba (3.5, 1.0, 4.0, 2.5)
probe uav 1 (2) rgba (3.5, 1.0, 4.0, 2.5)
probe uav 1 (3) rgba (3.5, 1.0, 4.0, 2.5)


[compute shader]
RWBuffer<float4> u0;
RWBuffer<float4> u1;

    [numthreads(4, 1, 1)]
void main(uint id : SV_GroupIndex)
{
    u1[id] = WaveActiveMax(u0[id]);
}

[test]
dispatch 4 1 1
probe uav 1 (0) rgba (3.5, 1.5, 4.5, 2.5)
probe uav 1 (1) rgba (3.5, 1.5, 4.5, 2.5)
probe uav 1 (2) rgba (3.5, 1.5, 4.5, 2.5)
probe uav 1 (3) rgba (3.5, 1.5, 4.5, 2.5)


[compute shader]
RWBuffer<float4> u0;
RWBuffer<float4> u1;

    [numthreads(4, 1, 1)]
void main(uint id : SV_GroupIndex)
{
    u1[id] = WavePrefixSum(u0[id]);
}

[test]
dispatch 4 1 1
probe uav 1 (0) rgba (0.0, 0.0, 0.0, 0.0)
probe uav 1 (1) rgba (3.5, 1.0, 4.0, 2.5)
probe uav 1 (2) rgba (7.0, 2.0, 8.0, 5.0)
probe uav 1 (3) rgba (10.5, 3.5, 12.0, 7.5)


[compute shader]
RWBuffer<float4> u0;
RWBuffer<float4> u1;

    [numthreads(4, 1, 1)]
void main(uint id : SV_GroupIndex)
{
    u1[id] = WavePrefixProduct(u0[id]);
}

[test]
dispatch 4 1 1
probe uav 1 (0) rgba (1.0, 1.0, 1.0, 1.0)
probe uav 1 (1) rgba (3.5, 1.0, 4.0, 2.5)
probe uav 1 (2) rgba (12.25, 1.0, 16.0, 6.25)
probe uav 1 (3) rgba (42.875, 1.5, 64.0, 15.625)


[uav 0]
format r32g32b32a32-float
size (buffer, 4)

0.25 0.50 0.75 1.00
0.50 0.25 1.00 0.75
0.75 1.00 0.50 0.25
1.00 0.75 0.25 0.50

[compute shader]
RWBuffer<float4> u0;
RWBuffer<float4> u1;

    [numthreads(4, 1, 1)]
void main(uint id : SV_GroupIndex)
{
    uint i = WaveGetLaneIndex() % 4;
    float4 f = u0[i];
    u1[i] = QuadReadAcrossX(f);
}

[test]
dispatch 4 1 1
probe uav 1 (0) rgba (0.5, 0.25, 1.0, 0.75)
probe uav 1 (1) rgba (0.25, 0.5, 0.75, 1.0)
probe uav 1 (2) rgba (1.0, 0.75, 0.25, 0.5)
probe uav 1 (3) rgba (0.75, 1.0, 0.5, 0.25)


[compute shader]
RWBuffer<float4> u0;
RWBuffer<float4> u1;

    [numthreads(4, 1, 1)]
void main(uint id : SV_GroupIndex)
{
    uint i = WaveGetLaneIndex() % 4;
    float4 f = u0[i];
    // Constant lane id.
    u1[i] = QuadReadLaneAt(f, 2);
}

[test]
dispatch 4 1 1
probe uav 1 (0) rgba (0.75, 1.0, 0.5, 0.25)
probe uav 1 (1) rgba (0.75, 1.0, 0.5, 0.25)
probe uav 1 (2) rgba (0.75, 1.0, 0.5, 0.25)
probe uav 1 (3) rgba (0.75, 1.0, 0.5, 0.25)


[pixel shader]
RWBuffer<float4> u0;
RWBuffer<float4> u1;

float4 main(float4 pos : SV_Position) : SV_Target
{
    uint i = WaveGetLaneIndex() % 4;
    float4 f = u0[i];
    u1[i] = QuadReadAcrossX(f);
    return f;
}

[test]
draw quad
probe rtv 0 (0, 0) rgba (0.25, 0.5, 0.75, 1.0)
probe rtv 0 (1, 0) rgba (0.5, 0.25, 1.0, 0.75)
probe rtv 0 (0, 1) rgba (0.75, 1.0, 0.5, 0.25)
probe rtv 0 (1, 1) rgba (1.0, 0.75, 0.25, 0.5)
probe uav 1 (0) rgba (0.5, 0.25, 1.0, 0.75)
probe uav 1 (1) rgba (0.25, 0.5, 0.75, 1.0)
probe uav 1 (2) rgba (1.0, 0.75, 0.25, 0.5)
probe uav 1 (3) rgba (0.75, 1.0, 0.5, 0.25)


[pixel shader]
RWBuffer<float4> u0;
RWBuffer<float4> u1;

float4 main(float4 pos : SV_Position) : SV_Target
{
    uint i = WaveGetLaneIndex() % 4;
    float4 f = u0[i];
    u1[i] = QuadReadAcrossY(f);
    return f;
}

[test]
draw quad
probe uav 1 (0) rgba (0.75, 1.0, 0.5, 0.25)
probe uav 1 (1) rgba (1.0, 0.75, 0.25, 0.5)
probe uav 1 (2) rgba (0.25, 0.5, 0.75, 1.0)
probe uav 1 (3) rgba (0.5, 0.25, 1.0, 0.75)


[pixel shader]
RWBuffer<float4> u0;
RWBuffer<float4> u1;

float4 main(float4 pos : SV_Position) : SV_Target
{
    uint i = WaveGetLaneIndex() % 4;
    float4 f = u0[i];
    u1[i] = QuadReadAcrossDiagonal(f);
    return f;
}

[test]
draw quad
probe uav 1 (0) rgba (1.0, 0.75, 0.25, 0.5)
probe uav 1 (1) rgba (0.75, 1.0, 0.5, 0.25)
probe uav 1 (2) rgba (0.5, 0.25, 1.0, 0.75)
probe uav 1 (3) rgba (0.25, 0.5, 0.75, 1.0)


% Values in helper lanes are undefined for all wave ops except the quad ops.
[pixel shader]
RWBuffer<float4> u0;
RWBuffer<float4> u1;

float4 main(float4 pos : SV_Position) : SV_Target
{
    uint i = WaveGetLaneIndex() % 4;
    if (i >= 2)
        discard;
    float4 f = u0[i];
    u1[i] = QuadReadAcrossDiagonal(f);
    return float4(1.0, 0.0, 0.0, 1.0);
}

[test]
draw quad
probe rtv 0 (0, 0) rgba (1.0, 0.0, 0.0, 1.0)
probe rtv 0 (1, 0) rgba (1.0, 0.0, 0.0, 1.0)
probe rtv 0 (0, 1) rgba (0.75, 1.0, 0.5, 0.25)
probe rtv 0 (1, 1) rgba (1.0, 0.75, 0.25, 0.5)
probe uav 1 (0) rgba (1.0, 0.75, 0.25, 0.5)
probe uav 1 (1) rgba (0.75, 1.0, 0.5, 0.25)
probe uav 1 (2) rgba (0.5, 0.25, 1.0, 0.75)
probe uav 1 (3) rgba (0.25, 0.5, 0.75, 1.0)


[pixel shader]
RWBuffer<float4> u0;
RWBuffer<float4> u1;

float4 main(float4 pos : SV_Position) : SV_Target
{
    uint i = WaveGetLaneIndex() % 4;
    float4 f = u0[i];
    // Constant lane id.
    u1[i] = QuadReadLaneAt(f, 1);
    return f;
}

[test]
draw quad
probe uav 1 (0) rgba (0.5, 0.25, 1.0, 0.75)
probe uav 1 (1) rgba (0.5, 0.25, 1.0, 0.75)
probe uav 1 (2) rgba (0.5, 0.25, 1.0, 0.75)
probe uav 1 (3) rgba (0.5, 0.25, 1.0, 0.75)


[pixel shader]
uniform uint id;

RWBuffer<float4> u0;
RWBuffer<float4> u1;

float4 main(float4 pos : SV_Position) : SV_Target
{
    uint i = WaveGetLaneIndex() % 4;
    float4 f = u0[i];
    // Uniform lane id.
    u1[i] = QuadReadLaneAt(f, id);
    return f;
}

[test]
uniform 0 uint 0
todo draw quad
probe uav 1 (0) rgba (0.25, 0.5, 0.75, 1.0)
probe uav 1 (1) rgba (0.25, 0.5, 0.75, 1.0)
probe uav 1 (2) rgba (0.25, 0.5, 0.75, 1.0)
probe uav 1 (3) rgba (0.25, 0.5, 0.75, 1.0)
uniform 0 uint 1
todo draw quad
probe uav 1 (0) rgba (0.5, 0.25, 1.0, 0.75)
probe uav 1 (1) rgba (0.5, 0.25, 1.0, 0.75)
probe uav 1 (2) rgba (0.5, 0.25, 1.0, 0.75)
probe uav 1 (3) rgba (0.5, 0.25, 1.0, 0.75)
uniform 0 uint 2
todo draw quad
probe uav 1 (0) rgba (0.75, 1.0, 0.5, 0.25)
probe uav 1 (1) rgba (0.75, 1.0, 0.5, 0.25)
probe uav 1 (2) rgba (0.75, 1.0, 0.5, 0.25)
probe uav 1 (3) rgba (0.75, 1.0, 0.5, 0.25)
uniform 0 uint 3
todo draw quad
probe uav 1 (0) rgba (1.0, 0.75, 0.25, 0.5)
probe uav 1 (1) rgba (1.0, 0.75, 0.25, 0.5)
probe uav 1 (2) rgba (1.0, 0.75, 0.25, 0.5)
probe uav 1 (3) rgba (1.0, 0.75, 0.25, 0.5)


[pixel shader]
RWBuffer<float4> u0;
RWBuffer<float4> u1;

float4 main(float4 pos : SV_Position) : SV_Target
{
    uint i = WaveGetLaneIndex() % 4;
    if (!i)
        discard;
    float4 f = u0[i];
    // Lane 1 is the first active.
    u1[i] = WaveReadLaneFirst(f);
    return float4(1.0, 0.0, 0.0, 1.0);
}

[test]
clear rtv 0 0.25 0.5 0.75 1.0
draw quad
probe rtv 0 (0, 0) rgba (0.25, 0.5, 0.75, 1.0)
probe rtv 0 (1, 0) rgba (1.0, 0.0, 0.0, 1.0)
probe rtv 0 (0, 1) rgba (1.0, 0.0, 0.0, 1.0)
probe rtv 0 (1, 1) rgba (1.0, 0.0, 0.0, 1.0)
bug(mvk) probe uav 1 (1) rgba (0.5, 0.25, 1.0, 0.75)
bug(mvk) probe uav 1 (2) rgba (0.5, 0.25, 1.0, 0.75)
bug(mvk) probe uav 1 (3) rgba (0.5, 0.25, 1.0, 0.75)


[require]
shader model >= 6.0
wave-ops
float64
format r32g32-float uav-load
format r32g32b32a32-uint uav-load

[uav 0]
format r32g32-float
size (buffer, 4)

3.5 1.0
3.5 1.0
3.5 1.5
3.5 1.0

[uav 1]
format r32g32b32a32-uint
size (buffer, 16)

0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0

[compute shader]
RWBuffer<float2> u0;
RWBuffer<uint4> u1;

    [numthreads(4, 1, 1)]
void main(uint id : SV_GroupIndex)
{
    double2 d = u0[id];
    bool2 b = WaveActiveAllEqual(d);
    u1[id] = uint4(b.x, b.y, 0, 0);
}

[test]
dispatch 4 1 1
probe uav 1 (0) u32(1, 0, 0, 0)
probe uav 1 (1) u32(1, 0, 0, 0)
probe uav 1 (2) u32(1, 0, 0, 0)
probe uav 1 (3) u32(1, 0, 0, 0)


[compute shader]
RWBuffer<float2> u0;
RWBuffer<double2> u1;

    [numthreads(4, 1, 1)]
void main(uint id : SV_GroupIndex)
{
    double2 d = u0[id] + u0[id ^ 1];
    u1[id] = WaveReadLaneFirst(d);
    u1[4 + id] = WaveReadLaneAt(d, 3);
}

[test]
dispatch 4 1 1
probe uav 1 (0) f64(7.0, 2.0)
probe uav 1 (1) f64(7.0, 2.0)
probe uav 1 (2) f64(7.0, 2.0)
probe uav 1 (3) f64(7.0, 2.0)
probe uav 1 (4) f64(7.0, 2.5)
probe uav 1 (5) f64(7.0, 2.5)
probe uav 1 (6) f64(7.0, 2.5)
probe uav 1 (7) f64(7.0, 2.5)


[compute shader]
RWBuffer<float2> u0;
RWBuffer<double2> u1;

    [numthreads(4, 1, 1)]
void main(uint id : SV_GroupIndex)
{
    double2 d = u0[id];
    u1[id] = WaveActiveSum(d);
}

[test]
dispatch 4 1 1
probe uav 1 (0) f64(14.0, 4.5)
probe uav 1 (1) f64(14.0, 4.5)
probe uav 1 (2) f64(14.0, 4.5)
probe uav 1 (3) f64(14.0, 4.5)


[compute shader]
RWBuffer<float2> u0;
RWBuffer<double2> u1;

    [numthreads(4, 1, 1)]
void main(uint id : SV_GroupIndex)
{
    double2 d = u0[id];
    u1[id] = WaveActiveProduct(d);
}

[test]
dispatch 4 1 1
probe uav 1 (0) f64(150.0625, 1.5)
probe uav 1 (1) f64(150.0625, 1.5)
probe uav 1 (2) f64(150.0625, 1.5)
probe uav 1 (3) f64(150.0625, 1.5)


[compute shader]
RWBuffer<float2> u0;
RWBuffer<double2> u1;

    [numthreads(4, 1, 1)]
void main(uint id : SV_GroupIndex)
{
    double2 d = u0[id];
    u1[id] = WaveActiveMin(d);
}

[test]
dispatch 4 1 1
probe uav 1 (0) f64(3.5, 1.0)
probe uav 1 (1) f64(3.5, 1.0)
probe uav 1 (2) f64(3.5, 1.0)
probe uav 1 (3) f64(3.5, 1.0)


[compute shader]
RWBuffer<float2> u0;
RWBuffer<double2> u1;

    [numthreads(4, 1, 1)]
void main(uint id : SV_GroupIndex)
{
    double2 d = u0[id];
    u1[id] = WaveActiveMax(d);
}

[test]
dispatch 4 1 1
probe uav 1 (0) f64(3.5, 1.5)
probe uav 1 (1) f64(3.5, 1.5)
probe uav 1 (2) f64(3.5, 1.5)
probe uav 1 (3) f64(3.5, 1.5)


[compute shader]
RWBuffer<float2> u0;
RWBuffer<double2> u1;

    [numthreads(4, 1, 1)]
void main(uint id : SV_GroupIndex)
{
    double2 d = u0[id];
    u1[id] = WavePrefixSum(d);
}

[test]
dispatch 4 1 1
probe uav 1 (0) f64(0.0, 0.0)
probe uav 1 (1) f64(3.5, 1.0)
probe uav 1 (2) f64(7.0, 2.0)
probe uav 1 (3) f64(10.5, 3.5)


[compute shader]
RWBuffer<float2> u0;
RWBuffer<double2> u1;

    [numthreads(4, 1, 1)]
void main(uint id : SV_GroupIndex)
{
    double2 d = u0[id];
    u1[id] = WavePrefixProduct(d);
}

[test]
dispatch 4 1 1
probe uav 1 (0) f64(1.0, 1.0)
probe uav 1 (1) f64(3.5, 1.0)
probe uav 1 (2) f64(12.25, 1.0)
probe uav 1 (3) f64(42.875, 1.5)


[uav 0]
format r32g32b32a32-float
size (buffer, 4)

0.25 0.50 0.75 1.00
0.50 0.25 1.00 0.75
0.75 1.00 0.50 0.25
1.00 0.75 0.25 0.50

[compute shader]
RWBuffer<float2> u0;
RWBuffer<double2> u1;

    [numthreads(4, 1, 1)]
void main(uint id : SV_GroupIndex)
{
    uint i = WaveGetLaneIndex() % 4;
    double2 d = u0[i];
    u1[i] = QuadReadAcrossX(d);
}

[test]
dispatch 4 1 1
probe uav 1 (0) f64(0.5, 0.25)
probe uav 1 (1) f64(0.25, 0.5)
probe uav 1 (2) f64(1.0, 0.75)
probe uav 1 (3) f64(0.75, 1.0)


[compute shader]
RWBuffer<float2> u0;
RWBuffer<double2> u1;

    [numthreads(4, 1, 1)]
void main(uint id : SV_GroupIndex)
{
    uint i = WaveGetLaneIndex() % 4;
    double2 d = u0[i];
    u1[i] = QuadReadLaneAt(d, 2);
}

[test]
dispatch 4 1 1
probe uav 1 (0) f64(0.75, 1.0)
probe uav 1 (1) f64(0.75, 1.0)
probe uav 1 (2) f64(0.75, 1.0)
probe uav 1 (3) f64(0.75, 1.0)
