Browse Source

Implemented Program.getBinary() with Jocl.

The program cache now also works with Jocl.
Thanks to @gouessej for his help.
shamanDevel 9 năm trước cách đây
mục cha
commit
dd22ebefdd

+ 15 - 2
jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclContext.java

@@ -224,8 +224,21 @@ public class JoclContext extends Context {
 
     @Override
     public Program createProgramFromBinary(ByteBuffer binaries, Device device) {
-        //Not supported because JoclProgram.getBinaries is also not supported.
-        throw new UnsupportedOperationException("No supported by Jocl");
+        binaries.rewind();
+        Utils.errorBuffer.rewind();
+        Utils.tempBuffers[0].b16i.rewind();
+        Utils.pointers[0].rewind();
+        Utils.pointers[0].put(0, ((JoclDevice) device).id);
+        Utils.pointers[1].rewind();
+        Utils.pointers[1].put(0, binaries.remaining());
+        Utils.pointers[2].rewind();
+        Utils.pointers[2].referenceBuffer(0, binaries);
+        long p = cl.clCreateProgramWithBinary(id, 1, Utils.pointers[0], 
+                Utils.pointers[1], Utils.pointers[2], Utils.tempBuffers[0].b16i, 
+                Utils.errorBuffer);
+        Utils.checkError(Utils.errorBuffer, "clCreateProgramWithBinary");
+        Utils.checkError(Utils.tempBuffers[0].b16i, "clCreateProgramWithBinary");
+        return new JoclProgram(p, this);
     }
 
     private static class ReleaserImpl implements ObjectReleaser {

+ 42 - 10
jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclProgram.java

@@ -32,6 +32,7 @@
 package com.jme3.opencl.jocl;
 
 import com.jme3.opencl.*;
+import com.jogamp.common.nio.Buffers;
 import com.jogamp.common.nio.PointerBuffer;
 import com.jogamp.opencl.CLPlatform;
 import com.jogamp.opencl.CLProgram;
@@ -133,16 +134,47 @@ public class JoclProgram extends Program {
     }
 
     @Override
-    public ByteBuffer getBinary(Device device) {
-        //There is no way to do this in Jocl:
-        //The low-level bindings need a buffer of adresses to buffers. For that
-        //the class InternalBufferUtil is used, but this class is not public.
-        //I also can't create a temporal instance of CLProgram because the constructor
-        //that takes only the native pointer is private.
-        //So the only way would be to create the CLProgram directly from the beginning.
-        //I don't want to do this because then I would have to use the whole 
-        //bunch of garbage the CLProgram class is doing in background.
-        throw new UnsupportedOperationException("Jocl does not expose this operation");
+    public ByteBuffer getBinary(Device d) {
+        
+        JoclDevice device = (JoclDevice) d;
+        
+        Utils.tempBuffers[0].b16i.rewind();
+        int ret = cl.clGetProgramInfo(program, CL.CL_PROGRAM_NUM_DEVICES, 4, Utils.tempBuffers[0].b16i, null);
+        Utils.checkError(ret, "clGetProgramInfo: CL_PROGRAM_NUM_DEVICES");
+        int numDevices = Utils.tempBuffers[0].b16i.get(0);
+        
+        PointerBuffer devices = PointerBuffer.allocateDirect(numDevices);
+        ret = cl.clGetProgramInfo(program, CL.CL_PROGRAM_DEVICES, numDevices * PointerBuffer.ELEMENT_SIZE, devices.getBuffer(), null);
+        Utils.checkError(ret, "clGetProgramInfo: CL_PROGRAM_DEVICES");
+        int index = -1;
+        for (int i=0; i<numDevices; ++i) {
+            if (devices.get(i) == device.id) {
+                index = i;
+            }
+        }
+        if (index == -1) {
+             throw new com.jme3.opencl.OpenCLException("Program was not built against the specified device "+device);
+        }
+        
+        final PointerBuffer sizes = PointerBuffer.allocateDirect(numDevices);
+        ret = cl.clGetProgramInfo(program, CL.CL_PROGRAM_BINARY_SIZES, numDevices * PointerBuffer.ELEMENT_SIZE, sizes.getBuffer(), null);
+        Utils.checkError(ret, "clGetProgramInfo: CL_PROGRAM_BINARY_SIZES");
+
+        final ByteBuffer binaries = Buffers.newDirectByteBuffer((int) sizes.get(index));
+        final PointerBuffer addresses = PointerBuffer.allocateDirect(numDevices);
+        for (int i=0; i<numDevices; ++i) {
+            if (index == i) {
+                addresses.referenceBuffer(binaries);
+            } else {
+                addresses.put(0);
+            }
+        }
+        addresses.rewind();
+
+        ret = cl.clGetProgramInfo(program, CL.CL_PROGRAM_BINARIES, numDevices * PointerBuffer.ELEMENT_SIZE, addresses.getBuffer(), null);
+        Utils.checkError(ret, "clGetProgramInfo: CL_PROGRAM_BINARIES");
+
+        return binaries;
     }
 
     private static class ReleaserImpl implements ObjectReleaser {

+ 2 - 2
jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglContext.java

@@ -214,8 +214,8 @@ public class LwjglContext extends Context {
         Utils.tempBuffers[0].b16i.rewind();
         CLProgram p = CL10.clCreateProgramWithBinary(context, ((LwjglDevice) device).device, 
                 binaries, Utils.tempBuffers[0].b16i, Utils.errorBuffer);
-        Utils.checkError(Utils.errorBuffer, "clCreateProgramWithSource");
-        Utils.checkError(Utils.tempBuffers[0].b16i, "clCreateProgramWithSource");
+        Utils.checkError(Utils.errorBuffer, "clCreateProgramWithBinary");
+        Utils.checkError(Utils.tempBuffers[0].b16i, "clCreateProgramWithBinary");
         return new LwjglProgram(p, this);
     }
 

+ 2 - 2
jme3-lwjgl3/src/main/java/com/jme3/opencl/lwjgl/LwjglContext.java

@@ -229,8 +229,8 @@ public class LwjglContext extends Context {
         Utils.pointerBuffers[0].put(0, ((LwjglDevice) device).getDevice());
         long p = CL10.clCreateProgramWithBinary(context, Utils.pointerBuffers[0], 
                 binaries, Utils.tempBuffers[0].b16i, Utils.errorBuffer);
-        Utils.checkError(Utils.errorBuffer, "clCreateProgramWithSource");
-        Utils.checkError(Utils.tempBuffers[0].b16i, "clCreateProgramWithSource");
+        Utils.checkError(Utils.errorBuffer, "clCreateProgramWithBinary");
+        Utils.checkError(Utils.tempBuffers[0].b16i, "clCreateProgramWithBinary");
         return new LwjglProgram(p, this);
     }