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.nio.PointerBuffer;
37import com.jogamp.opencl.llb.CL;
38import com.jogamp.opencl.llb.impl.BuildProgramCallback;
39import com.jogamp.opencl.util.CLBuildListener;
40import java.nio.ByteBuffer;
41import java.nio.IntBuffer;
42import java.util.Collections;
43import java.util.HashMap;
44import java.util.HashSet;
45import java.util.LinkedHashMap;
46import java.util.Map.Entry;
49import java.util.concurrent.Semaphore;
51import static com.jogamp.opencl.CLException.*;
52import static com.jogamp.opencl.llb.CL.*;
53import static com.jogamp.common.nio.Buffers.*;
67 private final static Semaphore buildLock =
new Semaphore(1,
true);
68 private final CL binding;
70 private final Set<CLKernel> kernels;
73 private boolean executable;
74 private boolean released;
76 private boolean noSource;
80 this.kernels =
new HashSet<CLKernel>();
86 final IntBuffer status = newDirectIntBuffer(1);
88 final PointerBuffer length = PointerBuffer.allocateDirect(1).put(0, src.length());
89 final String[] srcArray =
new String[] {src};
95 final int err = status.get();
96 if(err != CL_SUCCESS) {
97 throw newException(err,
"can not create program with source on "+
context);
105 final Set<Entry<CLDevice, byte[]>> entries = binaries.entrySet();
109 for (
final Map.Entry<
CLDevice,
byte[]> entry : entries) {
110 binarySize += entry.getValue().length;
113 final int pbSize = AbstractBuffer.POINTER_SIZE;
114 final int deviceCount = binaries.size();
116 final CachedBufferFactory bf = CachedBufferFactory.create(binarySize + pbSize*deviceCount*3 + 4,
true);
117 final PointerBuffer devices = PointerBuffer.wrap(bf.newDirectByteBuffer(deviceCount*pbSize));
118 final PointerBuffer codeBuffers = PointerBuffer.wrap(bf.newDirectByteBuffer(deviceCount*pbSize));
119 final PointerBuffer lengths = PointerBuffer.wrap(bf.newDirectByteBuffer(deviceCount*pbSize));
122 for (
final Map.Entry<
CLDevice,
byte[]> entry : entries) {
124 final byte[] bytes = entry.getValue();
125 final CLDevice device = entry.getKey();
127 devices.put(device.
ID);
128 lengths.put(bytes.length);
130 codeBuffers.referenceBuffer(i, bf.newDirectByteBuffer(bytes));
136 final IntBuffer errBuffer = bf.newDirectIntBuffer(1);
145 final int err = errBuffer.get();
146 if(err != CL_SUCCESS) {
147 throw newException(err,
"can not create program on "+
context +
" with binaries "+binaries);
153 private void initBuildStatus() {
155 if(buildStatusMap ==
null) {
158 for (
final CLDevice device : devices) {
163 map.put(device, status);
165 this.buildStatusMap = Collections.unmodifiableMap(map);
169 private String getBuildInfoString(
final CLDevice device,
final int flag) {
175 final PointerBuffer size = PointerBuffer.allocateDirect(1);
178 if(ret != CL_SUCCESS) {
179 throw newException(ret,
"on clGetProgramBuildInfo with "+device);
182 final ByteBuffer buffer = newDirectByteBuffer((
int)size.get(0));
185 if(ret != CL_SUCCESS) {
186 throw newException(ret,
"on clGetProgramBuildInfo with "+device);
192 private String getProgramInfoString(
final int flag) {
198 final PointerBuffer size = PointerBuffer.allocateDirect(1);
201 checkForError(ret,
"on clGetProgramInfo");
203 final ByteBuffer buffer = newDirectByteBuffer((
int)size.get(0));
206 checkForError(ret,
"on clGetProgramInfo");
211 private int getBuildInfoInt(
final CLDevice device,
final int flag) {
213 final ByteBuffer buffer = newDirectByteBuffer(4);
216 checkForError(ret,
"error on clGetProgramBuildInfo");
218 return buffer.getInt();
247 build(
null, (String)
null, devices);
259 build(listener,
null, devices);
313 build(
null, options, devices);
329 throw new CLException(
"can not build a released program");
332 if(!kernels.isEmpty()) {
338 PointerBuffer deviceIDs =
null;
340 if(devices !=
null && devices.length != 0) {
341 deviceIDs = PointerBuffer.allocateDirect(devices.length);
342 for (
int i = 0; i < devices.length; i++) {
343 deviceIDs.put(i, devices[i].
ID);
346 count = devices.length;
350 if(options !=
null && options.trim().isEmpty()) {
355 buildStatusMap =
null;
359 if(listener !=
null) {
362 public void buildFinished(
final long cl_program) {
377 }
catch(
final InterruptedException e) {
378 throw newException(ret,
"\nInterrupted while waiting to get build lock");
381 boolean exception =
true;
386 if(callback ==
null || exception) {
392 if(ret != CL_SUCCESS) {
415 final int[] err =
new int[1];
417 if(err[0] != CL_SUCCESS) {
418 throw newException(err[0],
"unable to create Kernel with name: "+kernelName);
432 return Collections.emptyMap();
435 final HashMap<String, CLKernel> newKernels =
new HashMap<String, CLKernel>();
437 final IntBuffer numKernels = newDirectByteBuffer(4).asIntBuffer();
439 if(ret != CL_SUCCESS) {
440 throw newException(ret,
"can not create kernels for "+
this);
443 if(numKernels.get(0) > 0) {
445 final PointerBuffer kernelIDs = PointerBuffer.allocateDirect(numKernels.get(0));
447 if(ret != CL_SUCCESS) {
448 throw newException(ret,
"can not create "+kernelIDs.capacity()+
" kernels for "+
this);
451 for (
int i = 0; i < kernelIDs.capacity(); i++) {
454 newKernels.put(kernel.
name, kernel);
461 throw newException(CL_INVALID_PROGRAM_EXECUTABLE,
462 "can not initialize kernels, program is not executable. status: "+buildStatusMap);
469 void onKernelReleased(
final CLKernel kernel) {
470 this.kernels.remove(kernel);
484 buildStatusMap =
null;
487 context.onProgramReleased(
this);
488 if(ret != CL_SUCCESS) {
489 throw newException(ret,
"can not release "+
this);
493 private void releaseKernels() {
494 if(!kernels.isEmpty()) {
497 for (
final CLKernel kernel : array) {
511 final PointerBuffer size = PointerBuffer.allocateDirect(1);
513 if(ret != CL_SUCCESS) {
514 throw newException(ret,
"on clGetProgramInfo of "+
this);
517 final ByteBuffer bb = newDirectByteBuffer((
int) size.get(0));
519 if(ret != CL_SUCCESS) {
520 throw newException(ret,
"on clGetProgramInfo of "+
this);
523 final int count = bb.capacity() / (Platform.is32Bit()?4:8);
525 for (
int i = 0; i < count; i++) {
526 devices[i] =
context.getDevice(Platform.is32Bit()?bb.getInt():bb.getLong());
541 final StringBuilder sb =
new StringBuilder(200);
543 for (
int i = 0; i < devices.length; i++) {
545 sb.append(device).append(
" build log:\n");
547 sb.append(log.isEmpty()?
" <empty>":log);
548 if(i != devices.length-1)
551 return sb.toString();
559 return Collections.emptyMap();
562 return buildStatusMap;
582 return getBuildInfoString(device, CL_PROGRAM_BUILD_LOG);
592 final int clStatus = getBuildInfoInt(device, CL_PROGRAM_BUILD_STATUS);
613 return getProgramInfoString(CL_PROGRAM_SOURCE);
626 return Collections.emptyMap();
631 final PointerBuffer sizes = PointerBuffer.allocateDirect(devices.length);
632 int ret = binding.
clGetProgramInfo(
ID, CL_PROGRAM_BINARY_SIZES, sizes.capacity()*sizes.elementSize(), sizes.getBuffer(),
null);
633 if(ret != CL_SUCCESS) {
634 throw newException(ret,
"on clGetProgramInfo(CL_PROGRAM_BINARY_SIZES) of "+
this);
637 int binariesSize = 0;
638 while(sizes.remaining() != 0) {
639 final int size = (int) sizes.get();
640 binariesSize += size;
642 final ByteBuffer binaries = newDirectByteBuffer(binariesSize);
645 long address = InternalBufferUtil.getDirectBufferAddress(binaries);
646 final PointerBuffer addresses = PointerBuffer.allocateDirect(sizes.capacity());
648 while(sizes.remaining() != 0) {
649 addresses.put(address);
650 address += sizes.get();
654 ret = binding.
clGetProgramInfo(
ID, CL_PROGRAM_BINARIES, addresses.capacity()*addresses.elementSize(), addresses.getBuffer(),
null);
655 if(ret != CL_SUCCESS) {
656 throw newException(ret,
"on clGetProgramInfo(CL_PROGRAM_BINARIES) of "+
this);
661 for (
int i = 0; i < devices.length; i++) {
662 final byte[] bytes =
new byte[(int)sizes.get()];
664 map.put(devices[i], bytes);
673 public static String
optionsOf(
final String... options) {
674 final StringBuilder sb =
new StringBuilder(options.length * 24);
675 for (
int i = 0; i < options.length; i++) {
676 sb.append(options[i]);
677 if(i!= options.length-1)
680 return sb.toString();
686 public static String
define(
final String name) {
693 public static String
define(
final String name,
final Object value) {
694 return "-D "+name+
"="+value;
699 return "CLProgram [id: " +
ID
704 public boolean equals(
final Object obj) {
708 if (getClass() != obj.getClass()) {
712 if (this.
ID != other.
ID) {
724 hash = 37 * hash + (this.context !=
null ? this.context.
hashCode() : 0);
725 hash = 37 * hash + (int) (this.
ID ^ (this.
ID >>> 32));
741 private Status(
final int status) {
742 this.STATUS = status;
746 switch(clBuildStatus) {
747 case(CL_BUILD_SUCCESS):
748 return BUILD_SUCCESS;
751 case(CL_BUILD_IN_PROGRESS):
752 return BUILD_IN_PROGRESS;
753 case(CL_BUILD_ERROR):
822 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).