- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
使用 Vulkan VkImage 作为 CUDA cuArray 的正确方法是什么?
我一直在尝试遵循一些示例,但是我在调用 cuExternalMemoryGetMappedMipmappedArray()
时收到 CUDA_ERROR_INVALID_VALUE
以有序的方式提供信息。
我正在使用 CUDA 10.1
基础代码来自https://github.com/SaschaWillems/Vulkan ,特别是我正在使用 01 - Vulkan Gears演示,通过 saveScreenshot 方法丰富 09 - Capturing screenshots
我不会将快照图像保存到文件中,而是将快照图像作为 CUarray 发送到 CUDA。
我已启用以下实例和设备扩展:
std::vector<const char*> instanceExtensions = {
VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME };
std::vector<const char*> deviceExtensions = { VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME };
我有一个 VkImage,创建如下:
// Create the linear tiled destination image to copy to and to read the memory from
VkImageCreateInfo imageCreateCI(vks::initializers::imageCreateInfo());
imageCreateCI.imageType = VK_IMAGE_TYPE_2D;
// Note that vkCmdBlitImage (if supported) will also do format conversions if the swapchain color format would differ
imageCreateCI.format = VK_FORMAT_R8G8B8A8_UNORM;
imageCreateCI.extent.width = width;
imageCreateCI.extent.height = height;
imageCreateCI.extent.depth = 1;
imageCreateCI.arrayLayers = 1;
imageCreateCI.mipLevels = 1;
imageCreateCI.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageCreateCI.samples = VK_SAMPLE_COUNT_1_BIT;
imageCreateCI.tiling = VK_IMAGE_TILING_LINEAR;
imageCreateCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageCreateCI.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
VkExternalMemoryImageCreateInfoKHR extImageCreateInfo = {};
/*
* Indicate that the memory backing this image will be exported in an
* fd. In some implementations, this may affect the call to
* GetImageMemoryRequirements() with this image.
*/
extImageCreateInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR;
extImageCreateInfo.handleTypes |= VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
imageCreateCI.pNext = &extImageCreateInfo;
// Create the image
VkImage dstImage;
VK_CHECK_RESULT(vkCreateImage(device, &imageCreateCI, nullptr, &dstImage));
// Create memory to back up the image
VkMemoryRequirements memRequirements;
VkMemoryAllocateInfo memAllocInfo(vks::initializers::memoryAllocateInfo());
VkDeviceMemory dstImageMemory;
vkGetImageMemoryRequirements(device, dstImage, &memRequirements);
memAllocInfo.allocationSize = memRequirements.size;
// Memory must be host visible to copy from
memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
VkExportMemoryAllocateInfoKHR exportInfo = {};
exportInfo.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR;
exportInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
memAllocInfo.pNext = &exportInfo;
VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &dstImageMemory));
VK_CHECK_RESULT(vkBindImageMemory(device, dstImage, dstImageMemory, 0));
从那里我会:
获取 Vulkan 内存处理程序:
int CuEncoderImpl::getVulkanMemoryHandle(VkDevice device,
VkDeviceMemory memory) {
// Get handle to memory of the VkImage
int fd = -1;
VkMemoryGetFdInfoKHR fdInfo = { };
fdInfo.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR;
fdInfo.memory = memory;
fdInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
auto func = (PFN_vkGetMemoryFdKHR) vkGetDeviceProcAddr(device,
"vkGetMemoryFdKHR");
if (!func) {
printf("Failed to locate function vkGetMemoryFdKHR\n");
return -1;
}
VkResult r = func(device, &fdInfo, &fd);
if (r != VK_SUCCESS) {
printf("Failed executing vkGetMemoryFdKHR [%d]\n", r);
return -1;
}
return fd;
}
导入内存:
CUDA_EXTERNAL_MEMORY_HANDLE_DESC memDesc = { };
memDesc.type = CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD;
memDesc.handle.fd = getVulkanMemoryHandle(device, memory);
memDesc.size = extent.width*extent.height*4;
CUDA_DRVAPI_CALL(cuImportExternalMemory(&externalMem, &memDesc));
并映射内存:这是失败的步骤。
CUarray CuEncoderImpl::getCUDAArrayFromExternalMemory(const VkExtent3D &extent,const CUexternalMemory &m_extMem) {
CUmipmappedArray m_mipmapArray;
CUresult result = CUDA_SUCCESS;
CUarray array;
CUDA_ARRAY3D_DESCRIPTOR arrayDesc = { };
arrayDesc.Width = extent.width;
arrayDesc.Height = extent.height;
arrayDesc.Depth = 0;
arrayDesc.Format = CU_AD_FORMAT_UNSIGNED_INT32;
arrayDesc.NumChannels = 4;
arrayDesc.Flags = CUDA_ARRAY3D_SURFACE_LDST;
CUDA_EXTERNAL_MEMORY_MIPMAPPED_ARRAY_DESC mipmapArrayDesc = { };
mipmapArrayDesc.arrayDesc = arrayDesc;
mipmapArrayDesc.numLevels = 1;
mipmapArrayDesc.offset = 0;
CUDA_DRVAPI_CALL(cuExternalMemoryGetMappedMipmappedArray(&m_mipmapArray, m_extMem, &mipmapArrayDesc));
CUDA_DRVAPI_CALL(cuMipmappedArrayGetLevel(&array, m_mipmapArray, 0));
return array;
}
我一直在尝试多种参数组合,但到目前为止都失败了。该错误指向无效参数,但我不知道如何找到问题所在。
唯一有效的方法是将 Vulkan 图像内存映射到主机缓冲区,然后将其复制到 CUDA 数组中......但我想这很昂贵,如果可能的话我想避免它。
最佳答案
郑重声明,我终于让它发挥作用了。
我必须对问题中列出的代码进行的一些注释和修改:
imageCreateCI.tiling = VK_IMAGE_TILING_OPTIMAL;
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
分配该图像的内存 memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
size
是创建图像的代码中的memRequirements.size
) : CUDA_EXTERNAL_MEMORY_HANDLE_DESC memDesc = { };
memDesc.type = CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD;
memDesc.handle.fd = getVulkanMemoryHandle(device, memory);
memDesc.size = size;
CUDA_DRVAPI_CALL(cuImportExternalMemory(&externalMem, &memDesc));
CU_AD_FORMAT_UNSIGNED_INT8
,具有四个 channel 和 CUDA_ARRAY3D_COLOR_ATTACHMENT
CUDA_ARRAY3D_DESCRIPTOR arrayDesc = { };
arrayDesc.Width = extent.width;
arrayDesc.Height = extent.height;
arrayDesc.Depth = 0;
arrayDesc.Format = CU_AD_FORMAT_UNSIGNED_INT8;
arrayDesc.NumChannels = 4;
arrayDesc.Flags = CUDA_ARRAY3D_COLOR_ATTACHMENT;
CUDA_EXTERNAL_MEMORY_MIPMAPPED_ARRAY_DESC mipmapArrayDesc = { };
mipmapArrayDesc.arrayDesc = arrayDesc;
mipmapArrayDesc.numLevels = 1;
mipmapArrayDesc.offset = 0;
CUDA_DRVAPI_CALL(cuExternalMemoryGetMappedMipmappedArray(&m_mipmapArray, m_extMem, &mipmapArrayDesc));
经过这些更改后,我能够让它正常工作。我的一些变化是我这边明显的错误(比如大小),我在第 100 次仔细地重新阅读文档时发现了一些东西,其他的东西是对文档中的提示的猜测,最后是大量的试验和错误.
关于cuda - 使用 Vulkan VkImage 作为 CUDA cuArray,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55424875/
我有一个 CUarray,它是通过 cuGraphicsSubResourceGetMappedArray() 从我的 OpenGL 上下文中获得的。是否可以将它与 cuMemset*() 一起使用?
我有很多字符串操作要执行,我想使用 GPU 处理在 Julia 1.2.0 中实现代码。我马上就遇到了定义 CuArray 的问题,下面是一个例子。我基本上希望能够将一维字符串数组传递到 GPU 内核
使用 Vulkan VkImage 作为 CUDA cuArray 的正确方法是什么? 我一直在尝试遵循一些示例,但是我在调用 cuExternalMemoryGetMappedMipmapped
我有一台互联网连接缓慢且断断续续的机器,因此下载 2.4 Gb 的 CUDA 几乎要花很长时间。我想通过以下代码使用 GPU 编程: N = 2^2 using CuArrays x_d = CuAr
我是一名优秀的程序员,十分优秀!