diff --git a/include/cl_khr_icd2.h b/include/cl_khr_icd2.h index 6a9a78a8..de319515 100644 --- a/include/cl_khr_icd2.h +++ b/include/cl_khr_icd2.h @@ -66,3 +66,25 @@ clIcdSetPlatformDispatchDataKHR_t( typedef clIcdSetPlatformDispatchDataKHR_t * clIcdSetPlatformDispatchDataKHR_fn; #endif // !defined(CL_ICD2_TAG_KHR) + +#if !defined(CL_INSTANCE_PLATFORM_PROPERTIES_LIST_END_KHR) +#define CL_INSTANCE_PLATFORM_PROPERTIES_LIST_END_KHR ((cl_instance_platform_properties_khr)0) + +typedef cl_properties cl_instance_platform_properties_khr; + +typedef cl_platform_id CL_API_CALL +clIcdCreateInstancePlatformKHR_t( + cl_platform_id platform, + const cl_instance_platform_properties_khr *properties, + cl_int *errcode_ret); + +typedef clIcdCreateInstancePlatformKHR_t * +clIcdCreateInstancePlatformKHR_fn; + +typedef cl_int CL_API_CALL +clIcdDestroyInstancePlatformKHR_t( + cl_platform_id platform); + +typedef clIcdDestroyInstancePlatformKHR_t * +clIcdDestroyInstancePlatformKHR_fn; +#endif //!defined(CL_INSTANCE_PLATFORM_PROPERTIES_LIST_END_KHR) diff --git a/loader/icd.c b/loader/icd.c index 5747c2aa..9e9dd439 100644 --- a/loader/icd.c +++ b/loader/icd.c @@ -76,6 +76,8 @@ void khrIcdVendorAdd(const char *libraryName) #if defined(CL_ENABLE_LOADER_MANAGED_DISPATCH) clIcdGetFunctionAddressForPlatformKHR_fn p_clIcdGetFunctionAddressForPlatform = NULL; clIcdSetPlatformDispatchDataKHR_fn p_clIcdSetPlatformDispatchData = NULL; + clIcdCreateInstancePlatformKHR_fn p_clIcdCreateInstancePlatform = NULL; + clIcdDestroyInstancePlatformKHR_fn p_clIcdDestroyInstancePlatform = NULL; #endif cl_uint i = 0; cl_uint platformCount = 0; @@ -127,6 +129,8 @@ void khrIcdVendorAdd(const char *libraryName) // try to get clIcdGetFunctionAddressForPlatformKHR and clIcdSetPlatformDispatchDataKHR to detect cl_khr_icd2 support p_clIcdGetFunctionAddressForPlatform = (clIcdGetFunctionAddressForPlatformKHR_fn)(size_t)p_clGetExtensionFunctionAddress("clIcdGetFunctionAddressForPlatformKHR"); p_clIcdSetPlatformDispatchData = (clIcdSetPlatformDispatchDataKHR_fn)(size_t)p_clGetExtensionFunctionAddress("clIcdSetPlatformDispatchDataKHR"); + p_clIcdCreateInstancePlatform = (clIcdCreateInstancePlatformKHR_fn)(size_t)p_clGetExtensionFunctionAddress("clIcdCreateInstancePlatformKHR"); + p_clIcdDestroyInstancePlatform = (clIcdDestroyInstancePlatformKHR_fn)(size_t)p_clGetExtensionFunctionAddress("clIcdDestroyInstancePlatformKHR"); #endif // query the number of platforms available and allocate space to store them @@ -154,32 +158,48 @@ void khrIcdVendorAdd(const char *libraryName) for (i = 0; i < platformCount; ++i) { KHRicdVendor* vendor = NULL; - char *extensions; - size_t extensionsSize; - char *suffix; - size_t suffixSize; + char *extensions = NULL; + size_t extensionsSize = 0; + char *suffix = NULL; + size_t suffixSize = 0; + cl_platform_id platform = platforms[i]; +#if defined(CL_ENABLE_LOADER_MANAGED_DISPATCH) + cl_platform_id instance_platform = NULL; +#endif // skip NULL platforms and non dispatchable platforms - if (!platforms[i] || !platforms[i]->dispatch) + if (!platform || !platform->dispatch) { - continue; + KHR_ICD_TRACE("found null platform or non dispatchable platform\n"); + goto Error; } #if defined(CL_ENABLE_LOADER_MANAGED_DISPATCH) - if (KHR_ICD2_HAS_TAG(platforms[i]) && !p_clIcdGetFunctionAddressForPlatform) + if (KHR_ICD2_HAS_TAG(platform) && !p_clIcdGetFunctionAddressForPlatform) { KHR_ICD_TRACE("found icd 2 object, but platform is missing clIcdGetFunctionAddressForPlatformKHR\n"); - continue; + goto Error; } - if (KHR_ICD2_HAS_TAG(platforms[i]) && !p_clIcdSetPlatformDispatchData) + if (KHR_ICD2_HAS_TAG(platform) && !p_clIcdSetPlatformDispatchData) { KHR_ICD_TRACE("found icd 2 object, but platform is missing clIcdSetPlatformDispatchDataKHR\n"); - continue; + goto Error; } - if (KHR_ICD2_HAS_TAG(platforms[i]) && !((intptr_t)((platforms[i])->dispatch->clUnloadCompiler) == CL_ICD2_TAG_KHR)) + if (KHR_ICD2_HAS_TAG(platform) && !((intptr_t)((platform)->dispatch->clUnloadCompiler) == CL_ICD2_TAG_KHR)) { KHR_ICD_TRACE("found icd 2 object, but platform is missing tag in clUnloadCompiler\n"); - continue; + goto Error; + } + if (p_clIcdCreateInstancePlatform && p_clIcdDestroyInstancePlatform) + { + KHR_ICD_TRACE("found icd 2 object with instance support, creating instance platform\n"); + instance_platform = p_clIcdCreateInstancePlatform(platform, NULL, &result); + if (CL_SUCCESS != result || !instance_platform) + { + KHR_ICD_TRACE("failed to create instance platform\n"); + goto Error; + } + platform = instance_platform; } #endif @@ -188,23 +208,30 @@ void khrIcdVendorAdd(const char *libraryName) if (!vendor) { KHR_ICD_TRACE("failed to allocate memory\n"); - continue; + goto Error; } memset(vendor, 0, sizeof(*vendor)); #if defined(CL_ENABLE_LOADER_MANAGED_DISPATCH) // populate cl_khr_icd2 platform's loader managed dispatch tables - if (KHR_ICD2_HAS_TAG(platforms[i])) + if (KHR_ICD2_HAS_TAG(platform)) { - khrIcd2PopulateDispatchTable(platforms[i], p_clIcdGetFunctionAddressForPlatform, &vendor->dispData.dispatch); - p_clIcdSetPlatformDispatchData(platforms[i], &vendor->dispData); + khrIcd2PopulateDispatchTable(platform, p_clIcdGetFunctionAddressForPlatform, &vendor->dispData.dispatch); + p_clIcdSetPlatformDispatchData(platform, &vendor->dispData); KHR_ICD_TRACE("found icd 2 platform, using loader managed dispatch\n"); + if (p_clIcdCreateInstancePlatform && p_clIcdDestroyInstancePlatform) + { + vendor->clIcdSetPlatformDispatchData = p_clIcdSetPlatformDispatchData; + vendor->clIcdCreateInstancePlatform = p_clIcdCreateInstancePlatform; + vendor->clIcdDestroyInstancePlatform = p_clIcdDestroyInstancePlatform; + } } + vendor->instance_platform = instance_platform; #endif // call clGetPlatformInfo on the returned platform to get the supported extensions - result = KHR_ICD2_DISPATCH(platforms[i])->clGetPlatformInfo( - platforms[i], + result = KHR_ICD2_DISPATCH(platform)->clGetPlatformInfo( + platform, CL_PLATFORM_EXTENSIONS, 0, NULL, @@ -212,18 +239,16 @@ void khrIcdVendorAdd(const char *libraryName) if (CL_SUCCESS != result) { KHR_ICD_TRACE("failed query platform extensions\n"); - free(vendor); - continue; + goto Error; } extensions = (char *)malloc(extensionsSize); if (!extensions) { KHR_ICD_TRACE("failed to allocate memory\n"); - free(vendor); - continue; + goto Error; } - result = KHR_ICD2_DISPATCH(platforms[i])->clGetPlatformInfo( - platforms[i], + result = KHR_ICD2_DISPATCH(platform)->clGetPlatformInfo( + platform, CL_PLATFORM_EXTENSIONS, extensionsSize, extensions, @@ -231,17 +256,14 @@ void khrIcdVendorAdd(const char *libraryName) if (CL_SUCCESS != result) { KHR_ICD_TRACE("failed query platform extensions\n"); - free(extensions); - free(vendor); - continue; + goto Error; } if (strstr(extensions, "cl_khr_icd_unloadable")) { KHR_ICD_TRACE("found cl_khr_icd_unloadable extension support\n"); - free(extensions); - result = KHR_ICD2_DISPATCH(platforms[i])->clGetPlatformInfo( - platforms[i], + result = KHR_ICD2_DISPATCH(platform)->clGetPlatformInfo( + platform, CL_PLATFORM_UNLOADABLE_KHR, sizeof(vendor->unloadable), &vendor->unloadable, @@ -253,14 +275,13 @@ void khrIcdVendorAdd(const char *libraryName) if (CL_SUCCESS != result) { KHR_ICD_TRACE("found cl_khr_icd_unloadable but clGetPlatformInfo CL_PLATFORM_UNLOADABLE_KHR query failed\n"); - free(vendor); - continue; + goto Error; } } // call clGetPlatformInfo on the returned platform to get the suffix - result = KHR_ICD2_DISPATCH(platforms[i])->clGetPlatformInfo( - platforms[i], + result = KHR_ICD2_DISPATCH(platform)->clGetPlatformInfo( + platform, CL_PLATFORM_ICD_SUFFIX_KHR, 0, NULL, @@ -268,18 +289,16 @@ void khrIcdVendorAdd(const char *libraryName) if (CL_SUCCESS != result) { KHR_ICD_TRACE("failed query platform ICD suffix\n"); - free(vendor); - continue; + goto Error; } suffix = (char *)malloc(suffixSize); if (!suffix) { KHR_ICD_TRACE("failed to allocate memory\n"); - free(vendor); - continue; + goto Error; } - result = KHR_ICD2_DISPATCH(platforms[i])->clGetPlatformInfo( - platforms[i], + result = KHR_ICD2_DISPATCH(platform)->clGetPlatformInfo( + platform, CL_PLATFORM_ICD_SUFFIX_KHR, suffixSize, suffix, @@ -287,19 +306,15 @@ void khrIcdVendorAdd(const char *libraryName) if (CL_SUCCESS != result) { KHR_ICD_TRACE("failed query platform ICD suffix\n"); - free(suffix); - free(vendor); - continue; + goto Error; } // populate vendor data vendor->library = khrIcdOsLibraryLoad(libraryName); if (!vendor->library) { - free(suffix); - free(vendor); KHR_ICD_TRACE("failed get platform handle to library\n"); - continue; + goto Error; } vendor->clGetExtensionFunctionAddress = p_clGetExtensionFunctionAddress; vendor->platform = platforms[i]; @@ -314,8 +329,19 @@ void khrIcdVendorAdd(const char *libraryName) } lastVendor = vendor; + free(extensions); KHR_ICD_TRACE("successfully added vendor %s with suffix %s\n", libraryName, suffix); - + continue; +Error: + free(extensions); + free(suffix); +#if defined(CL_ENABLE_LOADER_MANAGED_DISPATCH) + if (instance_platform) + { + p_clIcdDestroyInstancePlatform(instance_platform); + } +#endif + free(vendor); } Done: @@ -564,7 +590,11 @@ void khrIcdContextPropertiesGetPlatform(const cl_context_properties *properties, { if (properties == NULL && khrIcdVendors != NULL) { +#if defined(CL_ENABLE_LOADER_MANAGED_DISPATCH) + *outPlatform = khrIcdVendors[0].instance_platform ? khrIcdVendors[0].instance_platform : khrIcdVendors[0].platform; +#else *outPlatform = khrIcdVendors[0].platform; +#endif } else { @@ -626,6 +656,10 @@ void khrIcdDeinitialize(void) { while (lastVendor) { KHRicdVendor *cur = lastVendor; free(cur->suffix); +#if defined(CL_ENABLE_LOADER_MANAGED_DISPATCH) + if (cur->instance_platform) + cur->clIcdDestroyInstancePlatform(cur->instance_platform); +#endif if (cur->unloadable && !khrDisableLibraryUnloading) khrIcdOsLibraryUnload(cur->library); lastVendor = cur->prev; diff --git a/loader/icd.h b/loader/icd.h index dd1ca469..5fe8a584 100644 --- a/loader/icd.h +++ b/loader/icd.h @@ -102,6 +102,10 @@ struct KHRicdVendorRec #if defined(CL_ENABLE_LOADER_MANAGED_DISPATCH) // the loader populated dispatch table for cl_khr_icd2 compliant platforms struct KHRDisp dispData; + clIcdSetPlatformDispatchDataKHR_fn clIcdSetPlatformDispatchData; + clIcdCreateInstancePlatformKHR_fn clIcdCreateInstancePlatform; + clIcdDestroyInstancePlatformKHR_fn clIcdDestroyInstancePlatform; + cl_platform_id instance_platform; #endif // next vendor in the list vendors diff --git a/loader/icd_dispatch.c b/loader/icd_dispatch.c index e316ffb5..137a76d8 100644 --- a/loader/icd_dispatch.c +++ b/loader/icd_dispatch.c @@ -183,7 +183,11 @@ static inline cl_int clGetPlatformIDs_body( { if (num_entries && platforms) { +#if defined(CL_ENABLE_LOADER_MANAGED_DISPATCH) + *(platforms++) = vendor->instance_platform ? vendor->instance_platform : vendor->platform; +#else *(platforms++) = vendor->platform; +#endif --num_entries; } if (num_platforms) diff --git a/test/driver_stub/cl.c b/test/driver_stub/cl.c index 3e5d134d..a31acce4 100644 --- a/test/driver_stub/cl.c +++ b/test/driver_stub/cl.c @@ -19,6 +19,11 @@ #include "icd_structs.h" #include "cl_khr_icd2.h" +#if defined(CL_ENABLE_ICD2) +CL_API_ENTRY clIcdCreateInstancePlatformKHR_t clIcdCreateInstancePlatformKHR; +CL_API_ENTRY clIcdDestroyInstancePlatformKHR_t clIcdDestroyInstancePlatformKHR; +#endif + #define CL_PLATFORM_ICD_SUFFIX_KHR 0x0920 CL_API_ENTRY cl_int CL_API_CALL clIcdGetPlatformIDsKHR(cl_uint, cl_platform_id *, cl_uint *); @@ -33,6 +38,7 @@ struct _cl_platform_id const char *extensions; const char *suffix; cl_device_id device; + cl_bool instance; }; struct _cl_device_id @@ -180,7 +186,7 @@ CL_API_ENTRY cl_int CL_API_CALL clGetDeviceIDs( if (devices != NULL) { if (!platform_id->device) { platform_id->device = (cl_device_id) malloc(sizeof(struct _cl_device_id)); - CL_INIT_OBJECT(platform_id->device, stub_platform); + CL_INIT_OBJECT(platform_id->device, platform_id); } devices[0] = platform_id->device; } @@ -1948,6 +1954,33 @@ clEnqueueBarrier(cl_command_queue command_queue) CL_API_SUFFIX__VERSION_1_0 extern cl_int cliIcdDispatchTableCreate(CLIicdDispatchTable **outDispatchTable); extern void cliIcdDispatchTableDestroy(CLIicdDispatchTable *dispatchTable); +static cl_platform_id createPlatform(void) +{ + cl_platform_id platform = + (cl_platform_id) malloc(sizeof(struct _cl_platform_id)); + memset(platform, 0, sizeof(struct _cl_platform_id)); + + CL_INIT_PLATFORM(platform, dispatchTable); + platform->version = "OpenCL 1.2 Stub"; + platform->vendor = "stubvendorxxx"; + platform->profile = "stubprofilexxx"; +#if defined(CL_ENABLE_ICD2) + platform->name = "ICD_LOADER_TEST_OPENCL_STUB_ICD2"; +#else + platform->name = "ICD_LOADER_TEST_OPENCL_STUB"; +#endif + platform->extensions = "cl_khr_icd cl_khr_icd_unloadable cl_khr_gl cl_khr_d3d10"; + platform->suffix = "ilts"; + return platform; +} + +static void destroyPlatform(cl_platform_id platform) +{ + free(platform->device); + platform->device = NULL; + free(platform); +} + CL_API_ENTRY cl_int CL_API_CALL clIcdGetPlatformIDsKHR(cl_uint num_entries, cl_platform_id * platforms, @@ -1956,20 +1989,7 @@ clIcdGetPlatformIDsKHR(cl_uint num_entries, cl_int result = CL_SUCCESS; if (!initialized) { result = cliIcdDispatchTableCreate(&dispatchTable); - stub_platform = (cl_platform_id) malloc(sizeof(struct _cl_platform_id)); - memset(stub_platform, 0, sizeof(struct _cl_platform_id)); - - CL_INIT_PLATFORM(stub_platform, dispatchTable); - stub_platform->version = "OpenCL 1.2 Stub"; - stub_platform->vendor = "stubvendorxxx"; - stub_platform->profile = "stubprofilexxx"; -#if defined(CL_ENABLE_ICD2) - stub_platform->name = "ICD_LOADER_TEST_OPENCL_STUB_ICD2"; -#else - stub_platform->name = "ICD_LOADER_TEST_OPENCL_STUB"; -#endif - stub_platform->extensions = "cl_khr_icd cl_khr_icd_unloadable cl_khr_gl cl_khr_d3d10"; - stub_platform->suffix = "ilts"; + stub_platform = createPlatform(); initialized = CL_TRUE; } @@ -1992,11 +2012,40 @@ clIcdGetPlatformIDsKHR(cl_uint num_entries, return result; } +#if defined(CL_ENABLE_ICD2) +CL_API_ENTRY cl_platform_id CL_API_CALL +clIcdCreateInstancePlatformKHR( + cl_platform_id platform, + const cl_instance_platform_properties_khr *properties, + cl_int *errcode_ret) +{ + (void)properties; + if (!platform || platform->dispatch != dispatchTable) { + *errcode_ret = CL_INVALID_PLATFORM; + return NULL; + } + cl_platform_id platform_ret = createPlatform(); + platform_ret->instance = CL_TRUE; + if (errcode_ret) { + *errcode_ret = CL_SUCCESS; + } + return platform_ret; +} + +CL_API_ENTRY cl_int CL_API_CALL +clIcdDestroyInstancePlatformKHR( + cl_platform_id platform) +{ + if (!platform || platform->dispatch != dispatchTable || !platform->instance) + return CL_INVALID_PLATFORM; + destroyPlatform(platform); + return CL_SUCCESS; +} +#endif + static void deinit(void) { if (initialized) { - free(stub_platform->device); - stub_platform->device = NULL; - free(stub_platform); + destroyPlatform(stub_platform); stub_platform = NULL; cliIcdDispatchTableDestroy(dispatchTable); dispatchTable = NULL; diff --git a/test/driver_stub/cl_ext.c b/test/driver_stub/cl_ext.c index b412f934..4caf4c4d 100644 --- a/test/driver_stub/cl_ext.c +++ b/test/driver_stub/cl_ext.c @@ -8,6 +8,8 @@ #if defined(CL_ENABLE_ICD2) CL_API_ENTRY clIcdGetFunctionAddressForPlatformKHR_t clIcdGetFunctionAddressForPlatformKHR; CL_API_ENTRY clIcdSetPlatformDispatchDataKHR_t clIcdSetPlatformDispatchDataKHR; +CL_API_ENTRY clIcdCreateInstancePlatformKHR_t clIcdCreateInstancePlatformKHR; +CL_API_ENTRY clIcdDestroyInstancePlatformKHR_t clIcdDestroyInstancePlatformKHR; #endif struct driverStubextFunc_st @@ -24,6 +26,8 @@ static struct driverStubextFunc_st clExtensions[] = #ifdef CL_ENABLE_ICD2 EXT_FUNC(clIcdGetFunctionAddressForPlatformKHR), EXT_FUNC(clIcdSetPlatformDispatchDataKHR), + EXT_FUNC(clIcdCreateInstancePlatformKHR), + EXT_FUNC(clIcdDestroyInstancePlatformKHR), #endif //CL_ENABLE_ICD2 };