29package com.jogamp.opencl;
31import com.jogamp.common.nio.AbstractBuffer;
32import com.jogamp.common.nio.CachedBufferFactory;
33import com.jogamp.opencl.util.CLProgramConfiguration;
34import com.jogamp.opencl.util.CLUtil;
35import com.jogamp.common.os.Platform;
36import com.jogamp.common.util.UnsafeUtil;
37import com.jogamp.common.nio.PointerBuffer;
38import com.jogamp.opencl.llb.CL;
39import com.jogamp.opencl.llb.impl.BuildProgramCallback;
40import com.jogamp.opencl.util.CLBuildListener;
41import java.nio.ByteBuffer;
42import java.nio.IntBuffer;
43import java.util.Collections;
44import java.util.HashMap;
45import java.util.HashSet;
46import java.util.LinkedHashMap;
47import java.util.Map.Entry;
50import java.util.concurrent.Semaphore;
52import static com.jogamp.opencl.CLException.*;
53import static com.jogamp.opencl.llb.CL.*;
54import static com.jogamp.common.nio.Buffers.*;
68 private final static Semaphore buildLock =
new Semaphore(1,
true);
69 private final CL binding;
71 private final Set<CLKernel> kernels;
74 private boolean executable;
75 private boolean released;
77 private boolean noSource;
81 this.kernels =
new HashSet<CLKernel>();
87 final IntBuffer status = newDirectIntBuffer(1);
89 final PointerBuffer length = PointerBuffer.allocateDirect(1).put(0, src.length());
90 final String[] srcArray =
new String[] {src};
96 final int err = status.get();
97 if(err != CL_SUCCESS) {
98 throw newException(err,
"can not create program with source on "+
context);
106 final Set<Entry<CLDevice, byte[]>> entries = binaries.entrySet();
110 for (
final Map.Entry<
CLDevice,
byte[]> entry : entries) {
111 binarySize += entry.getValue().length;
114 final int pbSize = AbstractBuffer.POINTER_SIZE;
115 final int deviceCount = binaries.size();
117 final CachedBufferFactory bf = CachedBufferFactory.create(binarySize + pbSize*deviceCount*3 + 4,
true);
118 final PointerBuffer devices = PointerBuffer.wrap(bf.newDirectByteBuffer(deviceCount*pbSize));
119 final PointerBuffer codeBuffers = PointerBuffer.wrap(bf.newDirectByteBuffer(deviceCount*pbSize));
120 final PointerBuffer lengths = PointerBuffer.wrap(bf.newDirectByteBuffer(deviceCount*pbSize));
123 for (
final Map.Entry<
CLDevice,
byte[]> entry : entries) {
125 final byte[] bytes = entry.getValue();
126 final CLDevice device = entry.getKey();
128 devices.put(device.
ID);
129 lengths.put(bytes.length);
131 codeBuffers.referenceBuffer(i, bf.newDirectByteBuffer(bytes));
137 final IntBuffer errBuffer = bf.newDirectIntBuffer(1);
146 final int err = errBuffer.get();
147 if(err != CL_SUCCESS) {
148 throw newException(err,
"can not create program on "+
context +
" with binaries "+binaries);
154 private void initBuildStatus() {
156 if(buildStatusMap ==
null) {
159 for (
final CLDevice device : devices) {
164 map.put(device, status);
166 this.buildStatusMap = Collections.unmodifiableMap(map);
170 private String getBuildInfoString(
final CLDevice device,
final int flag) {
176 final PointerBuffer size = PointerBuffer.allocateDirect(1);
179 if(ret != CL_SUCCESS) {
180 throw newException(ret,
"on clGetProgramBuildInfo with "+device);
183 final ByteBuffer buffer = newDirectByteBuffer((
int)size.get(0));
186 if(ret != CL_SUCCESS) {
187 throw newException(ret,
"on clGetProgramBuildInfo with "+device);
193 private String getProgramInfoString(
final int flag) {
199 final PointerBuffer size = PointerBuffer.allocateDirect(1);
202 checkForError(ret,
"on clGetProgramInfo");
204 final ByteBuffer buffer = newDirectByteBuffer((
int)size.get(0));
207 checkForError(ret,
"on clGetProgramInfo");
212 private int getBuildInfoInt(
final CLDevice device,
final int flag) {
214 final ByteBuffer buffer = newDirectByteBuffer(4);
217 checkForError(ret,
"error on clGetProgramBuildInfo");
219 return buffer.getInt();
248 build(
null, (String)
null, devices);
260 build(listener,
null, devices);
314 build(
null, options, devices);
330 throw new CLException(
"can not build a released program");
333 if(!kernels.isEmpty()) {
339 PointerBuffer deviceIDs =
null;
341 if(devices !=
null && devices.length != 0) {
342 deviceIDs = PointerBuffer.allocateDirect(devices.length);
343 for (
int i = 0; i < devices.length; i++) {
344 deviceIDs.put(i, devices[i].
ID);
347 count = devices.length;
351 if(options !=
null && options.trim().isEmpty()) {
356 buildStatusMap =
null;
360 if(listener !=
null) {
363 public void buildFinished(
final long cl_program) {
378 }
catch(
final InterruptedException e) {
379 throw newException(ret,
"\nInterrupted while waiting to get build lock");
382 boolean exception =
true;
387 if(callback ==
null || exception) {
393 if(ret != CL_SUCCESS) {
416 final int[] err =
new int[1];
418 if(err[0] != CL_SUCCESS) {
419 throw newException(err[0],
"unable to create Kernel with name: "+kernelName);
433 return Collections.emptyMap();
436 final HashMap<String, CLKernel> newKernels =
new HashMap<String, CLKernel>();
438 final IntBuffer numKernels = newDirectByteBuffer(4).asIntBuffer();
440 if(ret != CL_SUCCESS) {
441 throw newException(ret,
"can not create kernels for "+
this);
444 if(numKernels.get(0) > 0) {
446 final PointerBuffer kernelIDs = PointerBuffer.allocateDirect(numKernels.get(0));
448 if(ret != CL_SUCCESS) {
449 throw newException(ret,
"can not create "+kernelIDs.capacity()+
" kernels for "+
this);
452 for (
int i = 0; i < kernelIDs.capacity(); i++) {
455 newKernels.put(kernel.
name, kernel);
462 throw newException(CL_INVALID_PROGRAM_EXECUTABLE,
463 "can not initialize kernels, program is not executable. status: "+buildStatusMap);
470 void onKernelReleased(
final CLKernel kernel) {
471 this.kernels.remove(kernel);
485 buildStatusMap =
null;
488 context.onProgramReleased(
this);
489 if(ret != CL_SUCCESS) {
490 throw newException(ret,
"can not release "+
this);
494 private void releaseKernels() {
495 if(!kernels.isEmpty()) {
498 for (
final CLKernel kernel : array) {
512 final PointerBuffer size = PointerBuffer.allocateDirect(1);
514 if(ret != CL_SUCCESS) {
515 throw newException(ret,
"on clGetProgramInfo of "+
this);
518 final ByteBuffer bb = newDirectByteBuffer((
int) size.get(0));
520 if(ret != CL_SUCCESS) {
521 throw newException(ret,
"on clGetProgramInfo of "+
this);
524 final int count = bb.capacity() / (Platform.is32Bit()?4:8);
526 for (
int i = 0; i < count; i++) {
527 devices[i] =
context.getDevice(Platform.is32Bit()?bb.getInt():bb.getLong());
542 final StringBuilder sb =
new StringBuilder(200);
544 for (
int i = 0; i < devices.length; i++) {
546 sb.append(device).append(
" build log:\n");
548 sb.append(log.isEmpty()?
" <empty>":log);
549 if(i != devices.length-1)
552 return sb.toString();
560 return Collections.emptyMap();
563 return buildStatusMap;
583 return getBuildInfoString(device, CL_PROGRAM_BUILD_LOG);
593 final int clStatus = getBuildInfoInt(device, CL_PROGRAM_BUILD_STATUS);
614 return getProgramInfoString(CL_PROGRAM_SOURCE);
627 return Collections.emptyMap();
632 final PointerBuffer sizes = PointerBuffer.allocateDirect(devices.length);
633 int ret = binding.
clGetProgramInfo(
ID, CL_PROGRAM_BINARY_SIZES, sizes.capacity()*sizes.elementSize(), sizes.getBuffer(),
null);
634 if(ret != CL_SUCCESS) {
635 throw newException(ret,
"on clGetProgramInfo(CL_PROGRAM_BINARY_SIZES) of "+
this);
638 int binariesSize = 0;
639 while(sizes.remaining() != 0) {
640 final int size = (int) sizes.get();
641 binariesSize += size;
643 final ByteBuffer binaries = newDirectByteBuffer(binariesSize);
646 long address = UnsafeUtil.getDirectBufferAddress(binaries);
647 final PointerBuffer addresses = PointerBuffer.allocateDirect(sizes.capacity());
649 while(sizes.remaining() != 0) {
650 addresses.put(address);
651 address += sizes.get();
655 ret = binding.
clGetProgramInfo(
ID, CL_PROGRAM_BINARIES, addresses.capacity()*addresses.elementSize(), addresses.getBuffer(),
null);
656 if(ret != CL_SUCCESS) {
657 throw newException(ret,
"on clGetProgramInfo(CL_PROGRAM_BINARIES) of "+
this);
662 for (
int i = 0; i < devices.length; i++) {
663 final byte[] bytes =
new byte[(int)sizes.get()];
665 map.put(devices[i], bytes);
674 public static String
optionsOf(
final String... options) {
675 final StringBuilder sb =
new StringBuilder(options.length * 24);
676 for (
int i = 0; i < options.length; i++) {
677 sb.append(options[i]);
678 if(i!= options.length-1)
681 return sb.toString();
687 public static String
define(
final String name) {
694 public static String
define(
final String name,
final Object value) {
695 return "-D "+name+
"="+value;
700 return "CLProgram [id: " +
ID
705 public boolean equals(
final Object obj) {
709 if (getClass() != obj.getClass()) {
713 if (this.
ID != other.
ID) {
725 hash = 37 * hash + (this.context !=
null ? this.context.
hashCode() : 0);
726 hash = 37 * hash + (int) (this.
ID ^ (this.
ID >>> 32));
742 private Status(
final int status) {
743 this.STATUS = status;
747 switch(clBuildStatus) {
748 case(CL_BUILD_SUCCESS):
749 return BUILD_SUCCESS;
752 case(CL_BUILD_IN_PROGRESS):
753 return BUILD_IN_PROGRESS;
754 case(CL_BUILD_ERROR):
823 public final static String
UNSAFE_MATH =
"-cl-unsafe-math-optimizations";
CLContext is responsible for managing objects such as command-queues, memory, program and kernel obje...
boolean equals(final Object obj)
CLPlatform getPlatform()
Returns the CLPlatform this context is running on.
This object represents an OpenCL device.
CLException thrown on CL.CL_INVALID_VALUE errors.
Main Exception type for runtime OpenCL errors and failed function calls (e.g.
High level abstraction for an OpenCL Kernel.
void release()
Releases all resources of this kernel from its context.
final long ID
The OpenCL object handle.
CLProgramBuilder is a helper for building programs with more complex configurations or building multi...
static CLBuildConfiguration createConfiguration()
Creates a new CLBuildConfiguration.
Represents a OpenCL program executed on one or more CLDevices.
String getBuildLog()
Returns the build log of this program on all devices.
CLProgram build(final String options)
Builds this program for all devices associated with the context using the specified build options.
static String define(final String name)
Utility method for defining macros as build options (Returns "-D name").
boolean isExecutable()
Returns true if the build status 'BUILD_SUCCESS' for at least one device of this program exists.
CLProgram build(final String... options)
Builds this program for all devices associated with the context using the specified build options.
CLProgramConfiguration prepare()
Prepares the build for this program by returning a new CLProgramConfiguration.
Map< CLDevice, byte[]> getBinaries()
Returns the binaries for this program in an ordered Map containing the device as key and the program ...
String getBuildLog(final CLDevice device)
Returns the build log for this program on the specified device.
boolean equals(final Object obj)
CLProgram build(final CLBuildListener listener, final String options)
Builds this program for all devices associated with the context using the specified build options.
String getSource()
Returns the source code of this program.
CLProgram build()
Builds this program for all devices associated with the context.
CLProgram build(final CLDevice... devices)
Builds this program for the given devices.
CLDevice[] getCLDevices()
Returns all devices associated with this program.
CLProgram build(final CLBuildListener listener)
Builds this program for all devices associated with the context.
CLProgram build(final CLBuildListener listener, final String... options)
Builds this program for all devices associated with the context using the specified build options.
CLProgram build(final CLBuildListener listener, String options, final CLDevice... devices)
Builds this program for the given devices and with the specified build options.
Map< CLDevice, Status > getBuildStatus()
Returns the build status enum of this program for each device as Map.
CLProgram build(final String options, final CLDevice... devices)
Builds this program for the given devices and with the specified build options.
Status getBuildStatus(final CLDevice device)
Returns the build status enum for this program on the specified device.
Map< String, CLKernel > createCLKernels()
Creates all kernels of this program and stores them a Map with the kernel name as key.
CLProgram build(final CLBuildListener listener, final CLDevice... devices)
Builds this program for the given devices.
void release()
Releases this program with its kernels.
CLKernel createCLKernel(final String kernelName)
Creates a kernel with the specified kernel name.
void setNoSource()
Must set this if the program is created from binary so we know not to call getSource(),...
static String define(final String name, final Object value)
Utility method for defining macros as build options (Returns "-D name=value").
static String optionsOf(final String... options)
Utility method which builds a properly seperated option string.
static String clString2JavaString(final byte[] chars, int clLength)
Configures the mapping process.
static Status valueOf(final int clBuildStatus)
final int STATUS
Value of wrapped OpenCL device type.
Common compiler options for the OpenCL compiler.
static final String FINITE_MATH_ONLY
Allow optimizations for floating-point arithmetic that assume that arguments and results are not NaNs...
static final String ENABLE_MAD
Allow a * b + c to be replaced by a mad.
static final String SINGLE_PRECISION_CONSTANTS
Treat double precision floating-point constant as single precision constant.
static final String DISABLE_OPT
This option disables all optimizations.
static final String UNSAFE_MATH
Allow optimizations for floating-point arithmetic that (a) assume that arguments and results are val...
static final String DENORMS_ARE_ZERO
This option controls how single precision and double precision denormalized numbers are handled.
static final String WARNINGS_ARE_ERRORS
Make all warnings into errors.
static final String FAST_RELAXED_MATH
Sets the optimization options -cl-finite-math-only (FINITE_MATH_ONLY) and -cl-unsafe-math-optimizatio...
static final String DISABLE_WARNINGS
Inhibit all warning messages.
static final String STRICT_ALIASING
This option allows the compiler to assume the strictest aliasing rules.
static final String NO_SIGNED_ZEROS
Allow optimizations for floating-point arithmetic that ignore the signedness of zero.
Java bindings to OpenCL, the Open Computing Language.
long clCreateProgramWithBinary(long context, int num_devices, PointerBuffer device_list, PointerBuffer lengths, PointerBuffer binaries, IntBuffer binary_status, IntBuffer errcode_ret)
Interface to C language function: cl_program {@native clCreateProgramWithBinary}(cl_context context...
long clCreateKernel(long program, String kernel_name, IntBuffer errcode_ret)
Interface to C language function: cl_kernel {@native clCreateKernel}(cl_program program,...
int clBuildProgram(long program, int deviceCount, PointerBuffer devices, String options, BuildProgramCallback cb)
Interface to C language function: int32_t {@native clBuildProgram}(cl_program, uint32_t,...
int clGetProgramInfo(long program, int param_name, long param_value_size, Buffer param_value, PointerBuffer param_value_size_ret)
Interface to C language function: cl_int {@native clGetProgramInfo}(cl_program program,...
int clCreateKernelsInProgram(long program, int num_kernels, PointerBuffer kernels, IntBuffer num_kernels_ret)
Interface to C language function: cl_int {@native clCreateKernelsInProgram}(cl_program program,...
int clGetProgramBuildInfo(long program, long device, int param_name, long param_value_size, Buffer param_value, PointerBuffer param_value_size_ret)
Interface to C language function: cl_int {@native clGetProgramBuildInfo}(cl_program program,...
int clReleaseProgram(long program)
Interface to C language function: cl_int {@native clReleaseProgram}(cl_program program)
long clCreateProgramWithSource(long context, int count, String[] strings, PointerBuffer lengths, IntBuffer errcode_ret)
Interface to C language function: cl_program {@native clCreateProgramWithSource}(cl_context context...
A callback an application can register to be called when the program executable has been built (succe...
A callback an application can register to be called when the program executable has been built (succe...
void buildFinished(CLProgram program)
Called when the program executable has been built (successfully or unsuccessfully).
Configuration representing everything needed to build an OpenCL program (program included).