summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Bien <[email protected]>2010-02-24 17:59:23 +0100
committerMichael Bien <[email protected]>2010-02-24 17:59:23 +0100
commit2694d25e5ce59c4f4741b60242331d56601f90d1 (patch)
treea87802dcea13c761e8400e53353f822bb6139c77
parentdc4fc464ea969614e08c81dbaeefdaaff1673296 (diff)
initial import of CLProgramBuilder.
-rw-r--r--src/com/mbien/opencl/CLProgram.java38
-rw-r--r--src/com/mbien/opencl/CLProgramBuilder.java156
-rw-r--r--test/com/mbien/opencl/CLProgramTest.java40
3 files changed, 213 insertions, 21 deletions
diff --git a/src/com/mbien/opencl/CLProgram.java b/src/com/mbien/opencl/CLProgram.java
index 829809de..562df69b 100644
--- a/src/com/mbien/opencl/CLProgram.java
+++ b/src/com/mbien/opencl/CLProgram.java
@@ -206,6 +206,10 @@ public class CLProgram extends CLObject implements CLResource {
*/
public CLProgram build(String options, CLDevice... devices) {
+ if(released) {
+ throw new CLException("can not build a released program");
+ }
+
if(!kernels.isEmpty()) {
//No changes to the program executable are allowed while there are
//kernel objects associated with a program object.
@@ -214,7 +218,7 @@ public class CLProgram extends CLObject implements CLResource {
PointerBuffer deviceIDs = null;
int count = 0;
- if(devices != null) {
+ if(devices != null && devices.length != 0) {
deviceIDs = PointerBuffer.allocateDirect(devices.length);
for (int i = 0; i < devices.length; i++) {
deviceIDs.put(i, devices[i].ID);
@@ -223,6 +227,11 @@ public class CLProgram extends CLObject implements CLResource {
count = devices.length;
}
+ // nvidia driver doesn't like empty strings
+ if(options != null && options.trim().isEmpty()) {
+ options = null;
+ }
+
// invalidate build status
buildStatusMap = null;
executable = false;
@@ -238,6 +247,13 @@ public class CLProgram extends CLObject implements CLResource {
}
/**
+ * Prepares the build for this program by returning a {@link CLProgramBuilder}.
+ */
+ public CLProgramBuilder prepare() {
+ return new CLProgramBuilder(this);
+ }
+
+ /**
* Creates a kernel with the specified kernel name.
*/
public CLKernel createCLKernel(String kernelName) {
@@ -256,24 +272,6 @@ public class CLProgram extends CLObject implements CLResource {
}
/**
- * Creates n instances of a kernel with the specified kernel name.
- */
- /*
- public CLKernel[] createCLKernels(String kernelName, int instanceCount) {
-
- if(released) {
- return new CLKernel[0];
- }
-
- CLKernel[] newKernels = new CLKernel[instanceCount];
- for (int i = 0; i < newKernels.length; i++) {
- newKernels[i] = createCLKernel(kernelName);
- }
- return newKernels;
- }
- */
-
- /**
* Creates all kernels of this program and stores them a Map with the kernel name as key.
*/
public Map<String, CLKernel> createCLKernels() {
@@ -596,7 +594,7 @@ public class CLProgram extends CLObject implements CLResource {
* This option is ignored for single precision numbers if the device does not support single precision denormalized
* numbers i.e. {@link CLDevice.FPConfig#DENORM} is not present in the set returned by {@link CLDevice#getSingleFPConfig()}<br>
* This option is ignored for double precision numbers if the device does not support double precision or if it does support
- * double precison but {@link CLDevice.FPConfig#DENORM} is not present in the set returned by {@link CLDevice#getDoubleFPConfig()}.<br>
+ * double precision but {@link CLDevice.FPConfig#DENORM} is not present in the set returned by {@link CLDevice#getDoubleFPConfig()}.<br>
* This flag only applies for scalar and vector single precision floating-point variables and computations on
* these floating-point variables inside a program. It does not apply to reading from or writing to image objects.
*/
diff --git a/src/com/mbien/opencl/CLProgramBuilder.java b/src/com/mbien/opencl/CLProgramBuilder.java
new file mode 100644
index 00000000..3f7ab07b
--- /dev/null
+++ b/src/com/mbien/opencl/CLProgramBuilder.java
@@ -0,0 +1,156 @@
+package com.mbien.opencl;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+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 the same configuration.
+ * @see CLProgram#prepare()
+ * @author Michael Bien
+ */
+public final class CLProgramBuilder {
+
+ private transient CLProgram program;
+ private final Set<String> optionList = new HashSet<String>();
+ private final Set<String> defineList = new HashSet<String>();
+ private final Set<CLDevice> deviceList = new HashSet<CLDevice>();
+
+ public CLProgramBuilder() { }
+
+ public CLProgramBuilder(CLProgram program) {
+ this.program = program;
+ }
+
+ public CLProgramBuilder withOption(String option) {
+ this.optionList.add(option);
+ return this;
+ }
+
+ public CLProgramBuilder withOptions(String... options) {
+ for (String option : options) {
+ this.optionList.add(option);
+ }
+ return this;
+ }
+
+ public CLProgramBuilder withDefine(String name) {
+ this.defineList.add(CLProgram.define(name));
+ return this;
+ }
+
+ public CLProgramBuilder withDefines(String... names) {
+ for (String name : names) {
+ this.defineList.add(CLProgram.define(name));
+ }
+ return this;
+ }
+
+ public CLProgramBuilder withDefine(String name, Object value) {
+ this.defineList.add(CLProgram.define(name, value.toString()));
+ return this;
+ }
+
+ public CLProgramBuilder withDefines(Map<String, String> defines) {
+ for (String name : defines.keySet()) {
+ defineList.add(CLProgram.define(name, defines.get(name)));
+ }
+ return this;
+ }
+
+ public CLProgramBuilder forDevice(CLDevice device) {
+ CLDevice[] devices = new CLDevice[]{device};
+ for (CLDevice device1 : devices) {
+ this.deviceList.add(device1);
+ }
+ return this;
+ }
+
+ public CLProgramBuilder forDevices(CLDevice... devices) {
+ for (CLDevice device : devices) {
+ this.deviceList.add(device);
+ }
+ return this;
+ }
+
+ /**
+ * Builds or rebuilds a program.
+ */
+ public CLProgram build() {
+ return build(program);
+ }
+
+ /**
+ * Builds or rebuilds a program.
+ */
+ public CLProgram build(CLProgram program) {
+ if(program == null) {
+ throw new NullPointerException("no program has been set");
+ }
+ List<String> setup = new ArrayList<String>();
+ setup.addAll(optionList);
+ setup.addAll(defineList);
+ String options = CLProgram.optionsOf(setup.toArray(new String[setup.size()]));
+ CLDevice[] devices = deviceList.toArray(new CLDevice[deviceList.size()]);
+ return program.build(options, devices);
+ }
+
+ /**
+ * Resets this builder's configuration like options, devices and defines.
+ */
+ public CLProgramBuilder reset() {
+ optionList.clear();
+ defineList.clear();
+ deviceList.clear();
+ return this;
+ }
+
+ public CLProgram getProgram() {
+ return program;
+ }
+
+ /**
+ * Sets the program which should be build.
+ */
+ public CLProgramBuilder setProgram(CLProgram program) {
+ this.program = program;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("CLProgramBuilder");
+ sb.append("{optionList=").append(optionList);
+ sb.append(", defineList=").append(defineList);
+ sb.append(", deviceList=").append(deviceList);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ CLProgramBuilder that = (CLProgramBuilder) o;
+
+ if (defineList != null ? !defineList.equals(that.defineList) : that.defineList != null) return false;
+ if (deviceList != null ? !deviceList.equals(that.deviceList) : that.deviceList != null) return false;
+ if (optionList != null ? !optionList.equals(that.optionList) : that.optionList != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = optionList != null ? optionList.hashCode() : 0;
+ result = 31 * result + (defineList != null ? defineList.hashCode() : 0);
+ result = 31 * result + (deviceList != null ? deviceList.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/test/com/mbien/opencl/CLProgramTest.java b/test/com/mbien/opencl/CLProgramTest.java
index 84e0eed5..95ed5e8c 100644
--- a/test/com/mbien/opencl/CLProgramTest.java
+++ b/test/com/mbien/opencl/CLProgramTest.java
@@ -8,7 +8,6 @@ import org.junit.Test;
import static org.junit.Assert.*;
import static java.lang.System.*;
import static com.mbien.opencl.CLProgram.CompilerOptions.*;
-import static com.mbien.opencl.CLProgram.Status.*;
/**
*
@@ -143,6 +142,45 @@ public class CLProgramTest {
}
+ @Test
+ public void builderTest() throws IOException {
+ out.println(" - - - CLProgramTest; builder test - - - ");
+
+ CLContext context = CLContext.create();
+ CLProgram program = context.createProgram(getClass().getResourceAsStream("testkernels.cl"));
+
+ // same as program.build()
+ program.prepare().build();
+
+ assertTrue(program.isExecutable());
+// program.release();
+
+
+ // complex build
+ program.prepare().withOption(ENABLE_MAD)
+ .forDevice(context.getMaxFlopsDevice())
+ .withDefine("RADIUS", 5)
+ .withDefine("ENABLE_FOOBAR")
+ .build();
+
+ assertTrue(program.isExecutable());
+// program.release();
+
+ // reusable builder
+ CLProgramBuilder builder = new CLProgramBuilder()
+ .withOption(ENABLE_MAD)
+ .forDevice(context.getMaxFlopsDevice())
+ .withDefine("RADIUS", 5)
+ .withDefine("ENABLE_FOOBAR");
+
+ builder.build(program);
+
+ assertTrue(program.isExecutable());
+// program.release();
+
+
+ }
+
}