001/* 002 * JavaCL - Java API and utilities for OpenCL 003 * http://javacl.googlecode.com/ 004 * 005 * Copyright (c) 2009-2013, Olivier Chafik (http://ochafik.com/) 006 * All rights reserved. 007 * 008 * Redistribution and use in source and binary forms, with or without 009 * modification, are permitted provided that the following conditions are met: 010 * 011 * * Redistributions of source code must retain the above copyright 012 * notice, this list of conditions and the following disclaimer. 013 * * Redistributions in binary form must reproduce the above copyright 014 * notice, this list of conditions and the following disclaimer in the 015 * documentation and/or other materials provided with the distribution. 016 * * Neither the name of Olivier Chafik nor the 017 * names of its contributors may be used to endorse or promote products 018 * derived from this software without specific prior written permission. 019 * 020 * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY 021 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 022 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 023 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY 024 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 025 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 026 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 027 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 028 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 029 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 030 */ 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050package com.nativelibs4java.opencl; 051import static com.nativelibs4java.opencl.CLException.error; 052import static com.nativelibs4java.opencl.JavaCL.CL; 053import static com.nativelibs4java.opencl.library.OpenCLLibrary.*; 054import static com.nativelibs4java.opencl.library.IOpenCLLibrary.*; 055 056import java.util.EnumSet; 057 058import com.nativelibs4java.opencl.library.OpenCLLibrary; 059import com.nativelibs4java.opencl.library.IOpenCLLibrary.cl_mem; 060import com.nativelibs4java.util.EnumValue; 061import com.nativelibs4java.util.EnumValues; 062import org.bridj.ann.Ptr; 063import org.bridj.*; 064import static org.bridj.Pointer.*; 065import static com.nativelibs4java.opencl.proxy.PointerUtils.*; 066 067/** 068 * OpenCL memory object.<br> 069 * Memory objects are categorized into two types: buffer objects, and image objects. <br> 070 * A buffer object stores a one-dimensional collection of elements whereas an image object is used to store a two- or three- dimensional texture, frame-buffer or image.<br> 071 * Elements of a buffer object can be a scalar data type (such as an int, float), vector data type, or a user-defined structure. An image object is used to represent a buffer that can be used as a texture or a frame-buffer. The elements of an image object are selected from a list of predefined image formats. <br> 072 * The minimum number of elements in a memory object is one.<br> 073 * The fundamental differences between a buffer and an image object are: 074 * <ul> 075 * <li>Elements in a buffer are stored in sequential fashion and can be accessed using a pointer by a kernel executing on a device. Elements of an image are stored in a format that is opaque to the user and cannot be directly accessed using a pointer. Built-in functions are provided by the OpenCL C programming language to allow a kernel to read from or write to an image.</li> 076 * <li>For a buffer object, the data is stored in the same format as it is accessed by the kernel, but in the case of an image object the data format used to store the image elements may not be the same as the data format used inside the kernel. Image elements are always a 4- component vector (each component can be a float or signed/unsigned integer) in a kernel. The built-in function to read from an image converts image element from the format it is stored into a 4-component vector. Similarly, the built-in function to write to an image converts the image element from a 4-component vector to the appropriate image format specified such as 4 8-bit elements, for example.</li> 077 * </ul> 078 * 079 * Kernels take memory objects as input, and output to one or more memory objects. 080 * @author Olivier Chafik 081 */ 082public abstract class CLMem extends CLAbstractEntity { 083 084 protected final CLContext context; 085 protected long byteCount = -1; 086 boolean isGL; 087 088 protected static CLInfoGetter infos = new CLInfoGetter() { 089 @Override 090 protected int getInfo(long entity, int infoTypeEnum, long size, Pointer out, Pointer<SizeT> sizeOut) { 091 return CL.clGetImageInfo(entity, infoTypeEnum, size, getPeer(out), getPeer(sizeOut)); 092 } 093 }; 094 095 CLMem(CLContext context, long byteCount, long entityPeer) { 096 super(entityPeer); 097 this.byteCount = byteCount; 098 this.context = context; 099 } 100 101 public CLContext getContext() { 102 return context; 103 } 104 105 public interface DestructorCallback { 106 void callback(CLMem mem); 107 } 108 109 /** 110 * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clSetMemObjectDestructorCallback.html">clSetMemObjectDestructorCallback</a>.<br> 111 * Registers a user callback function that will be called when the memory object is deleted and its resources freed. <br> 112 * Each call to clSetMemObjectDestructorCallback registers the specified user callback function on a callback stack associated with memobj. <br> 113 * The registered user callback functions are called in the reverse order in which they were registered. <br> 114 * The user callback functions are called and then the memory object's resources are freed and the memory object is deleted. <br> 115 * This provides a mechanism for the application (and libraries) using memobj to be notified when the memory referenced by host_ptr, specified when the memory object is created and used as the storage bits for the memory object, can be reused or freed. 116 * @since OpenCL 1.1 117 * @param callback 118 */ 119 public void setDestructorCallback(final DestructorCallback callback) { 120 context.getPlatform().requireMinVersionValue("clSetMemObjectDestructorCallback", 1.1); 121 clSetMemObjectDestructorCallback_arg1_callback cb = new clSetMemObjectDestructorCallback_arg1_callback() { 122 @Override 123 public void apply(@Ptr long mem, @Ptr long userData) { 124 callback.callback(CLMem.this); 125 } 126 }; 127 BridJ.protectFromGC(cb); 128 error(CL.clSetMemObjectDestructorCallback(getEntity(), getPeer(getPointer(cb)), 0)); 129 } 130 131 public CLEvent acquireGLObject(CLQueue queue, CLEvent... eventsToWaitFor) { 132 return queue.enqueueAcquireGLObjects(new CLMem[] { this }, eventsToWaitFor); 133 } 134 135 public CLEvent releaseGLObject(CLQueue queue, CLEvent... eventsToWaitFor) { 136 return queue.enqueueReleaseGLObjects(new CLMem[] { this }, eventsToWaitFor); 137 } 138 139 /** 140 * Get the actual size of the memory object in bytes 141 * @return actual size of the memory object in bytes 142 */ 143 public long getByteCount() { 144 if (byteCount < 0) { 145 try { 146 byteCount = infos.getIntOrLong(getEntity(), CL_MEM_SIZE); 147 } catch (CLException.InvalidMemObject ex) { 148 if (isGL) 149 return -1; // GL objects are not (always?) considered as valid mem objects 150 else 151 throw ex; 152 } 153 } 154 return byteCount; 155 } 156 157 /** 158 * Memory Object Usage enum 159 */ 160 public enum Usage { 161 Input(CL_MEM_READ_ONLY, Flags.ReadOnly), 162 Output(CL_MEM_WRITE_ONLY, Flags.WriteOnly), 163 InputOutput(CL_MEM_READ_WRITE, Flags.ReadWrite); 164 165 private int intFlags; 166 private Flags flags; 167 Usage(int intFlags, Flags flags) { 168 this.intFlags = intFlags; 169 this.flags = flags; 170 } 171 public int getIntFlags() { 172 return intFlags; 173 } 174 public Flags getFlags() { 175 return flags; 176 } 177 } 178 179 /** 180 * Memory object migration options (see {@link CLQueue#enqueueMigrateMemObjects(CLMem[], java.lang.EnumSet, CLEvent[])}). 181 */ 182 public enum Migration implements com.nativelibs4java.util.ValuedEnum { 183 /** 184 * This flag indicates that the specified set of memory objects are to be migrated 185 * to the host, regardless of the target command-queue. 186 */ 187 Host(CL_MIGRATE_MEM_OBJECT_HOST), 188 /** 189 * This flag indicates that the contents of the set of memory objects are undefined after 190 * migration. The specified set of memory objects are migrated to the device associated with 191 * command_queue without incurring the overhead of migrating their contents. 192 */ 193 ContentUndefined(CL_MIGRATE_MEM_OBJECT_CONTENT_UNDEFINED); 194 195 Migration(long value) { this.value = value; } 196 long value; 197 @Override 198 public long value() { return value; } 199 public static long getValue(EnumSet<Migration> set) { 200 return EnumValues.getValue(set); 201 } 202 203 public static EnumSet<Migration> getEnumSet(long v) { 204 return EnumValues.getEnumSet(v, Migration.class); 205 } 206 } 207 208 public enum Flags implements com.nativelibs4java.util.ValuedEnum { 209 /** 210 * This flag specifies that the memory object will be read and written by a kernel. This is the default. 211 */ 212 ReadWrite(CL_MEM_READ_WRITE), 213 /** 214 * This flags specifies that the memory object will be written but not read by a kernel.<br> 215 * Reading from a buffer or image object created with CL_MEM_WRITE_ONLY inside a kernel is undefined. 216 */ 217 WriteOnly(CL_MEM_WRITE_ONLY), 218 /** 219 * This flag specifies that the memory object is a read-only memory object when used inside a kernel. <br> 220 * Writing to a buffer or image object created with CL_MEM_READ_ONLY inside a kernel is undefined. 221 */ 222 ReadOnly(CL_MEM_READ_ONLY), 223 /** 224 * This flag is valid only if host_ptr is not NULL. If specified, it indicates that the application wants the OpenCL implementation to use memory referenced by host_ptr as the storage bits for the memory object. <br> 225 * OpenCL implementations are allowed to cache the buffer contents pointed to by host_ptr in device memory. This cached copy can be used when kernels are executed on a device. <br> 226 * The result of OpenCL commands that operate on multiple buffer objects created with the same host_ptr or overlapping host regions is considered to be undefined. 227 */ 228 UseHostPtr(CL_MEM_USE_HOST_PTR), 229 /** 230 * This flag specifies that the application wants the OpenCL implementation to allocate memory from host accessible memory. <br> 231 * CL_MEM_ALLOC_HOST_PTR and CL_MEM_USE_HOST_PTR are mutually exclusive.<br> 232 * CL_MEM_COPY_HOST_PTR: This flag is valid only if host_ptr is not NULL. If specified, it indicates that the application wants the OpenCL implementation to allocate memory for the memory object and copy the data from memory referenced by host_ptr.<br> 233 * CL_MEM_COPY_HOST_PTR and CL_MEM_USE_HOST_PTR are mutually exclusive.<br> 234 * CL_MEM_COPY_HOST_PTR can be used with CL_MEM_ALLOC_HOST_PTR to initialize the contents of the cl_mem object allocated using host-accessible (e.g. PCIe) memory. 235 */ 236 AllocHostPtr(CL_MEM_ALLOC_HOST_PTR), 237 CopyHostPtr(CL_MEM_COPY_HOST_PTR); 238 239 Flags(long value) { this.value = value; } 240 long value; 241 @Override 242 public long value() { return value; } 243 public static long getValue(EnumSet<Flags> set) { return EnumValues.getValue(set); } 244 public static EnumSet<Flags> getEnumSet(long v) { return EnumValues.getEnumSet(v, Flags.class); } 245 } 246 public enum ObjectType implements com.nativelibs4java.util.ValuedEnum { 247 Buffer(CL_MEM_OBJECT_BUFFER), 248 Image2D(CL_MEM_OBJECT_IMAGE2D), 249 Image3D(CL_MEM_OBJECT_IMAGE3D); 250 251 ObjectType(long value) { this.value = value; } 252 long value; 253 @Override 254 public long value() { return value; } 255 public static ObjectType getEnum(long v) { return EnumValues.getEnum(v, ObjectType.class); } 256 } 257 258 public enum GLObjectType implements com.nativelibs4java.util.ValuedEnum { 259 Buffer(CL_GL_OBJECT_BUFFER), 260 RenderBuffer(CL_GL_OBJECT_RENDERBUFFER), 261 Texture2D(CL_GL_OBJECT_TEXTURE2D), 262 Texture3D(CL_GL_OBJECT_TEXTURE3D); 263 264 GLObjectType(long value) { this.value = value; } 265 long value; 266 @Override 267 public long value() { return value; } 268 public static GLObjectType getEnum(long v) { return EnumValues.getEnum(v, GLObjectType.class); } 269 } 270 271 public static class GLObjectInfo { 272 final GLObjectType type; 273 final int name; 274 public GLObjectInfo(GLObjectType type, int name) { 275 this.type = type; 276 this.name = name; 277 } 278 public GLObjectType getType() { 279 return type; 280 } 281 public int getName() { 282 return name; 283 } 284 } 285 /** 286 * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clGetGLObjectInfo.html">clGetGLObjectInfo</a>.<br> 287 */ 288 @SuppressWarnings("deprecation") 289 public GLObjectInfo getGLObjectInfo() { 290 ReusablePointers ptrs = ReusablePointers.get(); 291 Pointer<Integer> typeRef = ptrs.int1; 292 Pointer<Integer> nameRef = ptrs.int2; 293 CL.clGetGLObjectInfo(getEntity(), getPeer(typeRef), getPeer(nameRef)); 294 return new GLObjectInfo(GLObjectType.getEnum(typeRef.getInt()), nameRef.getInt()); 295 } 296 public enum MapFlags implements com.nativelibs4java.util.ValuedEnum { 297 Read(CL_MAP_READ), 298 Write(CL_MAP_WRITE), 299 ReadWrite(CL_MAP_READ | CL_MAP_WRITE), 300 WriteInvalidateRegion(CL_MAP_WRITE_INVALIDATE_REGION); 301 302 MapFlags(long value) { this.value = value; } 303 long value; 304 public long value() { return value; } 305 public static MapFlags getEnum(long v) { return EnumValues.getEnum(v, MapFlags.class); } 306 } 307 308 @Override 309 protected void clear() { 310 error(CL.clReleaseMemObject(getEntity())); 311 } 312}