diff --git a/layersvt/screenshot/screenshot.cpp b/layersvt/screenshot/screenshot.cpp index e0a03da5dd..23bf1fc0c1 100644 --- a/layersvt/screenshot/screenshot.cpp +++ b/layersvt/screenshot/screenshot.cpp @@ -1646,33 +1646,49 @@ VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCall } } -VKAPI_ATTR void VKAPI_CALL GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue) { - DispatchMapStruct* dispMap = get_dispatch_info(device); - assert(dispMap); - VkuDeviceDispatchTable* pDisp = dispMap->device_dispatch_table; - pDisp->GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue); +static void addDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, VkQueue queue, DispatchMapStruct* dispMap) { + if (queue == VK_NULL_HANDLE) return; // Save the device queue in a map if we are taking screenshots. std::lock_guard lg(globalLock); // Add this queue to deviceMap[device].queues, and queueFamilyIndex to deviceMap[device].queueIndexMap if (deviceMap.find(device) != deviceMap.end()) { - deviceMap[device]->queues.emplace(*pQueue); + deviceMap[device]->queues.emplace(queue); - if (deviceMap[device]->queueIndexMap.find(*pQueue) != deviceMap[device]->queueIndexMap.end()) - deviceMap[device]->queueIndexMap.erase(*pQueue); - deviceMap[device]->queueIndexMap.emplace(*pQueue, queueFamilyIndex); + if (deviceMap[device]->queueIndexMap.find(queue) != deviceMap[device]->queueIndexMap.end()) + deviceMap[device]->queueIndexMap.erase(queue); + deviceMap[device]->queueIndexMap.emplace(queue, queueFamilyIndex); } // queues are dispatchable objects. // Create dispatchMap entry with this queue as its key. // Copy the device dispatch table to the new dispatch table. - VkDevice que = static_cast(static_cast(*pQueue)); + VkDevice que = static_cast(static_cast(queue)); dispatchMap[que] = dispMap; } +VKAPI_ATTR void VKAPI_CALL GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue) { + DispatchMapStruct* dispMap = get_dispatch_info(device); + assert(dispMap); + VkuDeviceDispatchTable* pDisp = dispMap->device_dispatch_table; + pDisp->GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue); + + if (pQueue) { + addDeviceQueue(device, queueFamilyIndex, *pQueue, dispMap); + } +} + VKAPI_ATTR void VKAPI_CALL GetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue) { - if (pQueueInfo) GetDeviceQueue(device, pQueueInfo->queueFamilyIndex, pQueueInfo->queueIndex, pQueue); + if (!pQueueInfo) return; + DispatchMapStruct* dispMap = get_dispatch_info(device); + assert(dispMap); + VkuDeviceDispatchTable* pDisp = dispMap->device_dispatch_table; + pDisp->GetDeviceQueue2(device, pQueueInfo, pQueue); + + if (pQueue) { + addDeviceQueue(device, pQueueInfo->queueFamilyIndex, *pQueue, dispMap); + } } VKAPI_ATTR VkResult VKAPI_CALL CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, diff --git a/layersvt/test/test_screenshot.cpp b/layersvt/test/test_screenshot.cpp index 574a9b279d..fada699188 100644 --- a/layersvt/test/test_screenshot.cpp +++ b/layersvt/test/test_screenshot.cpp @@ -44,3 +44,54 @@ TEST_F(ScreenshotTests, init_layer) { VkResult err = inst_builder.Init(settings); EXPECT_EQ(err, VK_SUCCESS); } + +TEST_F(ScreenshotTests, get_device_queue2) { + TEST_DESCRIPTION("Test vkGetDeviceQueue2 forwards VkDeviceQueueInfo2 flags instead of downgrading to vkGetDeviceQueue"); + + layer_test::VulkanInstanceBuilder inst_builder; + VkResult err = inst_builder.Init(kLayerName); + ASSERT_EQ(err, VK_SUCCESS); + + VkPhysicalDevice phys_dev = VK_NULL_HANDLE; + err = inst_builder.GetPhysicalDevice(&phys_dev); + if (err != VK_SUCCESS || phys_dev == VK_NULL_HANDLE) { + GTEST_SKIP() << "No Vulkan physical device available"; + } + + float queue_priority = 1.0f; + VkDeviceQueueCreateInfo queue_create_info = {}; + queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queue_create_info.queueFamilyIndex = 0; + queue_create_info.queueCount = 1; + queue_create_info.pQueuePriorities = &queue_priority; + + VkDeviceCreateInfo device_create_info = {}; + device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + device_create_info.queueCreateInfoCount = 1; + device_create_info.pQueueCreateInfos = &queue_create_info; + + VkDevice device = VK_NULL_HANDLE; + err = vkCreateDevice(phys_dev, &device_create_info, nullptr, &device); + ASSERT_EQ(err, VK_SUCCESS); + ASSERT_NE(device, VK_NULL_HANDLE); + + VkDeviceQueueInfo2 queue_info = {}; + queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2; + queue_info.flags = 0; + queue_info.queueFamilyIndex = 0; + queue_info.queueIndex = 0; + + VkQueue queue = VK_NULL_HANDLE; + vkGetDeviceQueue2(device, &queue_info, &queue); + EXPECT_NE(queue, VK_NULL_HANDLE); + + // Querying a queue with mismatched flags (protected when created unprotected) must forward + // pQueueInfo to the driver's vkGetDeviceQueue2 rather than stripping flags via vkGetDeviceQueue. + VkDeviceQueueInfo2 protected_queue_info = queue_info; + protected_queue_info.flags = VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT; + VkQueue protected_queue = queue; + vkGetDeviceQueue2(device, &protected_queue_info, &protected_queue); + EXPECT_EQ(protected_queue, VK_NULL_HANDLE); + + vkDestroyDevice(device, nullptr); +}