|
@@ -50,44 +50,216 @@ import java.util.logging.Level;
|
|
import java.util.logging.Logger;
|
|
import java.util.logging.Logger;
|
|
|
|
|
|
/**
|
|
/**
|
|
- * The central OpenCL context. Every actions start from here.
|
|
|
|
- *
|
|
|
|
|
|
+ * The central OpenCL context. Every action starts from here.
|
|
|
|
+ * The context can be obtained by {@link com.jme3.system.JmeContext#getOpenCLContext() }.
|
|
|
|
+ * <p>
|
|
|
|
+ * The context is used to:
|
|
|
|
+ * <ul>
|
|
|
|
+ * <li>Query the available devices</li>
|
|
|
|
+ * <li>Create a command queue</li>
|
|
|
|
+ * <li>Create buffers and images</li>
|
|
|
|
+ * <li>Created buffers and images shared with OpenGL vertex buffers, textures and renderbuffers</li>
|
|
|
|
+ * <li>Create program objects from source code and source files</li>
|
|
|
|
+ * </ul>
|
|
* @author Sebastian Weiss
|
|
* @author Sebastian Weiss
|
|
*/
|
|
*/
|
|
public abstract class Context implements OpenCLObject {
|
|
public abstract class Context implements OpenCLObject {
|
|
private static final Logger LOG = Logger.getLogger(Context.class.getName());
|
|
private static final Logger LOG = Logger.getLogger(Context.class.getName());
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Returns all available devices for this context.
|
|
|
|
+ * These devices all belong to the same {@link Platform}.
|
|
|
|
+ * They are used to create a command queue sending commands to a particular
|
|
|
|
+ * device, see {@link #createQueue(com.jme3.opencl.Device) }.
|
|
|
|
+ * Also, device capabilities, like the supported OpenCL version, extensions,
|
|
|
|
+ * memory size and so on, are queried over the Device instances.
|
|
|
|
+ * <br>
|
|
|
|
+ * The available devices were specified by a {@link PlatformChooser}.
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
public abstract List<? extends Device> getDevices();
|
|
public abstract List<? extends Device> getDevices();
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Alternative version of {@link #createQueue(com.jme3.opencl.Device) },
|
|
|
|
+ * just uses the first device returned by {@link #getDevices() }.
|
|
|
|
+ * @return the command queue
|
|
|
|
+ */
|
|
public CommandQueue createQueue() {
|
|
public CommandQueue createQueue() {
|
|
return createQueue(getDevices().get(0));
|
|
return createQueue(getDevices().get(0));
|
|
}
|
|
}
|
|
|
|
+ /**
|
|
|
|
+ * Creates a command queue sending commands to the specified device.
|
|
|
|
+ * The device must be an entry of {@link #getDevices() }.
|
|
|
|
+ * @param device the target device
|
|
|
|
+ * @return the command queue
|
|
|
|
+ */
|
|
public abstract CommandQueue createQueue(Device device);
|
|
public abstract CommandQueue createQueue(Device device);
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Allocates a new buffer of the specific size and access type on the device.
|
|
|
|
+ * @param size the size of the buffer in bytes
|
|
|
|
+ * @param access the allowed access of this buffer from kernel code
|
|
|
|
+ * @return the new buffer
|
|
|
|
+ */
|
|
public abstract Buffer createBuffer(long size, MemoryAccess access);
|
|
public abstract Buffer createBuffer(long size, MemoryAccess access);
|
|
|
|
+ /**
|
|
|
|
+ * Alternative version of {@link #createBuffer(long, com.jme3.opencl.MemoryAccess) },
|
|
|
|
+ * creates a buffer with read and write access.
|
|
|
|
+ * @param size the size of the buffer in bytes
|
|
|
|
+ * @return the new buffer
|
|
|
|
+ */
|
|
public Buffer createBuffer(long size) {
|
|
public Buffer createBuffer(long size) {
|
|
return createBuffer(size, MemoryAccess.READ_WRITE);
|
|
return createBuffer(size, MemoryAccess.READ_WRITE);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Creates a new buffer wrapping the specific host memory. This host memory
|
|
|
|
+ * specified by a ByteBuffer can then be used directly by kernel code,
|
|
|
|
+ * although the access might be slower than with native buffers
|
|
|
|
+ * created by {@link #createBuffer(long, com.jme3.opencl.MemoryAccess) }.
|
|
|
|
+ * @param data the host buffer to use
|
|
|
|
+ * @param access the allowed access of this buffer from kernel code
|
|
|
|
+ * @return the new buffer
|
|
|
|
+ */
|
|
public abstract Buffer createBufferFromHost(ByteBuffer data, MemoryAccess access);
|
|
public abstract Buffer createBufferFromHost(ByteBuffer data, MemoryAccess access);
|
|
|
|
+ /**
|
|
|
|
+ * Alternative version of {@link #createBufferFromHost(java.nio.ByteBuffer, com.jme3.opencl.MemoryAccess) },
|
|
|
|
+ * creates a buffer with read and write access.
|
|
|
|
+ * @param data the host buffer to use
|
|
|
|
+ * @return the new buffer
|
|
|
|
+ */
|
|
public Buffer createBufferFromHost(ByteBuffer data) {
|
|
public Buffer createBufferFromHost(ByteBuffer data) {
|
|
return createBufferFromHost(data, MemoryAccess.READ_WRITE);
|
|
return createBufferFromHost(data, MemoryAccess.READ_WRITE);
|
|
}
|
|
}
|
|
|
|
|
|
- public abstract Image createImage(MemoryAccess access, ImageFormat format, ImageDescriptor descr, ByteBuffer hostPtr);
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Creates a new 1D, 2D, 3D image.<br>
|
|
|
|
+ * {@code ImageFormat} specifies the element type and order, like RGBA of floats.<br>
|
|
|
|
+ * {@code ImageDescriptor} specifies the dimension of the image.<br>
|
|
|
|
+ * Furthermore, a ByteBuffer can be specified in the ImageDescriptor together
|
|
|
|
+ * with row and slice pitches. This buffer is then used to store the image.
|
|
|
|
+ * If no ByteBuffer is specified, a new buffer is allocated (this is the
|
|
|
|
+ * normal behaviour).
|
|
|
|
+ * @param access the allowed access of this image from kernel code
|
|
|
|
+ * @param format the image format
|
|
|
|
+ * @param descr the image descriptor
|
|
|
|
+ * @return the new image object
|
|
|
|
+ */
|
|
|
|
+ public abstract Image createImage(MemoryAccess access, ImageFormat format, ImageDescriptor descr);
|
|
//TODO: add simplified methods for 1D, 2D, 3D textures
|
|
//TODO: add simplified methods for 1D, 2D, 3D textures
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Queries all supported image formats for a specified memory access and
|
|
|
|
+ * image type.
|
|
|
|
+ * <br>
|
|
|
|
+ * Note that the returned array may contain {@code ImageFormat} objects
|
|
|
|
+ * where {@code ImageChannelType} or {@code ImageChannelOrder} are {@code null}
|
|
|
|
+ * (or both). This is the case when the device supports new formats that
|
|
|
|
+ * are not included in this wrapper yet.
|
|
|
|
+ * @param access the memory access type
|
|
|
|
+ * @param type the image type (1D, 2D, 3D, ...)
|
|
|
|
+ * @return an array of all supported image formats
|
|
|
|
+ */
|
|
public abstract ImageFormat[] querySupportedFormats(MemoryAccess access, ImageType type);
|
|
public abstract ImageFormat[] querySupportedFormats(MemoryAccess access, ImageType type);
|
|
|
|
|
|
//Interop
|
|
//Interop
|
|
|
|
+ /**
|
|
|
|
+ * Creates a shared buffer from a VertexBuffer.
|
|
|
|
+ * The returned buffer and the vertex buffer operate on the same memory,
|
|
|
|
+ * changes in one view are visible in the other view.
|
|
|
|
+ * This can be used to modify meshes directly from OpenCL (e.g. for particle systems).
|
|
|
|
+ * <br>
|
|
|
|
+ * <b>Note:</b> The vertex buffer must already been uploaded to the GPU,
|
|
|
|
+ * i.e. it must be used at least once for drawing.
|
|
|
|
+ * <p>
|
|
|
|
+ * Before the returned buffer can be used, it must be acquried explicitly
|
|
|
|
+ * by {@link Buffer#acquireBufferForSharingAsync(com.jme3.opencl.CommandQueue) }
|
|
|
|
+ * and after modifying it, released by {@link Buffer#releaseBufferForSharingAsync(com.jme3.opencl.CommandQueue) }.
|
|
|
|
+ * This is needed so that OpenGL and OpenCL operations do not interfer with each other.
|
|
|
|
+ * @param vb the vertex buffer to share
|
|
|
|
+ * @param access the memory access for the kernel
|
|
|
|
+ * @return the new buffer
|
|
|
|
+ */
|
|
public abstract Buffer bindVertexBuffer(VertexBuffer vb, MemoryAccess access);
|
|
public abstract Buffer bindVertexBuffer(VertexBuffer vb, MemoryAccess access);
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Creates a shared image object from a jME3-image.
|
|
|
|
+ * The returned image shares the same memory with the jME3-image, changes
|
|
|
|
+ * in one view are visible in the other view.
|
|
|
|
+ * This can be used to modify textures and images directly from OpenCL
|
|
|
|
+ * (e.g. for post processing effects and other texture effects).
|
|
|
|
+ * <br>
|
|
|
|
+ * <b>Note:</b> The image must already been uploaded to the GPU,
|
|
|
|
+ * i.e. it must be used at least once for drawing.
|
|
|
|
+ * <p>
|
|
|
|
+ * Before the returned image can be used, it must be acquried explicitly
|
|
|
|
+ * by {@link Image#acquireImageForSharingAsync(com.jme3.opencl.CommandQueue) }
|
|
|
|
+ * and after modifying it, released by {@link Image#releaseImageForSharingAsync(com.jme3.opencl.CommandQueue) }
|
|
|
|
+ * This is needed so that OpenGL and OpenCL operations do not interfer with each other.
|
|
|
|
+ *
|
|
|
|
+ * @param image the jME3 image object
|
|
|
|
+ * @param textureType the texture type (1D, 2D, 3D), since this is not stored in the image
|
|
|
|
+ * @param miplevel the mipmap level that should be shared
|
|
|
|
+ * @param access the allowed memory access for kernels
|
|
|
|
+ * @return the OpenCL image
|
|
|
|
+ */
|
|
public abstract Image bindImage(com.jme3.texture.Image image, Texture.Type textureType, int miplevel, MemoryAccess access);
|
|
public abstract Image bindImage(com.jme3.texture.Image image, Texture.Type textureType, int miplevel, MemoryAccess access);
|
|
|
|
+ /**
|
|
|
|
+ * Creates a shared image object from a jME3 texture.
|
|
|
|
+ * The returned image shares the same memory with the jME3 texture, changes
|
|
|
|
+ * in one view are visible in the other view.
|
|
|
|
+ * This can be used to modify textures and images directly from OpenCL
|
|
|
|
+ * (e.g. for post processing effects and other texture effects).
|
|
|
|
+ * <br>
|
|
|
|
+ * <b>Note:</b> The image must already been uploaded to the GPU,
|
|
|
|
+ * i.e. it must be used at least once for drawing.
|
|
|
|
+ * <p>
|
|
|
|
+ * Before the returned image can be used, it must be acquried explicitly
|
|
|
|
+ * by {@link Image#acquireImageForSharingAsync(com.jme3.opencl.CommandQueue) }
|
|
|
|
+ * and after modifying it, released by {@link Image#releaseImageForSharingAsync(com.jme3.opencl.CommandQueue) }
|
|
|
|
+ * This is needed so that OpenGL and OpenCL operations do not interfer with each other.
|
|
|
|
+ * <p>
|
|
|
|
+ * This method is equivalent to calling
|
|
|
|
+ * {@code bindImage(texture.getImage(), texture.getType(), miplevel, access)}.
|
|
|
|
+ *
|
|
|
|
+ * @param texture the jME3 texture
|
|
|
|
+ * @param miplevel the mipmap level that should be shared
|
|
|
|
+ * @param access the allowed memory access for kernels
|
|
|
|
+ * @return the OpenCL image
|
|
|
|
+ */
|
|
public Image bindImage(Texture texture, int miplevel, MemoryAccess access) {
|
|
public Image bindImage(Texture texture, int miplevel, MemoryAccess access) {
|
|
return bindImage(texture.getImage(), texture.getType(), miplevel, access);
|
|
return bindImage(texture.getImage(), texture.getType(), miplevel, access);
|
|
}
|
|
}
|
|
|
|
+ /**
|
|
|
|
+ * Alternative version to {@link #bindImage(com.jme3.texture.Texture, int, com.jme3.opencl.MemoryAccess) },
|
|
|
|
+ * uses {@code miplevel=0}.
|
|
|
|
+ * @param texture the jME3 texture
|
|
|
|
+ * @param access the allowed memory access for kernels
|
|
|
|
+ * @return the OpenCL image
|
|
|
|
+ */
|
|
public Image bindImage(Texture texture, MemoryAccess access) {
|
|
public Image bindImage(Texture texture, MemoryAccess access) {
|
|
return bindImage(texture, 0, access);
|
|
return bindImage(texture, 0, access);
|
|
}
|
|
}
|
|
|
|
+ /**
|
|
|
|
+ * Creates a shared image object from a jME3 render buffer.
|
|
|
|
+ * The returned image shares the same memory with the jME3 render buffer, changes
|
|
|
|
+ * in one view are visible in the other view.
|
|
|
|
+ * <br>
|
|
|
|
+ * This can be used as an alternative to post processing effects
|
|
|
|
+ * (e.g. reduce sum operations, needed e.g. for tone mapping).
|
|
|
|
+ * <br>
|
|
|
|
+ * <b>Note:</b> The renderbuffer must already been uploaded to the GPU,
|
|
|
|
+ * i.e. it must be used at least once for drawing.
|
|
|
|
+ * <p>
|
|
|
|
+ * Before the returned image can be used, it must be acquried explicitly
|
|
|
|
+ * by {@link Image#acquireImageForSharingAsync(com.jme3.opencl.CommandQueue) }
|
|
|
|
+ * and after modifying it, released by {@link Image#releaseImageForSharingAsync(com.jme3.opencl.CommandQueue) }
|
|
|
|
+ * This is needed so that OpenGL and OpenCL operations do not interfer with each other.
|
|
|
|
+ *
|
|
|
|
+ * @param buffer
|
|
|
|
+ * @param access
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
public Image bindRenderBuffer(FrameBuffer.RenderBuffer buffer, MemoryAccess access) {
|
|
public Image bindRenderBuffer(FrameBuffer.RenderBuffer buffer, MemoryAccess access) {
|
|
if (buffer.getTexture() == null) {
|
|
if (buffer.getTexture() == null) {
|
|
return bindPureRenderBuffer(buffer, access);
|
|
return bindPureRenderBuffer(buffer, access);
|
|
@@ -97,12 +269,61 @@ public abstract class Context implements OpenCLObject {
|
|
}
|
|
}
|
|
protected abstract Image bindPureRenderBuffer(FrameBuffer.RenderBuffer buffer, MemoryAccess access);
|
|
protected abstract Image bindPureRenderBuffer(FrameBuffer.RenderBuffer buffer, MemoryAccess access);
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Creates a program object from the provided source code.
|
|
|
|
+ * The program still needs to be compiled using {@link Program#build() }.
|
|
|
|
+ *
|
|
|
|
+ * @param sourceCode the source code
|
|
|
|
+ * @return the program object
|
|
|
|
+ */
|
|
public abstract Program createProgramFromSourceCode(String sourceCode);
|
|
public abstract Program createProgramFromSourceCode(String sourceCode);
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Creates a program object from the provided source code and files.
|
|
|
|
+ * The source code is made up from the specified include string first,
|
|
|
|
+ * then all files specified by the resource array (array of asset paths)
|
|
|
|
+ * are loaded by the provided asset manager and appended to the source code.
|
|
|
|
+ * <p>
|
|
|
|
+ * The typical use case is:
|
|
|
|
+ * <ul>
|
|
|
|
+ * <li>The include string contains some compiler constants like the grid size </li>
|
|
|
|
+ * <li>Some common OpenCL files used as libraries (Convention: file names end with {@code .clh}</li>
|
|
|
|
+ * <li>One main OpenCL file containing the actual kernels (Convention: file name ends with {@code .cl})</li>
|
|
|
|
+ * </ul>
|
|
|
|
+ * Note: Files that can't be loaded are skipped.<br>
|
|
|
|
+ *
|
|
|
|
+ * The actual creation is handled by {@link #createProgramFromSourceCode(java.lang.String) }.
|
|
|
|
+ *
|
|
|
|
+ * @param assetManager the asset manager used to load the files
|
|
|
|
+ * @param include an additional include string
|
|
|
|
+ * @param resources an array of asset paths pointing to OpenCL source files
|
|
|
|
+ * @return the new program objects
|
|
|
|
+ */
|
|
public Program createProgramFromSourceFilesWithInclude(AssetManager assetManager, String include, String... resources) {
|
|
public Program createProgramFromSourceFilesWithInclude(AssetManager assetManager, String include, String... resources) {
|
|
return createProgramFromSourceFilesWithInclude(assetManager, include, Arrays.asList(resources));
|
|
return createProgramFromSourceFilesWithInclude(assetManager, include, Arrays.asList(resources));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Creates a program object from the provided source code and files.
|
|
|
|
+ * The source code is made up from the specified include string first,
|
|
|
|
+ * then all files specified by the resource array (array of asset paths)
|
|
|
|
+ * are loaded by the provided asset manager and appended to the source code.
|
|
|
|
+ * <p>
|
|
|
|
+ * The typical use case is:
|
|
|
|
+ * <ul>
|
|
|
|
+ * <li>The include string contains some compiler constants like the grid size </li>
|
|
|
|
+ * <li>Some common OpenCL files used as libraries (Convention: file names end with {@code .clh}</li>
|
|
|
|
+ * <li>One main OpenCL file containing the actual kernels (Convention: file name ends with {@code .cl})</li>
|
|
|
|
+ * </ul>
|
|
|
|
+ * Note: Files that can't be loaded are skipped.<br>
|
|
|
|
+ *
|
|
|
|
+ * The actual creation is handled by {@link #createProgramFromSourceCode(java.lang.String) }.
|
|
|
|
+ *
|
|
|
|
+ * @param assetManager the asset manager used to load the files
|
|
|
|
+ * @param include an additional include string
|
|
|
|
+ * @param resources an array of asset paths pointing to OpenCL source files
|
|
|
|
+ * @return the new program objects
|
|
|
|
+ */
|
|
public Program createProgramFromSourceFilesWithInclude(AssetManager assetManager, String include, List<String> resources) {
|
|
public Program createProgramFromSourceFilesWithInclude(AssetManager assetManager, String include, List<String> resources) {
|
|
StringBuilder str = new StringBuilder();
|
|
StringBuilder str = new StringBuilder();
|
|
str.append(include);
|
|
str.append(include);
|
|
@@ -127,10 +348,18 @@ public abstract class Context implements OpenCLObject {
|
|
return createProgramFromSourceCode(str.toString());
|
|
return createProgramFromSourceCode(str.toString());
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Alternative version of {@link #createProgramFromSourceFilesWithInclude(com.jme3.asset.AssetManager, java.lang.String, java.lang.String...) }
|
|
|
|
+ * with an empty include string
|
|
|
|
+ */
|
|
public Program createProgramFromSourceFiles(AssetManager assetManager, String... resources) {
|
|
public Program createProgramFromSourceFiles(AssetManager assetManager, String... resources) {
|
|
return createProgramFromSourceFilesWithInclude(assetManager, "", resources);
|
|
return createProgramFromSourceFilesWithInclude(assetManager, "", resources);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Alternative version of {@link #createProgramFromSourceFilesWithInclude(com.jme3.asset.AssetManager, java.lang.String, java.util.List) }
|
|
|
|
+ * with an empty include string
|
|
|
|
+ */
|
|
public Program createProgramFromSourceFiles(AssetManager assetManager, List<String> resources) {
|
|
public Program createProgramFromSourceFiles(AssetManager assetManager, List<String> resources) {
|
|
return createProgramFromSourceFilesWithInclude(assetManager, "", resources);
|
|
return createProgramFromSourceFilesWithInclude(assetManager, "", resources);
|
|
}
|
|
}
|