/* Copyright (C) 2024 Aiden Gall This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "util.h" #include #include #include #include #include cl_platform_id *get_platforms(cl_uint *num_platforms); cl_device_id *get_devices(cl_platform_id platform, cl_uint *num_devices); cl_program compile_spirv_program(cl_context context, cl_device_id device, const void *spirv_start, size_t spirv_size); const char *cl_strerror(cl_int err); cl_platform_id * get_platforms(cl_uint *const num_platforms) { cl_int err; cl_platform_id *platforms; cl_uint len; err = clGetPlatformIDs(0, NULL, &len); if (err != CL_SUCCESS) die("clGetPlatformIDs: %s\n", cl_strerror(err)); warn("number of platforms = %d\n", len); if (len < 1) die("clGetPlatformIDs: No OpenCL platforms\n"); platforms = calloc(len, sizeof(*platforms)); if (!platforms) die("calloc: Out of memory\n"); err = clGetPlatformIDs(len, platforms, NULL); if (err != CL_SUCCESS) die("clGetPlatformIDs: %s\n", cl_strerror(err)); *num_platforms = len; return platforms; } cl_device_id * get_devices(const cl_platform_id platform, cl_uint *const num_devices) { cl_int err; cl_device_id *devices; cl_uint len; err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 0, NULL, &len); if (err != CL_SUCCESS) die("clGetDeviceIDs: %s\n", cl_strerror(err)); warn("number of devices in platform = %d\n", len); if (len < 1) die("clGetDeviceIDs: No OpenCL devices in platform\n"); devices = calloc(len, sizeof(*devices)); if (!devices) die("calloc: Out of memory\n"); err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, len, devices, NULL); if (err != CL_SUCCESS) die("clGetDeviceIDs: %s\n", cl_strerror(err)); *num_devices = len; return devices; } cl_program compile_spirv_program(const cl_context context, const cl_device_id device, const void *const spirv_start, const size_t spirv_size) { cl_int err, build_err; cl_program program; program = clCreateProgramWithIL(context, spirv_start, spirv_size, &err); if (err != CL_SUCCESS) die("clCreateProgramWithIL: %s\n", cl_strerror(err)); build_err = clBuildProgram(program, 1, &device, NULL, NULL, NULL); if (build_err != CL_SUCCESS) { cl_char *log; size_t buffer_size; err = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &buffer_size); if (err != CL_SUCCESS) die("clGetProgramBuildInfo: %s\n", cl_strerror(err)); if (buffer_size < 1) die("clGetProgramBuildInfo: " "Build log buffer is empty\n"); log = calloc(buffer_size, sizeof(*log)); if (!log) die("calloc: Out of memory\n"); err = clGetProgramBuildInfo( program, device, CL_PROGRAM_BUILD_LOG, sizeof(*log) * buffer_size, log, NULL); if (err != CL_SUCCESS) die("clGetProgramBuildInfo: %s\n", cl_strerror(err)); efwrite(log, sizeof(*log), buffer_size, stderr); free(log); die("\nclBuildProgram: %s\n", cl_strerror(build_err)); } return program; } const char * cl_strerror(const cl_int err) { switch (err) { case CL_SUCCESS: return "CL_SUCCESS"; case CL_DEVICE_NOT_FOUND: return "CL_DEVICE_NOT_FOUND"; case CL_DEVICE_NOT_AVAILABLE: return "CL_DEVICE_NOT_AVAILABLE"; case CL_COMPILER_NOT_AVAILABLE: return "CL_COMPILER_NOT_AVAILABLE"; case CL_MEM_OBJECT_ALLOCATION_FAILURE: return "CL_MEM_OBJECT_ALLOCATION_FAILURE"; case CL_OUT_OF_RESOURCES: return "CL_OUT_OF_RESOURCES"; case CL_OUT_OF_HOST_MEMORY: return "CL_OUT_OF_HOST_MEMORY"; case CL_PROFILING_INFO_NOT_AVAILABLE: return "CL_PROFILING_INFO_NOT_AVAILABLE"; case CL_MEM_COPY_OVERLAP: return "CL_MEM_COPY_OVERLAP"; case CL_IMAGE_FORMAT_MISMATCH: return "CL_IMAGE_FORMAT_MISMATCH"; case CL_IMAGE_FORMAT_NOT_SUPPORTED: return "CL_IMAGE_FORMAT_NOT_SUPPORTED"; case CL_BUILD_PROGRAM_FAILURE: return "CL_BUILD_PROGRAM_FAILURE"; case CL_MAP_FAILURE: return "CL_MAP_FAILURE"; case CL_INVALID_VALUE: return "CL_INVALID_VALUE"; case CL_INVALID_DEVICE_TYPE: return "CL_INVALID_DEVICE_TYPE"; case CL_INVALID_PLATFORM: return "CL_INVALID_PLATFORM"; case CL_INVALID_DEVICE: return "CL_INVALID_DEVICE"; case CL_INVALID_CONTEXT: return "CL_INVALID_CONTEXT"; case CL_INVALID_QUEUE_PROPERTIES: return "CL_INVALID_QUEUE_PROPERTIES"; case CL_INVALID_COMMAND_QUEUE: return "CL_INVALID_COMMAND_QUEUE"; case CL_INVALID_HOST_PTR: return "CL_INVALID_HOST_PTR"; case CL_INVALID_MEM_OBJECT: return "CL_INVALID_MEM_OBJECT"; case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR: return "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR"; case CL_INVALID_IMAGE_SIZE: return "CL_INVALID_IMAGE_SIZE"; case CL_INVALID_SAMPLER: return "CL_INVALID_SAMPLER"; case CL_INVALID_BINARY: return "CL_INVALID_BINARY"; case CL_INVALID_BUILD_OPTIONS: return "CL_INVALID_BUILD_OPTIONS"; case CL_INVALID_PROGRAM: return "CL_INVALID_PROGRAM"; case CL_INVALID_PROGRAM_EXECUTABLE: return "CL_INVALID_PROGRAM_EXECUTABLE"; case CL_INVALID_KERNEL_NAME: return "CL_INVALID_KERNEL_NAME"; case CL_INVALID_KERNEL_DEFINITION: return "CL_INVALID_KERNEL_DEFINITION"; case CL_INVALID_KERNEL: return "CL_INVALID_KERNEL"; case CL_INVALID_ARG_INDEX: return "CL_INVALID_ARG_INDEX"; case CL_INVALID_ARG_VALUE: return "CL_INVALID_ARG_VALUE"; case CL_INVALID_ARG_SIZE: return "CL_INVALID_ARG_SIZE"; case CL_INVALID_KERNEL_ARGS: return "CL_INVALID_KERNEL_ARGS"; case CL_INVALID_WORK_DIMENSION: return "CL_INVALID_WORK_DIMENSION"; case CL_INVALID_WORK_GROUP_SIZE: return "CL_INVALID_WORK_GROUP_SIZE"; case CL_INVALID_WORK_ITEM_SIZE: return "CL_INVALID_WORK_ITEM_SIZE"; case CL_INVALID_GLOBAL_OFFSET: return "CL_INVALID_GLOBAL_OFFSET"; case CL_INVALID_EVENT_WAIT_LIST: return "CL_INVALID_EVENT_WAIT_LIST"; case CL_INVALID_EVENT: return "CL_INVALID_EVENT"; case CL_INVALID_OPERATION: return "CL_INVALID_OPERATION"; case CL_INVALID_GL_OBJECT: return "CL_INVALID_GL_OBJECT"; case CL_INVALID_BUFFER_SIZE: return "CL_INVALID_BUFFER_SIZE"; case CL_INVALID_MIP_LEVEL: return "CL_INVALID_MIP_LEVEL"; case CL_INVALID_GLOBAL_WORK_SIZE: return "CL_INVALID_GLOBAL_WORK_SIZE"; #ifdef CL_VERSION_1_1 case CL_MISALIGNED_SUB_BUFFER_OFFSET: return "CL_MISALIGNED_SUB_BUFFER_OFFSET"; case CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST: return "CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST"; case CL_INVALID_PROPERTY: return "CL_INVALID_PROPERTY"; #endif #ifdef CL_VERSION_1_2 case CL_COMPILE_PROGRAM_FAILURE: return "CL_COMPILE_PROGRAM_FAILURE"; case CL_LINKER_NOT_AVAILABLE: return "CL_LINKER_NOT_AVAILABLE"; case CL_LINK_PROGRAM_FAILURE: return "CL_LINK_PROGRAM_FAILURE"; case CL_DEVICE_PARTITION_FAILED: return "CL_DEVICE_PARTITION_FAILED"; case CL_KERNEL_ARG_INFO_NOT_AVAILABLE: return "CL_KERNEL_ARG_INFO_NOT_AVAILABLE"; case CL_INVALID_IMAGE_DESCRIPTOR: return "CL_INVALID_IMAGE_DESCRIPTOR"; case CL_INVALID_COMPILER_OPTIONS: return "CL_INVALID_COMPILER_OPTIONS"; case CL_INVALID_LINKER_OPTIONS: return "CL_INVALID_LINKER_OPTIONS"; case CL_INVALID_DEVICE_PARTITION_COUNT: return "CL_INVALID_DEVICE_PARTITION_COUNT"; #endif #ifdef CL_VERSION_2_0 case CL_INVALID_PIPE_SIZE: return "CL_INVALID_PIPE_SIZE"; case CL_INVALID_DEVICE_QUEUE: return "CL_INVALID_DEVICE_QUEUE"; #endif #ifdef CL_VERSION_2_2 case CL_INVALID_SPEC_ID: return "CL_INVALID_SPEC_ID"; case CL_MAX_SIZE_RESTRICTION_EXCEEDED: return "CL_MAX_SIZE_RESTRICTION_EXCEEDED"; #endif default: return "OpenCL unknown error"; } }