| /* |
| * Copyright (c) 2023-2026 Valve Corporation |
| * Copyright (c) 2023-2026 LunarG, Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| */ |
| |
| #include "../framework/layer_validation_tests.h" |
| #include "../framework/shader_helper.h" |
| |
| class PositiveDeviceQueue : public VkLayerTest {}; |
| |
| TEST_F(PositiveDeviceQueue, NoQueues) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_9_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::maintenance9); |
| RETURN_IF_SKIP(InitFramework()); |
| |
| VkDeviceCreateInfo device_ci = vku::InitStructHelper(); |
| device_ci.pNext = requested_features_.GetEnabledFeatures2(); |
| device_ci.enabledExtensionCount = static_cast<uint32_t>(m_device_extension_names.size()); |
| device_ci.ppEnabledExtensionNames = m_device_extension_names.data(); |
| |
| vkt::Device device(gpu_, device_ci); |
| |
| VkShaderObj cs(device, kMinimalShaderGlsl, VK_SHADER_STAGE_COMPUTE_BIT); |
| |
| std::vector<VkDescriptorSetLayoutBinding> bindings(0); |
| const vkt::DescriptorSetLayout pipeline_dsl(device, bindings); |
| const vkt::PipelineLayout pipeline_layout(device, {&pipeline_dsl}); |
| |
| VkComputePipelineCreateInfo compute_create_info = vku::InitStructHelper(); |
| compute_create_info.stage = cs.GetStageCreateInfo(); |
| compute_create_info.layout = pipeline_layout; |
| |
| VkPipeline pipeline; |
| vk::CreateComputePipelines(device, VK_NULL_HANDLE, 1, &compute_create_info, nullptr, &pipeline); |
| vk::DestroyPipeline(device, pipeline, nullptr); |
| } |
| |
| TEST_F(PositiveDeviceQueue, QueueFamilyIndexDifferentCreateFlags) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_INTERNALLY_SYNCHRONIZED_QUEUES_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::internallySynchronizedQueues); |
| RETURN_IF_SKIP(InitFramework()); |
| |
| bool found_queue = false; |
| VkQueueFamilyProperties queue_properties; |
| uint32_t queue_family_index = 0u; |
| uint32_t queue_family_count = 0u; |
| vk::GetPhysicalDeviceQueueFamilyProperties(Gpu(), &queue_family_count, nullptr); |
| std::vector<VkQueueFamilyProperties> queue_families(queue_family_count); |
| vk::GetPhysicalDeviceQueueFamilyProperties(Gpu(), &queue_family_count, queue_families.data()); |
| |
| for (size_t i = 0; i < queue_families.size(); i++) { |
| if (queue_families[i].queueCount > 1) { |
| found_queue = true; |
| queue_family_index = i; |
| queue_properties = queue_families[i]; |
| break; |
| } |
| } |
| |
| if (found_queue == false) { |
| GTEST_SKIP() << "test requires queue family with 2 queues, not available"; |
| } |
| |
| float queue_priority = 1.0f; |
| VkDeviceQueueCreateInfo device_queue_ci[2]; |
| device_queue_ci[0] = vku::InitStructHelper(); |
| device_queue_ci[0].flags = 0u; |
| device_queue_ci[0].queueFamilyIndex = queue_family_index; |
| device_queue_ci[0].queueCount = 1u; |
| device_queue_ci[0].pQueuePriorities = &queue_priority; |
| device_queue_ci[1] = vku::InitStructHelper(); |
| device_queue_ci[1].flags = VK_DEVICE_QUEUE_CREATE_INTERNALLY_SYNCHRONIZED_BIT_KHR; |
| device_queue_ci[1].queueFamilyIndex = queue_family_index; |
| device_queue_ci[1].queueCount = 1u; |
| device_queue_ci[1].pQueuePriorities = &queue_priority; |
| |
| VkDevice test_device = VK_NULL_HANDLE; |
| VkDeviceCreateInfo device_ci = vku::InitStructHelper(); |
| device_ci.pNext = requested_features_.GetEnabledFeatures2(); |
| device_ci.queueCreateInfoCount = 2u; |
| device_ci.pQueueCreateInfos = device_queue_ci; |
| device_ci.enabledExtensionCount = static_cast<uint32_t>(m_device_extension_names.size()); |
| device_ci.ppEnabledExtensionNames = m_device_extension_names.data(); |
| vk::CreateDevice(Gpu(), &device_ci, nullptr, &test_device); |
| vk::DestroyDevice(test_device, nullptr); |
| } |
| |
| TEST_F(PositiveDeviceQueue, MultipleQueuePerfHint) { |
| TEST_DESCRIPTION("Test vkQueueSetPerfHintQCOM on all supported queues."); |
| SetTargetApiVersion(VK_API_VERSION_1_3); |
| AddRequiredExtensions(VK_QCOM_QUEUE_PERF_HINT_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::queuePerfHint); |
| RETURN_IF_SKIP(InitFramework()); |
| |
| VkPhysicalDeviceQueuePerfHintPropertiesQCOM perf_hint_props = vku::InitStructHelper(); |
| GetPhysicalDeviceProperties2(perf_hint_props); |
| const VkQueueFlags supported_queues = perf_hint_props.supportedQueues; |
| |
| uint32_t queue_family_count = 0; |
| vk::GetPhysicalDeviceQueueFamilyProperties(Gpu(), &queue_family_count, nullptr); |
| std::vector<VkQueueFamilyProperties> queue_family_props(queue_family_count); |
| vk::GetPhysicalDeviceQueueFamilyProperties(Gpu(), &queue_family_count, queue_family_props.data()); |
| |
| std::vector<uint32_t> supported_queue_ids{}; |
| for (uint32_t index = 0; index < queue_family_count; ++index) { |
| if ((queue_family_props[index].queueFlags & supported_queues) != 0) { |
| supported_queue_ids.push_back(index); |
| } |
| } |
| if (supported_queue_ids.empty()) { |
| GTEST_SKIP() << "Failed to find the queue family that supports queue perf-hint property, skipping test."; |
| } |
| |
| RETURN_IF_SKIP(InitState()); |
| |
| constexpr std::array<VkPerfHintTypeQCOM, 3> hint_types{ |
| VK_PERF_HINT_TYPE_FREQUENCY_SCALED_QCOM, |
| VK_PERF_HINT_TYPE_DEFAULT_QCOM, |
| VK_PERF_HINT_TYPE_FREQUENCY_MIN_QCOM, |
| }; |
| |
| uint32_t index = 0; |
| for (const uint32_t family_id : supported_queue_ids) { |
| VkQueue queue = VK_NULL_HANDLE; |
| vk::GetDeviceQueue(device(), family_id, 0, &queue); |
| |
| VkPerfHintInfoQCOM perf_hint_info = vku::InitStructHelper(); |
| perf_hint_info.type = hint_types[index]; |
| perf_hint_info.scale = 0; |
| |
| if (hint_types[index] == VK_PERF_HINT_TYPE_FREQUENCY_SCALED_QCOM) { |
| perf_hint_info.scale = 65; |
| } |
| |
| vk::QueueSetPerfHintQCOM(queue, &perf_hint_info); |
| |
| ++index; |
| index = index % hint_types.size(); |
| } |
| } |