diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml index 806f758..765e648 100644 --- a/dependency-reduced-pom.xml +++ b/dependency-reduced-pom.xml @@ -2,7 +2,7 @@ 4.0.0 electrosphere - sample-cli-java + fluid-sim 1.0-SNAPSHOT @@ -55,11 +55,31 @@ 17 17 - --add-modules - jdk.incubator.vector + -h + src/main/c/includes + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + + compile-c-code + generate-resources + + exec + + + bash + + ./src/main/c/compile.sh + + + + + @@ -99,6 +119,6 @@ 17 UTF-8 1.10.5 - 3.3.2 + 3.2.3 diff --git a/pom.xml b/pom.xml index b1e600d..a923d85 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ UTF-8 17 17 - 3.3.2 + 3.2.3 1.10.5 @@ -133,7 +133,6 @@ - maven-assembly-plugin 3.0.0 @@ -164,11 +163,31 @@ 17 17 - --add-modules - jdk.incubator.vector + -h + src/main/c/includes + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + + compile-c-code + generate-resources + + exec + + + bash + + ./src/main/c/compile.sh + + + + + diff --git a/shared-folder/libfluidsim.dll b/shared-folder/libfluidsim.dll new file mode 100644 index 0000000..2fbdd2c Binary files /dev/null and b/shared-folder/libfluidsim.dll differ diff --git a/src/main/c/compile.sh b/src/main/c/compile.sh new file mode 100644 index 0000000..a64a457 --- /dev/null +++ b/src/main/c/compile.sh @@ -0,0 +1,62 @@ +cd ./src/main/c + +LIB_ENDING=".so" +BASE_INCLUDE_DIR="" +OS_INCLUDE_DIR="" + +if [[ "$OSTYPE" == "linux-gnu"* ]]; then + #linux + LIB_ENDING=".so" + BASE_INCLUDE_DIR="${JAVA_HOME}/include" + OS_INCLUDE_DIR="${JAVA_HOME}/include/linux" +elif [[ "$OSTYPE" == "darwin"* ]]; then + # Mac OSX + LIB_ENDING=".so" +elif [[ "$OSTYPE" == "cygwin" ]]; then + # POSIX compatibility layer and Linux environment emulation for Windows + LIB_ENDING=".dll" +elif [[ "$OSTYPE" == "msys" ]]; then + # Lightweight shell and GNU utilities compiled for Windows (part of MinGW) + LIB_ENDING=".dll" + BASE_INCLUDE_DIR="${JAVA_HOME}/include" + OS_INCLUDE_DIR="${JAVA_HOME}/include/win32" +elif [[ "$OSTYPE" == "win32" ]]; then + # I'm not sure this can happen. + LIB_ENDING=".dll" +elif [[ "$OSTYPE" == "freebsd"* ]]; then + # ... + LIB_ENDING=".so" +else + # Unknown. + LIB_ENDING=".so" +fi + +# echo $PWD + +#clean compile dir +rm -f ./*.o +rm -f ./*.so +rm -f ./*.dll + + +#compile object files +COMPILE_FLAGS="-c -fPIC -m64" +INPUT_FILES="./fluidsim.c" +OUTPUT_FILE="./fluidsim.o" +gcc $COMPILE_FLAGS -I"$BASE_INCLUDE_DIR" -I"$OS_INCLUDE_DIR" $INPUT_FILES -o $OUTPUT_FILE + + + +#compile shared object file +OUTPUT_FILE="libfluidsim$LIB_ENDING" +COMPILE_FLAGS="-shared" +INPUT_FILES="fluidsim.o" +gcc $COMPILE_FLAGS $INPUT_FILES -o $OUTPUT_FILE + +#move to resources +mv "./libfluidsim$LIB_ENDING" "../../../shared-folder/" + +#clean compile dir +rm -f ./*.o +rm -f ./*.so +rm -f ./*.dll \ No newline at end of file diff --git a/src/main/c/fluidsim.c b/src/main/c/fluidsim.c new file mode 100644 index 0000000..2fdfdba --- /dev/null +++ b/src/main/c/fluidsim.c @@ -0,0 +1,237 @@ +#include +#include + + + +#define SWAP(x0,x) {float *tmp=x0;x0=x;x=tmp;} +#define IX(i,j,k) ((i)+(N)*(j)+(N*N)*(k)) + +#define LINEARSOLVERTIMES 20 + + + + + +void diffuse(int N, int b, float * x, float * x0, float diff, float dt); +void advect(int N, int b, float * d, float * d0, float * u, float * v, float * w, float dt); +void project(int N, float * u, float * v, float * w, float * p, float * div); +void set_bnd(int N, int b, float * x); +void dens_step(int N, float * x, float * x0, float * u, float * v, float * w, float diff, float dt); +void vel_step(int N, float * u, float * v, float * w, float * u0, float * v0, float * w0, float visc, float dt); +void lin_solve(int N, int b, float* x, float* x0, float a, float c); + +JNIEXPORT void JNICALL Java_electrosphere_FluidSim_simulate( + JNIEnv * env, + jobject this, + jint DIM_X, + jint DIM_Y, + jint DIM_Z, + jfloatArray jx, + jfloatArray jx0, + jfloatArray ju, + jfloatArray jv, + jfloatArray jw, + jfloatArray ju0, + jfloatArray jv0, + jfloatArray jw0, + jfloat DIFFUSION_RATE, + jfloat VISCOSITY_RATE, + jfloat timestep){ + jboolean isCopy; + float * x = (*env)->GetFloatArrayElements(env,jx,&isCopy); + float * x0 = (*env)->GetFloatArrayElements(env,jx0,&isCopy); + float * u = (*env)->GetFloatArrayElements(env,ju,&isCopy); + float * v = (*env)->GetFloatArrayElements(env,jv,&isCopy); + float * w = (*env)->GetFloatArrayElements(env,jw,&isCopy); + float * u0 = (*env)->GetFloatArrayElements(env,ju0,&isCopy); + float * v0 = (*env)->GetFloatArrayElements(env,jv0,&isCopy); + float * w0 = (*env)->GetFloatArrayElements(env,jw0,&isCopy); + vel_step(DIM_X, u, v, w, u0, v0, w0, VISCOSITY_RATE, timestep); + dens_step(DIM_X, x, x0, u, v, w, DIFFUSION_RATE, timestep); + (*env)->SetFloatArrayRegion(env,jx,0,DIM_X*DIM_X*DIM_X,x); + (*env)->SetFloatArrayRegion(env,jx0,0,DIM_X*DIM_X*DIM_X,x0); + (*env)->SetFloatArrayRegion(env,ju,0,DIM_X*DIM_X*DIM_X,u); + (*env)->SetFloatArrayRegion(env,jv,0,DIM_X*DIM_X*DIM_X,v); + (*env)->SetFloatArrayRegion(env,jw,0,DIM_X*DIM_X*DIM_X,w); + (*env)->SetFloatArrayRegion(env,ju0,0,DIM_X*DIM_X*DIM_X,u0); + (*env)->SetFloatArrayRegion(env,jv0,0,DIM_X*DIM_X*DIM_X,v0); + (*env)->SetFloatArrayRegion(env,jw0,0,DIM_X*DIM_X*DIM_X,w0); + // for(int i=0; iSetFloatArrayRegion(env,jx,0,DIM_X*DIM_X*DIM_X,x); + // // jx[IX(i,j,k)] = x[IX(i,j,k)]; + // }}} +} + + + +int main() { + printf("Hello World from Project Panama Baeldung Article"); + return 0; +} + + +void diffuse(int N, int b, float * x, float * x0, float diff, float dt){ + float a=dt*diff*N*N*N; + lin_solve(N, b, x, x0, a, 1+6*a); +} + +void advect(int N, int b, float * d, float * d0, float * u, float * v, float * w, float dt){ + int i, j, k, i0, j0, k0, i1, j1, k1; + float x, y, z, s0, t0, s1, t1, u1, u0, dtx,dty,dtz; + + dtx=dty=dtz=dt*N; + + for ( i=1 ; iN+0.5f) x=N+0.5f; i0=(int)x; i1=i0+1; + if (y<0.5f) y=0.5f; if (y>N+0.5f) y=N+0.5f; j0=(int)y; j1=j0+1; + if (z<0.5f) z=0.5f; if (z>N+0.5f) z=N+0.5f; k0=(int)z; k1=k0+1; + + s1 = x-i0; s0 = 1-s1; t1 = y-j0; t0 = 1-t1; u1 = z-k0; u0 = 1-u1; + if(i0 >= N){ + i0 = N - 1; + } + if(j0 >= N){ + j0 = N - 1; + } + if(k0 >= N){ + k0 = N - 1; + } + if(i1 >= N){ + i1 = N - 1; + } + if(j1 >= N){ + j1 = N - 1; + } + if(k1 >= N){ + k1 = N - 1; + } + d[IX(i,j,k)] = s0*(t0*u0*d0[IX(i0,j0,k0)]+t1*u0*d0[IX(i0,j1,k0)]+t0*u1*d0[IX(i0,j0,k1)]+t1*u1*d0[IX(i0,j1,k1)])+ + s1*(t0*u0*d0[IX(i1,j0,k0)]+t1*u0*d0[IX(i1,j1,k0)]+t0*u1*d0[IX(i1,j0,k1)]+t1*u1*d0[IX(i1,j1,k1)]); + }}} + set_bnd(N, b, d); +} + +void dens_step(int N, float * x, float * x0, float * u, float * v, float * w, float diff, float dt){ + // add_source ( N, x, x0, dt ); + SWAP ( x0, x ); diffuse ( N, 0, x, x0, diff, dt ); + SWAP ( x0, x ); advect ( N, 0, x, x0, u, v, w, dt ); +} + +void vel_step(int N, float * u, float * v, float * w, float * u0, float * v0, float * w0, float visc, float dt){ + // add_source ( N, u, u0, dt ); add_source ( N, v, v0, dt ); + // SWAP ( u0, u ); diffuse ( N, 1, u, u0, visc, dt ); + // SWAP ( v0, v ); diffuse ( N, 2, v, v0, visc, dt ); + // project ( N, u, v, w, u0, v0 ); + // SWAP ( u0, u ); SWAP ( v0, v ); + // advect ( N, 1, u, u0, u0, v0, dt ); advect ( N, 2, v, v0, u0, v0, dt ); + // project ( N, u, v, w, u0, v0 ); + + // add_source(N, v, x, dt); + SWAP(u0, u); + diffuse(N, 1, u, u0, visc, dt); + SWAP(v0, v); + diffuse(N, 2, v, v0, visc, dt); + SWAP(w0, w); + diffuse(N, 3, w, w0, visc, dt); + project(N, u, v, w, u0, v0); + SWAP(u0, u); + SWAP(v0, v); + SWAP(w0, w); + advect(N, 1, u, u0, u0, v0, w0, dt); + advect(N, 2, v, v0, u0, v0, w0, dt); + advect(N, 3, w, w0, u0, v0, w0, dt); + project(N, u, v, w, u0, v0); +} + +void project(int N, float * u, float * v, float * w, float * p, float * div){ + int i, j, k; + + for ( i=1 ; i +/* Header for class electrosphere_FluidSim */ + +#ifndef _Included_electrosphere_FluidSim +#define _Included_electrosphere_FluidSim +#ifdef __cplusplus +extern "C" { +#endif +#undef electrosphere_FluidSim_DIM +#define electrosphere_FluidSim_DIM 18L +#undef electrosphere_FluidSim_DIFFUSION_CONSTANT +#define electrosphere_FluidSim_DIFFUSION_CONSTANT 1.0E-4f +#undef electrosphere_FluidSim_VISCOSITY_CONSTANT +#define electrosphere_FluidSim_VISCOSITY_CONSTANT 1.0E-4f +#undef electrosphere_FluidSim_LINEARSOLVERTIMES +#define electrosphere_FluidSim_LINEARSOLVERTIMES 20L +#undef electrosphere_FluidSim_GRAVITY +#define electrosphere_FluidSim_GRAVITY -10000.0f +/* + * Class: electrosphere_FluidSim + * Method: simulate + * Signature: (III[F[F[F[F[F[F[F[FFFF)V + */ +JNIEXPORT void JNICALL Java_electrosphere_FluidSim_simulate + (JNIEnv *, jobject, jint, jint, jint, jfloatArray, jfloatArray, jfloatArray, jfloatArray, jfloatArray, jfloatArray, jfloatArray, jfloatArray, jfloat, jfloat, jfloat); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/main/java/electrosphere/FluidSim.java b/src/main/java/electrosphere/FluidSim.java index 3eddf66..969721b 100644 --- a/src/main/java/electrosphere/FluidSim.java +++ b/src/main/java/electrosphere/FluidSim.java @@ -9,36 +9,21 @@ import java.util.List; import java.util.Random; import java.util.Set; -import jdk.incubator.foreign.MemorySegment; -import jdk.incubator.vector.FloatVector; -import jdk.incubator.vector.VectorMask; -import jdk.incubator.vector.VectorOperators; -import jdk.incubator.vector.VectorOperators.Associative; - import org.joml.Vector2i; import org.lwjgl.BufferUtils; import org.lwjgl.PointerBuffer; -import org.lwjgl.opencl.CL30; import org.lwjgl.system.MemoryUtil; -import electrosphere.opencl.CLBuffer; -import electrosphere.opencl.CLCommandQueue; -import electrosphere.opencl.CLContext; -import electrosphere.opencl.CLDevice; -import electrosphere.opencl.CLEvent; -import electrosphere.opencl.CLImage; -import electrosphere.opencl.CLKernel; -import electrosphere.opencl.CLPlatform; -import electrosphere.opencl.CLProgram; -import electrosphere.opencl.CLReadImageResult; -import electrosphere.opencl.CLUtilities; -import electrosphere.opencl.LWJGLContext; - /** * Simulates a fluid via opencl */ public class FluidSim { + static { + System.out.println(System.getProperty("user.dir")); + System.load(System.getProperty("user.dir") + "/shared-folder/libfluidsim.dll"); + } + public static final int DIM = 18; float[] x = new float[DIM * DIM * DIM]; @@ -118,10 +103,11 @@ public class FluidSim { } } + simulate(DIM, DIM, DIM, x, x0, u, v, w, u0, v0, w0, DIFFUSION_CONSTANT, VISCOSITY_CONSTANT, timestep); - vel_step(DIM, DIM, DIM, u, v, w, u0, v0, w0, VISCOSITY_CONSTANT, timestep); + // vel_step(DIM, DIM, DIM, u, v, w, u0, v0, w0, VISCOSITY_CONSTANT, timestep); - dens_step(DIM, DIM, DIM, x, x0, u, v, w, DIFFUSION_CONSTANT, timestep); + // dens_step(DIM, DIM, DIM, x, x0, u, v, w, DIFFUSION_CONSTANT, timestep); sum(); } @@ -144,7 +130,7 @@ public class FluidSim { void diffuse(int M, int N, int O, int b, float[] x, float[] x0, float diff, float dt){ int max = Math.max(Math.max(M, N), Math.max(N, O)); float a=dt*diff*max*max*max; - linSolveJacobian(M, N, O, b, x, x0, a, 1+6*a); + lin_solve(M, N, O, b, x, x0, a, 1+6*a); } void setBounds(float[] target, int b){ @@ -245,7 +231,7 @@ public class FluidSim { setBounds(div, 0); setBounds(p, 0); - linSolveJacobian(M, N, O, 0, p, div, 1, 6); + lin_solve(M, N, O, 0, p, div, 1, 6); for ( i=1 ; i mask = FloatVector.SPECIES_256.indexInRange(O, numLeft); - - // for ( i=1 ; i waitList, - Vector2i workersInEachDimension, - Vector2i workersInEachGroup - ){ - long[] dimensionArray = new long[]{ - workersInEachDimension.x, - workersInEachDimension.y - }; - long[] groupArray = new long[]{ - workersInEachGroup.x, - workersInEachGroup.y - }; - //dimensionality must be 2 as the work arrays are 2D vectors - CLEvent event = queueKernelWork(kernel,waitList,2,dimensionArray,groupArray); - return event; - } - - /** - * Queues kernel work with a default worker offset vector - * @param kernel The kernel to queue work on - * @param waitList The waitlist of events to wait for before executing this work - * @param workDimensions The dimensionality of the data to act upon - * @param workersInEachDimension The total number of workers in each dimension - * @param workersInEachGroup The total number of workers in each work group - * @return The opencl event for this work item - */ - public CLEvent queueKernelWork( - CLKernel kernel, - List waitList, - int workDimensions, - long[] workersInEachDimension, - long[] workersInEachGroup - ){ - return queueKernelWork(kernel, waitList, workDimensions, null, workersInEachDimension, workersInEachGroup); - } - - /** - * Queues work on a given opencl kernel - * @param kernel The kernel to queue work on - * @param waitList The waitlist of events to wait for before executing this work - * @param workDimensions The dimensionality of the data to act upon - * @param globalWorkerOffsetVector The vector specifying the amount of offset per dimension between given global workers - * @param workersInEachDimension The total number of workers in each dimension - * @param workersInEachGroup The total number of workers in each work group - * @return The opencl event for this work item - */ - public CLEvent queueKernelWork( - CLKernel kernel, - List waitList, - int workDimensions, - long[] globalWorkerOffsetVector, //basically a vector that describes the increment in each dimension. Unlikely to see use generally - long[] workersInEachDimension, //basically the number of sub arrays - long[] workersInEachGroup // basically the size of each subarray to work one - ){ - CLEvent rVal = null; - try(MemoryStack stack = MemoryStack.stackPush()){ - // - //construct and fill buffers for opencl call - - //global worker offsets - PointerBuffer globalWorkerOffset = null; - if(globalWorkerOffsetVector != null){ - globalWorkerOffset = stack.mallocPointer(workDimensions); - globalWorkerOffset.put(globalWorkerOffsetVector); - globalWorkerOffset.flip(); - } - - //global worker size - PointerBuffer globalWorkerSize = null; - globalWorkerSize = stack.mallocPointer(workDimensions); - globalWorkerSize.put(workersInEachDimension); - globalWorkerSize.flip(); - - //local worker size - PointerBuffer localWorkerSize = stack.mallocPointer(workDimensions); - localWorkerSize.put(workersInEachGroup); - localWorkerSize.flip(); - - //the events to wait for before executing this one - PointerBuffer eventWaitList = null; - if(waitList != null && waitList.size() > 0){ - eventWaitList = stack.mallocPointer(waitList.size()); - for(CLEvent toWaitEvent : waitList){ - eventWaitList.put(toWaitEvent.getPointer()); - } - } - PointerBuffer event = stack.mallocPointer(1); - - // - //queue work - CL30.clEnqueueNDRangeKernel( - this.pointer, - kernel.getPointer(), - workDimensions, - globalWorkerOffset, - globalWorkerSize, - localWorkerSize, - eventWaitList, - event - ); - - //create returned event - rVal = new CLEvent(event.get()); - } - return rVal; - } - - /** - * Sets an argument for a given kernel - * @param kernel The kernel - * @param argumentIndex The index of the argument (0-index'd) - * @param argumentValue The value to set the argument to - * @return The result of the argument set operation - */ - public int setKernelArgument(CLKernel kernel, int argumentIndex, long argumentValue){ - return CL30.clSetKernelArg(kernel.getPointer(),argumentIndex,argumentValue); - } - - /** - * Sets an argument for a given kernel to be equal to a given image - * @param kernel The kernel - * @param argumentIndex The index of the argument (0-index'd) - * @param image The value to set the argument to - * @return The result of the argument set operation - */ - public int setKernelArgument(CLKernel kernel, int argumentIndex, CLImage image){ - int rVal = 0; - try(MemoryStack stack = MemoryStack.stackPush()){ - PointerBuffer pointerBuffer = stack.mallocPointer(1); - pointerBuffer.put(image.getPointer()); - pointerBuffer.flip(); - rVal = CL30.clSetKernelArg(kernel.getPointer(),argumentIndex,pointerBuffer); - } - return rVal; - } - - /** - * Reads an image from opencl global memory - * @param image The image - * @param waitList The wait list of events to make this query pend on - * @return The byte buffer containing the data of the image - */ - public CLReadImageResult readImage(CLImage image, List waitList){ - CLReadImageResult rVal = null; - - //the cpu buffer to write into from gpu memory - int bufferSize = (int)(image.getWidth() * image.getByteWidth()); - if(image.getHeight() > 0){ - bufferSize = (int)(bufferSize * image.getHeight()); - } - if(image.getDepth() > 0){ - bufferSize = (int)(bufferSize * image.getDepth()); - } - ByteBuffer outputBuffer = MemoryUtil.memAlloc(bufferSize); - - try(MemoryStack stack = MemoryStack.stackPush()){ - boolean blocking = false; //should the call block execution until the image is read? - - //defines the offset in outputBuffer to start writing (should be a vec) - PointerBuffer origin = stack.mallocPointer(3); - origin.put(0); - origin.put(0); - origin.put(0); - origin.flip(); - - //The dimensions of the image - PointerBuffer region = stack.mallocPointer(3); - region.put(image.getWidth()); - if(image.getHeight() == 0){ - region.put(1); //If it's a 1D image, this should be set to 1 - } else { - region.put(image.getHeight()); - } - if(image.getDepth() == 0){ - region.put(1); //If it's a 2D image, this should be set to 1 - } else { - region.put(image.getDepth()); - } - region.flip(); - - //how many bytes make up 1 line of the data - long rowPitch = image.getByteWidth() * image.getWidth(); - - //how many bytes make up a single 2d plane of pixels. Should be 0 if image is 1d or 2d - long slicePitch = 0; - if(image.getDepth() > 0){ - slicePitch = image.getByteWidth() * image.getWidth() * image.getHeight(); - } - - - //the event management buffers - PointerBuffer eventWaitList = null; - if(waitList != null && waitList.size() > 0){ - eventWaitList = stack.mallocPointer(waitList.size()); - for(CLEvent toWaitEvent : waitList){ - eventWaitList.put(toWaitEvent.getPointer()); - } - eventWaitList.flip(); - } - PointerBuffer event = stack.mallocPointer(1); - - //actually send to opencl - int errorCode = CL30.clEnqueueReadImage( - this.getPointer(), - image.getPointer(), - blocking, - origin, - region, - rowPitch, - slicePitch, - outputBuffer, - eventWaitList, - event - ); - - //error check - CLUtilities.checkCLError(errorCode); - - //construct return object - CLEvent returnEvent = new CLEvent(event.get()); - rVal = new CLReadImageResult(outputBuffer,returnEvent); - } - return rVal; - } - - /** - * Writes an array of bytes to a device-side image in opencl - * @param image The image to write to - * @param data The data to write - * @param waitList The waitlist of events to pend this write operation on - * @return The CLEvent encapsulating this write operation - */ - public CLEvent writeToDeviceImage(CLImage image, List waitList, int[] data){ - CLEvent rVal = null; - try(MemoryStack stack = MemoryStack.stackPush()){ - boolean blocking = true; - - //defines the offset in outputBuffer to start writing (should be a vec) - PointerBuffer origin = stack.mallocPointer(3); - origin.put(0); - origin.put(0); - origin.put(0); - origin.flip(); - - //The dimensions of the image - PointerBuffer region = stack.mallocPointer(3); - region.put(image.getWidth()); - if(image.getHeight() == 0){ - region.put(1); //If it's a 1D image, this should be set to 1 - } else { - region.put(image.getHeight()); - } - if(image.getDepth() == 0){ - region.put(1); //If it's a 2D image, this should be set to 1 - } else { - region.put(image.getDepth()); - } - region.flip(); - - //how many bytes make up 1 line of the data - long rowPitch = image.getByteWidth() * image.getWidth(); - - //how many bytes make up a single 2d plane of pixels. Should be 0 if image is 1d or 2d - long slicePitch = 0; - if(image.getDepth() > 0){ - slicePitch = image.getByteWidth() * image.getWidth() * image.getHeight(); - } - - //the event management buffers - PointerBuffer eventWaitList = null; - if(waitList != null && waitList.size() > 0){ - eventWaitList = stack.mallocPointer(waitList.size()); - for(CLEvent toWaitEvent : waitList){ - eventWaitList.put(toWaitEvent.getPointer()); - } - eventWaitList.flip(); - } - PointerBuffer event = stack.mallocPointer(1); - - int errorCode = CL30.clEnqueueWriteImage(this.getPointer(), image.getPointer(), blocking, origin, region, rowPitch, slicePitch, data, eventWaitList, event); - - //error check - CLUtilities.checkCLError(errorCode); - - //construct return event - rVal = new CLEvent(event.get()); - } - return rVal; - } - - /** - * Writes a buffer of bytes to a device-side image in opencl - * @param image The image to write to - * @param data The data to write - * @param waitList The waitlist of events to pend this write operation on - * @return The CLEvent encapsulating this write operation - */ - public CLEvent writeToDeviceImage(CLImage image, List waitList, ByteBuffer data){ - CLEvent rVal = null; - - try(MemoryStack stack = MemoryStack.stackPush()){ - boolean blocking = false; - - //defines the offset in outputBuffer to start writing (should be a vec) - PointerBuffer origin = stack.mallocPointer(3); - origin.put(0); - origin.put(0); - origin.put(0); - origin.flip(); - - //The dimensions of the image - PointerBuffer region = stack.mallocPointer(3); - region.put(image.getWidth()); - if(image.getHeight() == 0){ - region.put(1); //If it's a 1D image, this should be set to 1 - } else { - region.put(image.getHeight()); - } - if(image.getDepth() == 0){ - region.put(1); //If it's a 2D image, this should be set to 1 - } else { - region.put(image.getDepth()); - } - region.flip(); - - //how many bytes make up 1 line of the data - long rowPitch = image.getByteWidth() * image.getWidth(); - - //how many bytes make up a single 2d plane of pixels. Should be 0 if image is 1d or 2d - long slicePitch = 0; - if(image.getDepth() > 0){ - slicePitch = image.getByteWidth() * image.getWidth() * image.getHeight(); - } - - //the event management buffers - PointerBuffer eventWaitList = null; - if(waitList != null && waitList.size() > 0){ - eventWaitList = stack.mallocPointer(waitList.size()); - for(CLEvent toWaitEvent : waitList){ - eventWaitList.put(toWaitEvent.getPointer()); - } - eventWaitList.flip(); - } - PointerBuffer event = stack.mallocPointer(1); - - int errorCode = CL30.clEnqueueWriteImage(this.getPointer(), image.getPointer(), blocking, origin, region, rowPitch, slicePitch, data, eventWaitList, event); - - //error check - CLUtilities.checkCLError(errorCode); - - //construct return event - rVal = new CLEvent(event.get()); - } - - return rVal; - } - - /** - * Blocks thread execution until the event list has completed or otherwise resolved - * @param eventList The event list - */ - public void waitForEventList(List waitList){ - try(MemoryStack stack = MemoryStack.stackPush()){ - PointerBuffer eventWaitList = null; - if(waitList != null && waitList.size() > 0){ - eventWaitList = stack.mallocPointer(waitList.size()); - for(CLEvent toWaitEvent : waitList){ - eventWaitList.put(toWaitEvent.getPointer()); - } - eventWaitList.flip(); - } - - //wait - int errorCode = CL30.clWaitForEvents(eventWaitList); - - //error check - CLUtilities.checkCLError(errorCode); - } - } - - - -} diff --git a/src/main/java/electrosphere/opencl/CLContext.java b/src/main/java/electrosphere/opencl/CLContext.java deleted file mode 100644 index 9175435..0000000 --- a/src/main/java/electrosphere/opencl/CLContext.java +++ /dev/null @@ -1,164 +0,0 @@ -package electrosphere.opencl; - -import java.nio.ByteBuffer; -import java.nio.IntBuffer; - -import org.lwjgl.BufferUtils; -import org.lwjgl.PointerBuffer; -import org.lwjgl.opencl.CL30; -import org.lwjgl.opencl.CLContextCallback; -import org.lwjgl.system.MemoryUtil; - -/** - * Wrapper object for an opencl context - */ -public class CLContext { - - //the context pointer - long pointer; - - //the context callback - CLContextCallback clContextCB; - //the error code buffer - IntBuffer errorCodeBuffer = BufferUtils.createIntBuffer(1); - int[] errorCodeArray = new int[1]; - - //the device this context is created on - CLDevice device; - - //creates an opencl context - public CLContext(CLDevice device, PointerBuffer ctxProps){ - pointer = CL30.clCreateContext(ctxProps, device.getId(), clContextCB = CLContextCallback.create( - (errinfo, private_info, cb, user_data) -> System.out.println(String.format("clCreateContext\n\tInfo: %s", MemoryUtil.memUTF8(errinfo))) - ), MemoryUtil.NULL, errorCodeBuffer); - this.device = device; - } - - /** - * Gets the pointer for this context - * @return The pointer - */ - public long getPointer(){ - return pointer; - } - - /** - * Gets the opencl error code storage buffer - * @return The opencl error code storage buffer - */ - protected IntBuffer getErrorCodeBuffer(){ - return errorCodeBuffer; - } - - /** - * Gets an array used for storing error codes in relevant api calls - * @return The array - */ - protected int[] getErrorCodeArray(){ - return errorCodeArray; - } - - /** - * Creates an opencl buffer with a specified size - * @param flags The flags for the buffer - * @param size The size of the opencl buffer in bytes - * @return The opencl buffer - */ - public CLBuffer createBuffer(long flags, long size){ - CLBuffer buffer = new CLBuffer(this, flags, size); - CLUtilities.checkCLError(errorCodeBuffer); - return buffer; - } - - /** - * Creates an opencl buffer based on a cpu buffer - * @param flags The flags for the buffer - * @param hostBuffer The cpu buffer to base the opencl buffer on - * @return The opencl buffer - */ - public CLBuffer createBuffer(long flags, IntBuffer hostBuffer){ - CLBuffer buffer = new CLBuffer(this, flags, hostBuffer); - CLUtilities.checkCLError(errorCodeBuffer); - return buffer; - } - - /** - * Creates a 2d opencl image buffer - * @param flags The flags for creation of the image - * @param width The width of the image - * @param height The height of the image - * @return The opencl image wrapper object - */ - public CLImage createImage(long flags, long width, long height){ - CLImage image = new CLImage(this, flags, width, height); - CLUtilities.checkCLError(errorCodeBuffer); - return image; - } - - /** - * Creates a 3d opencl image buffer - * @param flags The flags for creation of the image - * @param width The width of the image - * @param height The height of the image - * @param depth The depth of the image - * @return The opencl image wrapper object - */ - public CLImage createImage(long flags, long width, long height, long depth){ - CLImage image = new CLImage(this, flags, width, height, depth); - CLUtilities.checkCLError(errorCodeBuffer); - return image; - } - - /** - * Creates a 3d opencl image buffer - * @param flags The flags for creation of the image - * @param width The width of the image - * @param height The height of the image - * @param depth The depth of the image - * @param data The data to init the image with - * @return The opencl image wrapper object - */ - public CLImage createImage(long flags, long width, long height, long depth, ByteBuffer data){ - CLImage image = new CLImage(this, flags, width, height, depth, data); - CLUtilities.checkCLError(errorCodeBuffer); - return image; - } - - /** - * Creates a command queue for this context - * @return The command queue - */ - public CLCommandQueue createCommandQueue(LWJGLContext lwjglContext){ - return new CLCommandQueue(lwjglContext, this); - } - - /** - * Gets the opencl device this context was created on - * @return The device - */ - public CLDevice getDevice(){ - return device; - } - - /** - * Creates an opencl program with a provided source - * @param source The source - * @return The program - */ - public CLProgram createProgram(String source){ - CLProgram program = CLProgram.createProgram(this, source); - return program; - } - - /** - * Creates an opencl kernel from the specified program - * @param program The program - * @param kernelName The name of the kernel in the program source - * @return The kernel object - */ - public CLKernel createKernel(CLProgram program, String kernelName){ - CLKernel kernel = new CLKernel(this, program, kernelName); - return kernel; - } - -} diff --git a/src/main/java/electrosphere/opencl/CLDevice.java b/src/main/java/electrosphere/opencl/CLDevice.java deleted file mode 100644 index cd58076..0000000 --- a/src/main/java/electrosphere/opencl/CLDevice.java +++ /dev/null @@ -1,68 +0,0 @@ -package electrosphere.opencl; - -import org.lwjgl.opencl.CL30; - -/** - * Wrapper object for an opencl device - */ -public class CLDevice { - - //the id of the device - long id; - - //the name of the device - String deviceName; - - //true if the device is a gpu - boolean isGpu = false; - - //true if the device is available - boolean isAvailable = false; - - /** - * Creates a CL device wrapper object - * @param id the id of the device - * @param isGpu true if the device is a gpu - */ - protected CLDevice(long id){ - this.id = id; - //get device name - deviceName = CLUtilities.getDeviceInfoStringUTF8(id, CL30.CL_DEVICE_NAME); - //get if device is gpu - long deviceType = CLUtilities.getDeviceInfoLong(id, CL30.CL_DEVICE_TYPE); - if (deviceType == CL30.CL_DEVICE_TYPE_GPU) { - isGpu = true; - } - //check if is available - long isAvailableRaw = CLUtilities.getDeviceInfoLong(id, CL30.CL_DEVICE_AVAILABLE); - if(isAvailableRaw == CL30.CL_TRUE){ - isAvailable = true; - } - - } - - /** - * Gets the id of the device - * @return the id of the device - */ - public long getId(){ - return id; - } - - /** - * True if the device is a gpu - * @return True if the device is a gpu - */ - public boolean isGpu(){ - return isGpu; - } - - /** - * Gets the name of the device - * @return The name of the device - */ - public String getDeviceName(){ - return deviceName; - } - -} diff --git a/src/main/java/electrosphere/opencl/CLEvent.java b/src/main/java/electrosphere/opencl/CLEvent.java deleted file mode 100644 index 4e13222..0000000 --- a/src/main/java/electrosphere/opencl/CLEvent.java +++ /dev/null @@ -1,65 +0,0 @@ -package electrosphere.opencl; - -import java.nio.ByteBuffer; - -import org.lwjgl.BufferUtils; -import org.lwjgl.PointerBuffer; -import org.lwjgl.opencl.CL30; -import org.lwjgl.system.MemoryStack; -import org.lwjgl.system.MemoryUtil; - -/** - * Wrapper for an opencl event - */ -public class CLEvent { - - //The pointer for the event - long pointer; - - /** - * Constructs a wrapper object around an opencl event - * @param pointer The pointer for the event - */ - protected CLEvent(long pointer){ - this.pointer = pointer; - } - - /** - * Gets the pointer for this event - * @return The pointer as a long - */ - public long getPointer(){ - return pointer; - } - - - /** - * Queries the status of the event from opencl - * @return The event status code - */ - public int getStatus(){ - int rVal = 0; - try(MemoryStack stack = MemoryStack.stackPush()){ - //create buffers for call - ByteBuffer returnValueBuffer = stack.malloc(1); - PointerBuffer sizeBuffer = stack.mallocPointer(1); - - //submit request to opencl - int errorCode = CL30.clGetEventInfo(this.getPointer(),CL30.CL_EVENT_COMMAND_EXECUTION_STATUS,returnValueBuffer,sizeBuffer); - - //check error - CLUtilities.checkCLError(errorCode); - - //get return value - rVal = returnValueBuffer.getInt(); - - // //free buffers - // MemoryUtil.memFree(returnValueBuffer); - // sizeBuffer.free(); - } - - //return - return rVal; - } - -} diff --git a/src/main/java/electrosphere/opencl/CLImage.java b/src/main/java/electrosphere/opencl/CLImage.java deleted file mode 100644 index fd8e4ad..0000000 --- a/src/main/java/electrosphere/opencl/CLImage.java +++ /dev/null @@ -1,218 +0,0 @@ -package electrosphere.opencl; - -import java.nio.ByteBuffer; -import java.nio.IntBuffer; - -import org.lwjgl.BufferUtils; -import org.lwjgl.opencl.CL30; -import org.lwjgl.opencl.CLImageDesc; -import org.lwjgl.opencl.CLImageFormat; -import org.lwjgl.system.MemoryUtil; - -/** - * Wrapper object for an opencl image - */ -public class CLImage { - - //the pointer to the image - long pointer; - - //The dimensions of the image - long width; - long height; - long depth; - - //true if device can read from the image - boolean canRead; - //true if device can write to the image - boolean canWrite; - - //the number of bytes per pixel. This is used by the command queue fetching tasks to allocate buffer sizes - long byteWidth; - - /** - * Creates an empty 2d image - * @param context The context to create the image in - * @param flags The flags for the image - * @param width The width of the image - * @param height The height of the image - */ - protected CLImage(CLContext context, long flags, long width, long height){ - //set initial values - this.width = width; - this.height = height; - this.depth = 0; - - //parse flags - this.parseFlags(flags); - - // - //Get the image format - CLImageFormat imageFormat = CLImageFormat.create(); - imageFormat.image_channel_data_type(CL30.CL_SNORM_INT8); - byteWidth = 4; - imageFormat.image_channel_order(CL30.CL_RGBA); - - // - //Get the image description - CLImageDesc imageDesc = CLImageDesc.create(); - imageDesc.image_type(CL30.CL_MEM_OBJECT_IMAGE2D); - imageDesc.image_width(width); - imageDesc.image_height(height); - imageDesc.image_depth(0); //only used for 3d image - imageDesc.image_array_size(1); //only used for 1d and 2d images - imageDesc.image_row_pitch(0); //must be 0 if host ptr is null - imageDesc.image_slice_pitch(0); //must be 0 if host ptr is null - - // - //host pointer (the data to prepopulate with) - IntBuffer hostPointerBuffer = null; //BufferUtils.createIntBuffer(1); - - // - //Create the image object - pointer = CL30.clCreateImage(context.getPointer(), flags, imageFormat, imageDesc, hostPointerBuffer, context.getErrorCodeBuffer()); - - //error check - CLUtilities.checkCLError(context.getErrorCodeBuffer()); - } - - /** - * Creates an empty 3d image - * @param context The context to create the image in - * @param flags The flags for the image - * @param width The width of the image - * @param height The height of the image - * @param depth The depth of the image - */ - protected CLImage(CLContext context, long flags, long width, long height, long depth){ - //set initial values - this.width = width; - this.height = height; - this.depth = depth; - - //parse flags - this.parseFlags(flags); - - // - //Get the image format - CLImageFormat imageFormat = CLImageFormat.create(); - imageFormat.image_channel_data_type(CL30.CL_SNORM_INT8); - byteWidth = 4; - imageFormat.image_channel_order(CL30.CL_RGBA); - - // - //Get the image description - CLImageDesc imageDesc = CLImageDesc.create(); - imageDesc.image_type(CL30.CL_MEM_OBJECT_IMAGE3D); - imageDesc.image_width(width); - imageDesc.image_height(height); - imageDesc.image_depth(depth); //only used for 3d image - imageDesc.image_array_size(1); //only used for 1d and 2d images - imageDesc.image_row_pitch(0); //must be 0 if host ptr is null - imageDesc.image_slice_pitch(0); //must be 0 if host ptr is null - - // - //host pointer (the data to prepopulate with) - IntBuffer hostPointerBuffer = null; //BufferUtils.createIntBuffer(1); - - // - //Create the image object - pointer = CL30.clCreateImage(context.getPointer(), flags, imageFormat, imageDesc, hostPointerBuffer, context.getErrorCodeBuffer()); - } - - /** - * Creates an empty 3d image - * @param context The context to create the image in - * @param flags The flags for the image - * @param width The width of the image - * @param height The height of the image - * @param depth The depth of the image - */ - protected CLImage(CLContext context, long flags, long width, long height, long depth, ByteBuffer data){ - //set initial values - this.width = width; - this.height = height; - this.depth = depth; - - //parse flags - this.parseFlags(flags); - - // - //Get the image format - CLImageFormat imageFormat = CLImageFormat.create(); - imageFormat.image_channel_data_type(CL30.CL_SNORM_INT8); - byteWidth = 4; - imageFormat.image_channel_order(CL30.CL_RGBA); - - // - //Get the image description - CLImageDesc imageDesc = CLImageDesc.create(); - imageDesc.image_type(CL30.CL_MEM_OBJECT_IMAGE3D); - imageDesc.image_width(width); - imageDesc.image_height(height); - imageDesc.image_depth(depth); //only used for 3d image - imageDesc.image_array_size(1); //only used for 1d and 2d images - imageDesc.image_row_pitch(width * byteWidth); //must be 0 if host ptr is null - imageDesc.image_slice_pitch(width * height * byteWidth); //must be 0 if host ptr is null - - // - //Create the image object - pointer = CL30.clCreateImage(context.getPointer(), flags, imageFormat, imageDesc, data, context.getErrorCodeBuffer()); - - CLUtilities.checkCLError(context); - } - - /** - * Parses the flags passed in on image creation to set variables (eg read/write status) - * @param flags The flags passed in - */ - private void parseFlags(long flags){ - if((CL30.CL_MEM_READ_ONLY & flags) != 0){ - this.canRead = true; - } - if((CL30.CL_MEM_WRITE_ONLY & flags) != 0){ - this.canWrite = true; - } - } - - /** - * Gets the pointer for the image - * @return The image pointer - */ - public long getPointer(){ - return pointer; - } - - /** - * Gets the width of the image - * @return The width of the image - */ - public long getWidth(){ - return width; - } - - /** - * Gets the height of the image - * @return The height of the image - */ - public long getHeight(){ - return height; - } - - /** - * Gets the depth of the image - * @return The depth of the image - */ - public long getDepth(){ - return depth; - } - - /** - * Gets the byte width of the image - * @return The byte width - */ - public long getByteWidth(){ - return byteWidth; - } - -} diff --git a/src/main/java/electrosphere/opencl/CLKernel.java b/src/main/java/electrosphere/opencl/CLKernel.java deleted file mode 100644 index 7efc2d2..0000000 --- a/src/main/java/electrosphere/opencl/CLKernel.java +++ /dev/null @@ -1,32 +0,0 @@ -package electrosphere.opencl; - -import org.lwjgl.opencl.CL30; - -/** - * A wrapper object for an opencl kernel - */ -public class CLKernel { - - //The pointer to the kernel - long pointer; - - /** - * Creates a cl kernel from a context and a program - * @param context The opencl context - * @param program The opencl program - * @param kernelName The name of the kernel - */ - protected CLKernel(CLContext context, CLProgram program, String kernelName){ - pointer = CL30.clCreateKernel(program.getPointer(), kernelName, context.getErrorCodeBuffer()); - CLUtilities.checkCLError(context.getErrorCodeBuffer()); - } - - /** - * Gets the pointer for this kernel - * @return The pointer as a long - */ - public long getPointer(){ - return pointer; - } - -} diff --git a/src/main/java/electrosphere/opencl/CLPlatform.java b/src/main/java/electrosphere/opencl/CLPlatform.java deleted file mode 100644 index f309dea..0000000 --- a/src/main/java/electrosphere/opencl/CLPlatform.java +++ /dev/null @@ -1,153 +0,0 @@ -package electrosphere.opencl; - -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.IntBuffer; -import java.nio.LongBuffer; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; - -import org.lwjgl.PointerBuffer; -import org.lwjgl.opencl.CL; -import org.lwjgl.opencl.CL30; -import org.lwjgl.opencl.CLCapabilities; -import org.lwjgl.system.MemoryStack; - -/** - * An object that encapsulates an openCL platform - */ -public class CLPlatform { - - //the id of the platform - long id; - - //the capabilities of the platform - CLCapabilities caps; - - //Information about the platform - String vendor; - String name; - String version; - - // the list of all cl devices on this platform - List clDevices; - - /** - * Creates a platform object - * @param id The id of the platform - */ - protected CLPlatform(long id, CLCapabilities caps, String vendor, String name, String version, List clDevices){ - this.id = id; - this.caps = caps; - this.vendor = vendor; - this.name = name; - this.version = version; - this.clDevices = clDevices; - } - - - /** - * Gets a set containing all currently available platforms - * @return The set containing all currently available platforms - */ - public static Set getPlatforms(){ - Set platforms = new HashSet(); - - try(MemoryStack stack = MemoryStack.stackPush()){ - //check if there are any platforms - IntBuffer pi = stack.mallocInt(1); - CLUtilities.checkCLError(CL30.clGetPlatformIDs(null, pi)); - if (pi.get(0) == 0) { - throw new IllegalStateException("No OpenCL platforms found."); - } - //if there are platforms, get all platform IDs - PointerBuffer platformIDs = stack.mallocPointer(pi.get(0)); - CLUtilities.checkCLError(CL30.clGetPlatformIDs(platformIDs, (IntBuffer)null)); - - //add all platforms to the returned list - for (int i = 0; i < platformIDs.capacity(); i++) { - //get basic identification - long platformId = platformIDs.get(i); - CLCapabilities caps = CL.createPlatformCapabilities(platformId); - String vendor = CLUtilities.getPlatformInfoStringUTF8(platformId, CL30.CL_PLATFORM_VENDOR); - String name = CLUtilities.getPlatformInfoStringUTF8(platformId, CL30.CL_PLATFORM_NAME); - String version = CLUtilities.getPlatformInfoStringUTF8(platformId, CL30.CL_PLATFORM_VERSION); - - - //get devices on the platform - int errcode = CL30.clGetDeviceIDs(platformId, CL30.CL_DEVICE_TYPE_GPU, null, pi); - List devices = new LinkedList(); - if(errcode != CL30.CL_DEVICE_NOT_FOUND){ - CLUtilities.checkCLError(errcode); - PointerBuffer deviceIDs = stack.mallocPointer(pi.get(0)); - CLUtilities.checkCLError(CL30.clGetDeviceIDs(platformId, CL30.CL_DEVICE_TYPE_ALL, deviceIDs, (IntBuffer)null)); - for (int j = 0; j < deviceIDs.capacity(); j++) { - long deviceId = deviceIDs.get(j); - devices.add(new CLDevice(deviceId)); - } - } - - platforms.add(new CLPlatform(platformId, caps, vendor, name, version, devices)); - } - - if (platforms.isEmpty()) { - throw new IllegalStateException("No OpenCL platform found."); - } - } - - return platforms; - } - - /** - * Gets the id of the platform - * @return the id of the platfomr - */ - public long getId(){ - return id; - } - - /** - * Gets the capabilities object of the platform - * @return The capabilities - */ - public CLCapabilities getCapabilities(){ - return caps; - } - - /** - * Gets the name of the vendor the platform - * @return The name of the vendor of the platform - */ - public String getVendor(){ - return vendor; - } - - /** - * Gets the name of the platform - * @return The name of the platform - */ - public String getName(){ - return name; - } - - /** - * Gets the version of opencl on the platform - * @return The version of opencl on the platform - */ - public String getVersion(){ - return name; - } - - /** - * Gets the list of cl devices on this platform - * @return The list of devices - */ - public List getCLDevices(){ - return clDevices; - } - -} diff --git a/src/main/java/electrosphere/opencl/CLProgram.java b/src/main/java/electrosphere/opencl/CLProgram.java deleted file mode 100644 index f30797a..0000000 --- a/src/main/java/electrosphere/opencl/CLProgram.java +++ /dev/null @@ -1,70 +0,0 @@ -package electrosphere.opencl; - -import java.util.concurrent.CountDownLatch; - -import org.lwjgl.opencl.CL30; -import org.lwjgl.opencl.CLProgramCallback; -import org.lwjgl.system.MemoryUtil; - -/** - * Wrapper object for an opencl program - */ -public class CLProgram { - - //the pointer to the program - long pointer; - - /** - * Creates an opencl program from a context and a source - * @param context The context - * @param source The source - * @return The program - */ - protected static CLProgram createProgram(CLContext context, String source){ - CLProgram program = new CLProgram(); - - //create object - program.pointer = CL30.clCreateProgramWithSource(context.getPointer(), source, context.getErrorCodeBuffer()); - CLUtilities.checkCLError(context.getErrorCodeBuffer()); - - //latch for blocking execution until the program finishes compiling - CountDownLatch latch = new CountDownLatch(1); - - //build the program - String options = ""; - CLProgramCallback buildCallback; - int errcode = CL30.clBuildProgram(program.pointer, context.getDevice().getId(), options, buildCallback = CLProgramCallback.create((programId, user_data) -> { - System.out.println(String.format( - "The cl_program [0x%X] was built %s", - programId, - CLUtilities.getProgramBuildInfoInt(programId, context.getDevice().getId(), CL30.CL_PROGRAM_BUILD_STATUS) == CL30.CL_SUCCESS ? "successfully" : "unsuccessfully" - )); - String log = CLUtilities.getProgramBuildInfoStringASCII(programId, context.getDevice().getId(), CL30.CL_PROGRAM_BUILD_LOG); - if (!log.isEmpty()) { - System.out.println(String.format("BUILD LOG:\n----\n%s\n-----", log)); - } - - latch.countDown(); - }), MemoryUtil.NULL); - CLUtilities.checkCLError(errcode); - - //Block execution until the program finishes building - try { - latch.await(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - buildCallback.free(); - - return program; - } - - /** - * Gets the pointer for this program object - * @return The pointer as a long - */ - public long getPointer(){ - return pointer; - } - -} diff --git a/src/main/java/electrosphere/opencl/CLReadImageResult.java b/src/main/java/electrosphere/opencl/CLReadImageResult.java deleted file mode 100644 index ab3081b..0000000 --- a/src/main/java/electrosphere/opencl/CLReadImageResult.java +++ /dev/null @@ -1,41 +0,0 @@ -package electrosphere.opencl; - -import java.nio.ByteBuffer; - -/** - * A pair of an opencl event and the buffer from the read operation. Used so we can pass back both from the call. - */ -public class CLReadImageResult { - - //the buffer - ByteBuffer buffer; - //the event - CLEvent event; - - /** - * Constructs the pair - * @param buffer The buffer - * @param event The event - */ - protected CLReadImageResult(ByteBuffer buffer, CLEvent event){ - this.buffer = buffer; - this.event = event; - } - - /** - * Gets the buffer - * @return The buffer - */ - public ByteBuffer getBuffer(){ - return buffer; - } - - /** - * Gets the event - * @return The event - */ - public CLEvent getEvent(){ - return event; - } - -} diff --git a/src/main/java/electrosphere/opencl/CLUtilities.java b/src/main/java/electrosphere/opencl/CLUtilities.java deleted file mode 100644 index faa4875..0000000 --- a/src/main/java/electrosphere/opencl/CLUtilities.java +++ /dev/null @@ -1,181 +0,0 @@ -package electrosphere.opencl; - -import java.nio.ByteBuffer; -import java.nio.IntBuffer; -import java.nio.LongBuffer; - -import org.lwjgl.BufferUtils; -import org.lwjgl.PointerBuffer; -import org.lwjgl.opencl.CL30; -import org.lwjgl.system.MemoryStack; -import org.lwjgl.system.MemoryUtil; - -import static org.lwjgl.opencl.CL30.*; -import static org.lwjgl.system.MemoryStack.*; -import static org.lwjgl.system.MemoryUtil.*; - -/** - * Utilities for all opencl files (for instance error checking functions) - */ -public class CLUtilities { - - /** - * Checks an opencl error code - * @param errcode The error code - */ - public static void checkCLError(IntBuffer errcode) { - checkCLError(errcode.get(errcode.position())); - } - - /** - * Checks an opencl error code - * @param errcode The error code - */ - public static void checkCLError(int errcode) { - if (errcode != CL_SUCCESS) { - throw new RuntimeException(String.format("OpenCL error [%d]", errcode)); - } - } - - /** - * Checks an opencl error code - * @param context The context containing the error code buffer - */ - public static void checkCLError(CLContext context) { - int code = context.getErrorCodeBuffer().get(); - if (code != CL_SUCCESS) { - throw new RuntimeException(String.format("OpenCL error [%d]", code)); - } - context.getErrorCodeBuffer().flip(); - } - - /** - * Gets a platform info as a utf string - * @param platformId The platform id - * @param paramName The parameter name - * @return The string containing the information - */ - public static String getPlatformInfoStringUTF8(long platformId, int paramName) { - String rVal = ""; - try(MemoryStack stack = MemoryStack.stackPush()){ - PointerBuffer resultSizeBuffer = stack.mallocPointer(1); - checkCLError(CL30.clGetPlatformInfo(platformId, paramName, (ByteBuffer)null, resultSizeBuffer)); - int bytes = (int)resultSizeBuffer.get(0); - - ByteBuffer buffer = stack.malloc(bytes); - checkCLError(CL30.clGetPlatformInfo(platformId, paramName, buffer, null)); - rVal = memUTF8(buffer, bytes - 1); - } - - return rVal; - } - - /** - * Gets an opencl device parameter as a utf8 string - * @param deviceId The device id - * @param paramName The parameter name - * @return The string - */ - public static String getDeviceInfoStringUTF8(long deviceId, int paramName) { - String rVal = ""; - try(MemoryStack stack = MemoryStack.stackPush()){ - PointerBuffer pp = stack.mallocPointer(1); - checkCLError(clGetDeviceInfo(deviceId, paramName, (ByteBuffer)null, pp)); - int bytes = (int)pp.get(0); - - ByteBuffer buffer = stack.malloc(bytes); - checkCLError(clGetDeviceInfo(deviceId, paramName, buffer, null)); - rVal = memUTF8(buffer, bytes - 1); - } - return rVal; - } - - /** - * Gets a device parameter's value as an int - * @param deviceId The id of the device - * @param paramName The parameter name - * @return The int - */ - public static int getDeviceInfoInt(long deviceId, int paramName) { - int rVal = 0; - try(MemoryStack stack = MemoryStack.stackPush()){ - IntBuffer pl = stack.mallocInt(1); - checkCLError(clGetDeviceInfo(deviceId, paramName, pl, null)); - rVal = pl.get(0); - } - return rVal; - } - - /** - * Gets a device's parameter's value as a long - * @param deviceId The device's id - * @param paramName The parameter name - * @return The value as a long - */ - public static long getDeviceInfoLong(long deviceId, int paramName) { - long rVal = 0; - try(MemoryStack stack = MemoryStack.stackPush()){ - LongBuffer pl = stack.mallocLong(1); - checkCLError(clGetDeviceInfo(deviceId, paramName, pl, null)); - rVal = pl.get(0); - } - return rVal; - } - - /** - * Gets a device's parameter's value as a boolean - * @param deviceId The device's id - * @param paramName The parameter name - * @return The value as a boolean - */ - public static boolean getDeviceInfoBoolean(long deviceId, int paramName) { - byte rVal = 0; - try(MemoryStack stack = MemoryStack.stackPush()){ - ByteBuffer pl = stack.malloc(1); - checkCLError(clGetDeviceInfo(deviceId, paramName, pl, null)); - rVal = pl.get(0); - } - return rVal == 0; - } - - /** - * Gets an opencl program build parameter as an int - * @param programId The program id - * @param deviceId The device id - * @param parameterName The parameter name - * @return THe value of the parameter as an int - */ - public static int getProgramBuildInfoInt(long programId, long deviceId, int parameterName) { - int rVal = 0; - try(MemoryStack stack = MemoryStack.stackPush()){ - IntBuffer pl = stack.mallocInt(1); - checkCLError(clGetProgramBuildInfo(programId, deviceId, parameterName, pl, null)); - rVal = pl.get(0); - } - return rVal; - } - - /** - * Gets an opencl program build parameter as a string - * @param programId The program id - * @param deviceId The device id - * @param parameterName The parameter name - * @return The value of the parameter as a string - */ - public static String getProgramBuildInfoStringASCII(long programId, long deviceId, int parameterName) { - String rVal = ""; - try(MemoryStack stack = MemoryStack.stackPush()){ - PointerBuffer pp = stack.mallocPointer(1); - checkCLError(clGetProgramBuildInfo(programId, deviceId, parameterName, (ByteBuffer)null, pp)); - int bytes = (int)pp.get(0); - - ByteBuffer buffer = stack.malloc(bytes); - checkCLError(clGetProgramBuildInfo(programId, deviceId, parameterName, buffer, null)); - - rVal = memASCII(buffer, bytes - 1);; - } - - return rVal; - } - -} diff --git a/src/main/java/electrosphere/opencl/LWJGLContext.java b/src/main/java/electrosphere/opencl/LWJGLContext.java deleted file mode 100644 index 5a92439..0000000 --- a/src/main/java/electrosphere/opencl/LWJGLContext.java +++ /dev/null @@ -1,28 +0,0 @@ -package electrosphere.opencl; - -import org.lwjgl.system.MemoryStack; - -/** - * A context for the lwjgl framework. Contains stack used by opencl api. - */ -public class LWJGLContext { - - //The stack for memory allocation - MemoryStack stack; - - /** - * Constructor - */ - public LWJGLContext(){ - stack = MemoryStack.create(1000 * 1000 * 4 * 4); - } - - /** - * Gets the memory stack for the current context - * @return The lwjgl context's memory stack - */ - public MemoryStack getStack(){ - return stack; - } - -} diff --git a/src/main/java/electrosphere/render/GLFWContext.java b/src/main/java/electrosphere/render/GLFWContext.java index b2f3b1e..b2c7f77 100644 --- a/src/main/java/electrosphere/render/GLFWContext.java +++ b/src/main/java/electrosphere/render/GLFWContext.java @@ -39,14 +39,19 @@ public class GLFWContext { //Maximize it GLFW.glfwMaximizeWindow(window); //grab actual framebuffer - IntBuffer xBuffer = BufferUtils.createIntBuffer(1); - IntBuffer yBuffer = BufferUtils.createIntBuffer(1); - GLFW.glfwGetFramebufferSize(window, xBuffer, yBuffer); - MemoryUtil.memFree(xBuffer); - MemoryUtil.memFree(yBuffer); - - int bufferWidth = xBuffer.get(); - int bufferHeight = yBuffer.get(); + int bufferWidth = 0; + int bufferHeight = 0; + + try(MemoryStack stack = MemoryStack.stackPush()){ + IntBuffer xBuffer = MemoryUtil.memAllocInt(1); + IntBuffer yBuffer = MemoryUtil.memAllocInt(1); + GLFW.glfwGetFramebufferSize(window, xBuffer, yBuffer); + MemoryUtil.memFree(xBuffer); + MemoryUtil.memFree(yBuffer); + + bufferWidth = xBuffer.get(); + bufferHeight = yBuffer.get(); + } // // Attack controls callbacks diff --git a/src/main/java/electrosphere/render/GridCell.java b/src/main/java/electrosphere/render/GridCell.java new file mode 100644 index 0000000..033d0cb --- /dev/null +++ b/src/main/java/electrosphere/render/GridCell.java @@ -0,0 +1,19 @@ +package electrosphere.render; + +import org.joml.Vector3f; + +public class GridCell { + Vector3f[] points = new Vector3f[8]; //array of size 8 + double[] val = new double[8]; //array of size 8 + public void setValues( + Vector3f p1, Vector3f p2, Vector3f p3, Vector3f p4, + Vector3f p5, Vector3f p6, Vector3f p7, Vector3f p8, + double val1, double val2, double val3, double val4, + double val5, double val6, double val7, double val8 + ){ + points[0] = p1; points[1] = p2; points[2] = p3; points[3] = p4; + points[4] = p5; points[5] = p6; points[6] = p7; points[7] = p8; + val[0] = val1; val[1] = val2; val[2] = val3; val[3] = val4; + val[4] = val5; val[5] = val6; val[6] = val7; val[7] = val8; + } +} diff --git a/src/main/java/electrosphere/render/Mesh.java b/src/main/java/electrosphere/render/Mesh.java index 1e6fe62..bda1c20 100644 --- a/src/main/java/electrosphere/render/Mesh.java +++ b/src/main/java/electrosphere/render/Mesh.java @@ -38,7 +38,7 @@ public class Mesh { static Matrix4f projectionMatrix = new Matrix4f(); static Matrix4f model = new Matrix4f().identity(); - static MemoryStack stack = MemoryStack.create(16 * 1000 * 1000); + static MemoryStack stack = MemoryStack.create(32 * 1000 * 1000); public static void meshInitially(FluidSim sim){ //create and bind vao @@ -55,7 +55,7 @@ public class Mesh { GL44.glBindBuffer(GL44.GL_ARRAY_BUFFER, vertBufferPtr); try { int vertexCount = data.vertices.size(); - FloatBuffer vertData = BufferUtils.createFloatBuffer(vertexCount); + FloatBuffer vertData = MemoryUtil.memAllocFloat(vertexCount); for(float vertValue : data.vertices){ vertData.put(vertValue); } @@ -63,7 +63,7 @@ public class Mesh { GL44.glBufferData(GL44.GL_ARRAY_BUFFER,vertData,GL44.GL_STATIC_DRAW); GL44.glVertexAttribPointer(0, 3, GL44.GL_FLOAT, false, 0, 0); GL44.glEnableVertexAttribArray(0); - // MemoryUtil.memFree(vertData); + MemoryUtil.memFree(vertData); } catch (NullPointerException ex){ ex.printStackTrace(); } @@ -77,13 +77,13 @@ public class Mesh { GL44.glBindBuffer(GL44.GL_ELEMENT_ARRAY_BUFFER, faceBufferPtr); elementCount = data.elements.size(); try { - IntBuffer elementArrayBufferData = BufferUtils.createIntBuffer(elementCount); + IntBuffer elementArrayBufferData = MemoryUtil.memAllocInt(elementCount); for(int element : data.elements){ elementArrayBufferData.put(element); } elementArrayBufferData.flip(); GL44.glBufferData(GL45.GL_ELEMENT_ARRAY_BUFFER,elementArrayBufferData,GL44.GL_STATIC_DRAW); - // MemoryUtil.memFree(elementArrayBufferData); + MemoryUtil.memFree(elementArrayBufferData); } catch (NullPointerException ex){ ex.printStackTrace(); } @@ -100,7 +100,7 @@ public class Mesh { int normalCount = data.normals.size() / 3; FloatBuffer NormalArrayBufferData; if(normalCount > 0){ - NormalArrayBufferData = BufferUtils.createFloatBuffer(normalCount * 3); + NormalArrayBufferData = MemoryUtil.memAllocFloat(normalCount * 3); float[] temp = new float[3]; for(float normalValue : data.normals){ NormalArrayBufferData.put(normalValue); @@ -202,67 +202,66 @@ public class Mesh { //generate verts TerrainChunkData data = generateTerrainChunkData(sim.getData()); - try(MemoryStack stackLocal = stack.push()){ - // - //Buffer data to GPU - // - GL44.glBindBuffer(GL44.GL_ARRAY_BUFFER, vertBufferPtr); - try { - int vertexCount = data.vertices.size(); - FloatBuffer vertData = stackLocal.mallocFloat(vertexCount); - for(float vertValue : data.vertices){ - vertData.put(vertValue); - } - vertData.flip(); - GL44.glBufferData(GL44.GL_ARRAY_BUFFER,vertData,GL44.GL_STATIC_DRAW); - GL44.glVertexAttribPointer(0, 3, GL44.GL_FLOAT, false, 0, 0); - GL44.glEnableVertexAttribArray(0); - } catch (NullPointerException ex){ - ex.printStackTrace(); + // + //Buffer data to GPU + // + GL44.glBindBuffer(GL44.GL_ARRAY_BUFFER, vertBufferPtr); + try { + int vertexCount = data.vertices.size(); + FloatBuffer vertData = MemoryUtil.memAllocFloat(vertexCount); + for(float vertValue : data.vertices){ + vertData.put(vertValue); } - + vertData.flip(); + GL44.glBufferData(GL44.GL_ARRAY_BUFFER,vertData,GL44.GL_STATIC_DRAW); + GL44.glVertexAttribPointer(0, 3, GL44.GL_FLOAT, false, 0, 0); + GL44.glEnableVertexAttribArray(0); + MemoryUtil.memFree(vertData); + } catch (NullPointerException ex){ + ex.printStackTrace(); + } + - - // - // FACES - // - GL44.glBindBuffer(GL44.GL_ELEMENT_ARRAY_BUFFER, faceBufferPtr); - elementCount = data.elements.size(); - try { - IntBuffer elementArrayBufferData = stackLocal.mallocInt(elementCount); - for(int element : data.elements){ - elementArrayBufferData.put(element); - } - elementArrayBufferData.flip(); - GL44.glBufferData(GL45.GL_ELEMENT_ARRAY_BUFFER,elementArrayBufferData,GL44.GL_STATIC_DRAW); - } catch (NullPointerException ex){ - ex.printStackTrace(); + // + // FACES + // + GL44.glBindBuffer(GL44.GL_ELEMENT_ARRAY_BUFFER, faceBufferPtr); + elementCount = data.elements.size(); + try { + IntBuffer elementArrayBufferData = MemoryUtil.memAllocInt(elementCount); + for(int element : data.elements){ + elementArrayBufferData.put(element); } - - - - - // - // NORMALS - // - GL44.glBindBuffer(GL44.GL_ARRAY_BUFFER, normBufferPtr); - try { - int normalCount = data.normals.size() / 3; - FloatBuffer NormalArrayBufferData; - if(normalCount > 0){ - NormalArrayBufferData = stackLocal.mallocFloat(normalCount * 3); - for(float normalValue : data.normals){ - NormalArrayBufferData.put(normalValue); - } - NormalArrayBufferData.flip(); - GL44.glBufferData(GL44.GL_ARRAY_BUFFER,NormalArrayBufferData,GL44.GL_STATIC_DRAW); - GL44.glVertexAttribPointer(1, 3, GL44.GL_FLOAT, false, 0, 0); - GL44.glEnableVertexAttribArray(1); + elementArrayBufferData.flip(); + GL44.glBufferData(GL45.GL_ELEMENT_ARRAY_BUFFER,elementArrayBufferData,GL44.GL_STATIC_DRAW); + MemoryUtil.memFree(elementArrayBufferData); + } catch (NullPointerException ex){ + ex.printStackTrace(); + } + + + + // + // NORMALS + // + GL44.glBindBuffer(GL44.GL_ARRAY_BUFFER, normBufferPtr); + try { + int normalCount = data.normals.size() / 3; + FloatBuffer NormalArrayBufferData; + if(normalCount > 0){ + NormalArrayBufferData = MemoryUtil.memAllocFloat(normalCount * 3); + for(float normalValue : data.normals){ + NormalArrayBufferData.put(normalValue); } - } catch (NullPointerException ex){ - ex.printStackTrace(); + NormalArrayBufferData.flip(); + GL44.glBufferData(GL44.GL_ARRAY_BUFFER,NormalArrayBufferData,GL44.GL_STATIC_DRAW); + GL44.glVertexAttribPointer(1, 3, GL44.GL_FLOAT, false, 0, 0); + GL44.glEnableVertexAttribArray(1); + MemoryUtil.memFree(NormalArrayBufferData); } + } catch (NullPointerException ex){ + ex.printStackTrace(); } } @@ -613,33 +612,6 @@ public class Mesh { (byte)0x13 }; - static class Triangle { - int[] indices = new int[3]; //array of size 3 - - public Triangle(int index0, int index1, int index2){ - indices[0] = index0; - indices[1] = index1; - indices[2] = index2; - } - } - - static class GridCell { - Vector3f[] points = new Vector3f[8]; //array of size 8 - double[] val = new double[8]; //array of size 8 - public void setValues( - Vector3f p1, Vector3f p2, Vector3f p3, Vector3f p4, - Vector3f p5, Vector3f p6, Vector3f p7, Vector3f p8, - double val1, double val2, double val3, double val4, - double val5, double val6, double val7, double val8 - ){ - points[0] = p1; points[1] = p2; points[2] = p3; points[3] = p4; - points[4] = p5; points[5] = p6; points[6] = p7; points[7] = p8; - val[0] = val1; val[1] = val2; val[2] = val3; val[3] = val4; - val[4] = val5; val[5] = val6; val[6] = val7; val[7] = val8; - } - } - - protected static int polygonize( @@ -897,20 +869,6 @@ public class Mesh { return rVal; } - static class TerrainChunkData { - - List vertices; - List normals; - List elements; - - TerrainChunkData(List vertices, List normals, List elements){ - this.vertices = vertices; - this.normals = normals; - this.elements = elements; - } - - } - //TODO: more optimal key creation private static String getVertKeyFromPoints(float x, float y, float z){ return x + "_" + y + "_" + z; @@ -934,5 +892,7 @@ public class Mesh { rVal = rVal.mul(proportion0).add(new Vector3f(normal1).mul(proportion1)); return rVal; } + + static TerrainChunkData data = generateTerrainChunkData(new float[FluidSim.DIM * FluidSim.DIM * FluidSim.DIM]); } diff --git a/src/main/java/electrosphere/render/TerrainChunkData.java b/src/main/java/electrosphere/render/TerrainChunkData.java new file mode 100644 index 0000000..a099e62 --- /dev/null +++ b/src/main/java/electrosphere/render/TerrainChunkData.java @@ -0,0 +1,15 @@ +package electrosphere.render; + +import java.util.List; + +public class TerrainChunkData { + List vertices; + List normals; + List elements; + + TerrainChunkData(List vertices, List normals, List elements){ + this.vertices = vertices; + this.normals = normals; + this.elements = elements; + } +} diff --git a/src/main/java/electrosphere/render/Triangle.java b/src/main/java/electrosphere/render/Triangle.java new file mode 100644 index 0000000..bede795 --- /dev/null +++ b/src/main/java/electrosphere/render/Triangle.java @@ -0,0 +1,11 @@ +package electrosphere.render; + +public class Triangle { + int[] indices = new int[3]; //array of size 3 + + public Triangle(int index0, int index1, int index2){ + indices[0] = index0; + indices[1] = index1; + indices[2] = index2; + } +} diff --git a/src/main/resources/shader.fs b/src/main/resources/shader.fs index 401f626..905d839 100644 --- a/src/main/resources/shader.fs +++ b/src/main/resources/shader.fs @@ -1,7 +1,5 @@ #version 330 core -#define NR_POINT_LIGHTS 10 - out vec4 FragColor; @@ -26,19 +24,7 @@ void main(){ vec3 norm = normalize(Normal); vec3 viewDir = normalize(viewPos - FragPos); - // //grab light intensity - // float lightIntensity = calcLightIntensityTotal(norm); - - // //get color of base texture - // vec3 textureColor = vec3(1); - - - // //calculate final color - // vec3 finalColor = textureColor * lightIntensity; vec3 lightAmount = CalcDirLight(norm, viewDir); - // for(int i = 0; i < NR_POINT_LIGHTS; i++){ - // lightAmount += CalcPointLight(i, norm, FragPos, viewDir); - // } vec3 color = vec3(0.3,0.7,0.9) * lightAmount; @@ -54,7 +40,6 @@ vec3 CalcDirLight(vec3 normal, vec3 viewDir){ vec3 reflectDir = reflect(-lightDir, normal); float spec = pow(max(dot(viewDir, reflectDir), 0.0), 0.6); // combine results - // vec3 texColor = texture(material.diffuse, TexCoord).rgb; vec3 diffuse = dLDiffuse * diff; vec3 specular = spec * color; diff --git a/src/main/resources/shader.vs b/src/main/resources/shader.vs index 5222219..a2b344b 100644 --- a/src/main/resources/shader.vs +++ b/src/main/resources/shader.vs @@ -1,10 +1,6 @@ //Vertex Shader #version 330 core -//defines -#define TEXTURE_MAP_SCALE 3.0 - - //input buffers layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aNormal;