diff options
-rw-r--r-- | src/com/mbien/opencl/CLBuffer.java | 36 | ||||
-rw-r--r-- | test/com/mbien/opencl/HighLevelBindingTest.java | 77 |
2 files changed, 87 insertions, 26 deletions
diff --git a/src/com/mbien/opencl/CLBuffer.java b/src/com/mbien/opencl/CLBuffer.java index 0a001f6b..fb63b6ec 100644 --- a/src/com/mbien/opencl/CLBuffer.java +++ b/src/com/mbien/opencl/CLBuffer.java @@ -36,17 +36,29 @@ public class CLBuffer<B extends Buffer> implements CLResource { this.context = context; this.cl = context.cl; - int[] intArray = new int[1]; + int[] result = new int[1]; if(glBuffer == 0) { + B host_ptr = null; + if(isHostPointerFlag(flags)) { + host_ptr = directBuffer; + } this.ID = cl.clCreateBuffer(context.ID, flags, - sizeOfBufferElem(directBuffer)*directBuffer.capacity(), null, intArray, 0); + sizeOfBufferElem(directBuffer)*directBuffer.capacity(), host_ptr, result, 0); }else{ + if(isHostPointerFlag(flags)) { + throw new IllegalArgumentException( + "CL_MEM_COPY_HOST_PTR or CL_MEM_USE_HOST_PTR can not be used with OpenGL Buffers."); + } CLGLI clgli = (CLGLI)cl; - this.ID = clgli.clCreateFromGLBuffer(context.ID, flags, glBuffer, intArray, 0); + this.ID = clgli.clCreateFromGLBuffer(context.ID, flags, glBuffer, result, 0); } - checkForError(intArray[0], "can not create cl buffer"); + checkForError(result[0], "can not create cl buffer"); + + } + private final boolean isHostPointerFlag(int flags) { + return (flags & CL_MEM_COPY_HOST_PTR) != 0 || (flags & CL_MEM_USE_HOST_PTR) != 0; } public void release() { @@ -127,26 +139,28 @@ public class CLBuffer<B extends Buffer> implements CLResource { * object when used inside a kernel. Writing to a buffer or image object * created withREAD_ONLY inside a kernel is undefined. */ - READ_ONLY(CL_MEM_READ_ONLY); + READ_ONLY(CL_MEM_READ_ONLY), /** + * Enum representing CL.CL_MEM_USE_HOST_PTR. * If specified, it indicates that the application wants the OpenCL * implementation to use memory referenced by host_ptr as the storage * bits for the memory object. OpenCL implementations are allowed * to cache the buffer contents pointed to by host_ptr in device memory. * This cached copy can be used when kernels are executed on a device. */ -// USE_HOST_PTR(CL_MEM_USE_HOST_PTR), + USE_BUFFER(CL_MEM_USE_HOST_PTR), // ALLOC_HOST_PTR(CL_MEM_ALLOC_HOST_PTR), // this is the default in java world anyway /** + * Enum representing CL.CL_MEM_COPY_HOST_PTR. * If CL_MEM_COPY_HOST_PTR specified, it indicates that the application * wants the OpenCL implementation to allocate memory for the memory object * and copy the data from memory referenced by host_ptr.<br/> * COPY_HOST_PTR and USE_HOST_PTR are mutually exclusive. */ -// COPY_HOST_PTR(CL_MEM_COPY_HOST_PTR); + COPY_BUFFER(CL_MEM_COPY_HOST_PTR); /** * Value of wrapped OpenCL flag. @@ -163,12 +177,12 @@ public class CLBuffer<B extends Buffer> implements CLResource { return READ_WRITE; case(CL_MEM_READ_ONLY): return READ_ONLY; -// case(CL_MEM_USE_HOST_PTR): -// return USE_HOST_PTR; + case(CL_MEM_USE_HOST_PTR): + return USE_BUFFER; // case(CL_MEM_ALLOC_HOST_PTR): // return ALLOC_HOST_PTR; -// case(CL_MEM_COPY_HOST_PTR): -// return COPY_HOST_PTR; + case(CL_MEM_COPY_HOST_PTR): + return COPY_BUFFER; } return null; } diff --git a/test/com/mbien/opencl/HighLevelBindingTest.java b/test/com/mbien/opencl/HighLevelBindingTest.java index 5515cecc..da1080d1 100644 --- a/test/com/mbien/opencl/HighLevelBindingTest.java +++ b/test/com/mbien/opencl/HighLevelBindingTest.java @@ -3,6 +3,7 @@ package com.mbien.opencl; import com.mbien.opencl.CLBuffer.Mem; import com.mbien.opencl.CLCommandQueue.Mode; import com.mbien.opencl.CLDevice.SingleFPConfig; +import com.sun.opengl.util.BufferUtil; import java.io.IOException; import java.nio.ByteBuffer; import java.util.EnumSet; @@ -21,6 +22,9 @@ import static com.sun.gluegen.runtime.BufferFactory.*; */ public class HighLevelBindingTest { + //decrease this value on systems with few memory. + private final static int NUM_ELEMENTS = 10000000; + @BeforeClass public static void setUpClass() throws Exception { out.println("OS: " + System.getProperty("os.name")); @@ -187,7 +191,7 @@ public class HighLevelBindingTest { out.println(" - - - highLevelTest; copy buffer test - - - "); - final int elements = 10000000; //many.. + final int elements = NUM_ELEMENTS; CLContext context = CLContext.create(); @@ -208,24 +212,51 @@ public class HighLevelBindingTest { context.release(); - ByteBuffer a = clBufferA.buffer; - ByteBuffer b = clBufferB.buffer; - - // print first few elements of the resulting buffer to the console. out.println("validating computed results..."); - for(int i = 0; i < elements; i++) { - int aVal = a.getInt(); - int bVal = b.getInt(); - if(aVal != bVal) { - out.println("a: "+aVal); - out.println("b: "+bVal); - out.println("position: "+a.position()); - fail("a!=b"); - } + checkIfEqual(clBufferA.buffer, clBufferB.buffer, elements); + out.println("results are valid"); + + } + + @Test + public void bufferWithHostPointerTest() throws IOException { + + out.println(" - - - highLevelTest; host pointer test - - - "); + + final int elements = NUM_ELEMENTS; + + CLContext context = CLContext.create(); + + ByteBuffer buffer = BufferUtil.newByteBuffer(elements*SIZEOF_INT); + // fill only first read buffer -> we will copy the payload to the second later. + fillBuffer(buffer, 12345); + CLCommandQueue queue = context.getCLDevices()[0].createCommandQueue(); + + Mem[] bufferConfig = new Mem[] {Mem.COPY_BUFFER, Mem.USE_BUFFER}; + + for(int i = 0; i < bufferConfig.length; i++) { + + out.println("testing with "+bufferConfig[i] + " config"); + + CLBuffer<ByteBuffer> clBufferA = context.createBuffer(buffer, Mem.READ_ONLY, bufferConfig[i]); + CLBuffer<ByteBuffer> clBufferB = context.createByteBuffer(elements*SIZEOF_INT, Mem.READ_ONLY); + + // asynchronous write of data to GPU device, blocking read later to get the computed results back. + queue.putCopyBuffer(clBufferA, clBufferB, clBufferA.buffer.capacity()) // copy A -> B + .putReadBuffer(clBufferB, true) // read B + .finish(); + + clBufferA.release(); + clBufferB.release(); + + // uploading worked when a==b. + out.println("validating computed results..."); + checkIfEqual(clBufferA.buffer, clBufferB.buffer, elements); + out.println("results are valid"); } - out.println("results are valid"); + context.release(); } @Test @@ -267,5 +298,21 @@ public class HighLevelBindingTest { context.release(); } + + + private final void checkIfEqual(ByteBuffer a, ByteBuffer b, int elements) { + for(int i = 0; i < elements; i++) { + int aVal = a.getInt(); + int bVal = b.getInt(); + if(aVal != bVal) { + out.println("a: "+aVal); + out.println("b: "+bVal); + out.println("position: "+a.position()); + fail("a!=b"); + } + } + a.rewind(); + b.rewind(); + } } |