#include <maya/MFnPlugin.h>
#include <maya/MTypeId.h> 
#include <maya/MStringArray.h>
#include <maya/MPxDeformerNode.h> 
#include <maya/MItGeometry.h>
#include <maya/MPoint.h>
#include <maya/MPxGPUDeformer.h>
#include <maya/MGPUDeformerRegistry.h>
#include <maya/MOpenCLInfo.h>
#include <clew/clew_cl.h>
{
public:
    static  void*   creator();
    
    
                           unsigned int multiIndex);
};
const MTypeId identityNode::id( 0x8000d );
 
void* identityNode::creator()
{
    return new identityNode();
}
{
}
                      unsigned int multiIndex)
{
    
    
    
        
        
        
        
        
    }
    return returnStatus;
}
{
public:
    
    identityGPUDeformer();
    virtual ~identityGPUDeformer();
    
private:
    
    size_t fLocalWorkSize;
    size_t fGlobalWorkSize;
};
{
public:
    identityGPUDeformerInfo(){}
    virtual ~identityGPUDeformerInfo(){}
    {
        return new identityGPUDeformer();
    }
    {
        return identityGPUDeformer::validateNodeInGraph(block, evaluationNode, plug, messages);
    }
    {
        return identityGPUDeformer::validateNodeValues(block, evaluationNode, plug, messages);
    }
};
{
    static identityGPUDeformerInfo theOne;
    return &theOne;
}
identityGPUDeformer::identityGPUDeformer()
{
}
identityGPUDeformer::~identityGPUDeformer()
{
    terminate();
}
{
    
    return true;
}
{
    
    return true;
}
MPxGPUDeformer::DeformerStatus identityGPUDeformer::evaluate(
    unsigned int numElements,
    )
{
    cl_int err = CL_SUCCESS;    
    
    
    if ( !fKernel.get() )
    {
        
        const char* mayaLocation = getenv( "MAYA_LOCATION" );
        MString openCLKernelFile( mayaLocation );
 
        openCLKernelFile +="/../Extra/devkitBase/devkit/plug-ins/identityNode/identity.cl";
        MString openCLKernelName(
"identity");
 
        {
            return MPxGPUDeformer::kDeformerFailure;
        }
        fKernel = kernel;
        
        
        fLocalWorkSize = 0;
        fGlobalWorkSize = 0;
        size_t retSize = 0;
        err = clGetKernelWorkGroupInfo(
            fKernel.get(),
            CL_KERNEL_WORK_GROUP_SIZE,
            sizeof(size_t),
            &fLocalWorkSize,
            &retSize
            );
        if ( err != CL_SUCCESS || retSize == 0 || fLocalWorkSize == 0)
        {
            return MPxGPUDeformer::kDeformerFailure;
        }
        
        const size_t remain = numElements % fLocalWorkSize;
        if ( remain )
        {
            fGlobalWorkSize = numElements + ( fLocalWorkSize - remain );
        }
        else
        {
            fGlobalWorkSize = numElements;
        }
    }
    
    
    unsigned int parameterId = 0;
    err = clSetKernelArg(fKernel.get(), parameterId++, sizeof(cl_mem), (void*)outputBuffer.getReadOnlyRef());
    err = clSetKernelArg(fKernel.get(), parameterId++, sizeof(cl_mem), (void*)inputBuffer.getReadOnlyRef());
    err = clSetKernelArg(fKernel.get(), parameterId++, sizeof(cl_uint), (void*)&numElements);
    
    
    cl_event events[ 1 ] = { 0 };
    cl_uint eventCount = 0;
    {
        events[ eventCount++ ] = inputEvent.
get();
    }
    
    err = clEnqueueNDRangeKernel(
        fKernel.get() ,
        1 ,
        NULL ,
        &fGlobalWorkSize ,
        &fLocalWorkSize ,
        eventCount ,
        eventCount ? events : NULL ,
        );
    if ( err != CL_SUCCESS )
    {
        return MPxGPUDeformer::kDeformerFailure;
    }
    return MPxGPUDeformer::kDeformerSuccess;
}
void identityGPUDeformer::terminate()
{
    fKernel.reset();
}
{
    MFnPlugin plugin( obj, PLUGIN_COMPANY, 
"3.0", 
"Any");
 
    result = plugin.registerNode(
        "identity" ,
        identityNode::id ,
        &identityNode::creator ,
        &identityNode::initialize ,
        );
    MString registrantId(
"mayaPluginExample");
 
        nodeClassName,
        registrantId,
        identityGPUDeformer::getGPUDeformerInfo()
        );
    return result;
}
{
    MString registrantId(
"mayaPluginExample");
 
        nodeClassName,
        registrantId
        );
    result = plugin.deregisterNode( identityNode::id );
    return result;
}