@@ -89,6 +89,71 @@ pi_result piPluginGetLastError(char **message) {
8989 return ErrorMessageCode;
9090}
9191
92+ static cl_int getPlatformVersion (cl_platform_id plat,
93+ OCLV::OpenCLVersion &version) {
94+ cl_int ret_err = CL_INVALID_VALUE;
95+
96+ size_t platVerSize = 0 ;
97+ ret_err =
98+ clGetPlatformInfo (plat, CL_PLATFORM_VERSION, 0 , nullptr , &platVerSize);
99+
100+ std::string platVer (platVerSize, ' \0 ' );
101+ ret_err = clGetPlatformInfo (plat, CL_PLATFORM_VERSION, platVerSize,
102+ platVer.data (), nullptr );
103+
104+ if (ret_err != CL_SUCCESS)
105+ return ret_err;
106+
107+ version = OCLV::OpenCLVersion (platVer);
108+ if (!version.isValid ())
109+ return CL_INVALID_PLATFORM;
110+
111+ return ret_err;
112+ }
113+
114+ static cl_int getDeviceVersion (cl_device_id dev, OCLV::OpenCLVersion &version) {
115+ cl_int ret_err = CL_INVALID_VALUE;
116+
117+ size_t devVerSize = 0 ;
118+ ret_err = clGetDeviceInfo (dev, CL_DEVICE_VERSION, 0 , nullptr , &devVerSize);
119+
120+ std::string devVer (devVerSize, ' \0 ' );
121+ ret_err = clGetDeviceInfo (dev, CL_DEVICE_VERSION, devVerSize, devVer.data (),
122+ nullptr );
123+
124+ if (ret_err != CL_SUCCESS)
125+ return ret_err;
126+
127+ version = OCLV::OpenCLVersion (devVer);
128+ if (!version.isValid ())
129+ return CL_INVALID_DEVICE;
130+
131+ return ret_err;
132+ }
133+
134+ static cl_int checkDeviceExtensions (cl_device_id dev,
135+ const std::vector<std::string> &exts,
136+ bool &supported) {
137+ cl_int ret_err = CL_INVALID_VALUE;
138+
139+ size_t extSize = 0 ;
140+ ret_err = clGetDeviceInfo (dev, CL_DEVICE_EXTENSIONS, 0 , nullptr , &extSize);
141+
142+ std::string extStr (extSize, ' \0 ' );
143+ ret_err = clGetDeviceInfo (dev, CL_DEVICE_EXTENSIONS, extSize, extStr.data (),
144+ nullptr );
145+
146+ if (ret_err != CL_SUCCESS)
147+ return ret_err;
148+
149+ supported = true ;
150+ for (const std::string &ext : exts)
151+ if (!(supported = (extStr.find (ext) != std::string::npos)))
152+ break ;
153+
154+ return ret_err;
155+ }
156+
92157// USM helper function to get an extension function pointer
93158template <const char *FuncName, typename T>
94159static pi_result getExtFuncFromContext (pi_context context, T *fptr) {
@@ -215,17 +280,18 @@ pi_result piDeviceGetInfo(pi_device device, pi_device_info paramName,
215280 case PI_DEVICE_INFO_ATOMIC_MEMORY_SCOPE_CAPABILITIES:
216281 return PI_ERROR_INVALID_VALUE;
217282 case PI_DEVICE_INFO_ATOMIC_64: {
218- size_t extSize;
219- cl_bool result = clGetDeviceInfo (
220- cast<cl_device_id>(device), CL_DEVICE_EXTENSIONS, 0 , nullptr , &extSize);
221- std::string extStr (extSize, ' \0 ' );
222- result = clGetDeviceInfo (cast<cl_device_id>(device), CL_DEVICE_EXTENSIONS,
223- extSize, &extStr.front (), nullptr );
224- if (extStr.find (" cl_khr_int64_base_atomics" ) == std::string::npos ||
225- extStr.find (" cl_khr_int64_extended_atomics" ) == std::string::npos)
226- result = false ;
227- else
228- result = true ;
283+ cl_int ret_err = CL_SUCCESS;
284+ cl_bool result = CL_FALSE;
285+ bool supported = false ;
286+
287+ ret_err = checkDeviceExtensions (
288+ cast<cl_device_id>(device),
289+ {" cl_khr_int64_base_atomics" , " cl_khr_int64_extended_atomics" },
290+ supported);
291+ if (ret_err != CL_SUCCESS)
292+ return static_cast <pi_result>(ret_err);
293+
294+ result = supported;
229295 std::memcpy (paramValue, &result, sizeof (cl_bool));
230296 return PI_SUCCESS;
231297 }
@@ -402,18 +468,6 @@ pi_result piQueueCreate(pi_context context, pi_device device,
402468
403469 CHECK_ERR_SET_NULL_RET (ret_err, queue, ret_err);
404470
405- size_t platVerSize;
406- ret_err = clGetPlatformInfo (curPlatform, CL_PLATFORM_VERSION, 0 , nullptr ,
407- &platVerSize);
408-
409- CHECK_ERR_SET_NULL_RET (ret_err, queue, ret_err);
410-
411- std::string platVer (platVerSize, ' \0 ' );
412- ret_err = clGetPlatformInfo (curPlatform, CL_PLATFORM_VERSION, platVerSize,
413- &platVer.front (), nullptr );
414-
415- CHECK_ERR_SET_NULL_RET (ret_err, queue, ret_err);
416-
417471 // Check that unexpected bits are not set.
418472 assert (!(properties &
419473 ~(PI_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE |
@@ -425,9 +479,12 @@ pi_result piQueueCreate(pi_context context, pi_device device,
425479 CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_PROFILING_ENABLE |
426480 CL_QUEUE_ON_DEVICE | CL_QUEUE_ON_DEVICE_DEFAULT;
427481
428- if (platVer.find (" OpenCL 1.0" ) != std::string::npos ||
429- platVer.find (" OpenCL 1.1" ) != std::string::npos ||
430- platVer.find (" OpenCL 1.2" ) != std::string::npos) {
482+ OCLV::OpenCLVersion version;
483+ ret_err = getPlatformVersion (curPlatform, version);
484+
485+ CHECK_ERR_SET_NULL_RET (ret_err, queue, ret_err);
486+
487+ if (version >= OCLV::V2_0) {
431488 *queue = cast<pi_queue>(clCreateCommandQueue (
432489 cast<cl_context>(context), cast<cl_device_id>(device),
433490 cast<cl_command_queue_properties>(properties) & SupportByOpenCL,
@@ -482,38 +539,51 @@ pi_result piProgramCreate(pi_context context, const void *il, size_t length,
482539
483540 CHECK_ERR_SET_NULL_RET (ret_err, res_program, CL_INVALID_CONTEXT);
484541
485- size_t devVerSize;
486- ret_err = clGetPlatformInfo (curPlatform, CL_PLATFORM_VERSION, 0 , nullptr ,
487- &devVerSize);
488- std::string devVer (devVerSize, ' \0 ' );
489- ret_err = clGetPlatformInfo (curPlatform, CL_PLATFORM_VERSION, devVerSize,
490- &devVer.front (), nullptr );
542+ OCLV::OpenCLVersion platVer;
543+ ret_err = getPlatformVersion (curPlatform, platVer);
491544
492545 CHECK_ERR_SET_NULL_RET (ret_err, res_program, CL_INVALID_CONTEXT);
493546
494547 pi_result err = PI_SUCCESS;
495- if (devVer.find (" OpenCL 1.0" ) == std::string::npos &&
496- devVer.find (" OpenCL 1.1" ) == std::string::npos &&
497- devVer.find (" OpenCL 1.2" ) == std::string::npos &&
498- devVer.find (" OpenCL 2.0" ) == std::string::npos) {
548+ if (platVer >= OCLV::V2_1) {
549+
550+ /* Make sure all devices support CL 2.1 or newer as well. */
551+ for (cl_device_id dev : devicesInCtx) {
552+ OCLV::OpenCLVersion devVer;
553+
554+ ret_err = getDeviceVersion (dev, devVer);
555+ CHECK_ERR_SET_NULL_RET (ret_err, res_program, CL_INVALID_CONTEXT);
556+
557+ /* If the device does not support CL 2.1 or greater, we need to make sure
558+ * it supports the cl_khr_il_program extension.
559+ */
560+ if (devVer < OCLV::V2_1) {
561+ bool supported = false ;
562+
563+ ret_err = checkDeviceExtensions (dev, {" cl_khr_il_program" }, supported);
564+ CHECK_ERR_SET_NULL_RET (ret_err, res_program, CL_INVALID_CONTEXT);
565+
566+ if (!supported)
567+ return cast<pi_result>(CL_INVALID_OPERATION);
568+ }
569+ }
499570 if (res_program != nullptr )
500571 *res_program = cast<pi_program>(clCreateProgramWithIL (
501572 cast<cl_context>(context), il, length, cast<cl_int *>(&err)));
502573 return err;
503574 }
504575
505- size_t extSize;
506- ret_err = clGetPlatformInfo (curPlatform, CL_PLATFORM_EXTENSIONS, 0 , nullptr ,
507- &extSize);
508- std::string extStr (extSize, ' \0 ' );
509- ret_err = clGetPlatformInfo (curPlatform, CL_PLATFORM_EXTENSIONS, extSize,
510- &extStr.front (), nullptr );
576+ /* If none of the devices conform with CL 2.1 or newer make sure they all
577+ * support the cl_khr_il_program extension.
578+ */
579+ for (cl_device_id dev : devicesInCtx) {
580+ bool supported = false ;
511581
512- if ( ret_err != CL_SUCCESS ||
513- extStr. find ( " cl_khr_il_program " ) == std::string::npos) {
514- if (res_program != nullptr )
515- *res_program = nullptr ;
516- return cast<pi_result>(CL_INVALID_CONTEXT );
582+ ret_err = checkDeviceExtensions (dev, { " cl_khr_il_program " }, supported);
583+ CHECK_ERR_SET_NULL_RET (ret_err, res_program, CL_INVALID_CONTEXT);
584+
585+ if (!supported)
586+ return cast<pi_result>(CL_INVALID_OPERATION );
517587 }
518588
519589 using apiFuncT =
0 commit comments