
com.jogamp.opencl.CLProgramBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jocl-android Show documentation
Show all versions of jocl-android Show documentation
Java™ Binding for the OpenCL® API (Android runtime)
The newest version!
/*
* Copyright 2009 - 2010 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
package com.jogamp.opencl;
import com.jogamp.opencl.util.CLBuildConfiguration;
import com.jogamp.opencl.util.CLBuildListener;
import com.jogamp.opencl.util.CLProgramConfiguration;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* CLProgramBuilder is a helper for building programs with more complex configurations or
* building multiple programs with similar configurations.
* CLProgramBuilder is used to create {@link CLProgramConfiguration}s and {@link CLBuildConfiguration}s.
* @see CLProgram#prepare()
* @see #createConfiguration()
* @see #createConfiguration(com.jogamp.opencl.CLProgram)
* @see #loadConfiguration(java.io.ObjectInputStream)
* @see #loadConfiguration(java.io.ObjectInputStream, com.jogamp.opencl.CLContext)
* @author Michael Bien
*/
public final class CLProgramBuilder implements CLProgramConfiguration, Serializable, Cloneable {
static final long serialVersionUID = 42;
private static final byte[] NO_BINARIES = new byte[0];
private transient CLProgram program;
private transient Map binariesMap = new LinkedHashMap();
private String source;
private final Set optionSet = new LinkedHashSet();
private final Set defineSet = new LinkedHashSet();
private CLProgramBuilder() {
this(null);
}
private CLProgramBuilder(final CLProgram program) {
this(program, null, null);
}
private CLProgramBuilder(final CLProgram program, final String source, final Map map) {
this.program = program;
this.source = source;
if(map != null) {
this.binariesMap.putAll(map);
}
}
/**
* Creates a new CLBuildConfiguration.
*/
public static CLBuildConfiguration createConfiguration() {
return createConfiguration(null);
}
/**
* Creates a new CLProgramConfiguration for this program.
*/
public static CLProgramConfiguration createConfiguration(final CLProgram program) {
return new CLProgramBuilder(program);
}
/**
* Loads a CLBuildConfiguration.
* @param ois The ObjectInputStream for reading the object.
*/
public static CLBuildConfiguration loadConfiguration(final ObjectInputStream ois) throws IOException, ClassNotFoundException {
return (CLBuildConfiguration) ois.readObject();
}
/**
* Loads a CLProgramConfiguration containing a CLProgram.
* The CLProgram is initialized and ready to be build after this method call.
* This method prefers program initialization from binaries if this fails or if
* no binaries have been found, it will try to load the program from sources. If
* this also fails an appropriate exception will be thrown.
* @param ois The ObjectInputStream for reading the object.
* @param context The context used for program initialization.
*/
public static CLProgramConfiguration loadConfiguration(final ObjectInputStream ois, final CLContext context) throws IOException, ClassNotFoundException {
final CLProgramBuilder config = (CLProgramBuilder) ois.readObject();
if(allBinariesAvailable(config)) {
try{
config.program = context.createProgram(config.binariesMap);
}catch(final CLException.CLInvalidBinaryException ex) {
if(config.source != null) {
config.program = context.createProgram(config.source);
}else{
throw new IOException("Program configuration contained invalid program binaries and no source.", ex);
}
}
}else if(config.source != null) {
config.program = context.createProgram(config.source);
}else{
throw new IOException("Program configuration did not contain program sources or binaries");
}
return config;
}
private static boolean allBinariesAvailable(final CLProgramBuilder config) {
for (final Map.Entry entry : config.binariesMap.entrySet()) {
if(Arrays.equals(NO_BINARIES, entry.getValue())) {
return false;
}
}
return config.binariesMap.size() > 0;
}
@Override
public void save(final ObjectOutputStream oos) throws IOException {
if(program != null) {
this.source = program.getSource();
if(program.isExecutable()) {
binariesMap = program.getBinaries();
}
}
oos.writeObject(this);
}
@Override
public CLProgramBuilder withOption(final String option) {
optionSet.add(option);
return this;
}
@Override
public CLProgramBuilder withOptions(final String... options) {
optionSet.addAll(Arrays.asList(options));
return this;
}
@Override
public CLProgramBuilder withDefine(final String name) {
defineSet.add(CLProgram.define(name));
return this;
}
@Override
public CLProgramBuilder withDefines(final String... names) {
for (final String name : names) {
defineSet.add(CLProgram.define(name));
}
return this;
}
@Override
public CLProgramBuilder withDefine(final String name, final Object value) {
defineSet.add(CLProgram.define(name, value.toString()));
return this;
}
@Override
public CLProgramBuilder withDefines(final Map defines) {
for (final Map.Entry define : defines.entrySet()) {
final String name = define.getKey();
final Object value = define.getValue();
defineSet.add(CLProgram.define(name, value));
}
return this;
}
@Override
public CLProgramBuilder forDevice(final CLDevice device) {
if(!binariesMap.containsKey(device)) {
binariesMap.put(device, NO_BINARIES);
}
return this;
}
@Override
public CLProgramBuilder forDevices(final CLDevice... devices) {
for (final CLDevice device : devices) {
forDevice(device);
}
return this;
}
@Override
public CLProgram build() {
return build(program, null);
}
@Override
public CLProgram build(final CLBuildListener listener) {
return build(program, listener);
}
@Override
public CLProgram build(final CLProgram program) {
return build(program, null);
}
@Override
public CLProgram build(final CLProgram program, final CLBuildListener listener) {
if(program == null) {
throw new NullPointerException("no program has been set");
}
final List setup = new ArrayList();
setup.addAll(optionSet);
setup.addAll(defineSet);
final String options = CLProgram.optionsOf(setup.toArray(new String[setup.size()]));
final CLDevice[] devices = binariesMap.keySet().toArray(new CLDevice[binariesMap.size()]);
return program.build(listener, options, devices);
}
@Override
public CLProgramBuilder reset() {
resetOptions();
resetDefines();
resetDevices();
return this;
}
@Override
public CLProgramConfiguration resetDefines() {
defineSet.clear();
return this;
}
@Override
public CLProgramConfiguration resetDevices() {
binariesMap.clear();
return this;
}
@Override
public CLProgramConfiguration resetOptions() {
optionSet.clear();
return this;
}
// format: { platform_suffix, num_binaries, (device_name, length, binaries)+ }
private void writeObject(final ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
String suffix = "";
if(!binariesMap.isEmpty()) {
final CLDevice device = binariesMap.keySet().iterator().next();
if(device.isICDAvailable())
suffix = device.getPlatform().getICDSuffix();
}
// empty string if we have no binaries or no devices specified, or if cl_khr_icd isn't supported
out.writeUTF(suffix);
out.writeInt(binariesMap.size()); // may be 0
for (final Map.Entry entry : binariesMap.entrySet()) {
final CLDevice device = entry.getKey();
final byte[] binaries = entry.getValue();
out.writeUTF(device.getName());
out.writeInt(binaries.length);
out.write(binaries);
}
}
private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
final String suffix = in.readUTF(); // empty string means no suffix was written; just picks first platform
CLPlatform platform = null;
for (final CLPlatform p : CLPlatform.listCLPlatforms()) {
if(suffix.isEmpty() || p.getICDSuffix().equals(suffix)) {
platform = p;
break;
}
}
this.binariesMap = new LinkedHashMap();
List devices;
if(platform != null) {
devices = new ArrayList(Arrays.asList(platform.listCLDevices()));
}else{
devices = Collections.emptyList();
}
final int mapSize = in.readInt();
for (int i = 0; i < mapSize; i++) {
final String name = in.readUTF();
final int length = in.readInt();
final byte[] binaries = new byte[length];
in.readFully(binaries);
for (int d = 0; d < devices.size(); d++) {
final CLDevice device = devices.get(d);
if(device.getName().equals(name)) {
binariesMap.put(device, binaries);
devices.remove(d);
break;
}
}
}
}
@Override
public CLProgramBuilder asBuildConfiguration() {
final CLProgramBuilder builder = new CLProgramBuilder();
builder.defineSet.addAll(defineSet);
builder.optionSet.addAll(optionSet);
return builder;
}
@Override
public CLProgramBuilder clone() {
final CLProgramBuilder builder = new CLProgramBuilder(program, source, binariesMap);
builder.defineSet.addAll(defineSet);
builder.optionSet.addAll(optionSet);
return builder;
}
@Override
public CLProgram getProgram() {
return program;
}
@Override
public CLProgramBuilder setProgram(final CLProgram program) {
this.program = program;
return this;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("CLProgramBuilder");
sb.append("{options=").append(optionSet);
sb.append(", defines=").append(defineSet);
sb.append(", devices=").append(binariesMap);
sb.append('}');
return sb.toString();
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final CLProgramBuilder that = (CLProgramBuilder) o;
if (source != null ? !source.equals(that.source) : that.source != null) return false;
if (defineSet != null ? !defineSet.equals(that.defineSet) : that.defineSet != null) return false;
if (optionSet != null ? !optionSet.equals(that.optionSet) : that.optionSet != null) return false;
if(binariesMap != null && that.binariesMap != null) {
if(binariesMap.size() != that.binariesMap.size()) {
return false;
}
final Iterator iterator0 = binariesMap.keySet().iterator();
final Iterator iterator1 = that.binariesMap.keySet().iterator();
for (int i = 0; i < binariesMap.size(); i++) {
final CLDevice device0 = iterator0.next();
final CLDevice device1 = iterator1.next();
if(!device0.equals(device1) || !Arrays.equals(binariesMap.get(device0), that.binariesMap.get(device1)))
return false;
}
}else if(binariesMap != null || that.binariesMap != null) {
return false;
}
return true;
}
@Override
public int hashCode() {
int result = optionSet != null ? optionSet.hashCode() : 0;
result = 31 * result + (defineSet != null ? defineSet.hashCode() : 0);
result = 31 * result + (binariesMap != null ? binariesMap.hashCode() : 0);
return result;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy