// Miyabi reference skinning shader, with only resource names made generic.
// The combined mesh already stores global BLENDINDICES in assembled order.

Texture1D<float4> IniParams : register(t120);
Buffer<float4> t0 : register(t0);
Buffer<float> t1 : register(t1);
Buffer<float> t2 : register(t2);
RWBuffer<float> u0 : register(u0);

[numthreads(64, 1, 1)]
void main(uint3 thread_id : SV_DispatchThreadID)
{
    uint id = thread_id.x;
    uint vertex_count = asuint(IniParams[0].x);
    if (id >= vertex_count)
        return;

    uint base10 = id * 10;
    float3 position = float3(t1[base10], t1[base10 + 1], t1[base10 + 2]);
    float3 normal = float3(t1[base10 + 3], t1[base10 + 4], t1[base10 + 5]);
    float4 tangent = float4(t1[base10 + 6], t1[base10 + 7], t1[base10 + 8], t1[base10 + 9]);

    uint base8 = id * 8;
    float4 weights = float4(t2[base8], t2[base8 + 1], t2[base8 + 2], t2[base8 + 3]);
    int4 indices = int4(asint(t2[base8 + 4]), asint(t2[base8 + 5]), asint(t2[base8 + 6]), asint(t2[base8 + 7]));
    int4 row0_indices = indices * 3;

    float4 blend = t0.Load(row0_indices.y) * weights.yyyy;
    blend = weights.xxxx * t0.Load(row0_indices.x) + blend;
    blend = weights.zzzz * t0.Load(row0_indices.z) + blend;
    float4 row0 = weights.wwww * t0.Load(row0_indices.w) + blend;

    int4 row12_a = indices.xxyy * 3 + int4(2, 1, 2, 1);
    int4 row12_b = indices.zzww * 3 + int4(2, 1, 2, 1);
    blend = t0.Load(row12_a.w) * weights.yyyy;
    blend = weights.xxxx * t0.Load(row12_a.y) + blend;
    blend = weights.zzzz * t0.Load(row12_b.y) + blend;
    float4 row1 = weights.wwww * t0.Load(row12_b.w) + blend;
    blend = t0.Load(row12_a.z) * weights.yyyy;
    blend = weights.xxxx * t0.Load(row12_a.x) + blend;
    blend = weights.zzzz * t0.Load(row12_b.x) + blend;
    float4 row2 = weights.wwww * t0.Load(row12_b.z) + blend;

    float4 p = float4(position, 1.0);
    float3 out_position = float3(dot(p, row0), dot(p, row1), dot(p, row2));
    float3 out_normal = float3(dot(normal, row0.xyz), dot(normal, row1.xyz), dot(normal, row2.xyz));
    float3 out_tangent = float3(dot(tangent.xyz, row0.xyz), dot(tangent.xyz, row1.xyz), dot(tangent.xyz, row2.xyz));
    u0[base10] = out_position.x;
    u0[base10 + 1] = out_position.y;
    u0[base10 + 2] = out_position.z;
    u0[base10 + 3] = out_normal.x;
    u0[base10 + 4] = out_normal.y;
    u0[base10 + 5] = out_normal.z;
    u0[base10 + 6] = out_tangent.x;
    u0[base10 + 7] = out_tangent.y;
    u0[base10 + 8] = out_tangent.z;
    u0[base10 + 9] = tangent.w;
}
