//
// Copyright (c) 2017 The Khronos Group Inc.
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "testBase.h"

#ifndef _WIN32
#include <unistd.h>
#endif

#include "harness/conversions.h"

static void CL_CALLBACK test_native_kernel_fn( void *userData )
{
    struct arg_struct {
        cl_int * source;
        cl_int * dest;
        cl_int count;
    } *args = (arg_struct *)userData;

    for( cl_int i = 0; i < args->count; i++ )
        args->dest[ i ] = args->source[ i ];
}

int test_native_kernel(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems )
{
    int error;
    RandomSeed seed( gRandomSeed );
    // Check if we support native kernels
    cl_device_exec_capabilities capabilities;
    error = clGetDeviceInfo(device, CL_DEVICE_EXECUTION_CAPABILITIES, sizeof(capabilities), &capabilities, NULL);
    if (!(capabilities & CL_EXEC_NATIVE_KERNEL)) {
        log_info("Device does not support CL_EXEC_NATIVE_KERNEL.\n");
        return 0;
    }

    clMemWrapper streams[ 2 ];
#if !(defined (_WIN32) && defined (_MSC_VER))
    cl_int inBuffer[ n_elems ], outBuffer[ n_elems ];
#else
    cl_int* inBuffer  = (cl_int *)_malloca( n_elems * sizeof(cl_int) );
    cl_int* outBuffer = (cl_int *)_malloca( n_elems * sizeof(cl_int) );
#endif
    clEventWrapper finishEvent;

    struct arg_struct
    {
        cl_mem inputStream;
        cl_mem outputStream;
        cl_int count;
    } args;


    // Create some input values
    generate_random_data( kInt, n_elems, seed, inBuffer );


    // Create I/O streams
    streams[ 0 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, n_elems * sizeof(cl_int), inBuffer, &error );
    test_error( error, "Unable to create I/O stream" );
    streams[ 1 ] = clCreateBuffer( context, 0, n_elems * sizeof(cl_int), NULL, &error );
    test_error( error, "Unable to create I/O stream" );


    // Set up the arrays to call with
    args.inputStream = streams[ 0 ];
    args.outputStream = streams[ 1 ];
    args.count = n_elems;

    void * memLocs[ 2 ] = { &args.inputStream, &args.outputStream };


    // Run the kernel
    error = clEnqueueNativeKernel( queue, test_native_kernel_fn,
                                      &args, sizeof( args ),
                                      2, &streams[ 0 ],
                                      (const void **)memLocs,
                                      0, NULL, &finishEvent );
    test_error( error, "Unable to queue native kernel" );

    // Finish and wait for the kernel to complete
    error = clFinish( queue );
    test_error(error, "clFinish failed");

    error = clWaitForEvents( 1, &finishEvent );
    test_error(error, "clWaitForEvents failed");

    // Now read the results and verify
    error = clEnqueueReadBuffer( queue, streams[ 1 ], CL_TRUE, 0, n_elems * sizeof(cl_int), outBuffer, 0, NULL, NULL );
    test_error( error, "Unable to read results" );

    for( int i = 0; i < n_elems; i++ )
    {
        if( inBuffer[ i ] != outBuffer[ i ] )
        {
            log_error( "ERROR: Data sample %d for native kernel did not validate (expected %d, got %d)\n",
                      i, (int)inBuffer[ i ], (int)outBuffer[ i ] );
            return 1;
        }
    }

    return 0;
}





