commit deb6c72f2428afd5ca5c69559982073659fabbee
parent b13a64eea668fafb689305a3eae0c1c365c93216
Author: Pollux <pollux@pollux.codes>
Date: Sun, 19 Jan 2025 13:47:20 -0600
refactor: Break up main and better error handling
Signed-off-by: Pollux <pollux@pollux.codes>
Diffstat:
M | src/runcl.c | | | 300 | ++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------- |
1 file changed, 199 insertions(+), 101 deletions(-)
diff --git a/src/runcl.c b/src/runcl.c
@@ -6,6 +6,9 @@
#define DEF_WIDTH 640
#define DEF_HEIGHT 480
+#define MAX_SRC_SIZE 1048576
+#define MAX_PLATFORM_COUNT 16
+#define MAX_PLATFORM_NAME_SIZE 256
#define STR_LITERAL(x) #x
#define STRINGIFY(x) STR_LITERAL(x)
@@ -20,6 +23,8 @@ struct Args {
int img_width;
int img_height;
int platform_index;
+ char *source_file;
+ char *out_file;
};
void print_help() { printf(USAGE "\n"); }
@@ -52,141 +57,267 @@ int parse_args(int argc, char **argv, struct Args *out) {
break;
case 'H':
print_help();
- return 255;
+ exit(0);
case 'v':
print_version();
- return 255;
+ exit(0);
case '?':
- fprintf(stderr, "Error parsing command-line arguments...\n");
- return 1;
+ return -1;
}
}
- if (argc < optind + 2) {
- fprintf(stderr, "Error parsing command-line arguments...\n");
- return 1;
+ if (argc < optind + 2)
+ return -1;
+
+ out->source_file = argv[optind];
+ out->out_file = argv[optind + 1];
+
+ return 0;
+}
+
+int read_source(char *path, char *out, size_t max_size, size_t *source_size) {
+
+ FILE *fp;
+
+ fp = fopen(path, "r");
+ if (!fp) {
+ return -1;
+ }
+
+ *source_size = fread(out, 1, max_size, fp);
+
+ if (!feof(fp)) {
+ return -1;
}
+ fclose(fp);
+
return 0;
}
-int main(int argc, char **argv) {
+int get_device(int platform_index, cl_device_id *device) {
+
+ cl_platform_id platforms[MAX_PLATFORM_COUNT];
+ cl_uint num_platforms;
+ cl_platform_id platform_id;
+
+ char name[MAX_PLATFORM_NAME_SIZE];
- struct Args args;
int res;
- char *source_file = NULL;
- char *out_file = NULL;
+ res = clGetPlatformIDs(MAX_PLATFORM_COUNT, platforms, &num_platforms);
- int data_size_out;
- float *data_out;
+ if (platform_index >= (int)num_platforms) {
+ fprintf(stderr, "Platform index exceeds number of platforms...\n");
+ return -1;
+ }
- cl_platform_id platform_id = NULL;
+ platform_id = platforms[platform_index];
- cl_device_id device_id = NULL;
+ res = clGetPlatformInfo(platform_id, CL_PLATFORM_NAME, MAX_PLATFORM_NAME_SIZE,
+ name, NULL);
- cl_mem out_buff;
+ if (res == CL_OUT_OF_HOST_MEMORY) {
+ fprintf(stderr, "Insufficient resources...\n");
+ return -1;
+ }
- cl_context context = NULL;
- cl_command_queue command_queue = NULL;
- cl_kernel kernel = NULL;
- cl_program program = NULL;
+ printf("Platform in Use: %s\n", name);
- char *source_str = NULL;
- size_t source_size = 0;
+ res = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_GPU, 1, device, NULL);
- FILE *fp;
+ if (res == CL_DEVICE_NOT_FOUND) {
+ fprintf(stderr, "Specified platform does not provide a GPU...\n");
+ return -1;
+ }
- cl_uint platform_count = 256;
- cl_platform_id *platforms;
+ if (res == CL_OUT_OF_RESOURCES || res == CL_OUT_OF_HOST_MEMORY) {
+ fprintf(stderr, "Insufficient resources...\n");
+ return -1;
+ }
- size_t g_work_size, l_work_size;
+ return 0;
+}
+
+int write_image(char *out_file, int width, int height, float *raster) {
- char name[100];
- size_t name_size;
+ FILE *fp;
png_structp png_ptr;
png_infop info_ptr;
png_bytep row;
- res = parse_args(argc, argv, &args);
+ row = (png_bytep)malloc(3 * width * sizeof(png_byte));
- if (res) {
- if (res == 255) {
- exit(0);
- }
- exit(res);
+ fp = fopen(out_file, "wb");
+
+ if (!fp) {
+ printf("Couldn't open output file\n");
+ free(row);
+ return -1;
}
- data_size_out = sizeof(float) * args.img_width * args.img_height * 3;
- data_out = (float *)malloc(data_size_out);
+ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
- platforms = malloc(platform_count * sizeof(cl_platform_id));
- row = (png_bytep)malloc(3 * args.img_width * sizeof(png_byte));
+ info_ptr = png_create_info_struct(png_ptr);
- source_file = argv[optind];
- out_file = argv[optind + 1];
+ png_init_io(png_ptr, fp);
- // Load Program Source
+ png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB,
+ PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
+ PNG_FILTER_TYPE_BASE);
- fp = fopen(source_file, "r");
- if (!fp) {
- printf("Cannot open file: %s\n", source_file);
- goto error;
+ png_write_info(png_ptr, info_ptr);
+
+ int x, y;
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+ row[x * 3 + 0] = (int)(255 * raster[3 * (y * width + x) + 0]);
+ row[x * 3 + 1] = (int)(255 * raster[3 * (y * width + x) + 1]);
+ row[x * 3 + 2] = (int)(255 * raster[3 * (y * width + x) + 2]);
+ }
+ png_write_row(png_ptr, row);
}
- source_str = (char *)malloc(1048576);
- source_size = fread(source_str, 1, 1048576, fp);
+ png_write_end(png_ptr, NULL);
+
fclose(fp);
+ free(row);
- // Define Vars
+ return 0;
+}
- // Get Platform & Device
- clGetPlatformIDs(0, NULL, &platform_count);
+int main(int argc, char **argv) {
- clGetPlatformIDs(platform_count, platforms, NULL);
+ struct Args args;
+ int res;
- platform_id = platforms[args.platform_index];
+ float *data_out;
+ int data_out_size;
- clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_GPU, 1, &device_id, NULL);
+ cl_device_id device_id;
- clGetPlatformInfo(platform_id, CL_PLATFORM_NAME, 100, name, &name_size);
+ cl_mem out_buff;
- printf("Platform in Use: %s\n", name);
+ cl_context context = NULL;
+ cl_command_queue command_queue = NULL;
+ cl_kernel kernel = NULL;
+ cl_program program = NULL;
+
+ char *source_str;
+ size_t source_size;
+
+ size_t g_work_size, l_work_size;
+
+ res = parse_args(argc, argv, &args);
+
+ if (res) {
+ fprintf(stderr, "Error parsing command-line arguments...\n");
+
+ // This is before anything has been allocated, so no cleanup is needed.
+ exit(1);
+ }
+
+ data_out_size = sizeof(float) * args.img_width * args.img_height * 3;
+
+ data_out = (float *)malloc(data_out_size);
+ source_str = (char *)malloc(MAX_SRC_SIZE * sizeof(char));
+
+ res = read_source(args.source_file, source_str, MAX_SRC_SIZE, &source_size);
+
+ if (res) {
+ fprintf(stderr, "Error reading source file: %s", args.source_file);
+ goto error;
+ }
+
+ // Get Platform & Device
+ res = get_device(args.platform_index, &device_id);
+
+ if (res) {
+ goto error;
+ }
// Create Context & Queue
- context = clCreateContext(NULL, 1, &device_id, NULL, NULL, NULL);
+ context = clCreateContext(NULL, 1, &device_id, NULL, NULL, &res);
+
+ if (res == CL_DEVICE_NOT_AVAILABLE) {
+ fprintf(stderr, "Selected platform/device is not available...");
+ goto error;
+ }
+
+ if (res == CL_OUT_OF_HOST_MEMORY) {
+ fprintf(stderr, "Insufficient resources...\n");
+ goto error;
+ }
+
command_queue =
- clCreateCommandQueueWithProperties(context, device_id, 0, NULL);
+ clCreateCommandQueueWithProperties(context, device_id, NULL, &res);
+
+ if (res == CL_OUT_OF_RESOURCES || res == CL_OUT_OF_HOST_MEMORY) {
+ fprintf(stderr, "Insufficient resources...\n");
+ goto error;
+ }
// Create Buffers
out_buff =
- clCreateBuffer(context, CL_MEM_WRITE_ONLY, data_size_out, NULL, NULL);
+ clCreateBuffer(context, CL_MEM_WRITE_ONLY, data_out_size, NULL, &res);
+
+ if (res == CL_INVALID_BUFFER_SIZE) {
+ fprintf(stderr, "Invalid buffer size: %d...", data_out_size);
+ }
+
+ if (res == CL_MEM_OBJECT_ALLOCATION_FAILURE || res == CL_OUT_OF_RESOURCES ||
+ res == CL_OUT_OF_HOST_MEMORY) {
+ fprintf(stderr, "Insufficient resources...\n");
+ goto error;
+ }
program = clCreateProgramWithSource(context, 1, (const char **)&source_str,
- (const size_t *)&source_size, NULL);
+ &source_size, &res);
+
+ if (res == CL_OUT_OF_RESOURCES || res == CL_OUT_OF_HOST_MEMORY) {
+ fprintf(stderr, "Insufficient resources...\n");
+ goto error;
+ }
res = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL);
if (res != CL_SUCCESS) {
- printf("Failed to build program!\n");
+ fprintf(stderr, "Failed to build program!\n");
char build_log[16348];
clGetProgramBuildInfo(program, device_id, CL_PROGRAM_BUILD_LOG,
sizeof(build_log), build_log, NULL);
- printf("Build Error: %s\n", build_log);
+ fprintf(stderr, "Build Error: %s\n", build_log);
goto error;
}
kernel = clCreateKernel(program, "render", &res);
if (res != CL_SUCCESS) {
- printf("Error creating kernel: %d\n", res);
+ fprintf(stderr, "Error creating kernel: %d\n", res);
goto error;
}
- clSetKernelArg(kernel, 0, sizeof(cl_int), (void *)&args.img_width);
- clSetKernelArg(kernel, 1, sizeof(cl_int), (void *)&args.img_height);
- clSetKernelArg(kernel, 2, sizeof(cl_mem), (void *)&out_buff);
+ res = clSetKernelArg(kernel, 0, sizeof(cl_int), (void *)&args.img_width);
+
+ if (res != CL_SUCCESS) {
+ fprintf(stderr, "Error setting arguments...");
+ goto error;
+ }
+
+ res = clSetKernelArg(kernel, 1, sizeof(cl_int), (void *)&args.img_height);
+
+ if (res != CL_SUCCESS) {
+ fprintf(stderr, "Error setting arguments...");
+ goto error;
+ }
+
+ res = clSetKernelArg(kernel, 2, sizeof(cl_mem), (void *)&out_buff);
+
+ if (res != CL_SUCCESS) {
+ fprintf(stderr, "Error setting arguments...");
+ goto error;
+ }
l_work_size = 128;
g_work_size =
@@ -200,7 +331,7 @@ int main(int argc, char **argv) {
goto error;
}
- res = clEnqueueReadBuffer(command_queue, out_buff, CL_TRUE, 0, data_size_out,
+ res = clEnqueueReadBuffer(command_queue, out_buff, CL_TRUE, 0, data_out_size,
(void *)data_out, 0, NULL, NULL);
if (res != CL_SUCCESS) {
@@ -209,38 +340,7 @@ int main(int argc, char **argv) {
}
// Write PNG
- fp = fopen(out_file, "wb");
-
- if (!fp) {
- printf("Couldn't open output file\n");
- goto error;
- }
-
- png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
-
- info_ptr = png_create_info_struct(png_ptr);
-
- png_init_io(png_ptr, fp);
-
- png_set_IHDR(png_ptr, info_ptr, args.img_width, args.img_height, 8,
- PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
- PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
-
- png_write_info(png_ptr, info_ptr);
-
- int x, y;
- for (y = 0; y < args.img_height; y++) {
- for (x = 0; x < args.img_width; x++) {
- row[x * 3 + 0] = (int)(255 * data_out[3 * (y * args.img_width + x) + 0]);
- row[x * 3 + 1] = (int)(255 * data_out[3 * (y * args.img_width + x) + 1]);
- row[x * 3 + 2] = (int)(255 * data_out[3 * (y * args.img_width + x) + 2]);
- }
- png_write_row(png_ptr, row);
- }
-
- png_write_end(png_ptr, NULL);
-
- fclose(fp);
+ write_image(args.out_file, args.img_width, args.img_height, data_out);
error:
@@ -252,10 +352,8 @@ error:
clReleaseCommandQueue(command_queue);
clReleaseContext(context);
- free(platforms);
- free(source_str);
free(data_out);
- free(row);
+ free(source_str);
return 0;
}