Jogamp
Fix CLProgramTest for Intel OpenCL
[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         // make sure kernel creation does nothing after program release 
151         {
152             final Map<String, CLKernel> kernels = program.createCLKernels();
153             assertNotNull(kernels);
154             assertEquals(kernels.size(), 0);
155         }
156         assertNull(program.createCLKernel("foo"));
157
158         program = context.createProgram(binaries);
159
160         // as of 10/25/2015, Intel shows recreated programs as executable 
161         if(!context.getPlatform().isVendorIntel())
162                 assertFalse(program.isExecutable());
163         else
164                 assertTrue(program.isExecutable());
165                 
166         assertNotNull(program.getCLDevices());
167         assertTrue(program.getCLDevices().length != 0);
168
169         assertNotNull(program.getBinaries());
170         // as of 10/25/2015, Intel shows recreated programs binaries as having size 
171         if(!context.getPlatform().isVendorIntel())
172                 assertEquals(program.getBinaries().size(), 0);
173         else
174                 assertTrue(program.getBinaries().size() > 0);
175
176         assertNotNull(program.getBuildLog());
177         assertTrue(program.getBuildLog().length() != 0);
178
179         assertNotNull(program.getSource());
180         assertEquals(program.getSource().length(), 0);
181
182         // only test kernel creation error on unbuilt program if we're not on AMD or Intel -- as of
183         // (3/8/2014, 10/31/2015) (AMD, Intel) drivers segfault on this instead of returning CL_INVALID_PROGRAM_EXECUTABLE
184         if(!context.getPlatform().isVendorAMD() && !context.getPlatform().isVendorIntel()) {
185             try{
186                 final Map<String, CLKernel> kernels = program.createCLKernels();
187                 fail("expected an exception from createCLKernels but got: "+kernels);
188             }catch(final CLException ex) {
189                 // expected, not built yet
190             }
191         }
192
193         out.println(program.getBuildStatus());
194         program.build();
195         out.println(program.getBuildStatus());
196
197         assertNotNull(program.createCLKernel("Test"));
198
199         assertTrue(program.isExecutable());
200
201         context.release();
202
203     }
204
205     private void builderImpl(final boolean sync) throws IOException, ClassNotFoundException, InterruptedException {
206         final CLContext context = CLContext.create();
207         CLProgram program = context.createProgram(getClass().getResourceAsStream("testkernels.cl"));
208
209         // same as program.build()
210         program.prepare().build();
211
212         assertTrue(program.isExecutable());
213
214
215         // complex build
216         program.prepare().withOption(ENABLE_MAD)
217                          .forDevice(context.getMaxFlopsDevice())
218                          .withDefine("RADIUS", 5)
219                          .withDefine("ENABLE_FOOBAR")
220                          .build();
221
222         assertTrue(program.isExecutable());
223
224         // reusable builder
225         final CLBuildConfiguration builder = CLProgramBuilder.createConfiguration()
226                                      .withOption(ENABLE_MAD)
227                                      .forDevices(context.getDevices())
228                                      .withDefine("RADIUS", 5)
229                                      .withDefine("ENABLE_FOOBAR");
230
231         out.println(builder);
232
233         if( sync ) {
234             // sync build test
235             final CLProgram outerProgram = program;
236
237             builder.setProgram(program).build();
238             assertEquals(outerProgram, program);
239         } else {
240             // async build test
241             final CountDownLatch countdown = new CountDownLatch(1);
242             final CLProgram outerProgram = program;
243
244             final CLBuildListener buildCallback = new CLBuildListener() {
245                 @Override
246                 public void buildFinished(final CLProgram program) {
247                     assertEquals(outerProgram, program);
248                     countdown.countDown();
249                 }
250             };
251             builder.setProgram(program).build(buildCallback);
252             countdown.await();
253         }
254
255         assertTrue(program.isExecutable());
256
257         // serialization test
258         final File file = tmpFolder.newFile("foobar.builder");
259         final ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
260         builder.save(oos);
261         oos.close();
262
263         // build configuration
264         ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
265         final CLBuildConfiguration buildConfig = CLProgramBuilder.loadConfiguration(ois);
266         ois.close();
267
268         assertEquals(builder, buildConfig);
269
270         buildConfig.build(program);
271         assertTrue(program.isExecutable());
272
273         // program configuration
274         ois = new ObjectInputStream(new FileInputStream(file));
275         final CLProgramConfiguration programConfig = CLProgramBuilder.loadConfiguration(ois, context);
276         assertNotNull(programConfig.getProgram());
277         ois.close();
278         program = programConfig.build();
279         assertTrue(program.isExecutable());
280
281         // cloneing
282         assertEquals(builder, builder.clone());
283
284         context.release();
285     }
286
287
288     @Test
289     public void test10BuilderSync() throws IOException, ClassNotFoundException, InterruptedException {
290         builderImpl(true);
291     }
292
293     @Test
294     public void test11BuilderAsync() throws IOException, ClassNotFoundException, InterruptedException {
295         builderImpl(false);
296     }
297
298     private static final String test20KernelSource = "__attribute__((reqd_work_group_size(1, 1, 1))) kernel void foo(float a, int b, short c) { }\n";
299
300     @Test
301     public void test20Kernel() {
302         final CLContext context = CLContext.create();
303
304         try{
305             final CLProgram program = context.createProgram(test20KernelSource).build();
306             assertTrue(program.isExecutable());
307
308             final CLKernel kernel = program.createCLKernel("foo");
309             assertNotNull(kernel);
310
311             final long[] wgs = kernel.getCompileWorkGroupSize(context.getDevices()[0]);
312
313             out.println("compile workgroup size: " + wgs[0]+" "+wgs[1]+" "+wgs[2]);
314
315             assertEquals(1, wgs[0]);
316             assertEquals(1, wgs[1]);
317             assertEquals(1, wgs[2]);
318
319             // put args test
320             assertEquals(0, kernel.position());
321
322             kernel.putArg(1.0f);
323             assertEquals(1, kernel.position());
324
325             kernel.putArg(2);
326             assertEquals(2, kernel.position());
327
328             kernel.putArg((short)3);
329             assertEquals(3, kernel.position());
330
331             try{
332                 kernel.putArg(3);
333                 fail("exception not thrown");
334             }catch (final IndexOutOfBoundsException expected){ }
335
336             assertEquals(3, kernel.position());
337             assertEquals(0, kernel.rewind().position());
338
339         }finally{
340             context.release();
341         }
342
343     }
344
345     @Test
346     public void test21AllKernels() {
347         final String source = "kernel void foo(int a) { }\n"+
348                         "kernel void bar(float b) { }\n";
349
350         final CLContext context = CLContext.create();
351         try{
352             final CLProgram program = context.createProgram(source).build();
353             assertTrue(program.isExecutable());
354
355             final Map<String, CLKernel> kernels = program.createCLKernels();
356             for (final CLKernel kernel : kernels.values()) {
357                 out.println("kernel: "+kernel.toString());
358             }
359
360             assertNotNull(kernels.get("foo"));
361             assertNotNull(kernels.get("bar"));
362
363             kernels.get("foo").setArg(0, 42);
364             kernels.get("bar").setArg(0, 3.14f);
365
366
367         }finally{
368             context.release();
369         }
370
371     }
372
373 //    @Test
374     public void test60Load() throws IOException, ClassNotFoundException, InterruptedException {
375         for(int i = 0; i < 100; i++) {
376             test02RebuildProgram();
377             test11BuilderAsync();
378             test03ProgramBinaries();
379         }
380     }
381
382     public static void main(final String[] args) throws IOException {
383         final String tstname = CLProgramTest.class.getName();
384         org.junit.runner.JUnitCore.main(tstname);
385     }
386
387 }
http://JogAmp.org git info: FAQ, tutorial and man pages.