Jogamp
5946deb44c60abfd1c5e73615901a4e204f91c71
[jocl.git] / test / com / jogamp / opencl / CLProgramTest.java
1 /*
2  * Copyright 2010 JogAmp Community. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification, are
5  * permitted provided that the following conditions are met:
6  *
7  *    1. Redistributions of source code must retain the above copyright notice, this list of
8  *       conditions and the following disclaimer.
9  *
10  *    2. Redistributions in binary form must reproduce the above copyright notice, this list
11  *       of conditions and the following disclaimer in the documentation and/or other materials
12  *       provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
15  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  * The views and conclusions contained in the software and documentation are those of the
25  * authors and should not be interpreted as representing official policies, either expressed
26  * or implied, of JogAmp Community.
27  */
28
29 package com.jogamp.opencl;
30
31 import com.jogamp.opencl.test.util.UITestCase;
32 import com.jogamp.opencl.util.CLBuildConfiguration;
33 import com.jogamp.opencl.util.CLProgramConfiguration;
34 import com.jogamp.opencl.CLProgram.Status;
35 import com.jogamp.opencl.util.CLBuildListener;
36 import com.jogamp.opencl.llb.CL;
37
38 import java.io.File;
39 import java.io.FileInputStream;
40 import java.io.FileOutputStream;
41 import java.io.IOException;
42 import java.io.ObjectInputStream;
43 import java.io.ObjectOutputStream;
44 import java.util.Map;
45 import java.util.concurrent.CountDownLatch;
46
47 import org.junit.FixMethodOrder;
48 import org.junit.Rule;
49 import org.junit.Test;
50 import org.junit.rules.TemporaryFolder;
51 import org.junit.runners.MethodSorters;
52
53 import static org.junit.Assert.*;
54 import static java.lang.System.*;
55 import static com.jogamp.opencl.CLProgram.CompilerOptions.*;
56
57 /**
58  *
59  * @author Michael Bien, et.al
60  */
61 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
62 public class CLProgramTest extends UITestCase {
63
64     @Rule
65     public TemporaryFolder tmpFolder = new TemporaryFolder();
66
67
68     @Test
69     public void test01Enums() {
70
71         // CLProgram enums
72         for (final Status e : Status.values()) {
73             assertEquals(e, Status.valueOf(e.STATUS));
74         }
75     }
76
77     @Test
78     public void test02RebuildProgram() throws IOException {
79         final CLContext context = CLContext.create();
80         final CLProgram program = context.createProgram(getClass().getResourceAsStream("testkernels.cl"));
81
82         // only test kernel creation error on unbuilt program if we're not on AMD -- as of
83         // 3/8/2014, AMD drivers segfault on this instead of returning CL_INVALID_PROGRAM_EXECUTABLE
84         if(!context.getPlatform().isVendorAMD()) {
85             try{
86                 program.createCLKernels();
87                 fail("expected exception but got none :(");
88             }catch(final CLException ex) {
89                 out.println("got expected exception:  "+ex.getCLErrorString());
90                 assertEquals(ex.errorcode, CL.CL_INVALID_PROGRAM_EXECUTABLE);
91             }
92         }
93
94         out.println(program.getBuildStatus());
95         program.build();
96         out.println(program.getBuildStatus());
97
98         assertTrue(program.isExecutable());
99
100         CLKernel kernel = program.createCLKernel("VectorAddGM");
101         assertNotNull(kernel);
102
103         // rebuild
104         // 1. release kernels (internally)
105         // 2. build program
106         program.build();
107         assertTrue(program.isExecutable());
108         out.println(program.getBuildStatus());
109
110         // try again with rebuilt program
111         kernel = program.createCLKernel("VectorAddGM");
112         assertNotNull(kernel);
113
114         context.release();
115     }
116
117     @Test
118     public void test03ProgramBinaries() throws IOException {
119         final CLContext context = CLContext.create();
120         CLProgram program = context.createProgram(getClass().getResourceAsStream("testkernels.cl"))
121                                    .build(ENABLE_MAD, WARNINGS_ARE_ERRORS);
122
123         // obtain binaries
124         final Map<CLDevice, byte[]> binaries = program.getBinaries();
125         assertFalse(binaries.isEmpty());
126
127         final CLDevice[] devices = program.getCLDevices();
128         for (final CLDevice device : devices) {
129             assertTrue(binaries.containsKey(device));
130         }
131
132         // 1. release program
133         // 2. re-create program with old binaries
134         program.release();
135
136         assertFalse(program.isExecutable());
137
138         assertNotNull(program.getBinaries());
139         assertEquals(program.getBinaries().size(), 0);
140
141         assertNotNull(program.getBuildLog());
142         assertEquals(program.getBuildLog().length(), 0);
143
144         assertNotNull(program.getSource());
145         assertEquals(program.getSource().length(), 0);
146
147         assertNotNull(program.getCLDevices());
148         assertEquals(program.getCLDevices().length, 0);
149
150         {
151             final Map<String, CLKernel> kernels = program.createCLKernels();
152             assertNotNull(kernels);
153             assertEquals(kernels.size(), 0);
154         }
155         assertNull(program.createCLKernel("foo"));
156
157         program = context.createProgram(binaries);
158
159         assertFalse(program.isExecutable());
160
161         assertNotNull(program.getCLDevices());
162         assertTrue(program.getCLDevices().length != 0);
163
164         assertNotNull(program.getBinaries());
165         assertEquals(program.getBinaries().size(), 0);
166
167         assertNotNull(program.getBuildLog());
168         assertTrue(program.getBuildLog().length() != 0);
169
170         assertNotNull(program.getSource());
171         assertEquals(program.getSource().length(), 0);
172
173         // only test kernel creation error on unbuilt program if we're not on AMD -- as of
174         // 3/8/2014, AMD drivers segfault on this instead of returning CL_INVALID_PROGRAM_EXECUTABLE
175         if(!context.getPlatform().isVendorAMD()) {
176             try{
177                 final Map<String, CLKernel> kernels = program.createCLKernels();
178                 fail("expected an exception from createCLKernels but got: "+kernels);
179             }catch(final CLException ex) {
180                 // expected, not built yet
181             }
182         }
183
184         out.println(program.getBuildStatus());
185         program.build();
186         out.println(program.getBuildStatus());
187
188         assertNotNull(program.createCLKernel("Test"));
189
190         assertTrue(program.isExecutable());
191
192         context.release();
193
194     }
195
196     private void builderImpl(final boolean sync) throws IOException, ClassNotFoundException, InterruptedException {
197         final CLContext context = CLContext.create();
198         CLProgram program = context.createProgram(getClass().getResourceAsStream("testkernels.cl"));
199
200         // same as program.build()
201         program.prepare().build();
202
203         assertTrue(program.isExecutable());
204
205
206         // complex build
207         program.prepare().withOption(ENABLE_MAD)
208                          .forDevice(context.getMaxFlopsDevice())
209                          .withDefine("RADIUS", 5)
210                          .withDefine("ENABLE_FOOBAR")
211                          .build();
212
213         assertTrue(program.isExecutable());
214
215         // reusable builder
216         final CLBuildConfiguration builder = CLProgramBuilder.createConfiguration()
217                                      .withOption(ENABLE_MAD)
218                                      .forDevices(context.getDevices())
219                                      .withDefine("RADIUS", 5)
220                                      .withDefine("ENABLE_FOOBAR");
221
222         out.println(builder);
223
224         if( sync ) {
225             // sync build test
226             final CLProgram outerProgram = program;
227
228             builder.setProgram(program).build();
229             assertEquals(outerProgram, program);
230         } else {
231             // async build test
232             final CountDownLatch countdown = new CountDownLatch(1);
233             final CLProgram outerProgram = program;
234
235             final CLBuildListener buildCallback = new CLBuildListener() {
236                 @Override
237                 public void buildFinished(final CLProgram program) {
238                     assertEquals(outerProgram, program);
239                     countdown.countDown();
240                 }
241             };
242             builder.setProgram(program).build(buildCallback);
243             countdown.await();
244         }
245
246         assertTrue(program.isExecutable());
247
248         // serialization test
249         final File file = tmpFolder.newFile("foobar.builder");
250         final ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
251         builder.save(oos);
252         oos.close();
253
254         // build configuration
255         ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
256         final CLBuildConfiguration buildConfig = CLProgramBuilder.loadConfiguration(ois);
257         ois.close();
258
259         assertEquals(builder, buildConfig);
260
261         buildConfig.build(program);
262         assertTrue(program.isExecutable());
263
264         // program configuration
265         ois = new ObjectInputStream(new FileInputStream(file));
266         final CLProgramConfiguration programConfig = CLProgramBuilder.loadConfiguration(ois, context);
267         assertNotNull(programConfig.getProgram());
268         ois.close();
269         program = programConfig.build();
270         assertTrue(program.isExecutable());
271
272         // cloneing
273         assertEquals(builder, builder.clone());
274
275         context.release();
276     }
277
278
279     @Test
280     public void test10BuilderSync() throws IOException, ClassNotFoundException, InterruptedException {
281         builderImpl(true);
282     }
283
284     @Test
285     public void test11BuilderAsync() throws IOException, ClassNotFoundException, InterruptedException {
286         builderImpl(false);
287     }
288
289     private static final String test20KernelSource = "__attribute__((reqd_work_group_size(1, 1, 1))) kernel void foo(float a, int b, short c) { }\n";
290
291     @Test
292     public void test20Kernel() {
293         final CLContext context = CLContext.create();
294
295         try{
296             final CLProgram program = context.createProgram(test20KernelSource).build();
297             assertTrue(program.isExecutable());
298
299             final CLKernel kernel = program.createCLKernel("foo");
300             assertNotNull(kernel);
301
302             final long[] wgs = kernel.getCompileWorkGroupSize(context.getDevices()[0]);
303
304             out.println("compile workgroup size: " + wgs[0]+" "+wgs[1]+" "+wgs[2]);
305
306             assertEquals(1, wgs[0]);
307             assertEquals(1, wgs[1]);
308             assertEquals(1, wgs[2]);
309
310             // put args test
311             assertEquals(0, kernel.position());
312
313             kernel.putArg(1.0f);
314             assertEquals(1, kernel.position());
315
316             kernel.putArg(2);
317             assertEquals(2, kernel.position());
318
319             kernel.putArg((short)3);
320             assertEquals(3, kernel.position());
321
322             try{
323                 kernel.putArg(3);
324                 fail("exception not thrown");
325             }catch (final IndexOutOfBoundsException expected){ }
326
327             assertEquals(3, kernel.position());
328             assertEquals(0, kernel.rewind().position());
329
330         }finally{
331             context.release();
332         }
333
334     }
335
336     @Test
337     public void test21AllKernels() {
338         final String source = "kernel void foo(int a) { }\n"+
339                         "kernel void bar(float b) { }\n";
340
341         final CLContext context = CLContext.create();
342         try{
343             final CLProgram program = context.createProgram(source).build();
344             assertTrue(program.isExecutable());
345
346             final Map<String, CLKernel> kernels = program.createCLKernels();
347             for (final CLKernel kernel : kernels.values()) {
348                 out.println("kernel: "+kernel.toString());
349             }
350
351             assertNotNull(kernels.get("foo"));
352             assertNotNull(kernels.get("bar"));
353
354             kernels.get("foo").setArg(0, 42);
355             kernels.get("bar").setArg(0, 3.14f);
356
357
358         }finally{
359             context.release();
360         }
361
362     }
363
364 //    @Test
365     public void test60Load() throws IOException, ClassNotFoundException, InterruptedException {
366         for(int i = 0; i < 100; i++) {
367             test02RebuildProgram();
368             test11BuilderAsync();
369             test03ProgramBinaries();
370         }
371     }
372
373     public static void main(final String[] args) throws IOException {
374         final String tstname = CLProgramTest.class.getName();
375         org.junit.runner.JUnitCore.main(tstname);
376     }
377
378 }
http://JogAmp.org git info: FAQ, tutorial and man pages.