//NOTE: anything to do with program is probably partially useless //The "kernel" text cannot be used, they are vestigal structures #include "cl.cvl" #include #include #include $input int DEVICE_ID; $input int DEVICE_ID_BOUND; $assume 0 < DEVICE_ID && DEVICE_ID < DEVICE_ID_BOUND; //kernels //int get_global_id /* Gives back an int for the error code, fills devices with ids of devices See cl.cvl for files platform - The platform, can be NULL device_type - Has the device type num_entries - Is the max number of devices that can be filled devices - A pointer that will contain the IDs num_devices - Says how many devices were added, can be NULL */ int clGetDeviceIDs(cl_platform_id platform, cl_device_type device_type, cl_uint num_entries, cl_device_id * devices, cl_uint * num_devices) { //$assume device_type == CL_DEVICE_TYPE_DEFAULT; int i = 0; //cl_platform_id int value can be null //num_entries number of devices that can be added /* if(num_entries == 0 && devices != 0) { return CL_INVALID_VALUE; } if(num_entries == 0 && devices == 0) { return CL_INVALID_VALUE; } //CIVL cannot pass this if block if not commented out /* if(device_type & (CL_DEVICE_TYPE_DEFAULT | CL_DEVICE_TYPE_CPU | CL_DEVICE_TYPE_GPU | CL_DEVICE_TYPE_ACCELERATOR | CL_DEVICE_TYPE_CUSTOM | CL_DEVICE_TYPE_ALL)) { */ while (i < num_entries) { if(devices) { devices[0] = (cl_device_id)(&DEVICE_ID); i++; } else { break; } } if (num_devices) { *num_devices = i; } //} /* else { return CL_DEVICE_NOT_FOUND; } */ //*devices list of devices found, use //cl_device_id device_id; //&device_id return CL_SUCCESS; } /* Creates the cl_context that will be used in later types to be made properties - Context property names num_devices - Number of devices devices - Pointer to the devices from clGetDeviceIDs pfn_notify - Callback function to report errors. Can be NULL user_data - Part of pfn_notify. Can be NULL errcode_ret - Returns proper error code. */ cl_context clCreateContext(const cl_context_properties *properties, cl_uint num_devices, const cl_device_id * devices, void (CL_CALLBACK *pfn_notify)(const char *, const void *, size_t, void *), void * user_data, cl_int * errcode_ret) { cl_int default_errcode_ret; cl_context ctx; if(!errcode_ret) { errcode_ret = &default_errcode_ret; } if (!devices || !num_devices || (!pfn_notify && user_data)) { *errcode_ret = CL_INVALID_VALUE; return 0; } *errcode_ret = CL_SUCCESS; ctx = (cl_context)malloc(sizeof(_cl_context)); ctx->properties = properties; ctx->num_devices = num_devices; ctx->devices = devices; ctx->pfn_notify = pfn_notify; ctx->user_data = user_data; ctx->errcode_ret = errcode_ret; if(*errcode_ret != CL_SUCCESS) { //delete ctx; return 0; } return(cl_context) ctx; } /* Creates a cl_command_queue context - The context created from clCreateContext device - The pointer to IDs from clGetDeviceIDs properties - Bitfield for properties, see cl.cvl errcode_ret - Returns proper error code. */ cl_command_queue clCreateCommandQueue(cl_context context, cl_device_id device, cl_command_queue_properties properties, cl_int* errcode_ret) { cl_int default_errcode_ret; cl_command_queue cmd; // No errcode_ret ? if (!errcode_ret) { errcode_ret = &default_errcode_ret; } cmd = (cl_command_queue)malloc(sizeof(_cl_command_queue)); cmd->context = context; cmd->device = device; cmd->properties = properties; cmd->errcode_ret = errcode_ret; return cmd; } /*Makes a program from context. Not quite like the original implementation Note that the strings part is useless, that part cannot be used in CIVL context - From clCreateContext count - number of source codes for strings strings - Array of chars that makes up code lengths - string length, if NULL nulls the strings errcode_ret - Returns proper error code */ cl_program clCreateProgramWithSource(cl_context context, cl_uint count, const char** strings, const size_t * lengths, cl_int * errcode_ret) { cl_int default_errcode_ret; cl_program program; program = (cl_program)malloc(sizeof(_cl_program)); if(!errcode_ret) { errcode_ret = &default_errcode_ret; } if(!lengths) { strings == NULL; } *errcode_ret = CL_SUCCESS; //*errcode_ret = program->loadSources(count, strings, lengths); //corrects lengths for (cl_uint i = 0; i < count; i++) { size_t len = 0; const char *data = strings[i]; if (lengths && lengths[i]) { len = lengths[i]; } else { len = strlen(data); } //remove trailing \0's, or null characters at EOF //remember that '' is char, "" is string while (len > 0 && (data[len-1] == '\0')) { len--; } } program->context = context; program->count = count; program->strings = strings; program->lengths = lengths; $assert (*errcode_ret == CL_SUCCESS); //the original for loop can make *errcode_ret not CL_SUCCESS, this is a placeholder return (cl_program) program; } /*Makes a program from context. Not quite like the original implementation Still looks almost like clCreateProgramWithSource, change context - From clCreateContext num_devices - Number of devices in device_list device_list - Pointer to list of devices associated with a program lengths - Array of size in bytes the program binaries are binaries - Array of pointers to program binaries binary_status - Returns whether each device was loaded, an array of num_devices errcode_ret - Returns proper error code */ cl_program clCreateProgramWithBinaries(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const size_t *lengths, const unsigned char **binaries, cl_int *binary_status, cl_int *errcode_ret) { cl_int default_errcode_ret; cl_program program; cl_uint context_num_devices = 0; cl_device_id *context_devices; program = (cl_program)malloc(sizeof(_cl_program)); if(!errcode_ret) { errcode_ret = &default_errcode_ret; } *errcode_ret = CL_SUCCESS; //*errcode_ret = program->loadBinaries(count, strings, lengths); for (cl_uint i = 0; i < num_devices; i++) { bool found = false; if (!lengths[i] || !binaries[i]) { if(binary_status) { binary_status[i] = CL_INVALID_VALUE; break; } *errcode_ret = CL_INVALID_VALUE; } for (cl_uint j = 0; j < context_num_devices; j++) { if(device_list[i] == context_devices[j]) { found = true; return 0; } } if(!found) { *errcode_ret = CL_INVALID_DEVICE; break; } } program->context = context; program->lengths = lengths; $assert (*errcode_ret == CL_SUCCESS); return (cl_program) program; } /* "Builds" a program executable from the source/binary program - The program, from clCreateProgramWithBinary or clCreateProgramWithContext num_devices - Number of devices in device_list, can be 0 device_list - List of devices, can be NULL options - Pointer describing build options, can be NULL pfn_notify - Function pointer to notification routine, can be NULL and won't return until build is completed user_data - argument for pfn_notify, can be NULL */ cl_int clBuildProgram(cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, void (CL_CALLBACK *pfn_notify)(cl_program program, void *user_data), void *user_data) { if (num_devices) { cl_uint context_num_devices = 0; cl_device_id *context_devices; cl_context *context = (cl_context *) program->context; cl_int result; context_devices = (cl_device_id *) malloc(context_num_devices * sizeof(cl_device_id)); if(result != CL_SUCCESS) { return result; } for (int i = 0; i < num_devices; i++) { bool found = false; for (int j = 0; j < context_num_devices; j++) { if (device_list[i] == context_devices[j]) { found = true; break; } } if (!found) { return CL_INVALID_DEVICE; } } } return CL_SUCCESS; } /* Creates a kernel with the name of the method specified, and the program program - program from clCreateProgramWithX kernel_name - name of the kernel, should be the same as the method or else errcode_ret - Returns proper error code */ cl_kernel clCreateKernel(cl_program program, const char * kernel_name, cl_int * errcode_ret) { cl_int dummy_errcode; if (!errcode_ret) { errcode_ret = &dummy_errcode; } cl_kernel kernel = (cl_kernel)malloc(sizeof(_cl_kernel)); kernel->kernel_name = kernel_name; kernel->errcode_ret = errcode_ret; return (cl_kernel)kernel; } /*Creates the buffer object context - context made from clCreateContext flags - see cl.cvl and find the #define, determines what can be done with a buffer size - size of the buffer, using sizeof recommended host_ptr - pointer to buffer data, must be >= size of bytes, can be null errcode_ret - Returns proper error code, can be null */ //consider for example T* buffer = (T*) malloc(sizeof(T)); cl_mem clCreateBuffer(cl_context context, cl_mem_flags flags, size_t size, void * host_ptr, cl_int * errcode_ret) { cl_mem buf = (cl_mem)malloc(sizeof(_cl_mem)); cl_int dummy_errcode; if (!errcode_ret) { errcode_ret = &dummy_errcode; } *errcode_ret = CL_SUCCESS; if (size == 0) { *errcode_ret = CL_INVALID_BUFFER_SIZE; } buf->context = context; //buf->size = (size_t*)malloc(size); If you use this make it a pointer again in cl.cvl buf->size = size; //size_t * sizes = (size_t*)malloc(size); buf->host_ptr = host_ptr; buf->flags = flags; buf->errcode_ret = errcode_ret; //Have to put in init, which creates a buf for each device //http://people.freedesktop.org/~steckdenis/clover/memobject_8cpp_source.html#l00105 //number of devices is from context->num_devices, note that verify may cause it to print several times printf("num_devices is %d\n", context->num_devices); cl_device_id * devices = (cl_device_id *) malloc(context->num_devices * sizeof(cl_device_id)); /* for (int i = 0; i< context->num_devices; i++) { devices[i] = device } */ return (cl_mem)buf; }