int piglit_cl_get_device_version(cl_device_id device) { char* version_string; const char *version_number_string; int scanf_count; int major; int minor; /* * Returned format: * OpenCL<space><major_version.minor_version><space><platform-specific information> */ version_string = piglit_cl_get_device_info(device, CL_DEVICE_VERSION); /* skip to version number */ version_number_string = version_string + 6; /* Interpret version number */ scanf_count = sscanf(version_number_string, "%i.%i", &major, &minor); if (scanf_count != 2) { printf("Unable to interpret CL_DEVICE_VERSION string: %s\n", version_string); free(version_string); piglit_report_result(PIGLIT_FAIL); } free(version_string); return 10*major+minor; }
/* Print test configuration */ static void print_test_info(const struct piglit_cl_test_config_header* config, int version, const cl_platform_id platform_id, const cl_device_id device_id) { if(config->run_per_platform || config->run_per_device) { char* platform_name; platform_name = piglit_cl_get_platform_info(platform_id, CL_PLATFORM_NAME); printf("# Running on:\n" "# Platform: %s\n", platform_name); if(config->run_per_device) { char* device_name = piglit_cl_get_device_info(device_id, CL_DEVICE_NAME); printf("# Device: %s\n", device_name); free(device_name); } printf("# OpenCL version: %d.%d\n", version/10, version%10); free(platform_name); } else { // print nothing } }
bool piglit_cl_is_device_extension_supported(cl_device_id device, const char *name) { char* extensions = piglit_cl_get_device_info(device, CL_DEVICE_EXTENSIONS); bool supported = piglit_is_extension_in_string(extensions, name); free(extensions); return supported; }
bool piglit_cl_framework_check_local_work_size( cl_device_id device_id, size_t *local_work_size) { unsigned i; size_t workgroup_size = 1; size_t *max_workgroup_size = piglit_cl_get_device_info(device_id, CL_DEVICE_MAX_WORK_GROUP_SIZE); size_t *max_workitem_sizes = piglit_cl_get_device_info(device_id, CL_DEVICE_MAX_WORK_ITEM_SIZES); bool ret = true; if (!local_work_size) { goto out; } if (!max_workgroup_size || !max_workitem_sizes) { ret = false; goto out; } for (i = 0; i < 3; i++) { size_t local_size = local_work_size[i]; if (local_size > max_workitem_sizes[i]) { ret = false; goto out; } if (local_size > 0) { workgroup_size *= local_size; } } if (workgroup_size > *max_workgroup_size) { ret = false; } out: free(max_workgroup_size); free(max_workitem_sizes); return ret; }
bool piglit_cl_get_device_image_support(cl_device_id device) { bool ret = false; cl_bool *image_support = piglit_cl_get_device_info(device, CL_DEVICE_IMAGE_SUPPORT); if (image_support) ret = *image_support; free(image_support); return ret; }
bool piglit_cl_get_device_arg(const int argc, const char** argv, cl_platform_id platform_id, cl_device_id* device_id) { int i; const char* arg_value; /* First check argument then environment */ arg_value = piglit_cl_get_arg_value(argc, argv, "device"); if(arg_value == NULL) { arg_value = getenv("PIGLIT_CL_DEVICE"); } if(arg_value != NULL) { unsigned int num_devices; cl_device_id* device_ids; num_devices = piglit_cl_get_device_ids(platform_id, CL_DEVICE_TYPE_ALL, &device_ids); for(i = 0; i < num_devices; i++) { char* device_name = piglit_cl_get_device_info(device_ids[i], CL_DEVICE_NAME); if(!strncmp(arg_value, device_name, strlen(arg_value))) { *device_id = device_ids[i]; free(device_ids); free(device_name); return true; } free(device_name); } free(device_ids); fprintf(stderr, "Could not find device: %s\n", arg_value); piglit_report_result(PIGLIT_WARN); } return false; }
bool check_device_extensions(cl_device_id device_id, char* extensions) { char* pch; if (!extensions) return true; pch = strtok(extensions, " "); while(pch != NULL) { if( strlen(pch) > 0 && !piglit_cl_is_device_extension_supported(device_id, pch)) { char* device_name = piglit_cl_get_device_info(device_id, CL_DEVICE_NAME); printf("\n# Skipping device %s because extension %s is not supported.\n\n", device_name, pch); free(device_name); return false; } pch = strtok(NULL, " "); } return true; }
enum piglit_result piglit_cl_test(const int argc, const char** argv, const struct piglit_cl_api_test_config* config, const struct piglit_cl_api_test_env* env) { #if defined(CL_VERSION_1_2) enum piglit_result result = PIGLIT_PASS; int i; cl_program_binary_type* binary_type; cl_program compiled_programs[2]; cl_program function_prog; cl_program kernel_prog; cl_program linked_prog; /* Create compiled program */ function_prog = compile_program(env->context->cl_ctx, env->context->num_devices, env->context->device_ids, 1, &strings[0], "function program"); kernel_prog = compile_program(env->context->cl_ctx, env->context->num_devices, env->context->device_ids, 2, &strings[1], "kernel program"); if (!function_prog || !kernel_prog) { clReleaseProgram(function_prog); clReleaseProgram(kernel_prog); return PIGLIT_FAIL; } compiled_programs[0] = function_prog; compiled_programs[1] = kernel_prog; /*** Normal usage ***/ test(env->context->cl_ctx, env->context->num_devices, env->context->device_ids, "-create-library", 1, compiled_programs, NULL, NULL, &linked_prog, CL_SUCCESS, &result, "Link program as library"); for(i = 0; i < env->context->num_devices; ++i) { binary_type = piglit_cl_get_program_build_info(linked_prog, env->context->device_ids[i], CL_PROGRAM_BINARY_TYPE); if (*binary_type != CL_PROGRAM_BINARY_TYPE_LIBRARY) { piglit_merge_result(&result, PIGLIT_FAIL); fprintf(stderr, "Failed: binary is not of type CL_PROGRAM_BINARY_TYPE_LIBRARY.\n"); } free(binary_type); } clReleaseProgram(linked_prog); test(env->context->cl_ctx, env->context->num_devices, env->context->device_ids, "", 2, compiled_programs, NULL, NULL, &linked_prog, CL_SUCCESS, &result, "Link program as executable"); for(i = 0; i < env->context->num_devices; ++i) { binary_type = piglit_cl_get_program_build_info(linked_prog, env->context->device_ids[i], CL_PROGRAM_BINARY_TYPE); if (*binary_type != CL_PROGRAM_BINARY_TYPE_EXECUTABLE) { piglit_merge_result(&result, PIGLIT_FAIL); fprintf(stderr, "Failed: binary is not of type CL_PROGRAM_BINARY_TYPE_EXECUTABLE.\n"); } free(binary_type); } /*** Errors ***/ /* * CL_INVALID_VALUE if device_list is NULL and num_devices is greater than * zero, or if device_list is not NULL and num_devices is zero */ test(env->context->cl_ctx, env->context->num_devices, NULL, "", 2, compiled_programs, NULL, NULL, NULL, CL_INVALID_VALUE, &result, "Trigger CL_INVALID_VALUE if device_list is NULL and num_devices is greater than zero"); test(env->context->cl_ctx, 0, env->context->device_ids, "", 2, compiled_programs, NULL, NULL, NULL, CL_INVALID_VALUE, &result, "Trigger CL_INVALID_VALUE if device_list is not NULL and num_devices is zero"); /* * CL_INVALID_VALUE if num_input_programs is zero and input_programs is NULL * or if num_input_programs is zero and input_programs is not NULL * or if num_input_programs is not zero and input_programs is NULL */ test(env->context->cl_ctx, env->context->num_devices, env->context->device_ids, "", 0, NULL, NULL, NULL, NULL, CL_INVALID_VALUE, &result, "Trigger CL_INVALID_VALUE if num_input_programs is zero and input_programs is NULL"); test(env->context->cl_ctx, env->context->num_devices, env->context->device_ids, "", 0, compiled_programs, NULL, NULL, NULL, CL_INVALID_VALUE, &result, "Trigger CL_INVALID_VALUE if num_input_programs is zero and input_programs is not NULL"); test(env->context->cl_ctx, env->context->num_devices, env->context->device_ids, "", 2, NULL, NULL, NULL, NULL, CL_INVALID_VALUE, &result, "Trigger CL_INVALID_VALUE if num_input_programs is not zero and input_programs is NULL"); /* * CL_INVALID_PROGRAM if programs specified in input_programs are not valid program objects */ /* * CL_INVALID_VALUE if pfn_notify is NULL but user_data is not NULL. */ test(env->context->cl_ctx, env->context->num_devices, env->context->device_ids, "", 2, compiled_programs, NULL, &i, NULL, CL_INVALID_VALUE, &result, "Trigger CL_INVALID_VALUE if pfn_notify is NULL but user_data is not NULL"); /* * CL_INVALID_DEVICE if OpenCL devices listed in device_list are not in the * list of devices associated with context */ /* * CL_INVALID_LINKER_OPTIONS if the linker options specified by options are * invalid */ test(env->context->cl_ctx, env->context->num_devices, env->context->device_ids, "-invalid- --link-- options", 2, compiled_programs, NULL, NULL, NULL, CL_INVALID_LINKER_OPTIONS, &result, "Trigger CL_INVALID_LINKER_OPTIONS if the linker options specified by options are invalid"); /* * CL_INVALID_OPERATION if the compilation or build of a program executable * for any of the devices listed in device_list by a previous call to * clCompileProgram or clBuildProgram for program has not completed */ /* * CL_INVALID_OPERATION if the rules for devices containing compiled binaries * or libraries as described in input_programs argument above are not followed */ compiled_programs[0] = linked_prog; test(env->context->cl_ctx, env->context->num_devices, env->context->device_ids, "", 2, compiled_programs, NULL, NULL, NULL, CL_INVALID_OPERATION, &result, "Trigger CL_INVALID_OPERATION if the rules for devices containing compiled binaries or libraries as described in input_programs argument above are not followed"); /* * CL_LINKER_NOT_AVAILABLE if a linker is not available * i.e. CL_DEVICE_LINKER_AVAILABLE specified in the table of allowed values * for param_name for clGetDeviceInfo is set to CL_FALSE. */ for(i = 0; i < env->context->num_devices; ++i) { cl_bool* linker_available = piglit_cl_get_device_info(env->context->device_ids[i], CL_DEVICE_LINKER_AVAILABLE); if(!(*linker_available)) { test(env->context->cl_ctx, env->context->num_devices, env->context->device_ids, "", 2, compiled_programs, NULL, NULL, NULL, CL_LINKER_NOT_AVAILABLE, &result, "Trigger CL_LINKER_NOT_AVAILABLE if a linker is not available"); } free(linker_available); } /* Release programs */ clReleaseProgram(function_prog); clReleaseProgram(kernel_prog); clReleaseProgram(linked_prog); /* * CL_LINK_PROGRAM_FAILURE if there is a failure to link the compiled binaries * and/or libraries. */ function_prog = compile_program(env->context->cl_ctx, env->context->num_devices, env->context->device_ids, 1, &strings[0], "2nd function program"); kernel_prog = compile_program(env->context->cl_ctx, env->context->num_devices, env->context->device_ids, 2, &strings[2], "2nd kernel program"); if (!function_prog || !kernel_prog) { result = PIGLIT_FAIL; } else { compiled_programs[0] = function_prog; compiled_programs[1] = kernel_prog; test(env->context->cl_ctx, env->context->num_devices, env->context->device_ids, "", 2, compiled_programs, NULL, NULL, NULL, CL_LINK_PROGRAM_FAILURE, &result, "Trigger CL_LINK_PROGRAM_FAILURE if there is a failure to link the compiled binaries and/or libraries"); } /* Release programs */ clReleaseProgram(function_prog); clReleaseProgram(kernel_prog); return result; #else return PIGLIT_SKIP; #endif }
cl_program piglit_cl_build_program_with_binary_extended(piglit_cl_context context, size_t* lenghts, unsigned char** binaries, const char* options, bool fail) { cl_int errNo; cl_program program; cl_int* binary_status = malloc(sizeof(cl_int) * context->num_devices); program = clCreateProgramWithBinary(context->cl_ctx, context->num_devices, context->device_ids, lenghts, (const unsigned char**)binaries, binary_status, &errNo); if(errNo != CL_SUCCESS) { int i; fprintf(stderr, "Could not create program with binary: %s\n", piglit_cl_get_error_name(errNo)); printf("Create error with binaries:\n"); for(i = 0; i < context->num_devices; i++) { char* device_name = piglit_cl_get_device_info(context->device_ids[i], CL_DEVICE_NAME); printf("Error for %s: %s\n", device_name, piglit_cl_get_error_name(binary_status[i])); free(device_name); } free(binary_status); return NULL; } free(binary_status); errNo = clBuildProgram(program, context->num_devices, context->device_ids, options, NULL, NULL); if( (!fail && errNo != CL_SUCCESS) || ( fail && errNo == CL_SUCCESS)) { int i; fprintf(stderr, !fail ? "Could not build program: %s\n" : "Program built when it should have failed: %s\n", piglit_cl_get_error_name(errNo)); printf("Build log for binaries.\n"); for(i = 0; i < context->num_devices; i++) { char* device_name = piglit_cl_get_device_info(context->device_ids[i], CL_DEVICE_NAME); char* log = piglit_cl_get_program_build_info(program, context->device_ids[i], CL_PROGRAM_BUILD_LOG); printf("Build log for device %s:\n -------- \n%s\n -------- \n", device_name, log); free(device_name); free(log); } clReleaseProgram(program); return NULL; } return program; }
cl_program piglit_cl_build_program_with_source_extended(piglit_cl_context context, cl_uint count, char** strings, const char* options, bool fail) { cl_int errNo; cl_program program; program = clCreateProgramWithSource(context->cl_ctx, count, (const char**)strings, NULL, &errNo); if(errNo != CL_SUCCESS) { fprintf(stderr, "Could not create program with source: %s\n", piglit_cl_get_error_name(errNo)); return NULL; } errNo = clBuildProgram(program, context->num_devices, context->device_ids, options, NULL, NULL); if( (!fail && errNo != CL_SUCCESS) || ( fail && errNo == CL_SUCCESS)) { int i; fprintf(stderr, !fail ? "Could not build program: %s\n" : "Program built when it should have failed: %s\n", piglit_cl_get_error_name(errNo)); /*printf("Build log for source:\n"); for(i = 0; i < count; i++) { printf("%s\n", strings[i]); }*/ for(i = 0; i < context->num_devices; i++) { char* device_name = piglit_cl_get_device_info(context->device_ids[i], CL_DEVICE_NAME); char* log = piglit_cl_get_program_build_info(program, context->device_ids[i], CL_PROGRAM_BUILD_LOG); printf("Build log for device %s:\n -------- \n%s\n -------- \n", device_name, log); free(device_name); free(log); } clReleaseProgram(program); return NULL; } return program; }
enum piglit_result piglit_cl_test(const int argc, const char **argv, const struct piglit_cl_api_test_config* config, const struct piglit_cl_api_test_env* env) { #if defined(CL_VERSION_1_2) enum piglit_result result = PIGLIT_PASS; cl_int err; #define IMG_WIDTH 4 #define IMG_HEIGHT 4 #define IMG_DATA_SIZE 4 #define IMG_BUFFER_SIZE IMG_WIDTH * IMG_HEIGHT * IMG_DATA_SIZE unsigned char img_buf[IMG_BUFFER_SIZE] = {0}; unsigned char dst_buf[IMG_BUFFER_SIZE] = {0}; unsigned char exp_buf[IMG_BUFFER_SIZE] = {0}; int pattern[4] = {129, 33, 77, 255}; size_t origin[3] = {0, 0, 0}; size_t region[3] = {2, 2, 1}; size_t tmp; cl_event event; cl_mem image; cl_image_format img_format; cl_image_desc img_desc = {0}; cl_command_queue queue = env->context->command_queues[0]; int i; cl_bool *image_support = piglit_cl_get_device_info(env->context->device_ids[0], CL_DEVICE_IMAGE_SUPPORT); if (!*image_support) { fprintf(stderr, "No image support\n"); free(image_support); return PIGLIT_SKIP; } img_format.image_channel_order = CL_RGBA; img_format.image_channel_data_type = CL_UNSIGNED_INT8; img_desc.image_type = CL_MEM_OBJECT_IMAGE2D; img_desc.image_width = IMG_WIDTH; img_desc.image_height = IMG_HEIGHT; img_desc.buffer = NULL; /*** Normal usage ***/ image = clCreateImage(env->context->cl_ctx, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, &img_format, &img_desc, &img_buf, &err); if(!piglit_cl_check_error(err, CL_SUCCESS)) { fprintf(stderr, "Failed (error code: %s): Creating an image\n", piglit_cl_get_error_name(err)); return PIGLIT_FAIL; } if (!test(queue, image, pattern, origin, region, 0, NULL, NULL, CL_SUCCESS, &result, "Enqueuing the image to be filled")) { return PIGLIT_FAIL; } region[0] = IMG_WIDTH; region[1] = IMG_HEIGHT; err = clEnqueueReadImage(queue, image, 1, origin, region, 0, 0, dst_buf, 0, NULL, NULL); if(!piglit_cl_check_error(err, CL_SUCCESS)) { fprintf(stderr, "Failed (error code: %s): Reading image\n", piglit_cl_get_error_name(err)); return PIGLIT_FAIL; } /* * fill the host buffer with the pattern * for exemple : pattern == 1234 * * 12341234abcdabcd * 12341234abcdabcd * abcdabcdabcdabcd * abcdabcdabcdabcd */ exp_buf[0] = pattern[0]; exp_buf[1] = pattern[1]; exp_buf[2] = pattern[2]; exp_buf[3] = pattern[3]; memcpy(exp_buf + (IMG_DATA_SIZE * 1), exp_buf, IMG_DATA_SIZE); memcpy(exp_buf + (IMG_DATA_SIZE * 4), exp_buf, IMG_DATA_SIZE); memcpy(exp_buf + (IMG_DATA_SIZE * 5), exp_buf, IMG_DATA_SIZE); for (i = 0; i < sizeof(dst_buf) / sizeof(dst_buf[0]); ++i) { if (!piglit_cl_probe_integer(dst_buf[i], exp_buf[i], 0)) { fprintf(stderr, "Error at %d: got %d, expected %d\n", i, dst_buf[i], exp_buf[i]); return PIGLIT_FAIL; } } /*** Errors ***/ /* * CL_INVALID_COMMAND_QUEUE if command_queue is not a valid command-queue. */ test(NULL, image, pattern, origin, region, 0, NULL, NULL, CL_INVALID_COMMAND_QUEUE, &result, "CL_INVALID_COMMAND_QUEUE if command_queue is not a valid command-queue"); /* * CL_INVALID_CONTEXT if the context associated with command_queue and * image are not the same or if the context associated with command_queue * and events in event_wait_list are not the same. */ { piglit_cl_context context; cl_int err; context = piglit_cl_create_context(env->platform_id, env->context->device_ids, 1); if (context) { event = clCreateUserEvent(context->cl_ctx, &err); if (err == CL_SUCCESS) { err = clSetUserEventStatus(event, CL_COMPLETE); if (err == CL_SUCCESS) { test(context->command_queues[0], image, pattern, origin, region, 0, NULL, NULL, CL_INVALID_CONTEXT, &result, "CL_INVALID_CONTEXT if the context associated with command_queue and image are not the same"); test(queue, image, pattern, origin, region, 1, &event, NULL, CL_INVALID_CONTEXT, &result, "CL_INVALID_CONTEXT if the context associated with command_queue and events in event_wait_list are not the same"); } else { fprintf(stderr, "Could not set event status.\n"); piglit_merge_result(&result, PIGLIT_WARN); } clReleaseEvent(event); } else { fprintf(stderr, "Could not create user event.\n"); piglit_merge_result(&result, PIGLIT_WARN); } piglit_cl_release_context(context); } else { fprintf(stderr, "Could not test triggering CL_INVALID_CONTEXT.\n"); piglit_merge_result(&result, PIGLIT_WARN); } } /* * CL_INVALID_MEM_OBJECT if image is not a valid buffer object. */ test(queue, NULL, pattern, origin, region, 0, NULL, NULL, CL_INVALID_MEM_OBJECT, &result, "CL_INVALID_MEM_OBJECT if image is not a valid buffer object"); /* * CL_INVALID_VALUE if fill_color is NULL. */ test(queue, image, NULL, origin, region, 0, NULL, NULL, CL_INVALID_VALUE, &result, "CL_INVALID_VALUE if fill_color is NULL"); /* * CL_INVALID_VALUE if the region being written specified by origin and * region is out of bounds or if ptr is a NULL value. */ tmp = origin[0]; origin[0] = IMG_WIDTH + 1; test(queue, image, pattern, origin, region, 0, NULL, NULL, CL_INVALID_VALUE, &result, "CL_INVALID_VALUE if the region being written specified by origin and region is out of bounds (origin)"); origin[0] = tmp; tmp = region[0]; region[0] = IMG_WIDTH + 1; test(queue, image, pattern, origin, region, 0, NULL, NULL, CL_INVALID_VALUE, &result, "CL_INVALID_VALUE if the region being written specified by origin and region is out of bounds (region)"); region[0] = tmp; test(queue, image, pattern, NULL, region, 0, NULL, NULL, CL_INVALID_VALUE, &result, "CL_INVALID_VALUE if ptr is a NULL value (origin)"); test(queue, image, pattern, origin, NULL, 0, NULL, NULL, CL_INVALID_VALUE, &result, "CL_INVALID_VALUE if ptr is a NULL value (region)"); /* * CL_INVALID_VALUE if values in origin and region do not follow rules * described in the argument description for origin and region. */ tmp = origin[2]; origin[2] = 1; test(queue, image, pattern, origin, region, 0, NULL, NULL, CL_INVALID_VALUE, &result, "CL_INVALID_VALUE if values in origin do not follow rules described in the argument description for origin"); origin[2] = tmp; tmp = region[2]; region[2] = 0; test(queue, image, pattern, origin, region, 0, NULL, NULL, CL_INVALID_VALUE, &result, "CL_INVALID_VALUE if values in region do not follow rules described in the argument description for region"); region[2] = tmp; /* * CL_INVALID_EVENT_WAIT_LIST if event_wait_list is NULL and * num_events_in_wait_list > 0, or event_wait_list is not NULL and * num_events_in_wait_list is 0, or if event objects in event_wait_list * are not valid events. */ event = NULL; test(queue, image, pattern, origin, region, 1, NULL, NULL, CL_INVALID_EVENT_WAIT_LIST, &result, "CL_INVALID_EVENT_WAIT_LIST if event_wait_list is NULL and num_events_in_wait_list > 0"); test(queue, image, pattern, origin, region, 0, &event, NULL, CL_INVALID_EVENT_WAIT_LIST, &result, "CL_INVALID_EVENT_WAIT_LIST if event_wait_list is not NULL and num_events_in_wait_list is 0"); test(queue, image, pattern, origin, region, 1, &event, NULL, CL_INVALID_EVENT_WAIT_LIST, &result, "CL_INVALID_EVENT_WAIT_LIST if event objects in event_wait_list are not valid events"); /* * CL_INVALID_IMAGE_SIZE if image dimensions (image width, height, specified * or compute row and/or slice pitch) for image are not supported by device * associated with queue. */ /* This is a per device test, clCreateImage would have failed before */ /* * CL_INVALID_IMAGE_FORMAT if image format (image channel order and data type) * for image are not supported by device associated with queue. */ /* This is a per device test, clCreateImage would have failed before */ free(image_support); clReleaseMemObject(image); return result; #else return PIGLIT_SKIP; #endif }
enum piglit_result piglit_cl_test(const int argc, const char** argv, const struct piglit_cl_api_test_config* config, const struct piglit_cl_api_test_env* env) { enum piglit_result result = PIGLIT_PASS; int i; cl_int errNo; cl_program program; cl_program temp_program; cl_kernel kernel; /*** Normal usage ***/ /* Create program */ /* with binary */ //TODO /* with source */ program = clCreateProgramWithSource(env->context->cl_ctx, 2, strings, NULL, &errNo); if(!piglit_cl_check_error(errNo, CL_SUCCESS)) { fprintf(stderr, "Failed (error code: %s): Create program with source.\n", piglit_cl_get_error_name(errNo)); return PIGLIT_FAIL; } test(program, env->context->num_devices, env->context->device_ids, "", NULL, NULL, CL_SUCCESS, &result, "Build program"); // TODO: test callback /*** Errors ***/ /* * CL_INVALID_PROGRAM if program is not a valid program object. */ test(NULL, env->context->num_devices, env->context->device_ids, "", NULL, NULL, CL_INVALID_PROGRAM, &result, "Trigger CL_INVALID_PROGRAM if program is not a valid program object"); /* * CL_INVALID_VALUE if device_list is NULL and num_devices is greater than * zero, or if device_list is not NULL and num_devices is zero. */ test(program, 1, NULL, "", NULL, NULL, CL_INVALID_VALUE, &result, "Trigger CL_INVALID_VALUE if device_list is NULL and num_devices is greater than zero"); test(program, 0, env->context->device_ids, "", NULL, NULL, CL_INVALID_VALUE, &result, "Trigger CL_INVALID_VALUE if device_list is not NULL and num_devices is zero"); /* * CL_INVALID_VALUE if pfn_notify is NULL but user_data is not NULL. */ test(program, env->context->num_devices, env->context->device_ids, "", NULL, &result, CL_INVALID_VALUE, &result, "Trigger CL_INVALID_VALUE if pfn_notify is NULL and user_data is not NULL"); /* * CL_INVALID_DEVICE if OpenCL devices listed in device_list are not in the * list of devices associated with program. * * TODO */ /* * CL_INVALID_BINARY if program is created with * clCreateWithProgramWithBinary and devices listed in device_list do not * have a valid program binary loaded. * * TODO */ /* * CL_INVALID_BUILD_OPTIONS if the build options specified by options are * invalid. */ test(program, env->context->num_devices, env->context->device_ids, "-invalid- --build-- options", NULL, NULL, CL_INVALID_BUILD_OPTIONS, &result, "Trigger CL_INVALID_BUILD_OPTIONS if the build options specified by options are invalid"); /* * CL_INVALID_OPERATION if the build of a program executable for any of the * devices listed in device_list by a previous call to clBuildProgram for * program has not completed. * * TODO */ /* * CL_COMPILER_NOT_AVAILABLE if program is created with * clCreateProgramWithSource and a compiler is not available i.e. * CL_DEVICE_COMPILER_AVAILABLE specified in the table of OpenCL Device * Queries for clGetDeviceInfo is set to CL_FALSE. * * Note: If this is true for any device, then a normal usage test returns a * false error. */ for(i = 0; i < env->context->num_devices; i++) { cl_bool* compiler_available = piglit_cl_get_device_info(env->context->device_ids[i], CL_DEVICE_COMPILER_AVAILABLE); if(!(*compiler_available)) { test(program, env->context->num_devices, env->context->device_ids, "", NULL, NULL, CL_COMPILER_NOT_AVAILABLE, &result, "Trigger CL_COMPILER_NOT_AVAILABLE if program is created with clCreateProgramWithSource and a compiler is not available"); } free(compiler_available); } /* * CL_BUILD_PROGRAM_FAILURE if there is a failure to build the program * executable. This error will be returned if clBuildProgram does not return * until the build has completed. */ temp_program = clCreateProgramWithSource(env->context->cl_ctx, 1, invalid_strings, NULL, &errNo); if(piglit_cl_check_error(errNo, CL_SUCCESS)) { test(temp_program, env->context->num_devices, env->context->device_ids, "", NULL, NULL, CL_BUILD_PROGRAM_FAILURE, &result, "Trigger CL_BUILD_PROGRAM_FAILURE if there is a failure to build the program executable"); clReleaseProgram(temp_program); } /* * CL_INVALID_OPERATION if there are kernel objects attached to program. */ test(program, env->context->num_devices, env->context->device_ids, "", NULL, NULL, CL_SUCCESS, &result, "Build program"); kernel = clCreateKernel(program, "dummy_kernel", &errNo); if(piglit_cl_check_error(errNo, CL_SUCCESS)) { test(program, env->context->num_devices, env->context->device_ids, "", NULL, NULL, CL_INVALID_OPERATION, &result, "Trigger CL_INVALID_OPERATION if there are kernel objects attached to program"); clReleaseKernel(kernel); } /* * CL_SUCCESS when compiling an empty string */ temp_program = clCreateProgramWithSource(env->context->cl_ctx, 1, empty_strings, NULL, &errNo); if(piglit_cl_check_error(errNo, CL_SUCCESS)) { test(temp_program, env->context->num_devices, env->context->device_ids, "", NULL, NULL, CL_SUCCESS, &result, "CL_SUCCESS when compiling an empty string."); clReleaseProgram(temp_program); } /* * CL_INVALID_OPERATION if program was not created with * clCreateProgramWithSource or clCreateProgramWithBinary. * * Version: 1.2 * * TODO */ clReleaseProgram(program); return result; }
enum piglit_result piglit_cl_test(const int argc, const char** argv, const struct piglit_cl_api_test_config* config, const struct piglit_cl_api_test_env* env) { enum piglit_result result = PIGLIT_PASS; char test_str[1024]; int i; int mask; cl_ulong alloc_size = BUFFER_SIZE; // max alloc size per device >= 128*1024*1024 cl_ulong max_alloc; unsigned char host_buffer[BUFFER_SIZE]; unsigned char host_buffer_read[BUFFER_SIZE]; cl_mem_flags mixed_mem_flags; int num_mem_flags = PIGLIT_CL_ENUM_NUM(cl_mem_flags, env->version); const cl_mem_flags* mem_flags = PIGLIT_CL_ENUM_ARRAY(cl_mem_flags); int num_mutexes = PIGLIT_CL_ENUM_NUM(cl_mem_flags_mutexes, env->version); const cl_mem_flags* mutexes = PIGLIT_CL_ENUM_ARRAY(cl_mem_flags_mutexes); /*** Normal usage ***/ for (i = 0; i < BUFFER_SIZE; i++){ host_buffer[i] = (unsigned char)i; } /* * For each memory flags mix. * There are 2^(num_mem_flags)-1 possible options without * excluding mutually exclusive options. */ for(mask = 1; mask < (1 << num_mem_flags); mask++) { mixed_mem_flags = get_mixed_mem_flags(mask, mem_flags); /* exclude invalid mixes */ if(!mem_flags_valid(mixed_mem_flags, num_mutexes, mutexes)) { continue; } sprintf(test_str, "Create buffer using 0x%X as memory flags", (unsigned int)mixed_mem_flags); if( (mixed_mem_flags & CL_MEM_USE_HOST_PTR) || (mixed_mem_flags & CL_MEM_COPY_HOST_PTR)) { cl_mem buffer; /* test if function returns right values */ test(env->context->cl_ctx, mixed_mem_flags, alloc_size, host_buffer, CL_SUCCESS, &result, test_str); /* test if buffer gets initialized properly */ buffer = clCreateBuffer(env->context->cl_ctx, mixed_mem_flags, alloc_size, host_buffer, NULL); if(buffer) { cl_int errNo; errNo = clEnqueueReadBuffer(env->context->command_queues[0], buffer, true, 0, alloc_size, host_buffer_read, 0, NULL, NULL); if(errNo == CL_SUCCESS) { for(i = 0; i < BUFFER_SIZE; i++) { if(host_buffer[i] != host_buffer_read[i]) { printf("Buffer data was not initialized properly.\n"); fprintf(stderr, "Buffer data was not properly initialized using 0x%X as memory flags.\n", (unsigned int)mixed_mem_flags); piglit_merge_result(&result, PIGLIT_FAIL); break; } } } } } else { test(env->context->cl_ctx, mixed_mem_flags, alloc_size, NULL, CL_SUCCESS, &result, test_str); } } #if defined(CL_VERSION_1_2) if(env->version >= 12) { test(env->context->cl_ctx, 0, // defaults to CL_MEM_READ_WRITE alloc_size, NULL, CL_SUCCESS, &result, "Create buffer using 0 (defaults to CL_MEM_READ_WRITE) as memory flags"); } #endif //CL_VERSION_1_2 /*** Errors ***/ /* * CL_INVALID_CONTEXT if context is not a valid context. */ test(NULL, CL_MEM_READ_WRITE, alloc_size, NULL, CL_INVALID_CONTEXT, &result, "Trigger CL_INVALID_CONTEXT if context is not a valid context"); /* * CL_INVALID_VALUE if values specified in flags are not valid. */ for(mask = 1; mask < (1 << num_mem_flags); mask++) { mixed_mem_flags = get_mixed_mem_flags(mask, mem_flags); /* only invalid mixes */ if(!mem_flags_valid(mixed_mem_flags, num_mutexes, mutexes)) { sprintf(test_str, "Trigger CL_INVALID_VALUE if values specified in flags are not valid (using 0x%X as memory flags)", (unsigned int)mixed_mem_flags); if( (mixed_mem_flags & CL_MEM_USE_HOST_PTR) || (mixed_mem_flags & CL_MEM_COPY_HOST_PTR)) { test(env->context->cl_ctx, mixed_mem_flags, alloc_size, host_buffer, CL_INVALID_VALUE, &result, test_str); } else { test(env->context->cl_ctx, mixed_mem_flags, alloc_size, NULL, CL_INVALID_VALUE, &result, test_str); } } } /* * CL_INVALID_BUFFER_SIZE if size is 0 or is greater than * CL_DEVICE_MAX_MEM_ALLOC_SIZE value specified in table of * OpenCL Device Queries for clGetDeviceInfo for all devices * in context. */ test(env->context->cl_ctx, CL_MEM_READ_WRITE, 0, NULL, CL_INVALID_BUFFER_SIZE, &result, "Trigger CL_INVALID_BUFFER_SIZE if size is 0"); max_alloc = 0; for(i = 0; i < env->context->num_devices; i++) { cl_ulong* max_device_alloc; max_device_alloc = piglit_cl_get_device_info(env->context->device_ids[i], CL_DEVICE_MAX_MEM_ALLOC_SIZE); if(*max_device_alloc > max_alloc) { max_alloc = *max_device_alloc; } free(max_device_alloc); } test(env->context->cl_ctx, CL_MEM_READ_WRITE, max_alloc+1, // if we get to overflow, we're back at 0 and errNo must be the same NULL, CL_INVALID_BUFFER_SIZE, &result, "Trigger CL_INVALID_BUFFER_SIZE if size is greater than CL_DEVICE_MAX_MEM_ALLOC_SIZE"); /* * CL_INVALID_HOST_PTR if host_ptr is NULL and CL_MEM_USE_HOST_PTR * or CL_MEM_COPY_HOST_PTR are set in flags or if host_ptr is not * NULL but CL_MEM_COPY_HOST_PTR or CL_MEM_USE_HOST_PTR are not * set in flags. */ test(env->context->cl_ctx, CL_MEM_USE_HOST_PTR, alloc_size, NULL, CL_INVALID_HOST_PTR, &result, "Trigger CL_INVALID_HOST_PTR if host_ptr is NULL and CL_MEM_USE_HOST_PTR is set in flags"); test(env->context->cl_ctx, CL_MEM_COPY_HOST_PTR, alloc_size, NULL, CL_INVALID_HOST_PTR, &result, "Trigger CL_INVALID_HOST_PTR if host_ptr is NULL and CL_MEM_COPY_HOST_PTR is set in flags"); test(env->context->cl_ctx, CL_MEM_READ_WRITE, alloc_size, host_buffer, CL_INVALID_HOST_PTR, &result, "Trigger CL_INVALID_HOST_PTR if host_ptr is not NULL CL_MEM_USE_HOST_PTR or CL_MEM_COPY_HOST_PTR are not set in flags"); return result; }
/* Run the test(s) */ int piglit_cl_framework_run(int argc, char** argv) { enum piglit_result result = PIGLIT_SKIP; int version = 0; cl_platform_id platform_id = NULL; cl_device_id device_id = NULL; /* Get test configuration */ struct piglit_cl_test_config_header *config = piglit_cl_get_test_config(argc, (const char**)argv, &PIGLIT_CL_DEFAULT_TEST_CONFIG_HEADER); /* Check that config is valid */ // run_per_platform, run_per_device if(config->run_per_platform && config->run_per_device) { fprintf(stderr, "Invalid configuration, only one of run_per_platform and run_per_device can be true.\n"); piglit_report_result(PIGLIT_WARN); } /* Init */ if(config->init_func != NULL) { config->init_func(argc, (const char**)argv, config); } /* Print test name and file */ printf("## Test: %s (%s) ##\n\n", config->name != NULL ? config->name : "", config->_filename); /* Get version to test against */ version = piglit_cl_get_version_arg(argc, (const char **)argv); if(version > 0) { if(version > PIGLIT_CL_VERSION) { printf("Piglit was compiled with lower OpenCL version (%d.%d) than version argument: %d.%d.\n", PIGLIT_CL_VERSION/10, PIGLIT_CL_VERSION%10, version/10, version%10); piglit_report_result(PIGLIT_SKIP); } } else { /* * If version was not provided on the command line, set it to * the version against which Piglit was compiled (PIGLIT_CL_VERSION) */ version = PIGLIT_CL_VERSION; } /* Run the actual test */ if(!(config->run_per_platform || config->run_per_device)) { print_test_info(config, version, NULL, NULL); result = config->_test_run(argc, (const char**)argv, (void*)config, version, NULL, NULL); } else { /* Run tests per platform or device */ int i; regex_t platform_regex; regex_t device_regex; bool platform_defined; unsigned int num_platforms; cl_platform_id* platform_ids; /* Create regexes */ if( config->platform_regex != NULL && regcomp(&platform_regex, config->platform_regex, REG_EXTENDED | REG_NEWLINE)) { fprintf(stderr, "Regex to filter platforms is invalid, ignoring it.\n"); regcomp(&platform_regex, "", REG_EXTENDED | REG_NEWLINE); piglit_merge_result(&result, PIGLIT_WARN); } if( config->device_regex != NULL && regcomp(&device_regex, config->device_regex, REG_EXTENDED | REG_NEWLINE)) { fprintf(stderr, "Regex to filter devices is invalid, ignoring it.\n"); regcomp(&device_regex, "", REG_EXTENDED | REG_NEWLINE); piglit_merge_result(&result, PIGLIT_WARN); } /* check for command-line/environment platform */ platform_defined = piglit_cl_get_platform_arg(argc, (const char**)argv, &platform_id); /* generate platforms list */ if(platform_defined) { /* use platform defined by command-line/environment */ num_platforms = 1; platform_ids = malloc(sizeof(cl_platform_id)); platform_ids[0] = platform_id; } else { /* use all available platforms */ num_platforms = piglit_cl_get_platform_ids(&platform_ids); } /* execute test for each platform in platforms list */ for(i = 0; i < num_platforms; i++) { int final_version = version; int platform_version; platform_id = platform_ids[i]; /* Filter platform */ if(config->platform_regex != NULL) { char* platform_name; platform_name = piglit_cl_get_platform_info(platform_id, CL_PLATFORM_NAME); if(regexec(&platform_regex, platform_name, 0, NULL, 0)) { printf("\n# Skipping platform %s because it does not match platform_regex.\n\n", platform_name); free(platform_name); continue; } free(platform_name); } /* Check platform extensions */ if(!check_platform_extensions(platform_id, config->require_platform_extensions)) { continue; } /* Get platform version */ platform_version = piglit_cl_get_platform_version(platform_id); if(config->run_per_platform) { /* Check platform version */ if(platform_version < final_version) { printf("# Platform supporting only version %d.%d. Running test on that version.\n", platform_version/10, platform_version%10); final_version = platform_version; } /* run test on platform */ print_test_info(config, final_version, platform_id, NULL); piglit_merge_result(&result, config->_test_run(argc, (const char**)argv, (void*)config, final_version, platform_id, NULL)); } else { //config->run_per_device int j; bool device_defined; unsigned int num_devices; cl_device_id* device_ids; /* check for command-line/environment device */ device_defined = piglit_cl_get_device_arg(argc, (const char**)argv, platform_id, &device_id); /* generate devices list */ if(device_defined) { /* use device defined by command-line/environment */ num_devices = 1; device_ids = malloc(sizeof(cl_device_id)); device_ids[0] = device_id; } else { /* use all available devices */ num_devices = piglit_cl_get_device_ids(platform_id, CL_DEVICE_TYPE_ALL, &device_ids); } /* run tests per each device */ for(j = 0; j < num_devices; j++) { int device_version; device_id = device_ids[j]; /* Filter device */ if(config->device_regex != NULL) { char* device_name; device_name = piglit_cl_get_device_info(device_id, CL_DEVICE_NAME); if(regexec(&device_regex, device_name, 0, NULL, 0)) { printf("\n# Skipping device %s because it does not match device_regex.\n\n", device_name); free(device_name); continue; } free(device_name); } /* Check device extensions */ if(!check_device_extensions(device_id, config->require_device_extensions)) { continue; } /* Check platform version */ if(platform_version < final_version) { printf("# Platform supporting only version %d.%d. Running test on that version.\n", platform_version/10, platform_version%10); final_version = platform_version; } /* Check device version */ device_version = piglit_cl_get_device_version(device_id); if(device_version < final_version) { printf("# Device supporting only version %d.%d. Running test on that version.\n", device_version/10, device_version%10); final_version = device_version; } print_test_info(config, version, platform_id, device_id); piglit_merge_result(&result, config->_test_run(argc, (const char**)argv, (void*)config, final_version, platform_id, device_id)); } free(device_ids); } } if(config->platform_regex != NULL) { regfree(&platform_regex); } if(config->device_regex != NULL) { regfree(&device_regex); } free(platform_ids); } /* Clean */ if(config->clean_func != NULL) { config->clean_func(argc, (const char**)argv, config); } /* Report merged result */ printf("# Result:\n"); piglit_report_result(result); /* UNREACHED */ return 1; }