Skip navigation links

Package com.jme3.opencl

This package contains an API for using OpenCL together with jME3.

See: Description

Package com.jme3.opencl Description

This package contains an API for using OpenCL together with jME3.

Activation:
OpenCL is deactivated by default. To activate it, set AppSettings.setOpenCLSupport(boolean) to true. If the current platform supports OpenCL, then the central Context can be fetched by JmeContext.getOpenCLContext() which is available in each application. If OpenCL is deactivated or not available, this method returns null.

First steps:
Once you have obtained your Context you start by creating a CommandQueue by calling Context.createQueue() or alternative versions. The command queue must be passed to every following method that execute some action involving the GPU. All actions are executed in the order in which they are added to the queue.
Programs and Kernels: The main purpose of OpenCL is to execute code in parallel on the GPU. From the source code, a Program object is created by Context.createProgramFromSourceCode(java.lang.String), Context.createProgramFromSourceFilesWithInclude(com.jme3.asset.AssetManager, java.lang.String, java.util.List) or alternative versions. Before using it, the source code must be build using Program.build(). Any compilation error is thrown here. Each program consists of multiple kernels. Each kernel represents one executable unit and is declared in the source code with the following syntax: __kernel void KernelName(KernelArgs) {Code} . On the programming side, a Kernel instance is obtained by calling Program.createKernel(java.lang.String). To execute the kernel, the method Kernel.Run1(com.jme3.opencl.CommandQueue, com.jme3.opencl.Kernel.WorkSize, java.lang.Object...) is provided. You first pass the command queue and the work size (i.e. the number of parallel executed threads) followed by the kernel arguments.
Buffers and Images: OpenCL Kernels show their true power first when they operate on buffers and images. Buffers are simple one dimensional consecutive chunks of memory of arbitrary size. These Buffer instances are created by calling Context.createBuffer(long) with the size in bytes as the argument. A buffer on its own is typeless. In the kernel, you then specify the type of the buffer by argument declarations like __global float* buffer. Note that OpenCL does not check buffer boundaries. If you read or write outside of the buffer, the behavior is completely undefined and may often result in a program cache later on. Image objects are structured one, two or three dimensional memory chunks of a fixed type. They are created by Context.createImage(). They need special functions in the kernel code to write to or read from images. Both buffer and image objects provide methods for copying between buffers and images, reading and writing to host code and directly mapping memory parts to the host code.
Events: Most methods are provided in two variations: blocking calls or asynchronous calls (the later one have the suffix -Async, or all kernel calls). These async calls all return Event objects. These events can be used to check (non-blocking) if the action has completed, e.g. a memory copy is finished, or to block the execution until the action has finished.
Some methods have the suffix -NoEvent. This means that these methods don't return an event object even if the OpenCL function would return an event. There exists always an alternative version that does return an event. These methods exist to increase the performance: since all actions (like multiple kernel calls) that are sent to the same command queue are executed in order, there is no need for intermediate events. (These intermediate events would be released immediately). Therefore, the no-event alternatives increase the performance because no additional event object has to be allocated and less system calls are necessary.

Interoperability between OpenCL and jME3:
This Wrapper allows to share jME3 Images and VertexBuffers with OpenCL.
VertexBuffer objects can be shared with OpenCL by calling Context.bindVertexBuffer(com.jme3.scene.VertexBuffer, com.jme3.opencl.MemoryAccess) resulting in a Buffer object. This buffer object can then be used as usual, allowing e.g. the dynamic modification of position buffers for particle systems.
Image and Texture objects can be used in OpenCL with the method Context.bindImage(com.jme3.texture.Texture, com.jme3.opencl.MemoryAccess) or variations of this method. The same holds for FrameBuffer.RenderBuffer objects using Context.bindRenderBuffer(com.jme3.texture.FrameBuffer.RenderBuffer, com.jme3.opencl.MemoryAccess). These methods result in an OpenCL-Image. Usages are e.g. animated textures, terrain based on height maps, post processing effects and so forth.
Important: Before shared objects can be used by any OpenCL function like kernel calls or read/write/copy methods, they must be acquired explicitly by Buffer.acquireBufferForSharingAsync(com.jme3.opencl.CommandQueue) or Image.acquireImageForSharingAsync(com.jme3.opencl.CommandQueue). After the work is done, release the resource with Buffer.releaseBufferForSharingAsync(com.jme3.opencl.CommandQueue) or Image.releaseImageForSharingAsync(com.jme3.opencl.CommandQueue). This ensures the synchronization of OpenCL and OpenGL.

Experts: choosing the right platform and devices
OpenCL can run on different platforms and different devices. On some systems, like multi-GPU setups, this choice really matters. To specify which platform and which devices are used, a custom implementation of PlatformChooser can be used by calling AppSettings.setOpenCLPlatformChooser(java.lang.Class). For more details, see the documentation of PlatformChooser.

Exception handling:
All OpenCL-wrapper classes in this package (this includes Platform, Device, Context, CommandQueue, Buffer, Image, Program, Kernel and Event) may throw the following exceptions in each method without being mentioned explicitly in the documentation:

Skip navigation links