|
|
|
@ -34,98 +34,283 @@ package com.jme3.opencl; |
|
|
|
|
import java.nio.ByteBuffer; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* |
|
|
|
|
* Wrapper for an OpenCL buffer object. |
|
|
|
|
* A buffer object stores a one-dimensional collection of elements. Elements of a buffer object can |
|
|
|
|
* be a scalar data type (such as an int, float), vector data type, or a user-defined structure. |
|
|
|
|
* <br> |
|
|
|
|
* Buffers are created by the {@link Context}. |
|
|
|
|
* <br> |
|
|
|
|
* All access methods (read/write/copy/map) are available in both sychronized/blocking versions |
|
|
|
|
* and in async/non-blocking versions. The later ones always return an {@link Event} object |
|
|
|
|
* and have the prefix -Async in their name. |
|
|
|
|
* |
|
|
|
|
* @see Context#createBuffer(long, com.jme3.opencl.MemoryAccess) |
|
|
|
|
* @author Sebastian Weiss |
|
|
|
|
*/ |
|
|
|
|
public abstract class Buffer implements OpenCLObject { |
|
|
|
|
|
|
|
|
|
public abstract int getSize(); |
|
|
|
|
/** |
|
|
|
|
* @return the size of the buffer in bytes. |
|
|
|
|
* @see Context#createBuffer(long) |
|
|
|
|
*/ |
|
|
|
|
public abstract long getSize(); |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @return the memory access flags set on creation. |
|
|
|
|
* @see Context#createBuffer(long, com.jme3.opencl.MemoryAccess) |
|
|
|
|
*/ |
|
|
|
|
public abstract MemoryAccess getMemoryAccessFlags(); |
|
|
|
|
|
|
|
|
|
public abstract void read(CommandQueue queue, ByteBuffer dest, int size, int offset); |
|
|
|
|
/** |
|
|
|
|
* Performs a blocking read of the buffer. |
|
|
|
|
* The target buffer must have at least {@code size} bytes remaining. |
|
|
|
|
* This method may set the limit to the last byte read. |
|
|
|
|
* @param queue the command queue |
|
|
|
|
* @param dest the target buffer |
|
|
|
|
* @param size the size in bytes being read |
|
|
|
|
* @param offset the offset in bytes in the buffer to read from |
|
|
|
|
*/ |
|
|
|
|
public abstract void read(CommandQueue queue, ByteBuffer dest, long size, long offset); |
|
|
|
|
|
|
|
|
|
public void read(CommandQueue queue, ByteBuffer dest, int size) { |
|
|
|
|
/** |
|
|
|
|
* Alternative version of {@link #read(com.jme3.opencl.CommandQueue, java.nio.ByteBuffer, long, long) }, |
|
|
|
|
* sets {@code offset} to zero. |
|
|
|
|
*/ |
|
|
|
|
public void read(CommandQueue queue, ByteBuffer dest, long size) { |
|
|
|
|
read(queue, dest, size, 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Alternative version of {@link #read(com.jme3.opencl.CommandQueue, java.nio.ByteBuffer, long) }, |
|
|
|
|
* sets {@code size} to {@link #getSize() }. |
|
|
|
|
*/ |
|
|
|
|
public void read(CommandQueue queue, ByteBuffer dest) { |
|
|
|
|
read(queue, dest, getSize()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public abstract Event readAsync(CommandQueue queue, ByteBuffer dest, int size, int offset); |
|
|
|
|
/** |
|
|
|
|
* Performs an async/non-blocking read of the buffer. |
|
|
|
|
* The target buffer must have at least {@code size} bytes remaining. |
|
|
|
|
* This method may set the limit to the last byte read. |
|
|
|
|
* @param queue the command queue |
|
|
|
|
* @param dest the target buffer |
|
|
|
|
* @param size the size in bytes being read |
|
|
|
|
* @param offset the offset in bytes in the buffer to read from |
|
|
|
|
* @return the event indicating when the memory has been fully read into the provided buffer |
|
|
|
|
*/ |
|
|
|
|
public abstract Event readAsync(CommandQueue queue, ByteBuffer dest, long size, long offset); |
|
|
|
|
|
|
|
|
|
public Event readAsync(CommandQueue queue, ByteBuffer dest, int size) { |
|
|
|
|
/** |
|
|
|
|
* Alternative version of {@link #readAsync(com.jme3.opencl.CommandQueue, java.nio.ByteBuffer, long, long) }, |
|
|
|
|
* sets {@code offset} to zero. |
|
|
|
|
*/ |
|
|
|
|
public Event readAsync(CommandQueue queue, ByteBuffer dest, long size) { |
|
|
|
|
return readAsync(queue, dest, size, 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Alternative version of {@link #readAsync(com.jme3.opencl.CommandQueue, java.nio.ByteBuffer, long) }, |
|
|
|
|
* sets {@code size} to {@link #getSize() } |
|
|
|
|
*/ |
|
|
|
|
public Event readAsync(CommandQueue queue, ByteBuffer dest) { |
|
|
|
|
return readAsync(queue, dest, getSize()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public abstract void write(CommandQueue queue, ByteBuffer src, int size, int offset); |
|
|
|
|
/** |
|
|
|
|
* Performs a blocking write to the buffer. |
|
|
|
|
* The target buffer must have at least {@code size} bytes remaining. |
|
|
|
|
* This method may set the limit to the last byte that will be written. |
|
|
|
|
* @param queue the command queue |
|
|
|
|
* @param src the source buffer, its data is written to this buffer |
|
|
|
|
* @param size the size in bytes to write |
|
|
|
|
* @param offset the offset into the target buffer |
|
|
|
|
*/ |
|
|
|
|
public abstract void write(CommandQueue queue, ByteBuffer src, long size, long offset); |
|
|
|
|
|
|
|
|
|
public void write(CommandQueue queue, ByteBuffer src, int size) { |
|
|
|
|
/** |
|
|
|
|
* Alternative version of {@link #write(com.jme3.opencl.CommandQueue, java.nio.ByteBuffer, long, long) }, |
|
|
|
|
* sets {@code offset} to zero. |
|
|
|
|
*/ |
|
|
|
|
public void write(CommandQueue queue, ByteBuffer src, long size) { |
|
|
|
|
write(queue, src, size, 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Alternative version of {@link #write(com.jme3.opencl.CommandQueue, java.nio.ByteBuffer, long) }, |
|
|
|
|
* sets {@code size} to {@link #getSize() }. |
|
|
|
|
*/ |
|
|
|
|
public void write(CommandQueue queue, ByteBuffer src) { |
|
|
|
|
write(queue, src, getSize()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public abstract Event writeAsync(CommandQueue queue, ByteBuffer src, int size, int offset); |
|
|
|
|
/** |
|
|
|
|
* Performs an async/non-blocking write to the buffer. |
|
|
|
|
* The target buffer must have at least {@code size} bytes remaining. |
|
|
|
|
* This method may set the limit to the last byte that will be written. |
|
|
|
|
* @param queue the command queue |
|
|
|
|
* @param src the source buffer, its data is written to this buffer |
|
|
|
|
* @param size the size in bytes to write |
|
|
|
|
* @param offset the offset into the target buffer |
|
|
|
|
* @return the event object indicating when the write operation is completed |
|
|
|
|
*/ |
|
|
|
|
public abstract Event writeAsync(CommandQueue queue, ByteBuffer src, long size, long offset); |
|
|
|
|
|
|
|
|
|
public Event writeAsync(CommandQueue queue, ByteBuffer src, int size) { |
|
|
|
|
/** |
|
|
|
|
* Alternative version of {@link #writeAsync(com.jme3.opencl.CommandQueue, java.nio.ByteBuffer, long, long) }, |
|
|
|
|
* sets {@code offset} to zero. |
|
|
|
|
*/ |
|
|
|
|
public Event writeAsync(CommandQueue queue, ByteBuffer src, long size) { |
|
|
|
|
return writeAsync(queue, src, size, 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Alternative version of {@link #writeAsync(com.jme3.opencl.CommandQueue, java.nio.ByteBuffer, long) }, |
|
|
|
|
* sets {@code size} to {@link #getSize() }. |
|
|
|
|
*/ |
|
|
|
|
public Event writeAsync(CommandQueue queue, ByteBuffer src) { |
|
|
|
|
return writeAsync(queue, src, getSize()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public abstract void copyTo(CommandQueue queue, Buffer dest, int size, int srcOffset, int destOffset); |
|
|
|
|
/** |
|
|
|
|
* Performs a blocking copy operation from this buffer to the specified buffer. |
|
|
|
|
* @param queue the command queue |
|
|
|
|
* @param dest the target buffer |
|
|
|
|
* @param size the size in bytes to copy |
|
|
|
|
* @param srcOffset offset in bytes into this buffer |
|
|
|
|
* @param destOffset offset in bytes into the target buffer |
|
|
|
|
*/ |
|
|
|
|
public abstract void copyTo(CommandQueue queue, Buffer dest, long size, long srcOffset, long destOffset); |
|
|
|
|
|
|
|
|
|
public void copyTo(CommandQueue queue, Buffer dest, int size) { |
|
|
|
|
/** |
|
|
|
|
* Alternative version of {@link #copyTo(com.jme3.opencl.CommandQueue, com.jme3.opencl.Buffer, long, long, long) }, |
|
|
|
|
* sets {@code srcOffset} and {@code destOffset} to zero. |
|
|
|
|
*/ |
|
|
|
|
public void copyTo(CommandQueue queue, Buffer dest, long size) { |
|
|
|
|
copyTo(queue, dest, size, 0, 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Alternative version of {@link #copyTo(com.jme3.opencl.CommandQueue, com.jme3.opencl.Buffer, long) }, |
|
|
|
|
* sets {@code size} to {@code this.getSize()}. |
|
|
|
|
*/ |
|
|
|
|
public void copyTo(CommandQueue queue, Buffer dest) { |
|
|
|
|
copyTo(queue, dest, getSize()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public abstract Event copyToAsync(CommandQueue queue, Buffer dest, int size, int srcOffset, int destOffset); |
|
|
|
|
/** |
|
|
|
|
* Performs an async/non-blocking copy operation from this buffer to the specified buffer. |
|
|
|
|
* @param queue the command queue |
|
|
|
|
* @param dest the target buffer |
|
|
|
|
* @param size the size in bytes to copy |
|
|
|
|
* @param srcOffset offset in bytes into this buffer |
|
|
|
|
* @param destOffset offset in bytes into the target buffer |
|
|
|
|
* @return the event object indicating when the copy operation is finished |
|
|
|
|
*/ |
|
|
|
|
public abstract Event copyToAsync(CommandQueue queue, Buffer dest, long size, long srcOffset, long destOffset); |
|
|
|
|
|
|
|
|
|
public Event copyToAsync(CommandQueue queue, Buffer dest, int size) { |
|
|
|
|
/** |
|
|
|
|
* Alternative version of {@link #copyToAsync(com.jme3.opencl.CommandQueue, com.jme3.opencl.Buffer, long, long, long) }, |
|
|
|
|
* sets {@code srcOffset} and {@code destOffset} to zero. |
|
|
|
|
*/ |
|
|
|
|
public Event copyToAsync(CommandQueue queue, Buffer dest, long size) { |
|
|
|
|
return copyToAsync(queue, dest, size, 0, 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Alternative version of {@link #copyToAsync(com.jme3.opencl.CommandQueue, com.jme3.opencl.Buffer, long) }, |
|
|
|
|
* sets {@code size} to {@code this.getSize()}. |
|
|
|
|
*/ |
|
|
|
|
public Event copyToAsync(CommandQueue queue, Buffer dest) { |
|
|
|
|
return copyToAsync(queue, dest, getSize()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public abstract ByteBuffer map(CommandQueue queue, int size, int offset, MappingAccess access); |
|
|
|
|
/** |
|
|
|
|
* Maps this buffer directly into host memory. This might be the fastest method |
|
|
|
|
* to access the contents of the buffer since the OpenCL implementation directly |
|
|
|
|
* provides the memory.<br> |
|
|
|
|
* <b>Important:</b> The mapped memory MUST be released by calling |
|
|
|
|
* {@link #unmap(com.jme3.opencl.CommandQueue, java.nio.ByteBuffer) }. |
|
|
|
|
* @param queue the command queue |
|
|
|
|
* @param size the size in bytes to map |
|
|
|
|
* @param offset the offset into this buffer |
|
|
|
|
* @param access specifies the possible access to the memory: READ_ONLY, WRITE_ONLY, READ_WRITE |
|
|
|
|
* @return the byte buffer directly reflecting the buffer contents |
|
|
|
|
*/ |
|
|
|
|
public abstract ByteBuffer map(CommandQueue queue, long size, long offset, MappingAccess access); |
|
|
|
|
|
|
|
|
|
public ByteBuffer map(CommandQueue queue, int size, MappingAccess access) { |
|
|
|
|
/** |
|
|
|
|
* Alternative version of {@link #map(com.jme3.opencl.CommandQueue, long, long, com.jme3.opencl.MappingAccess) }, |
|
|
|
|
* sets {@code offset} to zero. |
|
|
|
|
* <b>Important:</b> The mapped memory MUST be released by calling |
|
|
|
|
* {@link #unmap(com.jme3.opencl.CommandQueue, java.nio.ByteBuffer) }. |
|
|
|
|
*/ |
|
|
|
|
public ByteBuffer map(CommandQueue queue, long size, MappingAccess access) { |
|
|
|
|
return map(queue, size, 0, access); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Alternative version of {@link #map(com.jme3.opencl.CommandQueue, long, com.jme3.opencl.MappingAccess) }, |
|
|
|
|
* sets {@code size} to {@link #getSize() }. |
|
|
|
|
* <b>Important:</b> The mapped memory MUST be released by calling |
|
|
|
|
* {@link #unmap(com.jme3.opencl.CommandQueue, java.nio.ByteBuffer) }. |
|
|
|
|
*/ |
|
|
|
|
public ByteBuffer map(CommandQueue queue, MappingAccess access) { |
|
|
|
|
return map(queue, getSize(), access); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Unmaps a previously mapped memory. |
|
|
|
|
* This releases the native resources and for WRITE_ONLY or READ_WRITE access, |
|
|
|
|
* the memory content is sent back to the GPU. |
|
|
|
|
* @param queue the command queue |
|
|
|
|
* @param ptr the buffer that was previously mapped |
|
|
|
|
*/ |
|
|
|
|
public abstract void unmap(CommandQueue queue, ByteBuffer ptr); |
|
|
|
|
|
|
|
|
|
public abstract AsyncMapping mapAsync(CommandQueue queue, int size, int offset, MappingAccess access); |
|
|
|
|
public AsyncMapping mapAsync(CommandQueue queue, int size, MappingAccess access) { |
|
|
|
|
/** |
|
|
|
|
* Maps this buffer asynchronously into host memory. This might be the fastest method |
|
|
|
|
* to access the contents of the buffer since the OpenCL implementation directly |
|
|
|
|
* provides the memory.<br> |
|
|
|
|
* <b>Important:</b> The mapped memory MUST be released by calling |
|
|
|
|
* {@link #unmap(com.jme3.opencl.CommandQueue, java.nio.ByteBuffer) }. |
|
|
|
|
* @param queue the command queue |
|
|
|
|
* @param size the size in bytes to map |
|
|
|
|
* @param offset the offset into this buffer |
|
|
|
|
* @param access specifies the possible access to the memory: READ_ONLY, WRITE_ONLY, READ_WRITE |
|
|
|
|
* @return the byte buffer directly reflecting the buffer contents |
|
|
|
|
* and the event indicating when the buffer contents are available |
|
|
|
|
*/ |
|
|
|
|
public abstract AsyncMapping mapAsync(CommandQueue queue, long size, long offset, MappingAccess access); |
|
|
|
|
/** |
|
|
|
|
* Alternative version of {@link #mapAsync(com.jme3.opencl.CommandQueue, long, long, com.jme3.opencl.MappingAccess) }, |
|
|
|
|
* sets {@code offset} to zero. |
|
|
|
|
* <b>Important:</b> The mapped memory MUST be released by calling |
|
|
|
|
* {@link #unmap(com.jme3.opencl.CommandQueue, java.nio.ByteBuffer) }. |
|
|
|
|
*/ |
|
|
|
|
public AsyncMapping mapAsync(CommandQueue queue, long size, MappingAccess access) { |
|
|
|
|
return mapAsync(queue, size, 0, access); |
|
|
|
|
} |
|
|
|
|
/** |
|
|
|
|
* Alternative version of {@link #mapAsync(com.jme3.opencl.CommandQueue, long, com.jme3.opencl.MappingAccess) }, |
|
|
|
|
* sets {@code size} to {@link #getSize() }. |
|
|
|
|
* <b>Important:</b> The mapped memory MUST be released by calling |
|
|
|
|
* {@link #unmap(com.jme3.opencl.CommandQueue, java.nio.ByteBuffer) }. |
|
|
|
|
*/ |
|
|
|
|
public AsyncMapping mapAsync(CommandQueue queue, MappingAccess access) { |
|
|
|
|
return mapAsync(queue, getSize(), 0, access); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public abstract Event fillAsync(CommandQueue queue, ByteBuffer pattern, int size, int offset); |
|
|
|
|
|
|
|
|
|
//TODO: copy to image
|
|
|
|
|
/** |
|
|
|
|
* Enqueues a fill operation. This method can be used to initialize or clear |
|
|
|
|
* a buffer with a certain value. |
|
|
|
|
* @param queue the command queue |
|
|
|
|
* @param pattern the buffer containing the filling pattern. |
|
|
|
|
* The remaining bytes specify the pattern length |
|
|
|
|
* @param size the size in bytes to fill, must be a multiple of the pattern length |
|
|
|
|
* @param offset the offset in bytes into the buffer, must be a multiple of the pattern length |
|
|
|
|
* @return an event indicating when this operation is finished |
|
|
|
|
*/ |
|
|
|
|
public abstract Event fillAsync(CommandQueue queue, ByteBuffer pattern, long size, long offset); |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Result of an async mapping operation, contains the event and the target byte buffer. |
|
|
|
@ -144,18 +329,58 @@ public abstract class Buffer implements OpenCLObject { |
|
|
|
|
this.buffer = buffer; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @return the event object indicating when the data in the mapped buffer |
|
|
|
|
* is available |
|
|
|
|
*/ |
|
|
|
|
public Event getEvent() { |
|
|
|
|
return event; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @return the mapped buffer, only valid when the event object signals completion |
|
|
|
|
*/ |
|
|
|
|
public ByteBuffer getBuffer() { |
|
|
|
|
return buffer; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Copies this buffer to the specified image. |
|
|
|
|
* Note that no format conversion is done. |
|
|
|
|
* <br> |
|
|
|
|
* For detailed description of the origin and region paramenter, see the |
|
|
|
|
* documentation of the {@link Image} class. |
|
|
|
|
* |
|
|
|
|
* @param queue the command queue |
|
|
|
|
* @param dest the target image |
|
|
|
|
* @param srcOffset the offset in bytes into this buffer |
|
|
|
|
* @param destOrigin the origin of the copied area |
|
|
|
|
* @param destRegion the size of the copied area |
|
|
|
|
* @return the event object |
|
|
|
|
*/ |
|
|
|
|
public abstract Event copyToImageAsync(CommandQueue queue, Image dest, long srcOffset, long[] destOrigin, long[] destRegion); |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Aquires this buffer object for using. Only call this method if this buffer |
|
|
|
|
* represents a shared object from OpenGL, created with e.g. |
|
|
|
|
* {@link Context#bindVertexBuffer(com.jme3.scene.VertexBuffer, com.jme3.opencl.MemoryAccess) }. |
|
|
|
|
* This method must be called before the buffer is used. After the work is |
|
|
|
|
* done, the buffer must be released by calling |
|
|
|
|
* {@link #releaseBufferForSharingAsync(com.jme3.opencl.CommandQueue) } |
|
|
|
|
* so that OpenGL can use the VertexBuffer again. |
|
|
|
|
* @param queue the command queue |
|
|
|
|
* @return the event object |
|
|
|
|
*/ |
|
|
|
|
public abstract Event acquireBufferForSharingAsync(CommandQueue queue); |
|
|
|
|
/** |
|
|
|
|
* Releases a shared buffer object. |
|
|
|
|
* Call this method after the buffer object was acquired by |
|
|
|
|
* {@link #acquireBufferForSharingAsync(com.jme3.opencl.CommandQueue) } |
|
|
|
|
* to hand the control back to OpenGL. |
|
|
|
|
* @param queue the command queue |
|
|
|
|
* @return the event object |
|
|
|
|
*/ |
|
|
|
|
public abstract Event releaseBufferForSharingAsync(CommandQueue queue); |
|
|
|
|
//TODO: add variants of the above two methods that don't create the event object, but release the event immediately
|
|
|
|
|
} |
|
|
|
|