// =========================================================
// yihuan_collect_t0_cs.hlsl
//
// Generated by mod_importer.
// Collect is keyed by current cs-cb0 contents plus CharacterMetaTable collect rows.
//
// Expected bindings inherited from the original skin CS:
//   cb0 = original skin dispatch params
//   t0  = original local T0 palette for that dispatch
// Expected bindings set by the INI:
//   t2  = CharacterMetaTable
//   u0  = global T0 store UAV
// =========================================================

cbuffer OriginalSkinCB0 : register(b0)
{
    uint4 SkinCB0_0;
};

StructuredBuffer<uint4> OriginalT0 : register(t0);
Buffer<uint4> CharacterMeta : register(t2);
RWStructuredBuffer<uint4> GlobalT0Store : register(u0);

static const uint MetaBoneRow = 2u;
static const uint MetaIndexRow = 3u;

bool CurrentCB0Matches(uint expected_start, uint expected_count)
{
    bool primary_form = (SkinCB0_0.y == expected_start && SkinCB0_0.z == expected_count);
    bool final_form = (SkinCB0_0.z == expected_start && SkinCB0_0.w == expected_count);
    return primary_form || final_form;
}

uint CollectCount()
{
    return CharacterMeta[MetaBoneRow].w;
}

uint CollectRowBase()
{
    return CharacterMeta[MetaIndexRow].z;
}

uint GlobalT0StoreCapacity()
{
    uint rows = 0u;
    uint stride = 0u;
    GlobalT0Store.GetDimensions(rows, stride);
    return rows;
}

uint4 LoadCollectMeta(uint meta_index)
{
    return CharacterMeta[CollectRowBase() + meta_index];
}

[numthreads(64, 1, 1)]
void main(uint3 tid : SV_DispatchThreadID)
{
    uint local_row = tid.x;
    uint meta_count = CollectCount();
    uint store_capacity = GlobalT0StoreCapacity();

    for (uint meta_index = 0u; meta_index < meta_count; ++meta_index)
    {
        uint4 meta = LoadCollectMeta(meta_index);
        uint expected_start = meta.x;
        uint expected_count = meta.y;
        uint global_bone_base = meta.z;
        uint bone_count = meta.w;
        if (!CurrentCB0Matches(expected_start, expected_count))
        {
            continue;
        }

        uint row_count = bone_count * 3u;
        if (local_row >= row_count)
        {
            return;
        }

        uint local_bone = local_row / 3u;
        uint row_in_bone = local_row % 3u;
        uint global_bone = global_bone_base + local_bone;

        uint src_row = local_bone * 3u + row_in_bone;
        uint dst_row = global_bone * 3u + row_in_bone;
        if (dst_row >= store_capacity)
        {
            return;
        }

        GlobalT0Store[dst_row] = OriginalT0[src_row];
        return;
    }
}
