1 module grain.cl.testing; 2 3 import grain.dpp.cl; 4 5 6 pure @safe @nogc nothrow 7 string getErrorString()(cl_int error) 8 { 9 switch(error){ 10 // run-time and JIT compiler errors 11 case 0: return "CL_SUCCESS"; 12 case -1: return "CL_DEVICE_NOT_FOUND"; 13 case -2: return "CL_DEVICE_NOT_AVAILABLE"; 14 case -3: return "CL_COMPILER_NOT_AVAILABLE"; 15 case -4: return "CL_MEM_OBJECT_ALLOCATION_FAILURE"; 16 case -5: return "CL_OUT_OF_RESOURCES"; 17 case -6: return "CL_OUT_OF_HOST_MEMORY"; 18 case -7: return "CL_PROFILING_INFO_NOT_AVAILABLE"; 19 case -8: return "CL_MEM_COPY_OVERLAP"; 20 case -9: return "CL_IMAGE_FORMAT_MISMATCH"; 21 case -10: return "CL_IMAGE_FORMAT_NOT_SUPPORTED"; 22 case -11: return "CL_BUILD_PROGRAM_FAILURE"; 23 case -12: return "CL_MAP_FAILURE"; 24 case -13: return "CL_MISALIGNED_SUB_BUFFER_OFFSET"; 25 case -14: return "CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST"; 26 case -15: return "CL_COMPILE_PROGRAM_FAILURE"; 27 case -16: return "CL_LINKER_NOT_AVAILABLE"; 28 case -17: return "CL_LINK_PROGRAM_FAILURE"; 29 case -18: return "CL_DEVICE_PARTITION_FAILED"; 30 case -19: return "CL_KERNEL_ARG_INFO_NOT_AVAILABLE"; 31 32 // compile-time errors 33 case -30: return "CL_INVALID_VALUE"; 34 case -31: return "CL_INVALID_DEVICE_TYPE"; 35 case -32: return "CL_INVALID_PLATFORM"; 36 case -33: return "CL_INVALID_DEVICE"; 37 case -34: return "CL_INVALID_CONTEXT"; 38 case -35: return "CL_INVALID_QUEUE_PROPERTIES"; 39 case -36: return "CL_INVALID_COMMAND_QUEUE"; 40 case -37: return "CL_INVALID_HOST_PTR"; 41 case -38: return "CL_INVALID_MEM_OBJECT"; 42 case -39: return "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR"; 43 case -40: return "CL_INVALID_IMAGE_SIZE"; 44 case -41: return "CL_INVALID_SAMPLER"; 45 case -42: return "CL_INVALID_BINARY"; 46 case -43: return "CL_INVALID_BUILD_OPTIONS"; 47 case -44: return "CL_INVALID_PROGRAM"; 48 case -45: return "CL_INVALID_PROGRAM_EXECUTABLE"; 49 case -46: return "CL_INVALID_KERNEL_NAME"; 50 case -47: return "CL_INVALID_KERNEL_DEFINITION"; 51 case -48: return "CL_INVALID_KERNEL"; 52 case -49: return "CL_INVALID_ARG_INDEX"; 53 case -50: return "CL_INVALID_ARG_VALUE"; 54 case -51: return "CL_INVALID_ARG_SIZE"; 55 case -52: return "CL_INVALID_KERNEL_ARGS"; 56 case -53: return "CL_INVALID_WORK_DIMENSION"; 57 case -54: return "CL_INVALID_WORK_GROUP_SIZE"; 58 case -55: return "CL_INVALID_WORK_ITEM_SIZE"; 59 case -56: return "CL_INVALID_GLOBAL_OFFSET"; 60 case -57: return "CL_INVALID_EVENT_WAIT_LIST"; 61 case -58: return "CL_INVALID_EVENT"; 62 case -59: return "CL_INVALID_OPERATION"; 63 case -60: return "CL_INVALID_GL_OBJECT"; 64 case -61: return "CL_INVALID_BUFFER_SIZE"; 65 case -62: return "CL_INVALID_MIP_LEVEL"; 66 case -63: return "CL_INVALID_GLOBAL_WORK_SIZE"; 67 case -64: return "CL_INVALID_PROPERTY"; 68 case -65: return "CL_INVALID_IMAGE_DESCRIPTOR"; 69 case -66: return "CL_INVALID_COMPILER_OPTIONS"; 70 case -67: return "CL_INVALID_LINKER_OPTIONS"; 71 case -68: return "CL_INVALID_DEVICE_PARTITION_COUNT"; 72 73 // extension errors 74 case -1000: return "CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR"; 75 case -1001: return "CL_PLATFORM_NOT_FOUND_KHR"; 76 case -1002: return "CL_INVALID_D3D10_DEVICE_KHR"; 77 case -1003: return "CL_INVALID_D3D10_RESOURCE_KHR"; 78 case -1004: return "CL_D3D10_RESOURCE_ALREADY_ACQUIRED_KHR"; 79 case -1005: return "CL_D3D10_RESOURCE_NOT_ACQUIRED_KHR"; 80 default: return "Unknown OpenCL error"; 81 } 82 } 83 84 85 /// print opencl device info 86 @nogc nothrow 87 void printDeviceInfo(cl_device_id device) 88 { 89 import core.stdc.stdio : fprintf, stderr; 90 import core.memory : pureMalloc, pureFree; 91 cl_ulong len; 92 93 // print str info 94 static foreach (s; ["CL_DEVICE_NAME", "CL_DEVICE_VERSION", "CL_DRIVER_VERSION", "CL_DEVICE_OPENCL_C_VERSION"]) 95 { 96 { 97 mixin("enum d = " ~ s ~ ";"); 98 clGetDeviceInfo(device, d, 0, null, &len); 99 auto p = cast(char*) pureMalloc(len); 100 scope (exit) pureFree(p); 101 clGetDeviceInfo(device, d, len, p, null); 102 stderr.fprintf("%s: %s\n", s.ptr, p); 103 } 104 } 105 106 // print size info 107 static foreach (s; ["CL_DEVICE_MAX_CLOCK_FREQUENCY", "CL_DEVICE_MAX_COMPUTE_UNITS", "CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS", "CL_DEVICE_GLOBAL_MEM_SIZE", "CL_DEVICE_LOCAL_MEM_SIZE", "CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE", "CL_DEVICE_MAX_MEM_ALLOC_SIZE"]) 108 { 109 { 110 mixin("enum d = " ~ s ~ ";"); 111 clGetDeviceInfo(device, d, len.sizeof, &len, null); 112 stderr.fprintf("%s: %d\n", s.ptr, len); 113 } 114 } 115 } 116 117 /// assert opencl error and print where it was raised 118 @nogc nothrow 119 auto checkCl( 120 alias f, 121 string func = __FUNCTION__, 122 string file = __FILE__, 123 size_t line = __LINE__, 124 Args ... 125 )(auto return ref Args args) 126 { 127 // import std.format : format; 128 import std.functional : forward; 129 // enum msg = format!"error at line: %d, file: %s"(line, file); 130 import mir.format : getData, stringBuf; 131 static if (__traits(compiles, f(args))) 132 { 133 auto err = f(forward!args); 134 // assert(err == CL_SUCCESS, msg); 135 assert(err == CL_SUCCESS, 136 stringBuf() 137 << err.getErrorString 138 << " from " << func 139 << " at file: " << file 140 << " of line: " << line 141 << getData); 142 } 143 else 144 { 145 cl_int err; 146 scope (exit) 147 { 148 //assert(err == CL_SUCCESS, msg); 149 assert(err == CL_SUCCESS, 150 stringBuf() 151 << err.getErrorString 152 << " from " << func 153 << " at file: " << file 154 << " of line: " << line 155 << getData); 156 } 157 return f(forward!args, &err); 158 } 159 }