summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Anthony <sam@samanthony.xyz>2024-11-13 12:48:33 -0500
committerSam Anthony <sam@samanthony.xyz>2024-11-13 12:48:33 -0500
commitdaf29651a188a06041ed6d238f7f1b7ab2f5bd9a (patch)
tree6c4257a2df4811afca879c29431e6f5e26d8f951
parent5011ea1b44c055893c691e923f4e82cdaebd5b0c (diff)
downloadballs-daf29651a188a06041ed6d238f7f1b7ab2f5bd9a.zip
refactor cl initialization
-rw-r--r--Makefile2
-rw-r--r--balls.c241
-rw-r--r--balls.h2
-rw-r--r--cl.c251
4 files changed, 255 insertions, 241 deletions
diff --git a/Makefile b/Makefile
index c4e03a8..170ace4 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ CC = gcc
CFLAGS = -std=c99 -Wall -pedantic -Wno-deprecated-declarations
LDFLAGS = -lGLEW -lGL -lX11 -lGLU -lOpenGL -lOpenCL -lglut -lGLX
-SRC = balls.c sysfatal.c geo.c rand.c partition.c gl.c io.c
+SRC = balls.c sysfatal.c geo.c rand.c partition.c gl.c io.c cl.c
OBJ = ${SRC:.c=.o}
balls: ${OBJ}
diff --git a/balls.c b/balls.c
index 0eb3991..ef11527 100644
--- a/balls.c
+++ b/balls.c
@@ -7,36 +7,12 @@
#include <GL/glew.h>
#include <GL/glut.h>
#include <CL/cl_gl.h>
-#ifndef WINDOWS
-#include <GL/glx.h>
-#endif
#include "balls.h"
#include "sysfatal.h"
#include "gl.h"
#define nelem(arr) (sizeof(arr) / sizeof(arr[0]))
-#ifdef WINDOWS
-#define contextProperties(platform) { \
- CL_GL_CONTEXT_KHR, (cl_context_properties) wglGetCurrentContext(), \
- CL_WGL_HDC_KHR, (cl_context_properties) wglGetCurrentDC(), \
- CL_CONTEXT_PLATFORM, (cl_context_properties) (platform), \
- 0 \
-}
-#else
-#define contextProperties(platform) { \
- CL_GL_CONTEXT_KHR, (cl_context_properties) glXGetCurrentContext(), \
- CL_GLX_DISPLAY_KHR, (cl_context_properties) glXGetCurrentDisplay(), \
- CL_CONTEXT_PLATFORM, (cl_context_properties) (platform), \
- 0 \
-}
-#endif
-
-#define PROG_FILE "balls.cl"
-#define MOVE_KERNEL_FUNC "move"
-#define COLLIDE_WALLS_KERNEL_FUNC "collideWalls"
-#define COLLIDE_BALLS_KERNEL_FUNC "collideBalls"
-#define GEN_VERTICES_KERNEL_FUNC "genVertices"
#define RMIN 0.05 /* Minimum radius. */
#define RMAX 0.15 /* Maximum radius. */
@@ -51,12 +27,6 @@ enum { NBALLS_DEFAULT = 3 };
const Rect bounds = { {-1.0, -1.0}, {1.0, 1.0} };
-void initCL(void);
-int getDevicePlatform(cl_platform_id platforms[], int nPlatforms, cl_device_type devType, cl_device_id *device);
-void printPlatform(cl_platform_id platform);
-void printDevice(cl_device_id device);
-void printBuildLog(cl_program prog, cl_device_id device);
-cl_kernel createKernel(cl_program prog, const char *kernelFunc);
void setPositions(void);
void setVelocities(void);
void setRadii(void);
@@ -129,215 +99,6 @@ main(int argc, char *argv[]) {
}
void
-initCL(void) {
- cl_uint nPlatforms;
- cl_platform_id *platforms, cpuPlatform, gpuPlatform;
- size_t i;
- cl_device_id cpuDevice, gpuDevice;
- cl_int err;
- cl_program cpuProg, gpuProg;
- char *progBuf;
- size_t progSize;
-
- /* Get platforms. */
- if (clGetPlatformIDs(0, NULL, &nPlatforms) < 0)
- sysfatal("Can't get OpenCL platforms.\n");
- if ((platforms = malloc(nPlatforms*sizeof(cl_platform_id))) == NULL)
- sysfatal("Failed to allocate platform array.\n");
- if (clGetPlatformIDs(nPlatforms, platforms, NULL) < 0)
- sysfatal("Can't get OpenCL platforms.\n");
-
- /* Get CPU device. */
- i = getDevicePlatform(platforms, nPlatforms, CL_DEVICE_TYPE_CPU, &cpuDevice);
- if (i < 0)
- sysfatal("No CPU device available.\n");
- cpuPlatform = platforms[i];
- printf("CPU platform: ");
- printPlatform(cpuPlatform);
- printf("CPU device: ");
- printDevice(cpuDevice);
-
- /* Get GPU device. */
- i = getDevicePlatform(platforms, nPlatforms, CL_DEVICE_TYPE_GPU, &gpuDevice);
- if (i < 0)
- sysfatal("No GPU device available.\n");
- gpuPlatform = platforms[i];
- printf("GPU platform: ");
- printPlatform(gpuPlatform);
- printf("GPU device: ");
- printDevice(gpuDevice);
-
- /* Configure properties for OpenGL interoperability. */
- cl_context_properties cpuProperties[] = contextProperties(cpuPlatform);
- cl_context_properties gpuProperties[] = contextProperties(gpuPlatform);
-
- /* Create contexts. */
- cpuContext = clCreateContext(cpuProperties, 1, &cpuDevice, NULL, NULL, &err);
- if (err < 0)
- sysfatal("Failed to create CPU context.\n");
- gpuContext = clCreateContext(gpuProperties, 1, &gpuDevice, NULL, NULL, &err);
- if (err < 0)
- sysfatal("Failed to create GPU context.\n");
-
- free(platforms);
-
- /* Create program from file. */
- err = readFile(PROG_FILE, &progBuf, &progSize);
- if (err != 0)
- sysfatal("Failed to read %s\n", PROG_FILE);
- cpuProg = clCreateProgramWithSource(cpuContext, 1, (const char **) &progBuf, &progSize, &err);
- if (err < 0)
- sysfatal("Failed to create CPU program.\n");
- gpuProg = clCreateProgramWithSource(gpuContext, 1, (const char **) &progBuf, &progSize, &err);
- if (err < 0)
- sysfatal("Failed to create GPU program.\n");
- free(progBuf);
-
- /* Build program. */
- err = clBuildProgram(cpuProg, 0, NULL, "-I./", NULL, NULL);
- if (err < 0) {
- fprintf(stderr, "Failed to build CPU program.\n");
- printBuildLog(cpuProg, cpuDevice);
- exit(1);
- }
- err = clBuildProgram(gpuProg, 0, NULL, "-I./", NULL, NULL);
- if (err < 0) {
- /* Print build log. */
- fprintf(stderr, "Failed to build GPU program.\n");
- printBuildLog(gpuProg, gpuDevice);
- exit(1);
- }
-
- /* Create command queues. */
- cpuQueue = clCreateCommandQueue(cpuContext, cpuDevice, 0, &err);
- if (err < 0)
- sysfatal("Failed to create CPU command queue.\n");
- gpuQueue = clCreateCommandQueue(gpuContext, gpuDevice, 0, &err);
- if (err < 0)
- sysfatal("Failed to create GPU command queue.\n");
-
- /* Create kernels. */
- moveKernel = createKernel(cpuProg, MOVE_KERNEL_FUNC);
- collideWallsKernel = createKernel(cpuProg, COLLIDE_WALLS_KERNEL_FUNC);
- collideBallsKernel = createKernel(cpuProg, COLLIDE_BALLS_KERNEL_FUNC);
- genVerticesKernel = createKernel(gpuProg, GEN_VERTICES_KERNEL_FUNC);
-
- clReleaseProgram(cpuProg);
- clReleaseProgram(gpuProg);
-}
-
-/*
- * Find a platform with a certain type of device. Sets *device and returns the index
- * of the platform that it belongs to. Returns -1 if none of the platforms have the
- * specified type of device.
- */
-int
-getDevicePlatform(cl_platform_id platforms[], int nPlatforms, cl_device_type devType, cl_device_id *device) {
- int i, err;
-
- for (i = 0; i < nPlatforms; i++) {
- err = clGetDeviceIDs(platforms[i], devType, 1, device, NULL);
- if (err == CL_SUCCESS) {
- return i;
- }
- }
- return -1;
-}
-
-void
-printPlatform(cl_platform_id platform) {
- int err;
- size_t size;
- char *buf;
-
- /* Get size of string. */
- err = clGetPlatformInfo(platform, CL_PLATFORM_NAME, 0, NULL, &size);
- if (err < 0) {
- printf("ERROR getting platform name\n");
- return;
- }
-
- if ((buf = malloc(size+1)) == NULL) {
- printf("ERROR allocating buffer\n");
- return;
- }
-
- /* Get platform name. */
- err = clGetPlatformInfo(platform, CL_PLATFORM_NAME, size, buf, NULL);
- if (err < 0) {
- printf("ERROR getting platform name\n");
- return;
- }
- buf[size] = '\0';
- printf("%s\n", buf);
- free(buf);
-}
-
-void
-printDevice(cl_device_id device) {
- int err;
- size_t size;
- char *buf;
- cl_bool available;
-
- /* Get size of string. */
- err = clGetDeviceInfo(device, CL_DEVICE_NAME, 0, NULL, &size);
- if (err < 0) {
- printf("ERROR getting device name\n");
- return;
- }
-
- if ((buf = malloc(size+1)) == NULL) {
- printf("ERROR allocating buffer\n");
- return;
- }
-
- /* Get device name. */
- err = clGetDeviceInfo(device, CL_DEVICE_NAME, size, buf, NULL);
- if (err < 0) {
- printf("ERROR getting device nam\n");
- return;
- }
- buf[size] = '\0';
- printf("%s ", buf);
- free(buf);
-
- /* Get availability. */
- err = clGetDeviceInfo(device, CL_DEVICE_AVAILABLE, sizeof(available), &available, NULL);
- if (err < 0) {
- printf("ERROR getting device availability\n");
- return;
- }
- printf("(%savailable)\n", (!available) ? "un" : "");
-}
-
-
-void
-printBuildLog(cl_program prog, cl_device_id device) {
- size_t size;
- char *log;
-
- clGetProgramBuildInfo(prog, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &size);
- if ((log = malloc(size + 1)) == NULL)
- sysfatal("Failed to allocate program build log buffer.\n");
- log[size] = '\0';
- clGetProgramBuildInfo(prog, device, CL_PROGRAM_BUILD_LOG, size+1, log, NULL);
- fprintf(stderr, "%s\n", log);
- free(log);
-}
-
-cl_kernel
-createKernel(cl_program prog, const char *kernelFunc) {
- cl_kernel kernel;
- int err;
-
- kernel = clCreateKernel(prog, kernelFunc, &err);
- if (err < 0)
- sysfatal("Failed to create kernel '%s': %d\n", kernelFunc, err);
- return kernel;
-}
-
-void
setPositions(void) {
Vector *positions;
int err;
@@ -499,7 +260,7 @@ collideBalls(void) {
for (i = 0; i < collisionPartition.size; i++) {
err = clSetKernelArg(collideBallsKernel, 0, sizeof(collisionsCpuBufs[i]), collisionsCpuBufs+i);
if (err < 0)
- sysfatal("Failed to set argument of %s kernel.\n", COLLIDE_BALLS_KERNEL_FUNC);
+ sysfatal("Failed to set argument of collideBalls kernel.\n");
err = clEnqueueNDRangeKernel(cpuQueue, collideBallsKernel, 1, NULL, &collisionPartition.cells[i].size, NULL, 0, NULL, NULL);
if (err < 0)
sysfatal("Couldn't enqueue kernel.\n");
diff --git a/balls.h b/balls.h
index f17243b..7bcc124 100644
--- a/balls.h
+++ b/balls.h
@@ -21,6 +21,8 @@ typedef struct {
int readFile(const char *filename, char **contents, size_t *size);
+void initCL(void);
+
Partition partitionCollisions(size_t nBalls);
void freePartition(Partition part);
void printPartition(Partition part);
diff --git a/cl.c b/cl.c
new file mode 100644
index 0000000..97afcb3
--- /dev/null
+++ b/cl.c
@@ -0,0 +1,251 @@
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <CL/cl_gl.h>
+#ifndef WINDOWS
+#include <GL/glx.h>
+#endif
+
+#include "balls.h"
+#include "sysfatal.h"
+
+#ifdef WINDOWS
+#define contextProperties(platform) { \
+ CL_GL_CONTEXT_KHR, (cl_context_properties) wglGetCurrentContext(), \
+ CL_WGL_HDC_KHR, (cl_context_properties) wglGetCurrentDC(), \
+ CL_CONTEXT_PLATFORM, (cl_context_properties) (platform), \
+ 0 \
+}
+#else
+#define contextProperties(platform) { \
+ CL_GL_CONTEXT_KHR, (cl_context_properties) glXGetCurrentContext(), \
+ CL_GLX_DISPLAY_KHR, (cl_context_properties) glXGetCurrentDisplay(), \
+ CL_CONTEXT_PLATFORM, (cl_context_properties) (platform), \
+ 0 \
+}
+#endif
+
+#define PROG_FILE "balls.cl"
+#define MOVE_KERNEL_FUNC "move"
+#define COLLIDE_WALLS_KERNEL_FUNC "collideWalls"
+#define COLLIDE_BALLS_KERNEL_FUNC "collideBalls"
+#define GEN_VERTICES_KERNEL_FUNC "genVertices"
+
+static int getDevicePlatform(cl_platform_id platforms[], int nPlatforms, cl_device_type devType, cl_device_id *device);
+static void printPlatform(cl_platform_id platform);
+static void printDevice(cl_device_id device);
+static void printBuildLog(cl_program prog, cl_device_id device);
+static cl_kernel createKernel(cl_program prog, const char *kernelFunc);
+
+extern cl_context cpuContext, gpuContext;
+extern cl_command_queue cpuQueue, gpuQueue;
+extern cl_kernel moveKernel, collideWallsKernel, collideBallsKernel, genVerticesKernel;
+
+void
+initCL(void) {
+ cl_uint nPlatforms;
+ cl_platform_id *platforms, cpuPlatform, gpuPlatform;
+ size_t i;
+ cl_device_id cpuDevice, gpuDevice;
+ cl_int err;
+ cl_program cpuProg, gpuProg;
+ char *progBuf;
+ size_t progSize;
+
+ /* Get platforms. */
+ if (clGetPlatformIDs(0, NULL, &nPlatforms) < 0)
+ sysfatal("Can't get OpenCL platforms.\n");
+ if ((platforms = malloc(nPlatforms*sizeof(cl_platform_id))) == NULL)
+ sysfatal("Failed to allocate platform array.\n");
+ if (clGetPlatformIDs(nPlatforms, platforms, NULL) < 0)
+ sysfatal("Can't get OpenCL platforms.\n");
+
+ /* Get CPU device. */
+ i = getDevicePlatform(platforms, nPlatforms, CL_DEVICE_TYPE_CPU, &cpuDevice);
+ if (i < 0)
+ sysfatal("No CPU device available.\n");
+ cpuPlatform = platforms[i];
+ printf("CPU platform: ");
+ printPlatform(cpuPlatform);
+ printf("CPU device: ");
+ printDevice(cpuDevice);
+
+ /* Get GPU device. */
+ i = getDevicePlatform(platforms, nPlatforms, CL_DEVICE_TYPE_GPU, &gpuDevice);
+ if (i < 0)
+ sysfatal("No GPU device available.\n");
+ gpuPlatform = platforms[i];
+ printf("GPU platform: ");
+ printPlatform(gpuPlatform);
+ printf("GPU device: ");
+ printDevice(gpuDevice);
+
+ /* Configure properties for OpenGL interoperability. */
+ cl_context_properties cpuProperties[] = contextProperties(cpuPlatform);
+ cl_context_properties gpuProperties[] = contextProperties(gpuPlatform);
+
+ /* Create contexts. */
+ cpuContext = clCreateContext(cpuProperties, 1, &cpuDevice, NULL, NULL, &err);
+ if (err < 0)
+ sysfatal("Failed to create CPU context.\n");
+ gpuContext = clCreateContext(gpuProperties, 1, &gpuDevice, NULL, NULL, &err);
+ if (err < 0)
+ sysfatal("Failed to create GPU context.\n");
+
+ free(platforms);
+
+ /* Create program from file. */
+ err = readFile(PROG_FILE, &progBuf, &progSize);
+ if (err != 0)
+ sysfatal("Failed to read %s\n", PROG_FILE);
+ cpuProg = clCreateProgramWithSource(cpuContext, 1, (const char **) &progBuf, &progSize, &err);
+ if (err < 0)
+ sysfatal("Failed to create CPU program.\n");
+ gpuProg = clCreateProgramWithSource(gpuContext, 1, (const char **) &progBuf, &progSize, &err);
+ if (err < 0)
+ sysfatal("Failed to create GPU program.\n");
+ free(progBuf);
+
+ /* Build program. */
+ err = clBuildProgram(cpuProg, 0, NULL, "-I./", NULL, NULL);
+ if (err < 0) {
+ fprintf(stderr, "Failed to build CPU program.\n");
+ printBuildLog(cpuProg, cpuDevice);
+ exit(1);
+ }
+ err = clBuildProgram(gpuProg, 0, NULL, "-I./", NULL, NULL);
+ if (err < 0) {
+ /* Print build log. */
+ fprintf(stderr, "Failed to build GPU program.\n");
+ printBuildLog(gpuProg, gpuDevice);
+ exit(1);
+ }
+
+ /* Create command queues. */
+ cpuQueue = clCreateCommandQueue(cpuContext, cpuDevice, 0, &err);
+ if (err < 0)
+ sysfatal("Failed to create CPU command queue.\n");
+ gpuQueue = clCreateCommandQueue(gpuContext, gpuDevice, 0, &err);
+ if (err < 0)
+ sysfatal("Failed to create GPU command queue.\n");
+
+ /* Create kernels. */
+ moveKernel = createKernel(cpuProg, MOVE_KERNEL_FUNC);
+ collideWallsKernel = createKernel(cpuProg, COLLIDE_WALLS_KERNEL_FUNC);
+ collideBallsKernel = createKernel(cpuProg, COLLIDE_BALLS_KERNEL_FUNC);
+ genVerticesKernel = createKernel(gpuProg, GEN_VERTICES_KERNEL_FUNC);
+
+ clReleaseProgram(cpuProg);
+ clReleaseProgram(gpuProg);
+}
+
+/*
+ * Find a platform with a certain type of device. Sets *device and returns the index
+ * of the platform that it belongs to. Returns -1 if none of the platforms have the
+ * specified type of device.
+ */
+static int
+getDevicePlatform(cl_platform_id platforms[], int nPlatforms, cl_device_type devType, cl_device_id *device) {
+ int i, err;
+
+ for (i = 0; i < nPlatforms; i++) {
+ err = clGetDeviceIDs(platforms[i], devType, 1, device, NULL);
+ if (err == CL_SUCCESS) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+static void
+printPlatform(cl_platform_id platform) {
+ int err;
+ size_t size;
+ char *buf;
+
+ /* Get size of string. */
+ err = clGetPlatformInfo(platform, CL_PLATFORM_NAME, 0, NULL, &size);
+ if (err < 0) {
+ printf("ERROR getting platform name\n");
+ return;
+ }
+
+ if ((buf = malloc(size+1)) == NULL) {
+ printf("ERROR allocating buffer\n");
+ return;
+ }
+
+ /* Get platform name. */
+ err = clGetPlatformInfo(platform, CL_PLATFORM_NAME, size, buf, NULL);
+ if (err < 0) {
+ printf("ERROR getting platform name\n");
+ return;
+ }
+ buf[size] = '\0';
+ printf("%s\n", buf);
+ free(buf);
+}
+
+static void
+printDevice(cl_device_id device) {
+ int err;
+ size_t size;
+ char *buf;
+ cl_bool available;
+
+ /* Get size of string. */
+ err = clGetDeviceInfo(device, CL_DEVICE_NAME, 0, NULL, &size);
+ if (err < 0) {
+ printf("ERROR getting device name\n");
+ return;
+ }
+
+ if ((buf = malloc(size+1)) == NULL) {
+ printf("ERROR allocating buffer\n");
+ return;
+ }
+
+ /* Get device name. */
+ err = clGetDeviceInfo(device, CL_DEVICE_NAME, size, buf, NULL);
+ if (err < 0) {
+ printf("ERROR getting device nam\n");
+ return;
+ }
+ buf[size] = '\0';
+ printf("%s ", buf);
+ free(buf);
+
+ /* Get availability. */
+ err = clGetDeviceInfo(device, CL_DEVICE_AVAILABLE, sizeof(available), &available, NULL);
+ if (err < 0) {
+ printf("ERROR getting device availability\n");
+ return;
+ }
+ printf("(%savailable)\n", (!available) ? "un" : "");
+}
+
+static void
+printBuildLog(cl_program prog, cl_device_id device) {
+ size_t size;
+ char *log;
+
+ clGetProgramBuildInfo(prog, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &size);
+ if ((log = malloc(size + 1)) == NULL)
+ sysfatal("Failed to allocate program build log buffer.\n");
+ log[size] = '\0';
+ clGetProgramBuildInfo(prog, device, CL_PROGRAM_BUILD_LOG, size+1, log, NULL);
+ fprintf(stderr, "%s\n", log);
+ free(log);
+}
+
+static cl_kernel
+createKernel(cl_program prog, const char *kernelFunc) {
+ cl_kernel kernel;
+ int err;
+
+ kernel = clCreateKernel(prog, kernelFunc, &err);
+ if (err < 0)
+ sysfatal("Failed to create kernel '%s': %d\n", kernelFunc, err);
+ return kernel;
+}