Vulkan ---当使用某些队列系列时,vkAcquireNextImageKHR抛出std :: out_of_range

时间:2019-12-02 11:39:04

标签: c++ vulkan moltenvk

TL; DR

使用某些队列系列时,

vkAcquireNextImageKHR引发std::out_of_range。这是预期的行为吗?如何调试?

详细说明

我使用的Vulkan程序基于vulkan-tutorial.com。我发现我的VkPhysicalDevice有三个队列族,每个队列族都标有VK_QUEUE_GRAPHICS_BIT并提供支持:

uint32_t queueFamilyCount;
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());

std::vector<uint32_t> graphicsQueueFamilyIndices;
std::vector<uint32_t> presentQueueFamilyIndices;
int i = 0;
for (const auto& queueFamily : queueFamilies)
{
  if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)
  {
    graphicsQueueFamilyIndices.push_back(i);
  }

  VkBool32 presentSupport = false;           
  vkGetPhysicalDeviceSurfaceSupportKHR(         
      device,
      i,          
      surface,
      &presentSupport
    );
  if (presentSupport)
  {
    presentQueueFamilyIndices.push_back(i);
  }

  ++i;
}

// graphicsQueueFamilyIndices = {0, 1, 2}
// presentQueueFamilyIndices = {0, 1, 2}

稍后将在创建逻辑设备,交换链(所有队列系列都具有当前功能)和命令池时使用它们。后来程序调用

vkAcquireNextImageKHR(device, swapchain, UINT64_MAX, semaphore, VK_NULL_HANDLE, &imageIndex);

但是使用0之外的任何其他参数都会导致此API调用抛出未捕获的std::out_of_range(输出是lldb的输出): 但是使用以下项的当前和图形队列索引的任意组合会导致此API调用抛出未捕获的std::out_of_range(1, 1)(1, 2)(2, 1)(2, 2)

lldb的输出如下:

2019-12-01 11:36:35.599882+0100 main[22130:167876] flock failed to lock maps file: errno = 35
2019-12-01 11:36:35.600165+0100 main[22130:167876] flock failed to lock maps file: errno = 35
libc++abi.dylib: terminating with uncaught exception of type std::out_of_range: Index out of range
Process 22130 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
    frame #0: 0x00007fff675c949a libsystem_kernel.dylib`__pthread_kill + 10
libsystem_kernel.dylib`__pthread_kill:
->  0x7fff675c949a <+10>: jae    0x7fff675c94a4            ; <+20>
    0x7fff675c949c <+12>: movq   %rax, %rdi
    0x7fff675c949f <+15>: jmp    0x7fff675c33b7            ; cerror_nocancel
    0x7fff675c94a4 <+20>: retq
Target 0: (main) stopped.

使用甚至不引用队列的索引(如123)时,也会引起相同的错误。我正在使用VK_LAYER_KHRONOS_validation图层,它不会发出任何抱怨。

问题

(1)这是将错误的队列族索引传递给Vk的预期行为吗?

(2)是否有验证层能够捕获此错误并使它更加冗长?

(3)为什么选择这些队列族会导致此错误?

详细信息

在图形设备中使用队列族索引(1, 1)并在逻辑设备创建过程中使用当前队列族,而对其他所有索引使用0已经导致vkAcquireNextImage引发错误。当然,VK_LAYER_KHRONOS_validation在创建命令池时会引发以下警告:

Validation layer: vkCreateCommandPool: pCreateInfo->queueFamilyIndex (= 0) is not one of the queue families given via VkDeviceQueueCreateInfo structures when the device was created. The Vulkan spec states: pCreateInfo::queueFamilyIndex must be the index of a queue family available in the logical device device. (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-vkCreateCommandPool-queueFamilyIndex-01937)

我正在macOS Catalina 10.15.1上使用MoltenVK(来自Vulkan SDK,版本1.1.126.0)。

解决方法

  • 使用SDK的1.1.121.1版可以防止引发异常。

  • 创建索引为0的设备队列系列以及可能需要的任何其他设备队列,以防止发生抛出。

在GitHub上发布

现在已在GitHub [here]上提出该问题。

1 个答案:

答案 0 :(得分:0)

这似乎是MoltenVK中的错误。检查MoltenVK源表明,它始终隐式地将队列族0的队列0用于vkAcquireNextImage。如果您明确创建该队列,或者仅使用Fence都没有问题,这告诉我,MoltenVk可能会忘记正确地为其本身初始化该隐式队列。

GitHub问题归档于KhronosGroup/MoltenVK#791