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 }