Vulkan --- vkAcquireNextImageKHR 在使用某些队列系列时抛出 std::out_of_range
Vulkan --- vkAcquireNextImageKHR throws std::out_of_range when certain queue families are used
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)。
解决方法
使用 1.1.121.1 版本的 SDK 可以防止抛出。
创建索引为 0
的设备队列系列以及可能需要的任何其他设备队列可防止抛出发生。
问题 GitHub
这已在 GitHub [here] 上作为问题提出。
这似乎是 MoltenVK 中的一个错误。检查 MoltenVK 源表明它总是隐式使用队列家族 0
的队列 0
用于 vkAcquireNextImage
。如果您显式创建该队列,或者如果您仅使用 Fence,那么您没有问题的事实告诉我 MoltenVk 可能忘记为自己正确初始化该隐式队列。
GitHub 问题提交于 KhronosGroup/MoltenVK#791。
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);
但使用
但是使用以下的当前索引和图形队列索引的任意组合会导致此 API 调用抛出未捕获的 0
以外的任何其他方式会导致此 API 调用抛出未捕获的 std::out_of_range
(输出是 lldb
的):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)。
解决方法
使用 1.1.121.1 版本的 SDK 可以防止抛出。
创建索引为
0
的设备队列系列以及可能需要的任何其他设备队列可防止抛出发生。
问题 GitHub
这已在 GitHub [here] 上作为问题提出。
这似乎是 MoltenVK 中的一个错误。检查 MoltenVK 源表明它总是隐式使用队列家族 0
的队列 0
用于 vkAcquireNextImage
。如果您显式创建该队列,或者如果您仅使用 Fence,那么您没有问题的事实告诉我 MoltenVk 可能忘记为自己正确初始化该隐式队列。
GitHub 问题提交于 KhronosGroup/MoltenVK#791。