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.library.OpenCLLibrary.*; 052import static com.nativelibs4java.opencl.library.IOpenCLLibrary.*; 053import com.nativelibs4java.opencl.library.OpenCLLibrary; 054import com.ochafik.util.string.StringUtils; 055import java.lang.annotation.Retention; 056import java.lang.annotation.RetentionPolicy; 057import java.util.*; 058import java.lang.reflect.*; 059import static com.nativelibs4java.opencl.JavaCL.log; 060import java.util.logging.Level; 061import java.util.logging.Logger; 062 063/** 064 * OpenCL error 065 * @author ochafik 066 */ 067@SuppressWarnings("serial") 068public class CLException extends RuntimeException { 069 protected int code; 070 CLException(String message, int code) { 071 super(message); 072 this.code = code; 073 } 074 public int getCode() { 075 return code; 076 } 077 078 @Retention(RetentionPolicy.RUNTIME) 079 public @interface ErrorCode { 080 int value(); 081 } 082 083 public static class CLVersionException extends CLException { 084 public CLVersionException(String message) { 085 super(message, 0); 086 } 087 } 088 089 public static class CLTypedException extends CLException { 090 protected String message; 091 public CLTypedException() { 092 super("", 0); 093 ErrorCode code = getClass().getAnnotation(ErrorCode.class); 094 this.code = code.value(); 095 this.message = getClass().getSimpleName(); 096 } 097 098 @Override 099 public String getMessage() { 100 return message + logSuffix; 101 } 102 103 void setKernelArg(CLKernel kernel, int argIndex) { 104 message += " (kernel name = " + kernel.getFunctionName() + ", num args = " + kernel.getNumArgs() + ", arg index = " + argIndex; 105 CLProgram program = kernel.getProgram(); 106 if (program != null) 107 message += ", source = <<<\n\t" + program.getSource().replaceAll("\n", "\n\t"); 108 109 message += "\n>>> )"; 110 } 111 112 } 113 114 @ErrorCode(CL_DEVICE_PARTITION_FAILED) 115 public static class DevicePartitionFailed extends CLTypedException {} 116 @ErrorCode(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST) 117 public static class ExecStatusErrorForEventsInWaitList extends CLTypedException {} 118 @ErrorCode(CL_MISALIGNED_SUB_BUFFER_OFFSET) 119 public static class MisalignedSubBufferOffset extends CLTypedException {} 120 @ErrorCode(CL_COMPILE_PROGRAM_FAILURE) 121 public static class CompileProgramFailure extends CLTypedException {} 122 @ErrorCode(CL_LINKER_NOT_AVAILABLE) 123 public static class LinkerNotAvailable extends CLTypedException {} 124 @ErrorCode(CL_LINK_PROGRAM_FAILURE) 125 public static class LinkProgramFailure extends CLTypedException {} 126 @ErrorCode(CL_KERNEL_ARG_INFO_NOT_AVAILABLE) 127 public static class KernelArgInfoNotAvailable extends CLTypedException {} 128 @ErrorCode(CL_IMAGE_FORMAT_MISMATCH) 129 public static class ImageFormatMismatch extends CLTypedException {} 130 @ErrorCode(CL_PROFILING_INFO_NOT_AVAILABLE) 131 public static class ProfilingInfoNotAvailable extends CLTypedException {} 132 @ErrorCode(CL_DEVICE_NOT_AVAILABLE) 133 public static class DeviceNotAvailable extends CLTypedException {} 134 @ErrorCode(CL_OUT_OF_RESOURCES) 135 public static class OutOfResources extends CLTypedException {} 136 @ErrorCode(CL_COMPILER_NOT_AVAILABLE) 137 public static class CompilerNotAvailable extends CLTypedException {} 138 @ErrorCode(CL_INVALID_GLOBAL_WORK_SIZE) 139 public static class InvalidGlobalWorkSize extends CLTypedException {} 140 @ErrorCode(CL_MAP_FAILURE) 141 public static class MapFailure extends CLTypedException {} 142 @ErrorCode(CL_MEM_OBJECT_ALLOCATION_FAILURE) 143 public static class MemObjectAllocationFailure extends CLTypedException {} 144 @ErrorCode(CL_INVALID_EVENT_WAIT_LIST) 145 public static class InvalidEventWaitList extends CLTypedException {} 146 @ErrorCode(CL_INVALID_ARG_INDEX) 147 public static class InvalidArgIndex extends CLTypedException {} 148 @ErrorCode(CL_INVALID_ARG_SIZE) 149 public static class InvalidArgSize extends CLTypedException {} 150 @ErrorCode(CL_INVALID_ARG_VALUE) 151 public static class InvalidArgValue extends CLTypedException {} 152 @ErrorCode(CL_INVALID_BINARY) 153 public static class InvalidBinary extends CLTypedException {} 154 @ErrorCode(CL_INVALID_EVENT) 155 public static class InvalidEvent extends CLTypedException {} 156 @ErrorCode(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR) 157 public static class InvalidImageFormatDescriptor extends CLTypedException {} 158 @ErrorCode(CL_INVALID_IMAGE_SIZE) 159 public static class InvalidImageSize extends CLTypedException {} 160 @ErrorCode(CL_INVALID_WORK_DIMENSION) 161 public static class InvalidWorkDimension extends CLTypedException {} 162 @ErrorCode(CL_INVALID_WORK_GROUP_SIZE) 163 public static class InvalidWorkGroupSize extends CLTypedException {} 164 @ErrorCode(CL_INVALID_WORK_ITEM_SIZE) 165 public static class InvalidWorkItemSize extends CLTypedException {} 166 @ErrorCode(CL_INVALID_OPERATION) 167 public static class InvalidOperation extends CLTypedException {} 168 @ErrorCode(CL_INVALID_BUFFER_SIZE) 169 public static class InvalidBufferSize extends CLTypedException {} 170 @ErrorCode(CL_INVALID_GLOBAL_OFFSET) 171 public static class InvalidGlobalOffset extends CLTypedException {} 172 @ErrorCode(CL_OUT_OF_HOST_MEMORY) 173 public static class OutOfHostMemory extends CLTypedException {} 174 @ErrorCode(CL_INVALID_COMPILER_OPTIONS) 175 public static class InvalidCompilerOptions extends CLTypedException {} 176 @ErrorCode(CL_INVALID_DEVICE) 177 public static class InvalidDevice extends CLTypedException {} 178 @ErrorCode(CL_INVALID_DEVICE_PARTITION_COUNT) 179 public static class InvalidDevicePartitionCount extends CLTypedException {} 180 @ErrorCode(CL_INVALID_HOST_PTR) 181 public static class InvalidHostPtr extends CLTypedException {} 182 @ErrorCode(CL_INVALID_IMAGE_DESCRIPTOR) 183 public static class InvalidImageDescriptor extends CLTypedException {} 184 @ErrorCode(CL_INVALID_LINKER_OPTIONS) 185 public static class InvalidLinkerOptions extends CLTypedException {} 186 @ErrorCode(CL_INVALID_PLATFORM) 187 public static class InvalidPlatform extends CLTypedException {} 188 @ErrorCode(CL_INVALID_PROPERTY) 189 public static class InvalidProperty extends CLTypedException {} 190 @ErrorCode(CL_INVALID_COMMAND_QUEUE) 191 public static class InvalidCommandQueue extends CLTypedException {} 192 @ErrorCode(CL_MEM_COPY_OVERLAP) 193 public static class MemCopyOverlap extends CLTypedException {} 194 @ErrorCode(CL_INVALID_CONTEXT) 195 public static class InvalidContext extends CLTypedException {} 196 @ErrorCode(CL_INVALID_KERNEL) 197 public static class InvalidKernel extends CLTypedException {} 198 @ErrorCode(CL_INVALID_GL_CONTEXT_APPLE) 199 public static class InvalidGLContextApple extends CLTypedException {} 200 @ErrorCode(CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR) 201 public static class InvalidGLShareGroupReference extends CLTypedException {} 202 @ErrorCode(CL_INVALID_GL_OBJECT) 203 public static class InvalidGLObject extends CLTypedException {} 204 @ErrorCode(CL_INVALID_KERNEL_ARGS) 205 public static class InvalidKernelArgs extends CLTypedException {} 206 @ErrorCode(CL_INVALID_KERNEL_DEFINITION) 207 public static class InvalidKernelDefinition extends CLTypedException {} 208 @ErrorCode(CL_INVALID_KERNEL_NAME) 209 public static class InvalidKernelName extends CLTypedException {} 210 @ErrorCode(CL_INVALID_MEM_OBJECT) 211 public static class InvalidMemObject extends CLTypedException {} 212 @ErrorCode(CL_INVALID_MIP_LEVEL) 213 public static class InvalidMipLevel extends CLTypedException {} 214 @ErrorCode(CL_INVALID_PROGRAM) 215 public static class InvalidProgram extends CLTypedException {} 216 @ErrorCode(CL_INVALID_PROGRAM_EXECUTABLE) 217 public static class InvalidProgramExecutable extends CLTypedException {} 218 @ErrorCode(CL_INVALID_QUEUE_PROPERTIES) 219 public static class InvalidQueueProperties extends CLTypedException {} 220 @ErrorCode(CL_INVALID_VALUE) 221 public static class InvalidValue extends CLTypedException {} 222 @ErrorCode(CL_INVALID_SAMPLER) 223 public static class InvalidSampler extends CLTypedException {} 224 @ErrorCode(CL_INVALID_DEVICE_TYPE) 225 public static class InvalidDeviceType extends CLTypedException {} 226 @ErrorCode(CL_INVALID_BUILD_OPTIONS) 227 public static class InvalidBuildOptions extends CLTypedException {} 228 @ErrorCode(CL_BUILD_PROGRAM_FAILURE) 229 public static class BuildProgramFailure extends CLTypedException {} 230 231 public static String errorString(int err) { 232 if (err == CL_SUCCESS) 233 return null; 234 235 List<String> candidates = new ArrayList<String>(); 236 for (Field f : OpenCLLibrary.class.getDeclaredFields()) { 237 if (!Modifier.isStatic(f.getModifiers())) { 238 continue; 239 } 240 if (f.getType().equals(Integer.TYPE)) { 241 try { 242 int i = (Integer) f.get(null); 243 if (i == err) { 244 String name = f.getName(), lname = name.toLowerCase(); 245 if (lname.contains("invalid") || lname.contains("bad") || lname.contains("illegal") || lname.contains("wrong")) { 246 candidates.clear(); 247 candidates.add(name); 248 break; 249 } else 250 candidates.add(name); 251 } 252 } catch (Exception e) { 253 e.printStackTrace(); 254 } 255 } 256 } 257 return StringUtils.implode(candidates, " or "); 258 } 259 260 static boolean failedForLackOfMemory(int err, int previousAttempts) { 261 switch (err) { 262 case CL_SUCCESS: 263 return false; 264 case CL_OUT_OF_HOST_MEMORY: 265 case CL_OUT_OF_RESOURCES: 266 case CL_MEM_OBJECT_ALLOCATION_FAILURE: 267 if (previousAttempts <= 1) { 268 System.gc(); 269 if (previousAttempts == 1) { 270 try { 271 Thread.sleep(100); 272 } catch (InterruptedException ex) {} 273 } 274 return true; 275 } 276 default: 277 error(err); 278 assert false; // won't reach 279 return false; 280 } 281 } 282 static final String logSuffix = System.getenv("CL_LOG_ERRORS") == null ? " (make sure to log all errors with environment variable CL_LOG_ERRORS=stdout)" : ""; 283 284 static Map<Integer, Class<? extends CLTypedException>> typedErrorClassesByCode; 285 @SuppressWarnings("unchecked") 286 public static void error(int err) { 287 if (err == CL_SUCCESS) 288 return; 289 290 if (typedErrorClassesByCode == null) { 291 typedErrorClassesByCode = new HashMap<Integer, Class<? extends CLTypedException>>(); 292 for (Class<?> c : CLException.class.getDeclaredClasses()) { 293 if (c == CLTypedException.class || !CLTypedException.class.isAssignableFrom(c)) 294 continue; 295 typedErrorClassesByCode.put(c.getAnnotation(ErrorCode.class).value(), (Class<? extends CLTypedException>)c); 296 } 297 } 298 CLException toThrow = null; 299 Class<? extends CLTypedException> c = typedErrorClassesByCode.get(err); 300 if (c != null) { 301 try { 302 toThrow = c.newInstance(); 303 } catch (InstantiationException ex) { 304 assert log(Level.SEVERE, null, ex); 305 } catch (IllegalAccessException ex) { 306 assert log(Level.SEVERE, null, ex); 307 } 308 } 309 if (toThrow == null) 310 toThrow = new CLException("OpenCL Error : " + errorString(err) + logSuffix, err); 311 312 throw toThrow; 313 } 314}