static inline void pocl_device_common_init(struct _cl_device_id* dev) { POCL_INIT_OBJECT(dev); dev->driver_version = PACKAGE_VERSION; if(dev->version == NULL) dev->version = "OpenCL 1.2 pocl"; dev->short_name = strdup(dev->ops->device_name); }
cl_event pocl_mem_manager_new_event () { cl_event ev = NULL; POCL_LOCK (mm->event_lock); if ((ev = mm->event_list)) { LL_DELETE (mm->event_list, ev); POCL_UNLOCK (mm->event_lock); return ev; } POCL_UNLOCK (mm->event_lock); ev = (struct _cl_event*) calloc (1, sizeof (struct _cl_event)); POCL_INIT_OBJECT(ev); ev->pocl_refcount = 1; return ev; }
cl_int pocl_create_event (cl_event *event, cl_command_queue command_queue, cl_command_type command_type) { if (event != NULL) { *event = (cl_event)malloc (sizeof (struct _cl_event)); if (event == NULL) return CL_OUT_OF_HOST_MEMORY; POCL_INIT_OBJECT(*event); (*event)->queue = command_queue; POname(clRetainCommandQueue) (command_queue); (*event)->command_type = command_type; (*event)->callback_list = NULL; } return CL_SUCCESS; }
cl_event pocl_mem_manager_new_event () { cl_event ev = NULL; POCL_LOCK (mm->event_lock); if (ev = mm->event_list) { LL_DELETE (mm->event_list, ev); POCL_UNLOCK (mm->event_lock); ev->pocl_refcount = 2; /* no need to lock because event is not in use */ return ev; } POCL_UNLOCK (mm->event_lock); ev = calloc (1, sizeof (struct _cl_event)); POCL_INIT_OBJECT(ev); ev->pocl_refcount = 2; return ev; }
/* creates either a program with binaries, or an empty program. The latter * is useful for clLinkProgram() which needs an empty program to put the * compiled results in. */ cl_program create_program_skeleton (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, int allow_empty_binaries) { cl_program program; unsigned i,j; int errcode, is_spirv_opencl; cl_device_id *unique_devlist = NULL; POCL_GOTO_ERROR_COND((context == NULL), CL_INVALID_CONTEXT); POCL_GOTO_ERROR_COND((device_list == NULL), CL_INVALID_VALUE); POCL_GOTO_ERROR_COND((num_devices == 0), CL_INVALID_VALUE); if (!allow_empty_binaries) { POCL_GOTO_ERROR_COND ((lengths == NULL), CL_INVALID_VALUE); for (i = 0; i < num_devices; ++i) { POCL_GOTO_ERROR_ON ((lengths[i] == 0 || binaries[i] == NULL), CL_INVALID_VALUE, "%i-th binary is NULL or its length==0\n", i); } } // check for duplicates in device_list[]. for (i = 0; i < context->num_devices; i++) { int count = 0; for (j = 0; j < num_devices; j++) { count += context->devices[i] == device_list[j]; } // duplicate devices POCL_GOTO_ERROR_ON((count > 1), CL_INVALID_DEVICE, "device %s specified multiple times\n", context->devices[i]->long_name); } // convert subdevices to devices and remove duplicates cl_uint real_num_devices = 0; unique_devlist = pocl_unique_device_list(device_list, num_devices, &real_num_devices); num_devices = real_num_devices; device_list = unique_devlist; // check for invalid devices in device_list[]. for (i = 0; i < num_devices; i++) { int found = 0; for (j = 0; j < context->num_devices; j++) { found |= context->devices[j] == device_list[i]; } POCL_GOTO_ERROR_ON((!found), CL_INVALID_DEVICE, "device not found in the device list of the context\n"); } if ((program = (cl_program) calloc (1, sizeof (struct _cl_program))) == NULL) { errcode = CL_OUT_OF_HOST_MEMORY; goto ERROR; } POCL_INIT_OBJECT(program); if ((program->binary_sizes = (size_t*) calloc (num_devices, sizeof(size_t))) == NULL || (program->binaries = (unsigned char**) calloc (num_devices, sizeof(unsigned char*))) == NULL || (program->pocl_binaries = (unsigned char**) calloc (num_devices, sizeof(unsigned char*))) == NULL || (program->pocl_binary_sizes = (size_t*) calloc (num_devices, sizeof(size_t))) == NULL || (program->build_log = (char**) calloc (num_devices, sizeof(char*))) == NULL || ((program->llvm_irs = (void**) calloc (num_devices, sizeof(void*))) == NULL) || ((program->build_hash = (SHA1_digest_t*) calloc (num_devices, sizeof(SHA1_digest_t))) == NULL)) { errcode = CL_OUT_OF_HOST_MEMORY; goto ERROR_CLEAN_PROGRAM_AND_BINARIES; } program->context = context; program->num_devices = num_devices; program->devices = unique_devlist; program->build_status = CL_BUILD_NONE; program->binary_type = CL_PROGRAM_BINARY_TYPE_NONE; char program_bc_path[POCL_FILENAME_LENGTH]; if (allow_empty_binaries && (lengths == NULL) && (binaries == NULL)) goto SUCCESS; for (i = 0; i < num_devices; ++i) { /* LLVM IR */ if (!strncmp((const char *)binaries[i], "BC", 2)) { program->binary_sizes[i] = lengths[i]; program->binaries[i] = (unsigned char*) malloc(lengths[i]); memcpy (program->binaries[i], binaries[i], lengths[i]); if (binary_status != NULL) binary_status[i] = CL_SUCCESS; } /* SPIR-V binary needs to be converted, and requires * linking of the converted BC */ #ifdef OCS_AVAILABLE else if (bitcode_is_spirv ((const char *)binaries[i], lengths[i], &is_spirv_opencl)) { if (is_spirv_opencl == 0) { // SPIR-V but not OpenCL-type. POCL_GOTO_ERROR_ON ( 1, CL_BUILD_PROGRAM_FAILURE, "SPIR-V binary provided, but is not using Kernel mode." "Pocl can't process this binary.\n"); } int no_spir = strstr (device_list[i]->extensions, "cl_khr_spir") == NULL; POCL_GOTO_ERROR_ON ( no_spir, CL_BUILD_PROGRAM_FAILURE, "SPIR binary provided, but device has no SPIR support"); #ifdef ENABLE_SPIRV POCL_MSG_PRINT_LLVM ( "SPIR-V binary detected, converting to LLVM SPIR\n"); char program_bc_spirv[POCL_FILENAME_LENGTH]; char program_bc_temp[POCL_FILENAME_LENGTH]; pocl_cache_write_spirv (program_bc_spirv, (const char *)binaries[i], (uint64_t)lengths[i]); pocl_cache_tempname (program_bc_temp, ".bc", NULL); char *args[] = { LLVM_SPIRV, "-r", "-o", program_bc_temp, program_bc_spirv, NULL }; errcode = pocl_run_command (args); assert (errcode == 0); /* load LLVM SPIR binary. */ uint64_t fsize; char *content; pocl_read_file (program_bc_temp, &content, &fsize); program->binary_sizes[i] = fsize; program->binaries[i] = (unsigned char *)content; pocl_remove (program_bc_temp); #else POCL_GOTO_ERROR_ON ( 1, CL_BUILD_PROGRAM_FAILURE, "SPIR binary provided, but this pocl has no SPIR-V support." "SPIR-V support requires llvm-spirv converter binary.\n"); #endif } #endif /* Poclcc binary */ else if (pocl_binary_check_binary(device_list[i], binaries[i])) { program->pocl_binary_sizes[i] = lengths[i]; program->pocl_binaries[i] = (unsigned char*) malloc (lengths[i]); memcpy (program->pocl_binaries[i], binaries[i], lengths[i]); pocl_binary_set_program_buildhash (program, i, binaries[i]); int error = pocl_cache_create_program_cachedir (program, i, NULL, 0, program_bc_path); POCL_GOTO_ERROR_ON((error != 0), CL_BUILD_PROGRAM_FAILURE, "Could not create program cachedir"); POCL_GOTO_ERROR_ON(pocl_binary_deserialize (program, i), CL_INVALID_BINARY, "Could not unpack a pocl binary\n"); /* read program.bc, can be useful later */ if (pocl_exists (program_bc_path)) { pocl_read_file (program_bc_path, (char **)(&program->binaries[i]), (uint64_t *)(&program->binary_sizes[i])); } if (binary_status != NULL) binary_status[i] = CL_SUCCESS; } /* Unknown binary */ else { POCL_MSG_WARN ("Could not recognize binary\n"); if (binary_status != NULL) binary_status[i] = CL_INVALID_BINARY; errcode = CL_INVALID_BINARY; goto ERROR_CLEAN_PROGRAM_AND_BINARIES; } } SUCCESS: POCL_RETAIN_OBJECT(context); if (errcode_ret != NULL) *errcode_ret = CL_SUCCESS; return program; ERROR_CLEAN_PROGRAM_AND_BINARIES: if (program->binaries) for (i = 0; i < num_devices; ++i) POCL_MEM_FREE(program->binaries[i]); POCL_MEM_FREE(program->binaries); POCL_MEM_FREE(program->binary_sizes); if (program->pocl_binaries) for (i = 0; i < num_devices; ++i) POCL_MEM_FREE(program->pocl_binaries[i]); POCL_MEM_FREE(program->pocl_binaries); POCL_MEM_FREE(program->pocl_binary_sizes); /*ERROR_CLEAN_PROGRAM:*/ POCL_MEM_FREE(program); ERROR: POCL_MEM_FREE(unique_devlist); if(errcode_ret != NULL) { *errcode_ret = errcode; } return NULL; }