29package com.jogamp.opencl;
31import com.jogamp.common.nio.AbstractBuffer;
32import com.jogamp.common.nio.Buffers;
33import com.jogamp.common.nio.CachedBufferFactory;
34import com.jogamp.opencl.util.CLProgramConfiguration;
35import com.jogamp.opencl.util.CLUtil;
36import com.jogamp.common.os.Platform;
37import com.jogamp.common.util.UnsafeUtil;
38import com.jogamp.common.nio.PointerBuffer;
39import com.jogamp.opencl.llb.CL;
40import com.jogamp.opencl.llb.impl.BuildProgramCallback;
41import com.jogamp.opencl.util.CLBuildListener;
42import java.nio.ByteBuffer;
43import java.nio.IntBuffer;
44import java.util.Collections;
45import java.util.HashMap;
46import java.util.HashSet;
47import java.util.LinkedHashMap;
48import java.util.Map.Entry;
51import java.util.concurrent.Semaphore;
53import static com.jogamp.opencl.CLException.*;
54import static com.jogamp.opencl.llb.CL.*;
55import static com.jogamp.common.nio.Buffers.*;
69 private final static Semaphore buildLock =
new Semaphore(1,
true);
70 private final CL binding;
72 private final Set<CLKernel> kernels;
75 private boolean executable;
76 private boolean released;
78 private boolean noSource;
82 this.kernels =
new HashSet<CLKernel>();
88 final IntBuffer status = newDirectIntBuffer(1);
90 final PointerBuffer length = PointerBuffer.allocateDirect(1).put(0, src.length());
91 final String[] srcArray =
new String[] {src};
97 final int err = status.get();
98 if(err != CL_SUCCESS) {
99 throw newException(err,
"can not create program with source on "+
context);
107 final Set<Entry<CLDevice, byte[]>> entries = binaries.entrySet();
111 for (
final Map.Entry<
CLDevice,
byte[]> entry : entries) {
112 binarySize += entry.getValue().length;
115 final int pbSize = AbstractBuffer.POINTER_SIZE;
116 final int deviceCount = binaries.size();
118 final CachedBufferFactory bf = CachedBufferFactory.create(binarySize + pbSize*deviceCount*3 + 4,
true);
119 final PointerBuffer devices = PointerBuffer.wrap(bf.newDirectByteBuffer(deviceCount*pbSize));
120 final PointerBuffer codeBuffers = PointerBuffer.wrap(bf.newDirectByteBuffer(deviceCount*pbSize));
121 final PointerBuffer lengths = PointerBuffer.wrap(bf.newDirectByteBuffer(deviceCount*pbSize));
124 for (
final Map.Entry<
CLDevice,
byte[]> entry : entries) {
126 final byte[] bytes = entry.getValue();
127 final CLDevice device = entry.getKey();
129 devices.put(device.
ID);
130 lengths.put(bytes.length);
132 codeBuffers.referenceBuffer(i, bf.newDirectByteBuffer(bytes));
138 final IntBuffer errBuffer = bf.newDirectIntBuffer(1);
147 final int err = errBuffer.get();
148 if(err != CL_SUCCESS) {
149 throw newException(err,
"can not create program on "+
context +
" with binaries "+binaries);
155 private void initBuildStatus() {
157 if(buildStatusMap ==
null) {
160 for (
final CLDevice device : devices) {
165 map.put(device, status);
167 this.buildStatusMap = Collections.unmodifiableMap(map);
171 private String getBuildInfoString(
final CLDevice device,
final int flag) {
177 final PointerBuffer size = PointerBuffer.allocateDirect(1);
180 if(ret != CL_SUCCESS) {
181 throw newException(ret,
"on clGetProgramBuildInfo with "+device);
184 final ByteBuffer buffer = newDirectByteBuffer((
int)size.get(0));
187 if(ret != CL_SUCCESS) {
188 throw newException(ret,
"on clGetProgramBuildInfo with "+device);
194 private String getProgramInfoString(
final int flag) {
200 final PointerBuffer size = PointerBuffer.allocateDirect(1);
203 checkForError(ret,
"on clGetProgramInfo");
205 final ByteBuffer buffer = newDirectByteBuffer((
int)size.get(0));
208 checkForError(ret,
"on clGetProgramInfo");
213 private int getBuildInfoInt(
final CLDevice device,
final int flag) {
215 final ByteBuffer buffer = newDirectByteBuffer(4);
218 checkForError(ret,
"error on clGetProgramBuildInfo");
220 return buffer.getInt();
249 build(
null, (String)
null, devices);
261 build(listener,
null, devices);
315 build(
null, options, devices);
331 throw new CLException(
"can not build a released program");
334 if(!kernels.isEmpty()) {
340 PointerBuffer deviceIDs =
null;
342 if(devices !=
null && devices.length != 0) {
343 deviceIDs = PointerBuffer.allocateDirect(devices.length);
344 for (
int i = 0; i < devices.length; i++) {
345 deviceIDs.put(i, devices[i].
ID);
348 count = devices.length;
352 if(options !=
null && options.trim().isEmpty()) {
357 buildStatusMap =
null;
361 if(listener !=
null) {
364 public void buildFinished(
final long cl_program) {
379 }
catch(
final InterruptedException e) {
380 throw newException(ret,
"\nInterrupted while waiting to get build lock");
383 boolean exception =
true;
388 if(callback ==
null || exception) {
394 if(ret != CL_SUCCESS) {
417 final int[] err =
new int[1];
419 if(err[0] != CL_SUCCESS) {
420 throw newException(err[0],
"unable to create Kernel with name: "+kernelName);
434 return Collections.emptyMap();
437 final HashMap<String, CLKernel> newKernels =
new HashMap<String, CLKernel>();
439 final IntBuffer numKernels = newDirectByteBuffer(4).asIntBuffer();
441 if(ret != CL_SUCCESS) {
442 throw newException(ret,
"can not create kernels for "+
this);
445 if(numKernels.get(0) > 0) {
447 final PointerBuffer kernelIDs = PointerBuffer.allocateDirect(numKernels.get(0));
449 if(ret != CL_SUCCESS) {
450 throw newException(ret,
"can not create "+kernelIDs.capacity()+
" kernels for "+
this);
453 for (
int i = 0; i < kernelIDs.capacity(); i++) {
456 newKernels.put(kernel.
name, kernel);
463 throw newException(CL_INVALID_PROGRAM_EXECUTABLE,
464 "can not initialize kernels, program is not executable. status: "+buildStatusMap);
471 void onKernelReleased(
final CLKernel kernel) {
472 this.kernels.remove(kernel);
486 buildStatusMap =
null;
489 context.onProgramReleased(
this);
490 if(ret != CL_SUCCESS) {
491 throw newException(ret,
"can not release "+
this);
495 private void releaseKernels() {
496 if(!kernels.isEmpty()) {
499 for (
final CLKernel kernel : array) {
513 final PointerBuffer size = PointerBuffer.allocateDirect(1);
515 if(ret != CL_SUCCESS) {
516 throw newException(ret,
"on clGetProgramInfo of "+
this);
519 final ByteBuffer bb = newDirectByteBuffer((
int) size.get(0));
521 if(ret != CL_SUCCESS) {
522 throw newException(ret,
"on clGetProgramInfo of "+
this);
525 final int count = bb.capacity() / (Platform.is32Bit()?4:8);
527 for (
int i = 0; i < count; i++) {
528 devices[i] =
context.getDevice(Platform.is32Bit()?bb.getInt():bb.getLong());
543 final StringBuilder sb =
new StringBuilder(200);
545 for (
int i = 0; i < devices.length; i++) {
547 sb.append(device).append(
" build log:\n");
549 sb.append(log.isEmpty()?
" <empty>":log);
550 if(i != devices.length-1)
553 return sb.toString();
561 return Collections.emptyMap();
564 return buildStatusMap;
584 return getBuildInfoString(device, CL_PROGRAM_BUILD_LOG);
594 final int clStatus = getBuildInfoInt(device, CL_PROGRAM_BUILD_STATUS);
615 return getProgramInfoString(CL_PROGRAM_SOURCE);
628 return Collections.emptyMap();
633 final PointerBuffer sizes = PointerBuffer.allocateDirect(devices.length);
634 int ret = binding.
clGetProgramInfo(
ID, CL_PROGRAM_BINARY_SIZES, sizes.capacity()*sizes.elementSize(), sizes.getBuffer(),
null);
635 if(ret != CL_SUCCESS) {
636 throw newException(ret,
"on clGetProgramInfo(CL_PROGRAM_BINARY_SIZES) of "+
this);
639 int binariesSize = 0;
640 while(sizes.remaining() != 0) {
641 final int size = (int) sizes.get();
642 binariesSize += size;
644 final ByteBuffer binaries = newDirectByteBuffer(binariesSize);
647 long address = Buffers.getDirectBufferAddress(binaries);
648 final PointerBuffer addresses = PointerBuffer.allocateDirect(sizes.capacity());
650 while(sizes.remaining() != 0) {
651 addresses.put(address);
652 address += sizes.get();
656 ret = binding.
clGetProgramInfo(
ID, CL_PROGRAM_BINARIES, addresses.capacity()*addresses.elementSize(), addresses.getBuffer(),
null);
657 if(ret != CL_SUCCESS) {
658 throw newException(ret,
"on clGetProgramInfo(CL_PROGRAM_BINARIES) of "+
this);
663 for (
int i = 0; i < devices.length; i++) {
664 final byte[] bytes =
new byte[(int)sizes.get()];
666 map.put(devices[i], bytes);
675 public static String
optionsOf(
final String... options) {
676 final StringBuilder sb =
new StringBuilder(options.length * 24);
677 for (
int i = 0; i < options.length; i++) {
678 sb.append(options[i]);
679 if(i!= options.length-1)
682 return sb.toString();
688 public static String
define(
final String name) {
695 public static String
define(
final String name,
final Object value) {
696 return "-D "+name+
"="+value;
701 return "CLProgram [id: " +
ID
706 public boolean equals(
final Object obj) {
710 if (getClass() != obj.getClass()) {
714 if (this.
ID != other.
ID) {
726 hash = 37 * hash + (this.context !=
null ? this.context.
hashCode() : 0);
727 hash = 37 * hash + (int) (this.
ID ^ (this.
ID >>> 32));
743 private Status(
final int status) {
744 this.STATUS = status;
748 switch(clBuildStatus) {
749 case(CL_BUILD_SUCCESS):
750 return BUILD_SUCCESS;
753 case(CL_BUILD_IN_PROGRESS):
754 return BUILD_IN_PROGRESS;
755 case(CL_BUILD_ERROR):
824 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).