public AsyncGPUReadbackRequest Initialize()
    {
        _kernelInit         = CS.FindKernel("Init");
        _kernelStepVelocity = CS.FindKernel("StepV");
        _kernelStepPosition = CS.FindKernel("StepP");

        var vertexCount = _vertexCountPerDim;
        var totalVertex = vertexCount * vertexCount;
        var L0          = _clothSize / (vertexCount - 1);

        CS.SetInts("size", vertexCount, vertexCount, totalVertex);
        CS.SetVector("restLengths", new Vector3(L0, L0 * Mathf.Sqrt(2), L0 * 2));

        this.UpdateSimulateSetting();

        _positionBuffer   = new ComputeBuffer(totalVertex, 16);
        _velocitiesBuffer = new ComputeBuffer(totalVertex, 16);
        _normalBuffer     = new ComputeBuffer(totalVertex, 16);

        System.Action <int> setBufferForKernet = (k) => {
            CS.SetBuffer(k, "velocities", _velocitiesBuffer);
            CS.SetBuffer(k, "positions", _positionBuffer);
            CS.SetBuffer(k, "normals", _normalBuffer);
        };

        setBufferForKernet(_kernelInit);
        setBufferForKernet(_kernelStepVelocity);
        setBufferForKernet(_kernelStepPosition);

        CS.Dispatch(_kernelInit, _groupX, _groupY, 1);

        _totalVertexCount = totalVertex;

        CreateIndexBuffer();
        material.SetBuffer(ShaderIDs.position, _positionBuffer);
        material.SetBuffer(ShaderIDs.normals, _normalBuffer);

        return(AsyncGPUReadback.Request(_positionBuffer, (req) => {
            if (req.hasError)
            {
                Debug.LogError("Init error");
            }
            if (req.done && !req.hasError)
            {
                _initialized = true;
            }
        }));
    }
    public IEnumerator StartAsync()
    {
        yield return(Initialize());

        float dt    = 0;
        float minDt = _simulateSetting.stepTime;

        while (true)
        {
            dt += Time.deltaTime;
            while (dt > minDt)
            {
                CS.SetFloat("deltaTime", minDt);
                CS.Dispatch(_kernelStepVelocity, _groupX, _groupY, 1);
                CS.Dispatch(_kernelStepPosition, _groupX, _groupY, 1);
                dt -= minDt;
            }
            yield return(null);

            AsyncGPUReadback.WaitAllRequests();
        }
    }