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, ¶mSize);
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