From a81e907b30364b1abc2a75d446772f066fbf74ff Mon Sep 17 00:00:00 2001 From: Michael Bien Date: Mon, 5 Jul 2010 00:10:15 +0200 Subject: finished CLSubBuffer, added junit testcase, perf improvements and cleanup. CLMemory methods contain now NIO infix for nio buffer specific queries and CL infix for memory object queries. --- src/com/jogamp/opencl/CLBuffer.java | 65 ++++++++++++++++++---------- src/com/jogamp/opencl/CLCommandQueue.java | 4 +- src/com/jogamp/opencl/CLImage.java | 2 +- src/com/jogamp/opencl/CLMemory.java | 34 ++++++++++----- src/com/jogamp/opencl/CLSubBuffer.java | 18 +++++--- src/com/jogamp/opencl/gl/CLGLBuffer.java | 2 +- test/com/jogamp/opencl/CLBufferTest.java | 70 +++++++++++++++++++++++++++++++ 7 files changed, 155 insertions(+), 40 deletions(-) diff --git a/src/com/jogamp/opencl/CLBuffer.java b/src/com/jogamp/opencl/CLBuffer.java index e2c74c7d..2c3fd2af 100644 --- a/src/com/jogamp/opencl/CLBuffer.java +++ b/src/com/jogamp/opencl/CLBuffer.java @@ -6,23 +6,24 @@ import com.jogamp.common.nio.PointerBuffer; import com.jogamp.opencl.CLMemory.Mem; import java.nio.Buffer; import java.util.ArrayList; +import java.util.Collections; import static com.jogamp.opencl.CLException.*; /** - * OpenCL buffer object. + * OpenCL buffer object wrapping an optional NIO buffer. * @author Michael Bien */ public class CLBuffer extends CLMemory { - private List> childs; + private List> childs; - protected CLBuffer(CLContext context, long id, int flags) { - super(context, id, flags); + protected CLBuffer(CLContext context, long size, long id, int flags) { + this(context, null, size, id, flags); } - protected CLBuffer(CLContext context, B directBuffer, long id, int flags) { - super(context, directBuffer, id, flags); + protected CLBuffer(CLContext context, B directBuffer, long size, long id, int flags) { + super(context, directBuffer, size, id, flags); } @SuppressWarnings("unchecked") @@ -38,7 +39,7 @@ public class CLBuffer extends CLMemory { long id = cl.clCreateBuffer(context.ID, flags, size, null, result, 0); checkForError(result[0], "can not create cl buffer"); - return new CLBuffer(context, id, flags); + return new CLBuffer(context, size, id, flags); } static CLBuffer create(CLContext context, B directBuffer, int flags) { @@ -53,32 +54,43 @@ public class CLBuffer extends CLMemory { if(isHostPointerFlag(flags)) { host_ptr = directBuffer; } - long id = cl.clCreateBuffer(context.ID, flags, sizeOfBufferElem(directBuffer)*directBuffer.capacity(), host_ptr, result, 0); + int size = sizeOfBufferElem(directBuffer) * directBuffer.capacity(); + long id = cl.clCreateBuffer(context.ID, flags, size, host_ptr, result, 0); checkForError(result[0], "can not create cl buffer"); - return new CLBuffer(context, directBuffer, id, flags); + return new CLBuffer(context, directBuffer, size, id, flags); } /** * Creates a sub buffer with the specified region from this buffer. + * If this buffer contains a NIO buffer, the sub buffer will also contain a slice + * matching the specified region of the parent buffer. The region is specified + * by the offset and size in buffer elements or bytes if this buffer does not + * contain any NIO buffer. + * @param offset The offset in buffer elements. + * @param size The size in buffer elements. */ - public CLBuffer createSubBuffer(int origin, int size, Mem... flags) { + public CLSubBuffer createSubBuffer(int offset, int size, Mem... flags) { + + B slice = null; + if(buffer != null) { + slice = (B)Buffers.slice(buffer, offset, size); + int elemSize = Buffers.sizeOfBufferElem(buffer); + offset *= elemSize; + size *= elemSize; + } + PointerBuffer info = PointerBuffer.allocateDirect(2); - info.put(origin).put(size).rewind(); + info.put(offset).put(size).rewind(); int bitset = Mem.flagsToInt(flags); int[] err = new int[1]; long subID = cl.clCreateSubBuffer(ID, bitset, CL.CL_BUFFER_CREATE_TYPE_REGION, info.getBuffer(), err, 0); checkForError(err[0], "can not create sub buffer"); - B slice = null; - if(buffer != null) { - slice = (B)Buffers.slice(buffer, origin, size); - } - - CLSubBuffer clSubBuffer = new CLSubBuffer(this, origin, slice, subID, bitset); + CLSubBuffer clSubBuffer = new CLSubBuffer(this, offset, size, slice, subID, bitset); if(childs == null) { - childs = new ArrayList>(); + childs = new ArrayList>(); } childs.add(clSubBuffer); return clSubBuffer; @@ -87,8 +99,8 @@ public class CLBuffer extends CLMemory { @Override public void release() { if(childs != null) { - for (CLBuffer child : childs) { - child.release(); + while(!childs.isEmpty()) { + childs.get(0).release(); } } super.release(); @@ -98,6 +110,17 @@ public class CLBuffer extends CLMemory { childs.remove(sub); } + /** + * Returns the list of subbuffers. + */ + public List> getSubBuffers() { + if(childs == null) { + return Collections.EMPTY_LIST; + }else{ + return Collections.unmodifiableList(childs); + } + } + /** * Returns true if this is a sub buffer. */ @@ -107,7 +130,7 @@ public class CLBuffer extends CLMemory { @Override public CLBuffer cloneWith(T directBuffer) { - return new CLBuffer(context, directBuffer, ID, FLAGS); + return new CLBuffer(context, directBuffer, size, ID, FLAGS); } } diff --git a/src/com/jogamp/opencl/CLCommandQueue.java b/src/com/jogamp/opencl/CLCommandQueue.java index d7fc7748..7dee2cf7 100644 --- a/src/com/jogamp/opencl/CLCommandQueue.java +++ b/src/com/jogamp/opencl/CLCommandQueue.java @@ -89,7 +89,7 @@ public class CLCommandQueue extends CLObject implements CLResource { int ret = cl.clEnqueueWriteBuffer( ID, writeBuffer.ID, clBoolean(blockingWrite), - 0, writeBuffer.getSize(), writeBuffer.buffer, + 0, writeBuffer.getNIOSize(), writeBuffer.buffer, conditions, conditionIDs, events==null ? null : events.IDs); if(ret != CL_SUCCESS) { @@ -133,7 +133,7 @@ public class CLCommandQueue extends CLObject implements CLResource { int ret = cl.clEnqueueReadBuffer( ID, readBuffer.ID, clBoolean(blockingRead), - 0, readBuffer.getSize(), readBuffer.buffer, + 0, readBuffer.getNIOSize(), readBuffer.buffer, conditions, conditionIDs, events==null ? null : events.IDs); if(ret != CL_SUCCESS) { diff --git a/src/com/jogamp/opencl/CLImage.java b/src/com/jogamp/opencl/CLImage.java index cc1eb59e..434acc24 100644 --- a/src/com/jogamp/opencl/CLImage.java +++ b/src/com/jogamp/opencl/CLImage.java @@ -23,7 +23,7 @@ public abstract class CLImage extends CLMemory { } protected CLImage(CLContext context, B directBuffer, CLImageFormat format, CLImageInfoAccessor accessor, int width, int height, long id, int flags) { - super(context, directBuffer, id, flags); + super(context, directBuffer, getSizeImpl(context.cl, id), id, flags); this.imageInfo = accessor; this.format = format; this.width = width; diff --git a/src/com/jogamp/opencl/CLMemory.java b/src/com/jogamp/opencl/CLMemory.java index 6ab5cd02..d66db3c8 100644 --- a/src/com/jogamp/opencl/CLMemory.java +++ b/src/com/jogamp/opencl/CLMemory.java @@ -18,22 +18,24 @@ import static com.jogamp.opencl.gl.CLGLI.*; /** * Common superclass for all OpenCL memory types. + * Represents an OpenCL memory object and wraps an optional NIO buffer. * @author Michael Bien */ public abstract class CLMemory extends CLObject implements CLResource { B buffer; protected final int FLAGS; + protected final long size; - protected CLMemory(CLContext context, long id, int flags) { - super(context, id); - this.FLAGS = flags; + protected CLMemory(CLContext context, long size, long id, int flags) { + this(context, null, size, id, flags); } - protected CLMemory(CLContext context, B directBuffer, long id, int flags) { + protected CLMemory(CLContext context, B directBuffer, long size, long id, int flags) { super(context, id); this.buffer = directBuffer; this.FLAGS = flags; + this.size = size; } /** @@ -59,6 +61,13 @@ public abstract class CLMemory extends CLObject implements CL throw new RuntimeException("Unexpected buffer type " + buffer.getClass().getName()); } + protected static long getSizeImpl(CL cl, long id) { + PointerBuffer pb = PointerBuffer.allocateDirect(1); + int ret = cl.clGetMemObjectInfo(id, CL_MEM_SIZE, PointerBuffer.elementSize(), pb.getBuffer(), null); + checkForError(ret, "can not obtain buffer info"); + return pb.get(); + } + protected static CL getCL(CLContext context) { return context.cl; } @@ -89,7 +98,7 @@ public abstract class CLMemory extends CLObject implements CL /** * Returns the capacity of the wrapped direct buffer or 0 if no buffer available. */ - public int getCapacity() { + public int getNIOCapacity() { if(buffer == null) { return 0; } @@ -99,7 +108,7 @@ public abstract class CLMemory extends CLObject implements CL /** * Returns the size of the wrapped direct buffer in byte or 0 if no buffer available. */ - public int getSize() { + public int getNIOSize() { if(buffer == null) { return 0; } @@ -110,10 +119,15 @@ public abstract class CLMemory extends CLObject implements CL * Returns the size of the allocated OpenCL memory. */ public long getCLSize() { - PointerBuffer pb = PointerBuffer.allocateDirect(1); - int ret = cl.clGetMemObjectInfo(ID, CL_MEM_SIZE, PointerBuffer.elementSize(), pb.getBuffer(), null); - checkForError(ret, "can not obtain buffer info"); - return pb.get(); + return size; + } + + /** + * Returns the size in buffer elements of this memory object. + */ + public int getCLCapacity() { + int elemSize = buffer==null ? 1 : sizeOfBufferElem(buffer); + return (int) (getCLSize() / elemSize); } /** diff --git a/src/com/jogamp/opencl/CLSubBuffer.java b/src/com/jogamp/opencl/CLSubBuffer.java index 614dfa80..165df23f 100644 --- a/src/com/jogamp/opencl/CLSubBuffer.java +++ b/src/com/jogamp/opencl/CLSubBuffer.java @@ -12,18 +12,18 @@ public class CLSubBuffer extends CLBuffer { private CLBuffer parent; private final int offset; - CLSubBuffer(CLBuffer parent, int origin, B directBuffer, long id, int flags) { - super(parent.getContext(), directBuffer, id, flags); + CLSubBuffer(CLBuffer parent, int origin, int size, B directBuffer, long id, int flags) { + super(parent.getContext(), directBuffer, size, id, flags); this.parent = parent; this.offset = origin; } /** * Throws an UnsupportedOperationException since creating sub buffers - * from sub buffers is not allowed. + * from sub buffers is not allowed as of OpenCL 1.1. */ @Override - public CLBuffer createSubBuffer(int origin, int size, Mem... flags) { + public CLSubBuffer createSubBuffer(int origin, int size, Mem... flags) { throw new UnsupportedOperationException("creating sub buffers from sub buffers is not allowed."); } @@ -41,9 +41,17 @@ public class CLSubBuffer extends CLBuffer { } /** - * Returns the offset of this sub buffer to its parent. + * Returns the offset of this sub buffer to its parent in buffer elements. */ public int getOffset() { + int elemSize = buffer==null ? 1 : sizeOfBufferElem(buffer); + return offset/elemSize; + } + + /** + * Returns the offset of this sub buffer to its parent in bytes. + */ + public int getCLOffset() { return offset; } diff --git a/src/com/jogamp/opencl/gl/CLGLBuffer.java b/src/com/jogamp/opencl/gl/CLGLBuffer.java index 6a658ea5..ab998c14 100644 --- a/src/com/jogamp/opencl/gl/CLGLBuffer.java +++ b/src/com/jogamp/opencl/gl/CLGLBuffer.java @@ -21,7 +21,7 @@ public final class CLGLBuffer extends CLBuffer implements C public final int GLID; private CLGLBuffer(CLContext context, B directBuffer, long id, int glObject, int flags) { - super(context, directBuffer, id, flags); + super(context, directBuffer, getSizeImpl(context.getCL(), id), id, flags); this.GLID = glObject; } diff --git a/test/com/jogamp/opencl/CLBufferTest.java b/test/com/jogamp/opencl/CLBufferTest.java index d0c8c2f9..f2d2d609 100644 --- a/test/com/jogamp/opencl/CLBufferTest.java +++ b/test/com/jogamp/opencl/CLBufferTest.java @@ -4,6 +4,7 @@ import com.jogamp.opencl.CLMemory.Mem; import com.jogamp.opencl.CLMemory.Map; import com.jogamp.common.nio.Buffers; import java.nio.ByteBuffer; +import java.nio.FloatBuffer; import org.junit.Test; import static org.junit.Assert.*; @@ -145,5 +146,74 @@ public class CLBufferTest { context.release(); } + + @Test + public void subBufferTest() { + + CLPlatform[] platforms = CLPlatform.listCLPlatforms(); + CLPlatform theChosenOne = null; + for (CLPlatform platform : platforms) { + if(platform.isAtLeast(CLVersion.CL_1_1)) { + theChosenOne = platform; + break; + } + } + + if(theChosenOne == null) { + out.println("aborting subBufferTest"); + return; + } + + CLContext context = CLContext.create(theChosenOne); + try{ + final int subelements = 5; + // device only + { + CLBuffer buffer = context.createBuffer(64); + + assertFalse(buffer.isSubBuffer()); + assertNotNull(buffer.getSubBuffers()); + assertTrue(buffer.getSubBuffers().isEmpty()); + + CLSubBuffer subBuffer = buffer.createSubBuffer(10, subelements); + + assertTrue(subBuffer.isSubBuffer()); + assertEquals(subelements, subBuffer.getCLSize()); + assertEquals(10, subBuffer.getOffset()); + assertEquals(10, subBuffer.getCLOffset()); + assertEquals(buffer, subBuffer.getParent()); + assertEquals(1, buffer.getSubBuffers().size()); + + subBuffer.release(); + assertEquals(0, buffer.getSubBuffers().size()); + } + + // device + direct buffer + { + CLBuffer buffer = context.createFloatBuffer(64); + assertFalse(buffer.isSubBuffer()); + assertNotNull(buffer.getSubBuffers()); + assertTrue(buffer.getSubBuffers().isEmpty()); + + CLSubBuffer subBuffer = buffer.createSubBuffer(10, subelements); + + assertTrue(subBuffer.isSubBuffer()); + assertEquals(subelements, subBuffer.getBuffer().capacity()); + assertEquals(10, subBuffer.getOffset()); + assertEquals(40, subBuffer.getCLOffset()); + assertEquals(buffer, subBuffer.getParent()); + assertEquals(1, buffer.getSubBuffers().size()); + + assertEquals(subBuffer.getCLCapacity(), subBuffer.getBuffer().capacity()); + + subBuffer.release(); + assertEquals(0, buffer.getSubBuffers().size()); + } + + }finally{ + context.release(); + } + + } } -- cgit v1.2.3