NVIDIA驱动程序支持OpenCL和Vulkan进行互操作

网友投稿 496 2022-11-04

NVIDIA驱动程序支持OpenCL和Vulkan进行互操作

需要一种新的互操作方式

cl_khr_gl_sharing

cl_khr_gl_event

cl_khr_egl_image

cl_khr_egl_event

cl_khr_d3d10_sharing

cl_khr_d3d11_sharing

OpenCL 和 Vulkan 之间的互操作在移动和桌面平台上都有很强的需求。 NVIDIA 与 Khronos OpenCL 工作组密切合作,发布了一套临时跨供应商的 KHR 扩展。这些扩展使应用程序能够在 OpenCL 和 Vulkan 等 API 之间高效地共享数据,与使用隐式资源的前一代互操作 API 相比,灵活性显著提高。

这组新的外部内存和信号量共享扩展提供了一个通用框架,使 OpenCL 能够使用 Vulkan 开发人员熟悉的方法导入外部 API 导出的外部内存和信号量句柄。然后, OpenCL 使用这些信号量来同步外部运行时,协调共享内存的使用。

图 1 。 OpenCL 与 Vulkan 软件的互操作关系

然后可以添加特定于 API 的外部互操作扩展,以处理与特定 API 交互的细节。 Vulkan 互操作现在可用,并计划使用其他 API ,如 DirectX 12 。

OpenCL 新的外部信号量和内存共享功能包括单独的一组精心构造的扩展。

信号量扩展

这组扩展增加了从操作系统特定的信号量句柄创建 OpenCL 信号量对象的能力。

cl_khr_semaphore – 表示带有等待和信号的信号量。这是一个新的 OpenCL 对象类。

cl_khr_external_semaphore – 使用导入和导出外部信号量的机制扩展cl_khr_semaphore,类似于 VK_KHR_external_semaphore 。

以下扩展使用特定于句柄类型的行为扩展cl_khr_external_semaphore:

cl_khr_external_semaphore_win32 – 与 VK_KHR_external_semaphore_win32 类似,使用 win32 NT 和 KMT 句柄与引用转移共享外部信号量。

内存扩展

这些扩展增加了从操作系统特定的内存句柄创建 OpenCL 内存对象的能力。它们的设计与 Vulkan 外部存储器扩展 VK_KHR_external_memory 。 类似

cl_khr_external_memory – 从其他 API 导入外部内存。

以下扩展使用特定于句柄类型的行为扩展cl_khr_external_memory:

cl_khr_external_memory_opaque_fd – 使用 Linux fd 句柄共享外部内存,类似于 VK_KHR_external_memory_fd 。

cl_khr_external_memory_win32 – 使用 win32 NT 和 KMT 句柄共享外部内存,类似于 VK_KHR_external_memory_win32 。

使用 OpenCL

典型的互操作用例包括以下步骤。

检查所需的支持是否可用:

检查底层 OpenCL 平台和带有clGetPlatformInfo和clGetDeviceInfo的设备是否支持所需的扩展cl_khr_external_semaphore和cl_khr_external_memory。

为了能够使用 Win32 信号量和内存句柄,请检查cl_khr_external_semaphore_win32_khr和cl_khr_external_memory_win32_khr扩展是否存在。

为了能够使用 FD 信号量和内存句柄,请检查cl_khr_external_semaphore_opaque_fd_khr和cl_khr_external_memory_opaque_fd_khr扩展是否存在。这也可以通过查询支持的句柄类型来检查。

导入外部信号量需要cl_khr_external_semaphore。如果支持cl_khr_external_semaphore_opaque_fd,则可以使用clCreateSemaphoreWithPropertiesKHR和 OpenCL 中的 FD 句柄导入 Vulkan 导出的外部信号量。

导入图像需要cl_khr_external_memory和对图像的支持。在 OpenCL 中,通过clCreateSemaphoreWithPropertiesKHR使用 Win32 句柄导入 Vulkan 导出的外部信号量。

// Get cl_devices of the platform. clGetDeviceIDs(..., &devices, &deviceCount); // Create cl_context with just first device clCreateContext(..., 1, devices, ...); // Obtain fd/win32 or similar handle for external semaphore to be imported from the other API. void *handle = getWin32HandleForExternalSemaphore(); // Create clSema of type cl_semaphore_khr usable on the only available device assuming the semaphore was imported from the same device. cl_semaphore_properties_khr sema_props[] = {(cl_semaphore_properties_khr)CL_SEMAPHORE_TYPE_KHR, (cl_semaphore_properties_khr)CL_SEMAPHORE_TYPE_BINARY_KHR, (cl_semaphore_properties_khr)CL_SEMAPHORE_HANDLE_OPAQUE_WIN32_KHR, (cl_semaphore_properties_khr)handle, 0}; int errcode_ret = 0; cl_semaphore_khr clSema = clCreateSemaphoreWithPropertiesKHR(context, sema_props, &errcode_ret);

在 OpenCL 中,使用 FD 句柄将 Vulkan 导出的外部内存作为缓冲内存与clCreateBufferWithProperties一起导入。

// Get cl_devices of the platform. clGetDeviceIDs(..., &devices, &deviceCount); // Create cl_context with just first device clCreateContext(..., 1, devices, ...); // Obtain fd/win32 or similar handle for external memory to be imported from other API. int fd = getFdForExternalMemory(); // Create extMemBuffer of type cl_mem from fd. cl_mem_properties_khr extMemProperties[] = { (cl_mem_properties_khr)CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR, (cl_mem_properties_khr)fd,0}; cl_mem extMemBuffer = clCreateBufferWithProperties(/*context*/ clContext, /*properties*/ extMemProperties, /*flags*/ 0, /*size*/ size, /*host_ptr*/ NULL, /*errcode_ret*/ &errcode_ret);

在 OpenCL 中,使用clCreateImageWithProperties将 Vulkan 导出的外部内存作为图像内存导入。

// Create img of type cl_mem. Obtain fd/win32 or similar handle for external memory to be imported from other API. int fd = getFdForExternalMemory(); // Set cl_image_format based on external image info cl_image_format clImgFormat = { }; clImageFormat.image_channel_order = CL_RGBA; clImageFormat.image_channel_data_type = CL_UNORM_INT8; // Set cl_image_desc based on external image info size_t clImageFormatSize; cl_image_desc image_desc = { }; image_desc.image_type = CL_MEM_OBJECT_IMAGE2D_ARRAY; image_desc.image_width = width; image_desc.image_height = height; image_desc.image_depth = depth; cl_mem_properties_khr extMemProperties[] = { (cl_mem_properties_khr)CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR, (cl_mem_properties_khr)fd, 0 }; cl_mem img = clCreateImageWithProperties(/*context*/ clContext, /*properties*/ extMemProperties, /*flags*/ 0, /*image_format*/ &clImgFormat, /*image_desc*/ &image_desc, /*errcode_ret*/ &errcode_ret)

使用信号量 wait 和 signal 在 OpenCL 和 Vulkan 之间同步。

// Create clSema using one of the above examples of external semaphore creation. int errcode_ret = 0; cl_semaphore_khr clSema = clCreateSemaphoreWithPropertiesKHR(context, sema_props, &errcode_ret); while (true) { // (not shown) Signal the semaphore from the other API, // Wait for the semaphore in OpenCL clEnqueueWaitSemaphoresKHR( /*command_queue*/ command_queue, /*num_sema_objects*/ 1, /*sema_objects*/ &clSema, /*num_events_in_wait_list*/ 0, /*event_wait_list*/ NULL, /*event*/ NULL); clEnqueueNDRangeKernel(command_queue, ...); clEnqueueSignalSemaphoresKHR(/*command_queue*/ command_queue, /*num_sema_objects*/ 1, /*sema_objects*/ &clSema, /*num_events_in_wait_list*/ 0, /*event_wait_list*/ NULL, /*event*/ NULL); // (not shown) Launch work in the other API that waits on 'clSema'

Nikhil Joshi 目前在NVIDIA 管理 OpenCL 驱动程序团队。他还代表 NVIDIA 参加 Khronos OpenCL 工作组。他在 NVIDIA 的计算团队工作了 10 多年,致力于不同的计算 API ,包括 CUDA 、 Renderscript 和 OpenCL

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:#yyds干货盘点#K8S-日志系统部署
下一篇:Kubernets 亲和性
相关文章

 发表评论

暂时没有评论,来抢沙发吧~