void
OsdCudaComputeController::ApplyLoopVertexVerticesKernelB(
    FarKernelBatch const &batch, void * clientdata) const {

    OsdCudaComputeContext * context =
        static_cast<OsdCudaComputeContext*>(clientdata);
    assert(context);

    const OsdCudaTable * V_ITa = context->GetTable(FarSubdivisionTables<OsdVertex>::V_ITa);
    const OsdCudaTable * V_IT = context->GetTable(FarSubdivisionTables<OsdVertex>::V_IT);
    const OsdCudaTable * V_W = context->GetTable(FarSubdivisionTables<OsdVertex>::V_W);
    assert(V_ITa);
    assert(V_IT);
    assert(V_W);

    OsdCudaComputeLoopVertexB(
        context->GetCurrentVertexBuffer(),
        context->GetCurrentVaryingBuffer(),
        context->GetVertexDescriptor().numVertexElements-3,
        context->GetVertexDescriptor().numVaryingElements,
        static_cast<int*>(V_ITa->GetCudaMemory()),
        static_cast<int*>(V_IT->GetCudaMemory()),
        static_cast<float*>(V_W->GetCudaMemory()),
        batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd());
}
void
OsdCudaComputeController::ApplyVertexEdits(
    FarKernelBatch const &batch, void * clientdata) const {

    OsdCudaComputeContext * context =
        static_cast<OsdCudaComputeContext*>(clientdata);
    assert(context);

    const OsdCudaHEditTable *edit = context->GetEditTable(batch.GetTableIndex());
    assert(edit);

    const OsdCudaTable * primvarIndices = edit->GetPrimvarIndices();
    const OsdCudaTable * editValues = edit->GetEditValues();

    if (edit->GetOperation() == FarVertexEdit::Add) {
        OsdCudaEditVertexAdd(
            context->GetCurrentVertexBuffer(),
            context->GetVertexDescriptor().numVertexElements-3,
            edit->GetPrimvarOffset(),
            edit->GetPrimvarWidth(),
            batch.GetVertexOffset(),
            batch.GetTableOffset(),
            batch.GetStart(),
            batch.GetEnd(),
            static_cast<int*>(primvarIndices->GetCudaMemory()),
            static_cast<float*>(editValues->GetCudaMemory()));
    } else if (edit->GetOperation() == FarVertexEdit::Set) {
        // XXXX TODO
    }
}
void
OsdCudaComputeController::ApplyVertexEdits(
    FarKernelBatch const &batch, OsdCudaComputeContext const *context) const {

    assert(context);

    const OsdCudaHEditTable *edit = context->GetEditTable(batch.GetTableIndex());
    assert(edit);

    const OsdCudaTable * primvarIndices = edit->GetPrimvarIndices();
    const OsdCudaTable * editValues = edit->GetEditValues();

    float *vertex = _currentBindState.GetOffsettedVertexBuffer();

    if (edit->GetOperation() == FarVertexEdit::Add) {
        OsdCudaEditVertexAdd(
            vertex,
            _currentBindState.vertexDesc.length, _currentBindState.vertexDesc.stride,
            edit->GetPrimvarOffset(),
            edit->GetPrimvarWidth(),
            batch.GetVertexOffset(),
            batch.GetTableOffset(),
            batch.GetStart(),
            batch.GetEnd(),
            static_cast<int*>(primvarIndices->GetCudaMemory()),
            static_cast<float*>(editValues->GetCudaMemory()));
    } else if (edit->GetOperation() == FarVertexEdit::Set) {
        // XXXX TODO
    }
}
void
OsdCudaComputeController::ApplyLoopVertexVerticesKernelB(
    FarKernelBatch const &batch, OsdCudaComputeContext const *context) const {

    assert(context);

    const OsdCudaTable * V_ITa = context->GetTable(FarSubdivisionTables::V_ITa);
    const OsdCudaTable * V_IT = context->GetTable(FarSubdivisionTables::V_IT);
    const OsdCudaTable * V_W = context->GetTable(FarSubdivisionTables::V_W);
    assert(V_ITa);
    assert(V_IT);
    assert(V_W);

    float *vertex = _currentBindState.GetOffsettedVertexBuffer();
    float *varying = _currentBindState.GetOffsettedVaryingBuffer();

    OsdCudaComputeLoopVertexB(
        vertex, varying,
        _currentBindState.vertexDesc.length, _currentBindState.vertexDesc.stride,
        _currentBindState.varyingDesc.length, _currentBindState.varyingDesc.stride,
        static_cast<int*>(V_ITa->GetCudaMemory()),
        static_cast<int*>(V_IT->GetCudaMemory()),
        static_cast<float*>(V_W->GetCudaMemory()),
        batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd());
}
void
OsdGLSLTransformFeedbackComputeController::ApplyLoopVertexVerticesKernelA2(
    FarKernelBatch const &batch, OsdGLSLTransformFeedbackComputeContext const *context) const {

    assert(context);

    _currentBindState.kernelBundle->ApplyLoopVertexVerticesKernelA(
        _currentBindState.vertexBuffer, _currentBindState.varyingBuffer,
        _currentBindState.vertexDesc.offset, _currentBindState.varyingDesc.offset,
        batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd(), true);
}
void
OsdOmpComputeController::ApplyCatmarkQuadFaceVerticesKernel(
    FarKernelBatch const &batch, OsdCpuComputeContext const *context) const {

    assert(context);

    OsdOmpComputeQuadFace(
        _currentBindState.vertexBuffer, _currentBindState.varyingBuffer,
        _currentBindState.vertexDesc, _currentBindState.varyingDesc,
        (const int*)context->GetTable(FarSubdivisionTables::F_IT)->GetBuffer(),
        batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd());
}
void
OsdGLSLComputeController::ApplyBilinearEdgeVerticesKernel(
    FarKernelBatch const &batch, void * clientdata) const {

    OsdGLSLComputeContext * context =
        static_cast<OsdGLSLComputeContext*>(clientdata);
    assert(context);

    OsdGLSLComputeKernelBundle * kernelBundle = context->GetKernelBundle();

    kernelBundle->ApplyBilinearEdgeVerticesKernel(
        batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd());
}
void
OsdOmpComputeController::ApplyLoopVertexVerticesKernelA2(
    FarKernelBatch const &batch, OsdCpuComputeContext const *context) const {

    assert(context);

    OsdOmpComputeVertexA(
        _currentBindState.vertexBuffer, _currentBindState.varyingBuffer,
        _currentBindState.vertexDesc, _currentBindState.varyingDesc,
        (const int*)context->GetTable(FarSubdivisionTables::V_ITa)->GetBuffer(),
        (const float*)context->GetTable(FarSubdivisionTables::V_W)->GetBuffer(),
        batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd(), true);
}
void
OsdGcdComputeController::ApplyBilinearVertexVerticesKernel(
    FarKernelBatch const &batch, OsdCpuComputeContext const *context) const {

    assert(context);

    OsdGcdComputeBilinearVertex(
        _currentBindState.vertexBuffer, _currentBindState.varyingBuffer,
        _currentBindState.vertexDesc, _currentBindState.varyingDesc,
        (const int*)context->GetTable(FarSubdivisionTables::V_ITa)->GetBuffer(),
        batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd(),
        _gcd_queue);
}
void
OsdGcdComputeController::ApplyBilinearEdgeVerticesKernel(
    FarKernelBatch const &batch, OsdCpuComputeContext *context) const {

    assert(context);

    OsdGcdComputeBilinearEdge(
        context->GetVertexDescriptor(),
        context->GetCurrentVertexBuffer(),
        context->GetCurrentVaryingBuffer(),
        (const int*)context->GetTable(FarSubdivisionTables::E_IT)->GetBuffer(),
        batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd(),
	_gcd_queue);
}
void
OsdGcdComputeController::ApplyLoopVertexVerticesKernelA2(
    FarKernelBatch const &batch, OsdCpuComputeContext *context) const {

    assert(context);

    OsdGcdComputeVertexA(
        context->GetVertexDescriptor(),
        context->GetCurrentVertexBuffer(),
        context->GetCurrentVaryingBuffer(),
        (const int*)context->GetTable(FarSubdivisionTables::V_ITa)->GetBuffer(),
        (const float*)context->GetTable(FarSubdivisionTables::V_W)->GetBuffer(),
        batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd(), true,
        _gcd_queue);
}
void
OsdTbbComputeController::ApplyBilinearVertexVerticesKernel(
    FarKernelBatch const &batch, void *clientdata) const {

    OsdCpuComputeContext * context =
        static_cast<OsdCpuComputeContext*>(clientdata);
    assert(context);

    OsdTbbComputeBilinearVertex(
        context->GetVertexDescriptor(),
        context->GetCurrentVertexBuffer(),
        context->GetCurrentVaryingBuffer(),
        (const int*)context->GetTable(FarSubdivisionTables<OsdVertex>::V_ITa)->GetBuffer(),
        batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd());
}
void
OsdOmpComputeController::ApplyLoopEdgeVerticesKernel(
    FarKernelBatch const &batch, void *clientdata) const {

    OsdCpuComputeContext * context =
        static_cast<OsdCpuComputeContext*>(clientdata);
    assert(context);

    OsdOmpComputeEdge(
        context->GetVertexDescriptor(),
        context->GetCurrentVertexBuffer(),
        context->GetCurrentVaryingBuffer(),
        (const int*)context->GetTable(FarSubdivisionTables<OsdVertex>::E_IT)->GetBuffer(),
        (const float*)context->GetTable(FarSubdivisionTables<OsdVertex>::E_W)->GetBuffer(),
        batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd());
}
void
OsdGcdComputeController::ApplyCatmarkFaceVerticesKernel(
    FarKernelBatch const &batch, void * clientdata) const {

    OsdCpuComputeContext * context =
        static_cast<OsdCpuComputeContext*>(clientdata);
    assert(context);

    OsdGcdComputeFace(
        context->GetVertexDescriptor(),
        context->GetCurrentVertexBuffer(),
        context->GetCurrentVaryingBuffer(),
        (const int*)context->GetTable(FarSubdivisionTables<OsdVertex>::F_IT)->GetBuffer(),
        (const int*)context->GetTable(FarSubdivisionTables<OsdVertex>::F_ITa)->GetBuffer(),
        batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd(),
        _gcd_queue);
}
void
OsdCudaComputeController::ApplyBilinearEdgeVerticesKernel(
    FarKernelBatch const &batch, void * clientdata) const {

    OsdCudaComputeContext * context =
        static_cast<OsdCudaComputeContext*>(clientdata);
    assert(context);

    const OsdCudaTable * E_IT = context->GetTable(FarSubdivisionTables<OsdVertex>::E_IT);
    assert(E_IT);

    OsdCudaComputeBilinearEdge(
        context->GetCurrentVertexBuffer(),
        context->GetCurrentVaryingBuffer(),
        context->GetVertexDescriptor().numVertexElements-3,
        context->GetVertexDescriptor().numVaryingElements,
        static_cast<int*>(E_IT->GetCudaMemory()),
        batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd());
}
void
OsdCudaComputeController::ApplyCatmarkRestrictedEdgeVerticesKernel(
    FarKernelBatch const &batch, OsdCudaComputeContext const *context) const {

    assert(context);

    const OsdCudaTable * E_IT = context->GetTable(FarSubdivisionTables::E_IT);
    assert(E_IT);

    float *vertex = _currentBindState.GetOffsettedVertexBuffer();
    float *varying = _currentBindState.GetOffsettedVaryingBuffer();

    OsdCudaComputeRestrictedEdge(
        vertex, varying,
        _currentBindState.vertexDesc.length, _currentBindState.vertexDesc.stride,
        _currentBindState.varyingDesc.length, _currentBindState.varyingDesc.stride,
        static_cast<int*>(E_IT->GetCudaMemory()),
        batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd());
}
void
OsdGLSLComputeController::ApplyVertexEdits(
    FarKernelBatch const &batch, void * clientdata) const {

    OsdGLSLComputeContext * context =
        static_cast<OsdGLSLComputeContext*>(clientdata);
    assert(context);

    OsdGLSLComputeKernelBundle * kernelBundle = context->GetKernelBundle();

    const OsdGLSLComputeHEditTable * edit = context->GetEditTable(batch.GetTableIndex());
    assert(edit);

    context->BindEditShaderStorageBuffers(batch.GetTableIndex());

    int primvarOffset = edit->GetPrimvarOffset();
    int primvarWidth = edit->GetPrimvarWidth();
    
    if (edit->GetOperation() == FarVertexEdit::Add) {
        kernelBundle->ApplyEditAdd( primvarOffset, 
                                    primvarWidth,
                                    batch.GetVertexOffset(), 
                                    batch.GetTableOffset(), 
                                    batch.GetStart(), 
                                    batch.GetEnd());
    } else {
        // XXX: edit SET is not implemented yet.
    }
    
    context->UnbindEditShaderStorageBuffers();
}
void
OsdGLSLTransformFeedbackComputeController::ApplyVertexEdits(
    FarKernelBatch const &batch, OsdGLSLTransformFeedbackComputeContext const *context) const {

    assert(context);

    const OsdGLSLTransformFeedbackHEditTable * edit = context->GetEditTable(batch.GetTableIndex());
    assert(edit);

    context->BindEditTextures(batch.GetTableIndex(), _currentBindState.kernelBundle);

    int primvarOffset = edit->GetPrimvarOffset();
    int primvarWidth = edit->GetPrimvarWidth();

    if (edit->GetOperation() == FarVertexEdit::Add) {
        _currentBindState.kernelBundle->ApplyEditAdd(
            _currentBindState.vertexBuffer, _currentBindState.varyingBuffer,
            _currentBindState.vertexDesc.offset, _currentBindState.varyingDesc.offset,
            primvarOffset, primvarWidth,
            batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd());
    } else {
        // XXX: edit SET is not implemented yet.
    }
    
    context->UnbindEditTextures();
}
void
OsdGcdComputeController::ApplyVertexEdits(
    FarKernelBatch const &batch, void * clientdata) const {

    OsdCpuComputeContext * context =
        static_cast<OsdCpuComputeContext*>(clientdata);
    assert(context);

    const OsdCpuHEditTable *edit = context->GetEditTable(batch.GetTableIndex());
    assert(edit);

    const OsdCpuTable * primvarIndices = edit->GetPrimvarIndices();
    const OsdCpuTable * editValues = edit->GetEditValues();

    if (edit->GetOperation() == FarVertexEdit::Add) {
        OsdGcdEditVertexAdd(context->GetVertexDescriptor(),
                            context->GetCurrentVertexBuffer(),
                            edit->GetPrimvarOffset(),
                            edit->GetPrimvarWidth(),
                            batch.GetVertexOffset(),
                            batch.GetTableOffset(),
                            batch.GetStart(),
                            batch.GetEnd(),
                            static_cast<unsigned int*>(primvarIndices->GetBuffer()),
                            static_cast<float*>(editValues->GetBuffer()),
                            _gcd_queue);
    } else if (edit->GetOperation() == FarVertexEdit::Set) {
        OsdGcdEditVertexSet(context->GetVertexDescriptor(),
                            context->GetCurrentVertexBuffer(),
                            edit->GetPrimvarOffset(),
                            edit->GetPrimvarWidth(),
                            batch.GetVertexOffset(),
                            batch.GetTableOffset(),
                            batch.GetStart(),
                            batch.GetEnd(),
                            static_cast<unsigned int*>(primvarIndices->GetBuffer()),
                            static_cast<float*>(editValues->GetBuffer()),
                            _gcd_queue);
    }
}
void
OsdOmpComputeController::ApplyVertexEdits(
    FarKernelBatch const &batch, OsdCpuComputeContext const *context) const {

    assert(context);

    const OsdCpuHEditTable *edit = context->GetEditTable(batch.GetTableIndex());
    assert(edit);

    const OsdCpuTable * primvarIndices = edit->GetPrimvarIndices();
    const OsdCpuTable * editValues = edit->GetEditValues();

    if (edit->GetOperation() == FarVertexEdit::Add) {
        OsdOmpEditVertexAdd(_currentBindState.vertexBuffer,
                            _currentBindState.vertexDesc,
                            edit->GetPrimvarOffset(),
                            edit->GetPrimvarWidth(),
                            batch.GetVertexOffset(), 
                            batch.GetTableOffset(), 
                            batch.GetStart(), 
                            batch.GetEnd(),
                            static_cast<unsigned int*>(primvarIndices->GetBuffer()),
                            static_cast<float*>(editValues->GetBuffer()));
    } else if (edit->GetOperation() == FarVertexEdit::Set) {
        OsdOmpEditVertexSet(_currentBindState.vertexBuffer,
                            _currentBindState.vertexDesc,
                            edit->GetPrimvarOffset(),
                            edit->GetPrimvarWidth(),
                            batch.GetVertexOffset(), 
                            batch.GetTableOffset(), 
                            batch.GetStart(), 
                            batch.GetEnd(),
                            static_cast<unsigned int*>(primvarIndices->GetBuffer()),
                            static_cast<float*>(editValues->GetBuffer()));
    }
}