xref: /aosp_15_r20/external/OpenCL-CTS/test_conformance/common/vulkan_wrapper/opencl_vulkan_wrapper.cpp (revision 6467f958c7de8070b317fc65bcb0f6472e388d82)
1 //
2 // Copyright (c) 2022 The Khronos Group Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //    http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 #include <CL/cl_ext.h>
17 #include "opencl_vulkan_wrapper.hpp"
18 #include "vulkan_wrapper.hpp"
19 #include "harness/errorHelpers.h"
20 #include "harness/deviceInfo.h"
21 #include <assert.h>
22 #include <algorithm>
23 #include <stdexcept>
24 
25 #define ASSERT(x) assert((x))
26 #define GB(x) ((unsigned long long)(x) << 30)
27 
28 pfnclCreateSemaphoreWithPropertiesKHR clCreateSemaphoreWithPropertiesKHRptr;
29 pfnclEnqueueWaitSemaphoresKHR clEnqueueWaitSemaphoresKHRptr;
30 pfnclEnqueueSignalSemaphoresKHR clEnqueueSignalSemaphoresKHRptr;
31 pfnclEnqueueAcquireExternalMemObjectsKHR
32     clEnqueueAcquireExternalMemObjectsKHRptr;
33 pfnclEnqueueReleaseExternalMemObjectsKHR
34     clEnqueueReleaseExternalMemObjectsKHRptr;
35 pfnclReleaseSemaphoreKHR clReleaseSemaphoreKHRptr;
36 
init_cl_vk_ext(cl_platform_id opencl_platform)37 void init_cl_vk_ext(cl_platform_id opencl_platform)
38 {
39     clEnqueueWaitSemaphoresKHRptr =
40         (pfnclEnqueueWaitSemaphoresKHR)clGetExtensionFunctionAddressForPlatform(
41             opencl_platform, "clEnqueueWaitSemaphoresKHR");
42     if (NULL == clEnqueueWaitSemaphoresKHRptr)
43     {
44         throw std::runtime_error("Failed to get the function pointer of "
45                                  "clEnqueueWaitSemaphoresKHRptr!");
46     }
47     clEnqueueSignalSemaphoresKHRptr = (pfnclEnqueueSignalSemaphoresKHR)
48         clGetExtensionFunctionAddressForPlatform(
49             opencl_platform, "clEnqueueSignalSemaphoresKHR");
50     if (NULL == clEnqueueSignalSemaphoresKHRptr)
51     {
52         throw std::runtime_error("Failed to get the function pointer of "
53                                  "clEnqueueSignalSemaphoresKHRptr!");
54     }
55     clReleaseSemaphoreKHRptr =
56         (pfnclReleaseSemaphoreKHR)clGetExtensionFunctionAddressForPlatform(
57             opencl_platform, "clReleaseSemaphoreKHR");
58     if (NULL == clReleaseSemaphoreKHRptr)
59     {
60         throw std::runtime_error("Failed to get the function pointer of "
61                                  "clReleaseSemaphoreKHRptr!");
62     }
63     clCreateSemaphoreWithPropertiesKHRptr =
64         (pfnclCreateSemaphoreWithPropertiesKHR)
65             clGetExtensionFunctionAddressForPlatform(
66                 opencl_platform, "clCreateSemaphoreWithPropertiesKHR");
67     if (NULL == clCreateSemaphoreWithPropertiesKHRptr)
68     {
69         throw std::runtime_error("Failed to get the function pointer of "
70                                  "clCreateSemaphoreWithPropertiesKHRptr!");
71     }
72 }
73 
setMaxImageDimensions(cl_device_id deviceID,size_t & max_width,size_t & max_height)74 cl_int setMaxImageDimensions(cl_device_id deviceID, size_t &max_width,
75                              size_t &max_height)
76 {
77     cl_int result = CL_SUCCESS;
78     cl_ulong val;
79     size_t paramSize;
80 
81     result = clGetDeviceInfo(deviceID, CL_DEVICE_GLOBAL_MEM_SIZE,
82                              sizeof(cl_ulong), &val, &paramSize);
83 
84     if (result != CL_SUCCESS)
85     {
86         return result;
87     }
88 
89     if (val < GB(4))
90     {
91         max_width = 256;
92         max_height = 256;
93     }
94     else if (val < GB(8))
95     {
96         max_width = 512;
97         max_height = 256;
98     }
99     else
100     {
101         max_width = 1024;
102         max_height = 512;
103     }
104 
105     return result;
106 }
107 
getCLFormatFromVkFormat(VkFormat vkFormat,cl_image_format * clImageFormat)108 cl_int getCLFormatFromVkFormat(VkFormat vkFormat,
109                                cl_image_format *clImageFormat)
110 {
111     cl_int result = CL_SUCCESS;
112     switch (vkFormat)
113     {
114         case VK_FORMAT_R8G8B8A8_UNORM:
115             clImageFormat->image_channel_order = CL_RGBA;
116             clImageFormat->image_channel_data_type = CL_UNORM_INT8;
117             break;
118         case VK_FORMAT_B8G8R8A8_UNORM:
119             clImageFormat->image_channel_order = CL_BGRA;
120             clImageFormat->image_channel_data_type = CL_UNORM_INT8;
121             break;
122         case VK_FORMAT_R16G16B16A16_UNORM:
123             clImageFormat->image_channel_order = CL_RGBA;
124             clImageFormat->image_channel_data_type = CL_UNORM_INT16;
125             break;
126         case VK_FORMAT_R8G8B8A8_SINT:
127             clImageFormat->image_channel_order = CL_RGBA;
128             clImageFormat->image_channel_data_type = CL_SIGNED_INT8;
129             break;
130         case VK_FORMAT_R16G16B16A16_SINT:
131             clImageFormat->image_channel_order = CL_RGBA;
132             clImageFormat->image_channel_data_type = CL_SIGNED_INT16;
133             break;
134         case VK_FORMAT_R32G32B32A32_SINT:
135             clImageFormat->image_channel_order = CL_RGBA;
136             clImageFormat->image_channel_data_type = CL_SIGNED_INT32;
137             break;
138         case VK_FORMAT_R8G8B8A8_UINT:
139             clImageFormat->image_channel_order = CL_RGBA;
140             clImageFormat->image_channel_data_type = CL_UNSIGNED_INT8;
141             break;
142         case VK_FORMAT_R16G16B16A16_UINT:
143             clImageFormat->image_channel_order = CL_RGBA;
144             clImageFormat->image_channel_data_type = CL_UNSIGNED_INT16;
145             break;
146         case VK_FORMAT_R32G32B32A32_UINT:
147             clImageFormat->image_channel_order = CL_RGBA;
148             clImageFormat->image_channel_data_type = CL_UNSIGNED_INT32;
149             break;
150         case VK_FORMAT_R16G16B16A16_SFLOAT:
151             clImageFormat->image_channel_order = CL_RGBA;
152             clImageFormat->image_channel_data_type = CL_HALF_FLOAT;
153             break;
154         case VK_FORMAT_R32G32B32A32_SFLOAT:
155             clImageFormat->image_channel_order = CL_RGBA;
156             clImageFormat->image_channel_data_type = CL_FLOAT;
157             break;
158         case VK_FORMAT_R8_SNORM:
159             clImageFormat->image_channel_order = CL_R;
160             clImageFormat->image_channel_data_type = CL_SNORM_INT8;
161             break;
162         case VK_FORMAT_R16_SNORM:
163             clImageFormat->image_channel_order = CL_R;
164             clImageFormat->image_channel_data_type = CL_SNORM_INT16;
165             break;
166         case VK_FORMAT_R8_UNORM:
167             clImageFormat->image_channel_order = CL_R;
168             clImageFormat->image_channel_data_type = CL_UNORM_INT8;
169             break;
170         case VK_FORMAT_R16_UNORM:
171             clImageFormat->image_channel_order = CL_R;
172             clImageFormat->image_channel_data_type = CL_UNORM_INT16;
173             break;
174         case VK_FORMAT_R8_SINT:
175             clImageFormat->image_channel_order = CL_R;
176             clImageFormat->image_channel_data_type = CL_SIGNED_INT8;
177             break;
178         case VK_FORMAT_R16_SINT:
179             clImageFormat->image_channel_order = CL_R;
180             clImageFormat->image_channel_data_type = CL_SIGNED_INT16;
181             break;
182         case VK_FORMAT_R32_SINT:
183             clImageFormat->image_channel_order = CL_R;
184             clImageFormat->image_channel_data_type = CL_SIGNED_INT32;
185             break;
186         case VK_FORMAT_R8_UINT:
187             clImageFormat->image_channel_order = CL_R;
188             clImageFormat->image_channel_data_type = CL_UNSIGNED_INT8;
189             break;
190         case VK_FORMAT_R16_UINT:
191             clImageFormat->image_channel_order = CL_R;
192             clImageFormat->image_channel_data_type = CL_UNSIGNED_INT16;
193             break;
194         case VK_FORMAT_R32_UINT:
195             clImageFormat->image_channel_order = CL_R;
196             clImageFormat->image_channel_data_type = CL_UNSIGNED_INT32;
197             break;
198         case VK_FORMAT_R16_SFLOAT:
199             clImageFormat->image_channel_order = CL_R;
200             clImageFormat->image_channel_data_type = CL_HALF_FLOAT;
201             break;
202         case VK_FORMAT_R32_SFLOAT:
203             clImageFormat->image_channel_order = CL_R;
204             clImageFormat->image_channel_data_type = CL_FLOAT;
205             break;
206         case VK_FORMAT_R8G8_SNORM:
207             clImageFormat->image_channel_order = CL_RG;
208             clImageFormat->image_channel_data_type = CL_SNORM_INT8;
209             break;
210         case VK_FORMAT_R16G16_SNORM:
211             clImageFormat->image_channel_order = CL_RG;
212             clImageFormat->image_channel_data_type = CL_SNORM_INT16;
213             break;
214         case VK_FORMAT_R8G8_UNORM:
215             clImageFormat->image_channel_order = CL_RG;
216             clImageFormat->image_channel_data_type = CL_UNORM_INT8;
217             break;
218         case VK_FORMAT_R16G16_UNORM:
219             clImageFormat->image_channel_order = CL_RG;
220             clImageFormat->image_channel_data_type = CL_UNORM_INT16;
221             break;
222         case VK_FORMAT_R8G8_SINT:
223             clImageFormat->image_channel_order = CL_RG;
224             clImageFormat->image_channel_data_type = CL_SIGNED_INT8;
225             break;
226         case VK_FORMAT_R16G16_SINT:
227             clImageFormat->image_channel_order = CL_RG;
228             clImageFormat->image_channel_data_type = CL_SIGNED_INT16;
229             break;
230         case VK_FORMAT_R32G32_SINT:
231             clImageFormat->image_channel_order = CL_RG;
232             clImageFormat->image_channel_data_type = CL_SIGNED_INT32;
233             break;
234         case VK_FORMAT_R8G8_UINT:
235             clImageFormat->image_channel_order = CL_RG;
236             clImageFormat->image_channel_data_type = CL_UNSIGNED_INT8;
237             break;
238         case VK_FORMAT_R16G16_UINT:
239             clImageFormat->image_channel_order = CL_RG;
240             clImageFormat->image_channel_data_type = CL_UNSIGNED_INT16;
241             break;
242         case VK_FORMAT_R32G32_UINT:
243             clImageFormat->image_channel_order = CL_RG;
244             clImageFormat->image_channel_data_type = CL_UNSIGNED_INT32;
245             break;
246         case VK_FORMAT_R16G16_SFLOAT:
247             clImageFormat->image_channel_order = CL_RG;
248             clImageFormat->image_channel_data_type = CL_HALF_FLOAT;
249             break;
250         case VK_FORMAT_R32G32_SFLOAT:
251             clImageFormat->image_channel_order = CL_RG;
252             clImageFormat->image_channel_data_type = CL_FLOAT;
253             break;
254         case VK_FORMAT_R5G6B5_UNORM_PACK16:
255             clImageFormat->image_channel_order = CL_RGBA;
256             clImageFormat->image_channel_data_type = CL_UNORM_SHORT_565;
257             break;
258         case VK_FORMAT_R5G5B5A1_UNORM_PACK16:
259             clImageFormat->image_channel_order = CL_RGBA;
260             clImageFormat->image_channel_data_type = CL_UNORM_SHORT_555;
261             break;
262         case VK_FORMAT_R8G8B8A8_SNORM:
263             clImageFormat->image_channel_order = CL_RGBA;
264             clImageFormat->image_channel_data_type = CL_SNORM_INT8;
265             break;
266         case VK_FORMAT_R16G16B16A16_SNORM:
267             clImageFormat->image_channel_order = CL_RGBA;
268             clImageFormat->image_channel_data_type = CL_SNORM_INT16;
269             break;
270         case VK_FORMAT_B8G8R8A8_SNORM:
271             clImageFormat->image_channel_order = CL_BGRA;
272             clImageFormat->image_channel_data_type = CL_SNORM_INT8;
273             break;
274         case VK_FORMAT_B5G6R5_UNORM_PACK16:
275             clImageFormat->image_channel_order = CL_BGRA;
276             clImageFormat->image_channel_data_type = CL_UNORM_SHORT_565;
277             break;
278         case VK_FORMAT_B5G5R5A1_UNORM_PACK16:
279             clImageFormat->image_channel_order = CL_BGRA;
280             clImageFormat->image_channel_data_type = CL_UNORM_SHORT_555;
281             break;
282         case VK_FORMAT_B8G8R8A8_SINT:
283             clImageFormat->image_channel_order = CL_BGRA;
284             clImageFormat->image_channel_data_type = CL_SIGNED_INT8;
285             break;
286         case VK_FORMAT_B8G8R8A8_UINT:
287             clImageFormat->image_channel_order = CL_BGRA;
288             clImageFormat->image_channel_data_type = CL_UNSIGNED_INT8;
289             break;
290         case VK_FORMAT_A8B8G8R8_SNORM_PACK32: result = CL_INVALID_VALUE; break;
291         case VK_FORMAT_A8B8G8R8_UNORM_PACK32: result = CL_INVALID_VALUE; break;
292         case VK_FORMAT_A8B8G8R8_SINT_PACK32: result = CL_INVALID_VALUE; break;
293         case VK_FORMAT_A8B8G8R8_UINT_PACK32: result = CL_INVALID_VALUE; break;
294         default:
295             log_error("Unsupported format\n");
296             ASSERT(0);
297             break;
298     }
299     return result;
300 }
301 
getImageTypeFromVk(VkImageType imageType)302 cl_mem_object_type getImageTypeFromVk(VkImageType imageType)
303 {
304     cl_mem_object_type cl_image_type = CL_INVALID_VALUE;
305     switch (imageType)
306     {
307         case VK_IMAGE_TYPE_1D: cl_image_type = CL_MEM_OBJECT_IMAGE1D; break;
308         case VK_IMAGE_TYPE_2D: cl_image_type = CL_MEM_OBJECT_IMAGE2D; break;
309         case VK_IMAGE_TYPE_3D: cl_image_type = CL_MEM_OBJECT_IMAGE3D; break;
310         default: break;
311     }
312     return cl_image_type;
313 }
314 
GetElementNBytes(const cl_image_format * format)315 size_t GetElementNBytes(const cl_image_format *format)
316 {
317     size_t result;
318 
319     switch (format->image_channel_order)
320     {
321         case CL_R:
322         case CL_A:
323         case CL_INTENSITY:
324         case CL_LUMINANCE:
325         case CL_DEPTH: result = 1; break;
326         case CL_RG:
327         case CL_RA: result = 2; break;
328         case CL_RGB: result = 3; break;
329         case CL_RGBA:
330         case CL_ARGB:
331         case CL_BGRA:
332         case CL_sRGBA: result = 4; break;
333         default: result = 0; break;
334     }
335 
336     switch (format->image_channel_data_type)
337     {
338         case CL_SNORM_INT8:
339         case CL_UNORM_INT8:
340         case CL_SIGNED_INT8:
341         case CL_UNSIGNED_INT8:
342             // result *= 1;
343             break;
344 
345         case CL_SNORM_INT16:
346         case CL_UNORM_INT16:
347         case CL_SIGNED_INT16:
348         case CL_UNSIGNED_INT16:
349         case CL_HALF_FLOAT: result *= 2; break;
350 
351         case CL_SIGNED_INT32:
352         case CL_UNSIGNED_INT32:
353         case CL_FLOAT: result *= 4; break;
354 
355         case CL_UNORM_SHORT_565:
356         case CL_UNORM_SHORT_555:
357             if (result == 3)
358             {
359                 result = 2;
360             }
361             else
362             {
363                 result = 0;
364             }
365             break;
366 
367         case CL_UNORM_INT_101010:
368             if (result == 3)
369             {
370                 result = 4;
371             }
372             else
373             {
374                 result = 0;
375             }
376             break;
377 
378         default: result = 0; break;
379     }
380 
381     return result;
382 }
383 
get2DImageDimensions(const VkImageCreateInfo * VulkanImageCreateInfo,cl_image_format * img_fmt,size_t totalImageSize,size_t & width,size_t & height)384 cl_int get2DImageDimensions(const VkImageCreateInfo *VulkanImageCreateInfo,
385                             cl_image_format *img_fmt, size_t totalImageSize,
386                             size_t &width, size_t &height)
387 {
388     cl_int result = CL_SUCCESS;
389     if (totalImageSize == 0)
390     {
391         result = CL_INVALID_VALUE;
392     }
393     size_t element_size = GetElementNBytes(img_fmt);
394     size_t row_pitch = element_size * VulkanImageCreateInfo->extent.width;
395     row_pitch = row_pitch % 64 == 0 ? row_pitch : ((row_pitch / 64) + 1) * 64;
396 
397     width = row_pitch / element_size;
398     height = totalImageSize / row_pitch;
399 
400     return result;
401 }
402 
403 cl_int
getCLImageInfoFromVkImageInfo(const VkImageCreateInfo * VulkanImageCreateInfo,size_t totalImageSize,cl_image_format * img_fmt,cl_image_desc * img_desc)404 getCLImageInfoFromVkImageInfo(const VkImageCreateInfo *VulkanImageCreateInfo,
405                               size_t totalImageSize, cl_image_format *img_fmt,
406                               cl_image_desc *img_desc)
407 {
408     cl_int result = CL_SUCCESS;
409 
410     cl_image_format clImgFormat = { 0 };
411     result =
412         getCLFormatFromVkFormat(VulkanImageCreateInfo->format, &clImgFormat);
413     if (CL_SUCCESS != result)
414     {
415         return result;
416     }
417     memcpy(img_fmt, &clImgFormat, sizeof(cl_image_format));
418 
419     img_desc->image_type = getImageTypeFromVk(VulkanImageCreateInfo->imageType);
420     if (CL_INVALID_VALUE == img_desc->image_type)
421     {
422         return CL_INVALID_VALUE;
423     }
424 
425     result =
426         get2DImageDimensions(VulkanImageCreateInfo, img_fmt, totalImageSize,
427                              img_desc->image_width, img_desc->image_height);
428     if (CL_SUCCESS != result)
429     {
430         throw std::runtime_error("get2DImageDimensions failed!!!");
431     }
432 
433     img_desc->image_depth = 0; // VulkanImageCreateInfo->extent.depth;
434     img_desc->image_array_size = 0;
435     img_desc->image_row_pitch = 0; // Row pitch set to zero as host_ptr is NULL
436     img_desc->image_slice_pitch =
437         img_desc->image_row_pitch * img_desc->image_height;
438     img_desc->num_mip_levels = 1;
439     img_desc->num_samples = 0;
440     img_desc->buffer = NULL;
441 
442     return result;
443 }
444 
check_external_memory_handle_type(cl_device_id deviceID,cl_external_memory_handle_type_khr requiredHandleType)445 cl_int check_external_memory_handle_type(
446     cl_device_id deviceID,
447     cl_external_memory_handle_type_khr requiredHandleType)
448 {
449     unsigned int i;
450     cl_external_memory_handle_type_khr *handle_type;
451     size_t handle_type_size = 0;
452 
453     cl_int errNum = CL_SUCCESS;
454 
455     errNum = clGetDeviceInfo(deviceID,
456                              CL_DEVICE_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR,
457                              0, NULL, &handle_type_size);
458     handle_type =
459         (cl_external_memory_handle_type_khr *)malloc(handle_type_size);
460 
461     errNum = clGetDeviceInfo(deviceID,
462                              CL_DEVICE_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR,
463                              handle_type_size, handle_type, NULL);
464 
465     test_error(
466         errNum,
467         "Unable to query CL_DEVICE_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR \n");
468 
469     for (i = 0; i < handle_type_size; i++)
470     {
471         if (requiredHandleType == handle_type[i])
472         {
473             return CL_SUCCESS;
474         }
475     }
476     log_error("cl_khr_external_memory extension is missing support for %d\n",
477               requiredHandleType);
478 
479     return CL_INVALID_VALUE;
480 }
481 
check_external_semaphore_handle_type(cl_device_id deviceID,cl_external_semaphore_handle_type_khr requiredHandleType)482 cl_int check_external_semaphore_handle_type(
483     cl_device_id deviceID,
484     cl_external_semaphore_handle_type_khr requiredHandleType)
485 {
486     unsigned int i;
487     cl_external_semaphore_handle_type_khr *handle_type;
488     size_t handle_type_size = 0;
489     cl_int errNum = CL_SUCCESS;
490 
491     errNum =
492         clGetDeviceInfo(deviceID, CL_DEVICE_SEMAPHORE_IMPORT_HANDLE_TYPES_KHR,
493                         0, NULL, &handle_type_size);
494     handle_type =
495         (cl_external_semaphore_handle_type_khr *)malloc(handle_type_size);
496 
497     errNum =
498         clGetDeviceInfo(deviceID, CL_DEVICE_SEMAPHORE_IMPORT_HANDLE_TYPES_KHR,
499                         handle_type_size, handle_type, NULL);
500 
501     test_error(
502         errNum,
503         "Unable to query CL_DEVICE_SEMAPHORE_IMPORT_HANDLE_TYPES_KHR \n");
504 
505     for (i = 0; i < handle_type_size; i++)
506     {
507         if (requiredHandleType == handle_type[i])
508         {
509             return CL_SUCCESS;
510         }
511     }
512     log_error("cl_khr_external_semaphore extension is missing support for %d\n",
513               requiredHandleType);
514 
515     return CL_INVALID_VALUE;
516 }
clExternalMemory()517 clExternalMemory::clExternalMemory() {}
518 
clExternalMemory(const clExternalMemory & externalMemory)519 clExternalMemory::clExternalMemory(const clExternalMemory &externalMemory)
520     : m_externalMemory(externalMemory.m_externalMemory)
521 {}
522 
clExternalMemory(const VulkanDeviceMemory * deviceMemory,VulkanExternalMemoryHandleType externalMemoryHandleType,uint64_t offset,uint64_t size,cl_context context,cl_device_id deviceId)523 clExternalMemory::clExternalMemory(
524     const VulkanDeviceMemory *deviceMemory,
525     VulkanExternalMemoryHandleType externalMemoryHandleType, uint64_t offset,
526     uint64_t size, cl_context context, cl_device_id deviceId)
527 {
528     int err = 0;
529     m_externalMemory = NULL;
530     cl_device_id devList[] = { deviceId, NULL };
531     std::vector<cl_mem_properties> extMemProperties;
532 #ifdef _WIN32
533     if (!is_extension_available(devList[0], "cl_khr_external_memory_win32"))
534     {
535         throw std::runtime_error(
536             "Device does not support cl_khr_external_memory_win32 extension\n");
537     }
538 #else
539     if (!is_extension_available(devList[0], "cl_khr_external_memory_opaque_fd"))
540     {
541         throw std::runtime_error(
542             "Device does not support cl_khr_external_memory_opaque_fd "
543             "extension \n");
544     }
545 #endif
546 
547     switch (externalMemoryHandleType)
548     {
549         case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD:
550 #ifdef _WIN32
551             ASSERT(0);
552 #endif
553             log_info("Opaque file descriptors are not supported on Windows\n");
554             fd = (int)deviceMemory->getHandle(externalMemoryHandleType);
555             err = check_external_memory_handle_type(
556                 devList[0], CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR);
557             extMemProperties.push_back(
558                 (cl_mem_properties)CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR);
559             extMemProperties.push_back((cl_mem_properties)fd);
560             break;
561         case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT:
562 #ifndef _WIN32
563             ASSERT(0);
564 #else
565             log_info(" Opaque NT handles are only supported on Windows\n");
566             handle = deviceMemory->getHandle(externalMemoryHandleType);
567             err = check_external_memory_handle_type(
568                 devList[0], CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KHR);
569             extMemProperties.push_back(
570                 (cl_mem_properties)CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KHR);
571             extMemProperties.push_back((cl_mem_properties)handle);
572 #endif
573             break;
574         case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT:
575 #ifndef _WIN32
576             ASSERT(0);
577 #else
578             log_info("Opaque D3DKMT handles are only supported on Windows\n");
579             handle = deviceMemory->getHandle(externalMemoryHandleType);
580             err = check_external_memory_handle_type(
581                 devList[0], CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR);
582             extMemProperties.push_back(
583                 (cl_mem_properties)
584                     CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR);
585             extMemProperties.push_back((cl_mem_properties)handle);
586 #endif
587             break;
588         default:
589             ASSERT(0);
590             log_error("Unsupported external memory handle type\n");
591             break;
592     }
593     if (CL_SUCCESS != err)
594     {
595         throw std::runtime_error("Unsupported external memory type\n ");
596     }
597 
598     extMemProperties.push_back((cl_mem_properties)CL_DEVICE_HANDLE_LIST_KHR);
599     extMemProperties.push_back((cl_mem_properties)devList[0]);
600     extMemProperties.push_back(
601         (cl_mem_properties)CL_DEVICE_HANDLE_LIST_END_KHR);
602     extMemProperties.push_back(0);
603 
604     m_externalMemory = clCreateBufferWithProperties(
605         context, extMemProperties.data(), 1, size, NULL, &err);
606     if (CL_SUCCESS != err)
607     {
608         log_error("clCreateBufferWithProperties failed with %d\n", err);
609         throw std::runtime_error("clCreateBufferWithProperties failed ");
610     }
611 }
clExternalMemoryImage(const VulkanDeviceMemory & deviceMemory,VulkanExternalMemoryHandleType externalMemoryHandleType,cl_context context,size_t totalImageMemSize,size_t imageWidth,size_t imageHeight,size_t totalSize,const VulkanImage2D & image2D,cl_device_id deviceId)612 clExternalMemoryImage::clExternalMemoryImage(
613     const VulkanDeviceMemory &deviceMemory,
614     VulkanExternalMemoryHandleType externalMemoryHandleType, cl_context context,
615     size_t totalImageMemSize, size_t imageWidth, size_t imageHeight,
616     size_t totalSize, const VulkanImage2D &image2D, cl_device_id deviceId)
617 {
618     cl_int errcode_ret = 0;
619     std::vector<cl_mem_properties> extMemProperties1;
620     cl_device_id devList[] = { deviceId, NULL };
621 
622 #ifdef _WIN32
623     if (!is_extension_available(devList[0], "cl_khr_external_memory_win32"))
624     {
625         throw std::runtime_error("Device does not support "
626                                  "cl_khr_external_memory_win32 extension \n");
627     }
628 #elif !defined(__APPLE__)
629     if (!is_extension_available(devList[0], "cl_khr_external_memory_opaque_fd"))
630     {
631         throw std::runtime_error(
632             "Device does not support cl_khr_external_memory_opaque_fd "
633             "extension\n");
634     }
635 #endif
636 
637     switch (externalMemoryHandleType)
638     {
639 #ifdef _WIN32
640         case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT:
641             log_info("Opaque NT handles are only supported on Windows\n");
642             handle = deviceMemory.getHandle(externalMemoryHandleType);
643             errcode_ret = check_external_memory_handle_type(
644                 devList[0], CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KHR);
645             extMemProperties1.push_back(
646                 (cl_mem_properties)CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KHR);
647             extMemProperties1.push_back((cl_mem_properties)handle);
648             break;
649         case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT:
650             log_info("Opaque D3DKMT handles are only supported on Windows\n");
651             handle = deviceMemory.getHandle(externalMemoryHandleType);
652             errcode_ret = check_external_memory_handle_type(
653                 devList[0], CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR);
654             extMemProperties1.push_back(
655                 (cl_mem_properties)
656                     CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR);
657             extMemProperties1.push_back((cl_mem_properties)handle);
658             break;
659 #elif !defined(__APPLE__)
660         case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD:
661             log_info(" Opaque file descriptors are not supported on Windows\n");
662             fd = (int)deviceMemory.getHandle(externalMemoryHandleType);
663             errcode_ret = check_external_memory_handle_type(
664                 devList[0], CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR);
665             extMemProperties1.push_back(
666                 (cl_mem_properties)CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR);
667             extMemProperties1.push_back((cl_mem_properties)fd);
668             break;
669 #endif
670         default:
671             ASSERT(0);
672             log_error("Unsupported external memory handle type\n");
673             break;
674     }
675     if (CL_SUCCESS != errcode_ret)
676     {
677         throw std::runtime_error("Unsupported external memory type\n ");
678     }
679     // Set cl_image_desc
680     size_t clImageFormatSize;
681     cl_image_desc image_desc;
682     memset(&image_desc, 0x0, sizeof(cl_image_desc));
683     cl_image_format img_format = { 0 };
684     const VkImageCreateInfo VulkanImageCreateInfo =
685         image2D.getVkImageCreateInfo();
686 
687     errcode_ret = getCLImageInfoFromVkImageInfo(
688         &VulkanImageCreateInfo, image2D.getSize(), &img_format, &image_desc);
689     if (CL_SUCCESS != errcode_ret)
690     {
691         throw std::runtime_error("getCLImageInfoFromVkImageInfo failed!!!");
692     }
693 
694     extMemProperties1.push_back((cl_mem_properties)CL_DEVICE_HANDLE_LIST_KHR);
695     extMemProperties1.push_back((cl_mem_properties)devList[0]);
696     extMemProperties1.push_back(
697         (cl_mem_properties)CL_DEVICE_HANDLE_LIST_END_KHR);
698     extMemProperties1.push_back(0);
699     m_externalMemory = clCreateImageWithProperties(
700         context, extMemProperties1.data(), CL_MEM_READ_WRITE, &img_format,
701         &image_desc, NULL, &errcode_ret);
702     if (CL_SUCCESS != errcode_ret)
703     {
704         throw std::runtime_error("clCreateImageWithProperties failed!!!");
705     }
706 }
707 
getExternalMemoryBuffer()708 cl_mem clExternalMemory::getExternalMemoryBuffer() { return m_externalMemory; }
709 
getExternalMemoryImage()710 cl_mem clExternalMemoryImage::getExternalMemoryImage()
711 {
712     return m_externalMemory;
713 }
714 
~clExternalMemoryImage()715 clExternalMemoryImage::~clExternalMemoryImage()
716 {
717     clReleaseMemObject(m_externalMemory);
718 }
719 
~clExternalMemory()720 clExternalMemory::~clExternalMemory() { clReleaseMemObject(m_externalMemory); }
721 
clExternalMemoryImage()722 clExternalMemoryImage::clExternalMemoryImage() {}
723 
724 
725 //////////////////////////////////////////
726 // clExternalSemaphore implementation //
727 //////////////////////////////////////////
728 
clExternalSemaphore(const clExternalSemaphore & externalSemaphore)729 clExternalSemaphore::clExternalSemaphore(
730     const clExternalSemaphore &externalSemaphore)
731     : m_externalSemaphore(externalSemaphore.m_externalSemaphore)
732 {}
733 
clExternalSemaphore(const VulkanSemaphore & semaphore,cl_context context,VulkanExternalSemaphoreHandleType externalSemaphoreHandleType,cl_device_id deviceId)734 clExternalSemaphore::clExternalSemaphore(
735     const VulkanSemaphore &semaphore, cl_context context,
736     VulkanExternalSemaphoreHandleType externalSemaphoreHandleType,
737     cl_device_id deviceId)
738 {
739 
740     cl_int err = 0;
741     cl_device_id devList[] = { deviceId, NULL };
742 
743     switch (externalSemaphoreHandleType)
744     {
745         case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD:
746             if (!is_extension_available(devList[0],
747                                         "cl_khr_external_semaphore_opaque_fd"))
748             {
749                 throw std::runtime_error("Device does not support "
750                                          "cl_khr_external_semaphore_opaque_fd "
751                                          "extension \n");
752             }
753             break;
754         case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_NT:
755         case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT:
756         case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_NT_KMT:
757             if (!is_extension_available(devList[0],
758                                         "cl_khr_external_semaphore_win32"))
759             {
760                 throw std::runtime_error(
761                     "Device does not support "
762                     "cl_khr_external_semaphore_win32 extension\n");
763             }
764             break;
765         case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD:
766             if (!is_extension_available(devList[0],
767                                         "cl_khr_external_semaphore_sync_fd"))
768             {
769                 throw std::runtime_error(
770                     "Device does not support cl_khr_external_semaphore_sync_fd "
771                     "extension \n");
772             }
773             break;
774         default:
775             throw std::runtime_error(
776                 "Unsupported external semaphore handle type\n");
777             break;
778     }
779 
780     std::vector<cl_semaphore_properties_khr> sema_props{
781         (cl_semaphore_properties_khr)CL_SEMAPHORE_TYPE_KHR,
782         (cl_semaphore_properties_khr)CL_SEMAPHORE_TYPE_BINARY_KHR,
783     };
784     switch (externalSemaphoreHandleType)
785     {
786         case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD:
787 #ifdef _WIN32
788             ASSERT(0);
789 #else
790             log_info(" Opaque file descriptors are not supported on Windows\n");
791             fd = (int)semaphore.getHandle(externalSemaphoreHandleType);
792             err = check_external_semaphore_handle_type(
793                 devList[0], CL_SEMAPHORE_HANDLE_OPAQUE_FD_KHR);
794             sema_props.push_back(
795                 (cl_semaphore_properties_khr)CL_SEMAPHORE_HANDLE_OPAQUE_FD_KHR);
796             sema_props.push_back((cl_semaphore_properties_khr)fd);
797 #endif
798             break;
799         case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_NT:
800 #ifndef _WIN32
801             ASSERT(0);
802 #else
803             log_info(" Opaque NT handles are only supported on Windows\n");
804             handle = semaphore.getName().size()
805                 ? NULL
806                 : semaphore.getHandle(externalSemaphoreHandleType);
807             err = check_external_semaphore_handle_type(
808                 devList[0], CL_SEMAPHORE_HANDLE_OPAQUE_WIN32_KHR);
809             sema_props.push_back((cl_semaphore_properties_khr)
810                                      CL_SEMAPHORE_HANDLE_OPAQUE_WIN32_KHR);
811             sema_props.push_back((cl_semaphore_properties_khr)handle);
812 #endif
813             break;
814         case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT:
815 #ifndef _WIN32
816             ASSERT(0);
817 #else
818             log_info(" Opaque D3DKMT handles are only supported on Windows\n");
819             handle = semaphore.getHandle(externalSemaphoreHandleType);
820             err = check_external_semaphore_handle_type(
821                 devList[0], CL_SEMAPHORE_HANDLE_OPAQUE_WIN32_KMT_KHR);
822             sema_props.push_back((cl_semaphore_properties_khr)
823                                      CL_SEMAPHORE_HANDLE_OPAQUE_WIN32_KMT_KHR);
824             sema_props.push_back((cl_semaphore_properties_khr)handle);
825 #endif
826             break;
827         case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD:
828             err = check_external_semaphore_handle_type(
829                 devList[0], CL_SEMAPHORE_HANDLE_SYNC_FD_KHR);
830             sema_props.push_back(static_cast<cl_semaphore_properties_khr>(
831                 CL_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR));
832             sema_props.push_back(static_cast<cl_semaphore_properties_khr>(
833                 CL_SEMAPHORE_HANDLE_SYNC_FD_KHR));
834             sema_props.push_back(static_cast<cl_semaphore_properties_khr>(
835                 CL_SEMAPHORE_EXPORT_HANDLE_TYPES_LIST_END_KHR));
836             break;
837         default:
838             ASSERT(0);
839             log_error("Unsupported external memory handle type\n");
840             break;
841     }
842     if (CL_SUCCESS != err)
843     {
844         throw std::runtime_error(
845             "Unsupported external sempahore handle type\n ");
846     }
847 
848     sema_props.push_back(
849         (cl_semaphore_properties_khr)CL_DEVICE_HANDLE_LIST_KHR);
850     sema_props.push_back((cl_semaphore_properties_khr)devList[0]);
851     sema_props.push_back(
852         (cl_semaphore_properties_khr)CL_DEVICE_HANDLE_LIST_END_KHR);
853     sema_props.push_back(0);
854     m_externalSemaphore =
855         clCreateSemaphoreWithPropertiesKHRptr(context, sema_props.data(), &err);
856     if (CL_SUCCESS != err)
857     {
858         log_error("clCreateSemaphoreWithPropertiesKHRptr failed with %d\n",
859                   err);
860         throw std::runtime_error(
861             "clCreateSemaphoreWithPropertiesKHRptr failed! ");
862     }
863 }
864 
~clExternalSemaphore()865 clExternalSemaphore::~clExternalSemaphore() noexcept(false)
866 {
867     cl_int err = clReleaseSemaphoreKHRptr(m_externalSemaphore);
868     if (err != CL_SUCCESS)
869     {
870         throw std::runtime_error("clReleaseSemaphoreKHR failed!");
871     }
872 }
873 
signal(cl_command_queue cmd_queue)874 void clExternalSemaphore::signal(cl_command_queue cmd_queue)
875 {
876     clEnqueueSignalSemaphoresKHRptr(cmd_queue, 1, &m_externalSemaphore, NULL, 0,
877                                     NULL, NULL);
878 }
879 
wait(cl_command_queue cmd_queue)880 void clExternalSemaphore::wait(cl_command_queue cmd_queue)
881 {
882     clEnqueueWaitSemaphoresKHRptr(cmd_queue, 1, &m_externalSemaphore, NULL, 0,
883                                   NULL, NULL);
884 }
885 
getCLSemaphore()886 cl_semaphore_khr &clExternalSemaphore::getCLSemaphore()
887 {
888     return m_externalSemaphore;
889 }
890 
vkToOpenCLExternalMemoryHandleType(VulkanExternalMemoryHandleType vkExternalMemoryHandleType)891 cl_external_memory_handle_type_khr vkToOpenCLExternalMemoryHandleType(
892     VulkanExternalMemoryHandleType vkExternalMemoryHandleType)
893 {
894     switch (vkExternalMemoryHandleType)
895     {
896         case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD:
897             return CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR;
898         case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT:
899             return CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KHR;
900         case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT:
901         case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT_KMT:
902             return CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR;
903         case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_NONE: return 0;
904     }
905     return 0;
906 }
907 
vkClExternalMemoryHandleTilingAssumption(cl_device_id deviceId,VulkanExternalMemoryHandleType vkExternalMemoryHandleType,int * error_ret)908 VulkanImageTiling vkClExternalMemoryHandleTilingAssumption(
909     cl_device_id deviceId,
910     VulkanExternalMemoryHandleType vkExternalMemoryHandleType, int *error_ret)
911 {
912     size_t size = 0;
913     VulkanImageTiling mode = VULKAN_IMAGE_TILING_OPTIMAL;
914 
915     assert(error_ret
916            != nullptr); // errcode_ret is not optional, it must be checked
917 
918     *error_ret = clGetDeviceInfo(
919         deviceId,
920         CL_DEVICE_EXTERNAL_MEMORY_IMPORT_ASSUME_LINEAR_IMAGES_HANDLE_TYPES_KHR,
921         0, nullptr, &size);
922     if (*error_ret != CL_SUCCESS)
923     {
924         return mode;
925     }
926 
927     if (size == 0)
928     {
929         return mode;
930     }
931 
932     std::vector<cl_external_memory_handle_type_khr> assume_linear_types(
933         size / sizeof(cl_external_memory_handle_type_khr));
934 
935     *error_ret = clGetDeviceInfo(
936         deviceId,
937         CL_DEVICE_EXTERNAL_MEMORY_IMPORT_ASSUME_LINEAR_IMAGES_HANDLE_TYPES_KHR,
938         size, assume_linear_types.data(), nullptr);
939     if (*error_ret != CL_SUCCESS)
940     {
941         return mode;
942     }
943 
944     if (std::find(
945             assume_linear_types.begin(), assume_linear_types.end(),
946             vkToOpenCLExternalMemoryHandleType(vkExternalMemoryHandleType))
947         != assume_linear_types.end())
948     {
949         mode = VULKAN_IMAGE_TILING_LINEAR;
950     }
951 
952     return mode;
953 }
954