Using Vulkan -- Queues
应用程序通过VkQueue提交工作通常以VkCommandBuffer对象或稀疏绑定的形式提交。提交到同一个VkQueue的命令缓冲区按提交顺序开始执行但开始后允许独立推进并乱序完成。提交到不同队列的命令缓冲区彼此之间是无序的除非使用VkSemaphore显式同步。同一时间只能由一个线程向某个VkQueue提交工作但不同线程可以同时向不同VkQueue提交工作。VkQueue如何映射到底层硬件是实现定义的。部分实现会拥有多个硬件队列向多个VkQueue提交工作可以独立并发执行部分实现会在内核驱动层面做调度后再提交给硬件。Vulkan 目前没有办法暴露每个VkQueue具体的映射细节。并非所有应用都需要或能从多队列中受益。使用单个支持图形的 “通用” 队列向 GPU 提交所有工作是完全合理的。Queue Family一个VkQueue可以支持多种操作类型。Queue Family队列族表示一组拥有相同属性、支持相同功能的VkQueue具体能力在VkQueueFamilyProperties中声明。以下是VkQueueFlagBits中定义的队列操作VK_QUEUE_GRAPHICS_BIT用于vkCmdDraw*及图形管线相关命令。VK_QUEUE_COMPUTE_BIT用于vkCmdDispatch*、vkCmdTraceRays*及计算管线相关命令。VK_QUEUE_TRANSFER_BIT用于所有传输transfer命令。规范中的VK_PIPELINE_STAGE_TRANSFER_BIT对 “传输命令” 有详细说明。仅包含VK_QUEUE_TRANSFER_BIT的队列族通常用于在独立显卡上利用 DMA 异步在主机与设备内存之间传输数据使得传输可以与独立的图形 / 计算操作并发执行。VK_QUEUE_GRAPHICS_BIT和VK_QUEUE_COMPUTE_BIT总是可以隐式执行VK_QUEUE_TRANSFER_BIT命令。VK_QUEUE_SPARSE_BINDING_BIT用于通过vkQueueBindSparse对稀疏资源进行内存绑定。VK_QUEUE_PROTECTED_BIT用于受保护内存。VK_QUEUE_VIDEO_DECODE_BIT_KHR和VK_QUEUE_VIDEO_ENCODE_BIT_KHR用于 Vulkan Video。Knowing which Queue Family is neededVulkan 规范中的每个操作都有一个从vk.xml 生成的Supported Queue Types章节。以下是规范中的三种典型示Querying for Queue Family如果应用只需要一个图形队列最简单的查询逻辑如下uint32_t count 0; vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, count, nullptr); std::vectorVkQueueFamilyProperties properties(count); vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, count, properties.data()); // Vulkan 要求实现至少暴露一个支持图形的队列族 uint32_t graphicsQueueFamilyIndex; for (uint32_t i 0; i count; i) { if ((properties[i].queueFlags VK_QUEUE_GRAPHICS_BIT) ! 0) { // 此队列族支持图形 graphicsQueueFamilyIndex i; break; } }Creating and getting a Queue与VkDevice、VkBuffer、VkDeviceMemory等句柄不同Vulkan 没有vkCreateQueue或vkAllocateQueue。驱动会在vkCreateDevice/vkDestroyDevice期间负责创建和销毁VkQueue句柄。下面示例假设某个实现来自 2 个队列族共支持 3 个VkQueue以下示例展示如何在逻辑设备上创建全部 3 个VkQueueVkDeviceQueueCreateInfo queueCreateInfo[2]; queueCreateInfo[0].queueFamilyIndex 0; // Transfer queueCreateInfo[0].queueCount 1; queueCreateInfo[1].queueFamilyIndex 1; // Graphics queueCreateInfo[1].queueCount 2; VkDeviceCreateInfo deviceCreateInfo {}; deviceCreateInfo.pQueueCreateInfos queueCreateInfo; deviceCreateInfo.queueCreateInfoCount 2; vkCreateDevice(physicalDevice, deviceCreateInfo, nullptr, device);创建VkDevice后应用可以使用vkGetDeviceQueue获取VkQueue句柄VkQueue graphicsQueue0 VK_NULL_HANDLE; VkQueue graphicsQueue1 VK_NULL_HANDLE; VkQueue transferQueue0 VK_NULL_HANDLE; // 获取顺序可以任意 vkGetDeviceQueue(device, 0, 0, transferQueue0); // family 0 - queue 0 vkGetDeviceQueue(device, 1, 1, graphicsQueue1); // family 1 - queue 1 vkGetDeviceQueue(device, 1, 0, graphicsQueue0); // family 1 - queue 0
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2419510.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!