Explorar o código

implemented image operations

shamanDevel %!s(int64=9) %!d(string=hai) anos
pai
achega
d36c957f5e

+ 2 - 2
jme3-core/src/main/java/com/jme3/opencl/Context.java

@@ -63,8 +63,8 @@ public abstract class Context {
     }
 	public abstract CommandQueue createQueue(Device device);
 
-    public abstract Buffer createBuffer(int size, MemoryAccess access);
-    public Buffer createBuffer(int size) {
+    public abstract Buffer createBuffer(long size, MemoryAccess access);
+    public Buffer createBuffer(long size) {
         return createBuffer(size, MemoryAccess.READ_WRITE);
     }
 

+ 1 - 1
jme3-core/src/main/java/com/jme3/opencl/Image.java

@@ -230,7 +230,7 @@ public interface Image {
      * @param color
      * @return 
      */
-    Event fillIntegerAsync(CommandQueue queue, long[] origin, long[] region, int[] color);
+    Event fillAsync(CommandQueue queue, long[] origin, long[] region, int[] color);
     
     Event copyToBufferAsync(CommandQueue queue, Buffer dest, long[] srcOrigin, long[] srcRegion, long destOffset);
 }

+ 57 - 0
jme3-examples/src/main/java/jme3test/opencl/HelloOpenCL.java

@@ -35,6 +35,7 @@ package jme3test.opencl;
 import com.jme3.app.SimpleApplication;
 import com.jme3.font.BitmapFont;
 import com.jme3.font.BitmapText;
+import com.jme3.math.ColorRGBA;
 import com.jme3.opencl.*;
 import com.jme3.system.AppSettings;
 import com.jme3.util.BufferUtils;
@@ -86,6 +87,9 @@ public class HelloOpenCL extends SimpleApplication {
         txt1.setText(str.toString());
         txt1.setLocalTranslation(5, settings.getHeight() - 5, 0);
         guiNode.attachChild(txt1);
+        
+        flyCam.setEnabled(false);
+        inputManager.setCursorVisible(true);
     }
     
     private static void assertEquals(byte expected, byte actual, String message) {
@@ -223,6 +227,59 @@ public class HelloOpenCL extends SimpleApplication {
             assertEquals(descr.width, image.getWidth(), "Wrong width");
             assertEquals(descr.height, image.getHeight(), "Wrong height");
             
+            //fill with red and blue
+            ColorRGBA color1 = ColorRGBA.Red;
+            ColorRGBA color2 = ColorRGBA.Blue;
+            Event e1 = image.fillAsync(clQueue, new long[]{0,0,0}, new long[]{descr.width/2, descr.height, 1}, color1);
+            Event e2 = image.fillAsync(clQueue, new long[]{descr.width/2,0,0}, new long[]{descr.width/2, descr.height, 1}, color2);
+            e1.waitForFinished();
+            e2.waitForFinished();
+            
+            //copy to a buffer
+            Buffer buffer = clContext.createBuffer(4*4*500*1024);
+            image.copyToBufferAsync(clQueue, buffer, new long[]{10,10,0}, new long[]{500,1024,1}, 0);
+            //this buffer must be completely red
+            ByteBuffer map1 = buffer.map(clQueue, MappingAccess.MAP_READ_ONLY);
+            FloatBuffer map1F = map1.asFloatBuffer(); map1F.rewind();
+            for (int x=0; x<500; ++x) {
+                for (int y=0; y<1024; ++y) {
+                    float r = map1F.get(); 
+                    float g = map1F.get(); 
+                    float b = map1F.get(); 
+                    float a = map1F.get();
+                    assertEquals(1, r, "Wrong red component");
+                    assertEquals(0, g, "Wrong green component");
+                    assertEquals(0, b, "Wrong blue component");
+                    assertEquals(1, a, "Wrong alpha component");
+                }
+            }
+            buffer.unmap(clQueue, map1);
+            
+            //create a second image
+            format = new Image.ImageFormat(Image.ImageChannelOrder.RGBA, Image.ImageChannelType.FLOAT);
+            descr = new Image.ImageDescriptor(Image.ImageType.IMAGE_2D, 512, 512, 0, 0, 0, 0);
+            Image image2 = clContext.createImage(MemoryAccess.READ_WRITE, format, descr, null);
+            //copy an area of image1 to image2
+            image.copyTo(clQueue, image2, new long[]{1000, 20,0}, new long[]{0,0,0}, new long[]{512, 512,1});
+            //this area should be completely blue
+            Image.ImageMapping map2 = image2.map(clQueue, new long[]{0,0,0}, new long[]{512,512,1}, MappingAccess.MAP_READ_WRITE);
+            FloatBuffer map2F = map2.buffer.asFloatBuffer();
+            for (int y=0; y<512; ++y) {
+                for (int x=0; x<512; ++x) {
+                    long index = 4 * x + y * (map2.rowPitch / 4);
+                    map2F.position((int) index);
+                    float r = map2F.get();
+                    float g = map2F.get();
+                    float b = map2F.get();
+                    float a = map2F.get();
+                    assertEquals(0, r, "Wrong red component");
+                    assertEquals(0, g, "Wrong green component");
+                    assertEquals(1, b, "Wrong blue component");
+                    assertEquals(1, a, "Wrong alpha component");
+                }
+            }
+            image2.unmap(clQueue, map2);
+            
         } catch (AssertionError ex) {
             LOG.log(Level.SEVERE, "image test failed with an assertion error");
             return false;

+ 3 - 0
jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglBuffer.java

@@ -168,6 +168,9 @@ public class LwjglBuffer extends Buffer {
 
     @Override
     public Event copyToImageAsync(CommandQueue queue, Image dest, long srcOffset, long[] destOrigin, long[] destRegion) {
+        if (destOrigin.length!=3 || destRegion.length!=3) {
+            throw new IllegalArgumentException("origin and region must both be arrays of length 3");
+        }
         Utils.pointerBuffers[0].rewind();
         Utils.pointerBuffers[1].rewind();
         Utils.pointerBuffers[2].rewind();

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

@@ -87,9 +87,9 @@ public class LwjglContext extends Context {
     }
     
     @Override
-    public Buffer createBuffer(int size, MemoryAccess access) {
+    public Buffer createBuffer(long size, MemoryAccess access) {
         long flags = Utils.getMemoryAccessFlags(access);
-        CLMem mem = CL10.clCreateBuffer(context, flags, (long) size, Utils.errorBuffer);
+        CLMem mem = CL10.clCreateBuffer(context, flags, size, Utils.errorBuffer);
         Utils.checkError(Utils.errorBuffer, "clCreateBuffer");
         return new LwjglBuffer(mem);
     }

+ 11 - 0
jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglEvent.java

@@ -32,6 +32,7 @@
 package com.jme3.opencl.lwjgl;
 
 import com.jme3.opencl.Event;
+import java.util.logging.Logger;
 import org.lwjgl.opencl.CL10;
 import org.lwjgl.opencl.CLEvent;
 
@@ -40,10 +41,14 @@ import org.lwjgl.opencl.CLEvent;
  * @author Sebastian Weiss
  */
 public class LwjglEvent implements Event {
+    private static final Logger LOG = Logger.getLogger(LwjglEvent.class.getName());
     private final CLEvent event;
 
     public LwjglEvent(CLEvent event) {
         this.event = event;
+        if (event == null) {
+            LOG.warning("event is null!");
+        }
     }
 
     public CLEvent getEvent() {
@@ -52,11 +57,17 @@ public class LwjglEvent implements Event {
 
     @Override
     public void waitForFinished() {
+        if (event==null) {
+            return;
+        }
         CL10.clWaitForEvents(event);
     }
 
     @Override
     public boolean isCompleted() {
+        if (event==null) {
+            return true;
+        }
         int status = event.getInfoInt(CL10.CL_EVENT_COMMAND_EXECUTION_STATUS);
         if (status == CL10.CL_SUCCESS) {
             return true;

+ 202 - 28
jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglImage.java

@@ -36,10 +36,7 @@ import com.jme3.opencl.*;
 import java.nio.ByteBuffer;
 import java.util.logging.Level;
 import java.util.logging.Logger;
-import org.lwjgl.opencl.CL10;
-import org.lwjgl.opencl.CL11;
-import org.lwjgl.opencl.CL12;
-import org.lwjgl.opencl.CLMem;
+import org.lwjgl.opencl.*;
 import org.lwjgl.opencl.api.CLImageFormat;
 
 /**
@@ -121,7 +118,7 @@ public class LwjglImage implements Image {
             case CL11.CL_Rx:
                 return ImageChannelOrder.Rx;
             default:
-                //throw new OpenCLException("unknown image channel order id: " + order);
+                //throw new com.jme3.opencl.OpenCLException("unknown image channel order id: " + order);
                 LOG.log(Level.WARNING, "Unknown image channel order id: {0}", order);
                 return null;
         }
@@ -197,7 +194,7 @@ public class LwjglImage implements Image {
             case CL10.CL_UNSIGNED_INT8:
                 return ImageChannelType.UNSIGNED_INT8;
             default:
-                //throw new OpenCLException("unknown image channel type id: " + type);
+                //throw new com.jme3.opencl.OpenCLException("unknown image channel type id: " + type);
                 LOG.log(Level.WARNING, "Unknown image channel type id: {0}", type);
                 return null;
         }
@@ -237,44 +234,46 @@ public class LwjglImage implements Image {
             case CL10.CL_MEM_OBJECT_IMAGE3D:
                 return ImageType.IMAGE_3D;
             default:
-                throw new OpenCLException("Unknown image type id: " + type);
+                throw new com.jme3.opencl.OpenCLException("Unknown image type id: " + type);
         }
     }
 
     @Override
     public long getWidth() {
-        return image.getInfoSize(CL10.CL_IMAGE_WIDTH);
+        return image.getImageInfoSize(CL10.CL_IMAGE_WIDTH);
     }
 
     @Override
     public long getHeight() {
-        return image.getInfoSize(CL10.CL_IMAGE_HEIGHT);
+        return image.getImageInfoSize(CL10.CL_IMAGE_HEIGHT);
     }
 
     @Override
     public long getDepth() {
-        return image.getInfoSize(CL10.CL_IMAGE_DEPTH);
+        return image.getImageInfoSize(CL10.CL_IMAGE_DEPTH);
     }
 
     @Override
     public long getRowPitch() {
-        return image.getInfoSize(CL10.CL_IMAGE_ROW_PITCH);
+        return image.getImageInfoSize(CL10.CL_IMAGE_ROW_PITCH);
     }
 
     @Override
     public long getSlicePitch() {
-        return image.getInfoSize(CL10.CL_IMAGE_SLICE_PITCH);
+        return image.getImageInfoSize(CL10.CL_IMAGE_SLICE_PITCH);
     }
 
     @Override
     public long getArraySize() {
-        return image.getInfoSize(CL12.CL_IMAGE_ARRAY_SIZE);
+        return image.getImageInfoSize(CL12.CL_IMAGE_ARRAY_SIZE);
     }
 
     @Override
     public ImageFormat getImageFormat() {
         CLImageFormat format = image.getImageFormat();
-        return new ImageFormat(encodeImageChannelOrder(format.getChannelOrder()), encodeImageChannelType(format.getChannelType()));
+        return new ImageFormat(
+                encodeImageChannelOrder(format.getChannelOrder()), 
+                encodeImageChannelType(format.getChannelType()));
     }
 
     @Override
@@ -285,67 +284,242 @@ public class LwjglImage implements Image {
 
     @Override
     public int getElementSize() {
-        return (int) image.getInfoSize(CL10.CL_IMAGE_ELEMENT_SIZE);
+        return (int) image.getImageInfoSize(CL10.CL_IMAGE_ELEMENT_SIZE);
     }
 
     @Override
     public void readImage(CommandQueue queue, ByteBuffer dest, long[] origin, long[] region, long rowPitch, long slicePitch) {
-        throw new UnsupportedOperationException("Not supported yet.");
+        if (origin.length!=3 || region.length!=3) {
+            throw new IllegalArgumentException("origin and region must both be arrays of length 3");
+        }
+        Utils.pointerBuffers[1].rewind();
+        Utils.pointerBuffers[2].rewind();
+        Utils.pointerBuffers[1].put(origin).position(0);
+        Utils.pointerBuffers[2].put(region).position(0);
+        CLCommandQueue q = ((LwjglCommandQueue) queue).getQueue();
+        int ret = CL10.clEnqueueReadImage(q, image, CL10.CL_TRUE, 
+                Utils.pointerBuffers[1], Utils.pointerBuffers[2], 
+                rowPitch, slicePitch, dest, null, null);
+        Utils.checkError(ret, "clEnqueueReadImage");
     }
 
     @Override
     public Event readImageAsync(CommandQueue queue, ByteBuffer dest, long[] origin, long[] region, long rowPitch, long slicePitch) {
-        throw new UnsupportedOperationException("Not supported yet.");
+        if (origin.length!=3 || region.length!=3) {
+            throw new IllegalArgumentException("origin and region must both be arrays of length 3");
+        }
+        Utils.pointerBuffers[0].rewind();
+        Utils.pointerBuffers[1].rewind();
+        Utils.pointerBuffers[2].rewind();
+        Utils.pointerBuffers[1].put(origin).position(0);
+        Utils.pointerBuffers[2].put(region).position(0);
+        CLCommandQueue q = ((LwjglCommandQueue) queue).getQueue();
+        int ret = CL10.clEnqueueReadImage(q, image, CL10.CL_FALSE, 
+                Utils.pointerBuffers[1], Utils.pointerBuffers[2], 
+                rowPitch, slicePitch, dest, null, Utils.pointerBuffers[0]);
+        Utils.checkError(ret, "clEnqueueReadImage");
+        long event = Utils.pointerBuffers[0].get(0);
+        return new LwjglEvent(q.getCLEvent(event));
     }
 
     @Override
     public void writeImage(CommandQueue queue, ByteBuffer dest, long[] origin, long[] region, long rowPitch, long slicePitch) {
-        throw new UnsupportedOperationException("Not supported yet.");
+        if (origin.length!=3 || region.length!=3) {
+            throw new IllegalArgumentException("origin and region must both be arrays of length 3");
+        }
+        Utils.pointerBuffers[1].rewind();
+        Utils.pointerBuffers[2].rewind();
+        Utils.pointerBuffers[1].put(origin).position(0);
+        Utils.pointerBuffers[2].put(region).position(0);
+        CLCommandQueue q = ((LwjglCommandQueue) queue).getQueue();
+        int ret = CL10.clEnqueueWriteImage(q, image, CL10.CL_TRUE, 
+                Utils.pointerBuffers[1], Utils.pointerBuffers[2], 
+                rowPitch, slicePitch, dest, null, null);
+        Utils.checkError(ret, "clEnqueueWriteImage");
     }
 
     @Override
     public Event writeImageAsync(CommandQueue queue, ByteBuffer dest, long[] origin, long[] region, long rowPitch, long slicePitch) {
-        throw new UnsupportedOperationException("Not supported yet.");
+        if (origin.length!=3 || region.length!=3) {
+            throw new IllegalArgumentException("origin and region must both be arrays of length 3");
+        }
+        Utils.pointerBuffers[0].rewind();
+        Utils.pointerBuffers[1].rewind();
+        Utils.pointerBuffers[2].rewind();
+        Utils.pointerBuffers[1].put(origin).position(0);
+        Utils.pointerBuffers[2].put(region).position(0);
+        CLCommandQueue q = ((LwjglCommandQueue) queue).getQueue();
+        int ret = CL10.clEnqueueWriteImage(q, image, CL10.CL_FALSE, 
+                Utils.pointerBuffers[1], Utils.pointerBuffers[2], 
+                rowPitch, slicePitch, dest, null, Utils.pointerBuffers[0]);
+        Utils.checkError(ret, "clEnqueueWriteImage");
+        long event = Utils.pointerBuffers[0].get(0);
+        return new LwjglEvent(q.getCLEvent(event));
     }
 
     @Override
     public void copyTo(CommandQueue queue, Image dest, long[] srcOrigin, long[] destOrigin, long[] region) {
-        throw new UnsupportedOperationException("Not supported yet.");
+        if (srcOrigin.length!=3 || destOrigin.length!=3 || region.length!=3) {
+            throw new IllegalArgumentException("origin and region must both be arrays of length 3");
+        }
+        Utils.pointerBuffers[0].rewind();
+        Utils.pointerBuffers[1].rewind();
+        Utils.pointerBuffers[2].rewind();
+        Utils.pointerBuffers[3].rewind();
+        Utils.pointerBuffers[1].put(srcOrigin).position(0);
+        Utils.pointerBuffers[2].put(destOrigin).position(0);
+        Utils.pointerBuffers[3].put(region).position(0);
+        CLCommandQueue q = ((LwjglCommandQueue) queue).getQueue();
+        int ret = CL10.clEnqueueCopyImage(q, image, ((LwjglImage) dest).getImage(), 
+                Utils.pointerBuffers[1], Utils.pointerBuffers[2], Utils.pointerBuffers[3], 
+                null, Utils.pointerBuffers[0]);
+        Utils.checkError(ret, "clEnqueueCopyImage");
+        long event = Utils.pointerBuffers[0].get(0);
+        ret = CL10.clWaitForEvents(q.getCLEvent(event));
+        Utils.checkError(ret, "clWaitForEvents");
     }
 
     @Override
     public Event copyToAsync(CommandQueue queue, Image dest, long[] srcOrigin, long[] destOrigin, long[] region) {
-        throw new UnsupportedOperationException("Not supported yet.");
+        if (srcOrigin.length!=3 || destOrigin.length!=3 || region.length!=3) {
+            throw new IllegalArgumentException("origin and region must both be arrays of length 3");
+        }
+        Utils.pointerBuffers[0].rewind();
+        Utils.pointerBuffers[1].rewind();
+        Utils.pointerBuffers[2].rewind();
+        Utils.pointerBuffers[3].rewind();
+        Utils.pointerBuffers[1].put(srcOrigin).position(0);
+        Utils.pointerBuffers[2].put(destOrigin).position(0);
+        Utils.pointerBuffers[3].put(region).position(0);
+        CLCommandQueue q = ((LwjglCommandQueue) queue).getQueue();
+        int ret = CL10.clEnqueueCopyImage(q, image, ((LwjglImage) dest).getImage(), 
+                Utils.pointerBuffers[1], Utils.pointerBuffers[2], Utils.pointerBuffers[3], 
+                null, Utils.pointerBuffers[0]);
+        Utils.checkError(ret, "clEnqueueCopyImage");
+        long event = Utils.pointerBuffers[0].get(0);
+        return new LwjglEvent(q.getCLEvent(event));
     }
 
     @Override
     public ImageMapping map(CommandQueue queue, long[] origin, long[] region, MappingAccess access) {
-        throw new UnsupportedOperationException("Not supported yet.");
+        if (origin.length!=3 || region.length!=3) {
+            throw new IllegalArgumentException("origin and region must both be arrays of length 3");
+        }
+        Utils.pointerBuffers[1].rewind();
+        Utils.pointerBuffers[2].rewind();
+        Utils.pointerBuffers[3].rewind();
+        Utils.pointerBuffers[4].rewind();
+        Utils.pointerBuffers[1].put(origin).position(0);
+        Utils.pointerBuffers[2].put(region).position(0);
+        CLCommandQueue q = ((LwjglCommandQueue) queue).getQueue();
+        long flags = Utils.getMappingAccessFlags(access);
+        Utils.errorBuffer.rewind();
+        ByteBuffer buf = CL10.clEnqueueMapImage(q, image, CL10.CL_TRUE, flags, 
+                Utils.pointerBuffers[1], Utils.pointerBuffers[2], 
+                Utils.pointerBuffers[3], Utils.pointerBuffers[4], null, null, Utils.errorBuffer);
+        Utils.checkError(Utils.errorBuffer, "clEnqueueMapBuffer");
+        long event = Utils.pointerBuffers[0].get(0);
+        return new ImageMapping(buf, Utils.pointerBuffers[3].get(0), Utils.pointerBuffers[4].get(0), 
+                new LwjglEvent(q.getCLEvent(event)));
     }
 
     @Override
     public ImageMapping mapAsync(CommandQueue queue, long[] origin, long[] region, MappingAccess access) {
-        throw new UnsupportedOperationException("Not supported yet.");
+        if (origin.length!=3 || region.length!=3) {
+            throw new IllegalArgumentException("origin and region must both be arrays of length 3");
+        }
+        Utils.pointerBuffers[0].rewind();
+        Utils.pointerBuffers[1].rewind();
+        Utils.pointerBuffers[2].rewind();
+        Utils.pointerBuffers[3].rewind();
+        Utils.pointerBuffers[4].rewind();
+        Utils.pointerBuffers[1].put(origin).position(0);
+        Utils.pointerBuffers[2].put(region).position(0);
+        CLCommandQueue q = ((LwjglCommandQueue) queue).getQueue();
+        long flags = Utils.getMappingAccessFlags(access);
+        Utils.errorBuffer.rewind();
+        ByteBuffer buf = CL10.clEnqueueMapImage(q, image, CL10.CL_FALSE, flags, 
+                Utils.pointerBuffers[1], Utils.pointerBuffers[2], 
+                Utils.pointerBuffers[3], Utils.pointerBuffers[4], null, null, Utils.errorBuffer);
+        Utils.checkError(Utils.errorBuffer, "clEnqueueMapBuffer");
+        return new ImageMapping(buf, Utils.pointerBuffers[3].get(0), Utils.pointerBuffers[4].get(0));
     }
 
     @Override
     public void unmap(CommandQueue queue, ImageMapping mapping) {
-        throw new UnsupportedOperationException("Not supported yet.");
+        CLCommandQueue q = ((LwjglCommandQueue) queue).getQueue();
+        Utils.pointerBuffers[0].rewind();
+        int ret = CL10.clEnqueueUnmapMemObject(q, image, mapping.buffer, null, Utils.pointerBuffers[0]);
+        Utils.checkError(ret, "clEnqueueUnmapMemObject");
+        long event = Utils.pointerBuffers[0].get(0);
+        ret = CL10.clWaitForEvents(q.getCLEvent(event));
+        Utils.checkError(ret, "clWaitForEvents");
     }
 
     @Override
     public Event fillAsync(CommandQueue queue, long[] origin, long[] region, ColorRGBA color) {
-        throw new UnsupportedOperationException("Not supported yet.");
+        if (origin.length!=3 || region.length!=3) {
+            throw new IllegalArgumentException("origin and region must both be arrays of length 3");
+        }
+        Utils.pointerBuffers[0].rewind();
+        Utils.pointerBuffers[1].rewind();
+        Utils.pointerBuffers[2].rewind();
+        Utils.pointerBuffers[1].put(origin).position(0);
+        Utils.pointerBuffers[2].put(region).position(0);
+        Utils.tempBuffers[0].b16f.rewind();
+        Utils.tempBuffers[0].b16f.limit(4);
+        Utils.tempBuffers[0].b16f.put(color.r).put(color.g).put(color.b).put(color.a);
+        Utils.tempBuffers[0].b16.rewind();
+        CLCommandQueue q = ((LwjglCommandQueue) queue).getQueue();
+        int ret = CL12.clEnqueueFillImage(q, image, Utils.tempBuffers[0].b16, 
+                Utils.pointerBuffers[1], Utils.pointerBuffers[2], null, Utils.pointerBuffers[0]);
+        Utils.checkError(ret, "clEnqueueFillImage");
+        long event = Utils.pointerBuffers[0].get(0);
+        return new LwjglEvent(q.getCLEvent(event));
+        //TODO: why does q.getCLEvent(event) return null?
     }
 
     @Override
-    public Event fillIntegerAsync(CommandQueue queue, long[] origin, long[] region, int[] color) {
-        throw new UnsupportedOperationException("Not supported yet.");
+    public Event fillAsync(CommandQueue queue, long[] origin, long[] region, int[] color) {
+        if (color.length != 4) {
+            throw new IllegalArgumentException("the passed color array must have length 4");
+        }
+        if (origin.length!=3 || region.length!=3) {
+            throw new IllegalArgumentException("origin and region must both be arrays of length 3");
+        }
+        Utils.pointerBuffers[0].rewind();
+        Utils.pointerBuffers[1].rewind();
+        Utils.pointerBuffers[2].rewind();
+        Utils.pointerBuffers[1].put(origin).position(0);
+        Utils.pointerBuffers[2].put(region).position(0);
+        Utils.tempBuffers[0].b16i.rewind();
+        Utils.tempBuffers[0].b16i.limit(4);
+        Utils.tempBuffers[0].b16i.put(color);
+        Utils.tempBuffers[0].b16.rewind();
+        CLCommandQueue q = ((LwjglCommandQueue) queue).getQueue();
+        int ret = CL12.clEnqueueFillImage(q, image, Utils.tempBuffers[0].b16, 
+                Utils.pointerBuffers[1], Utils.pointerBuffers[2], null, Utils.pointerBuffers[0]);
+        Utils.checkError(ret, "clEnqueueFillImage");
+        long event = Utils.pointerBuffers[0].get(0);
+        return new LwjglEvent(q.getCLEvent(event));
     }
 
     @Override
     public Event copyToBufferAsync(CommandQueue queue, Buffer dest, long[] srcOrigin, long[] srcRegion, long destOffset) {
-        throw new UnsupportedOperationException("Not supported yet.");
+        if (srcOrigin.length!=3 || srcRegion.length!=3) {
+            throw new IllegalArgumentException("origin and region must both be arrays of length 3");
+        }
+        Utils.pointerBuffers[0].rewind();
+        Utils.pointerBuffers[1].rewind();
+        Utils.pointerBuffers[2].rewind();
+        Utils.pointerBuffers[1].put(srcOrigin).position(0);
+        Utils.pointerBuffers[2].put(srcRegion).position(0);
+        CLCommandQueue q = ((LwjglCommandQueue) queue).getQueue();
+        int ret = CL10.clEnqueueCopyImageToBuffer(q, image, ((LwjglBuffer) dest).getBuffer(), 
+                Utils.pointerBuffers[1], Utils.pointerBuffers[2], destOffset, null, Utils.pointerBuffers[0]);
+        Utils.checkError(ret, "clEnqueueCopyImageToBuffer");
+        long event = Utils.pointerBuffers[0].get(0);
+        return new LwjglEvent(q.getCLEvent(event));
     }
 
 }