Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ vvl_sources = [
"layers/stateless/sl_image.cpp",
"layers/stateless/sl_instance_device.cpp",
"layers/stateless/sl_pipeline.cpp",
"layers/stateless/sl_queue.cpp",
"layers/stateless/sl_ray_tracing.cpp",
"layers/stateless/sl_ray_tracing_micromap.cpp",
"layers/stateless/sl_ray_tracing_nv.cpp",
Expand Down
1 change: 1 addition & 0 deletions layers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,7 @@ target_sources(vvl PRIVATE
stateless/sl_image.cpp
stateless/sl_instance_device.cpp
stateless/sl_pipeline.cpp
stateless/sl_queue.cpp
stateless/sl_ray_tracing.cpp
stateless/sl_ray_tracing_micromap.cpp
stateless/sl_ray_tracing_nv.cpp
Expand Down
30 changes: 30 additions & 0 deletions layers/core_checks/cc_queue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -847,3 +847,33 @@ bool CoreChecks::ProcessSubmissionBatch(const vvl::SubmitTimeTracker& tracker,
}
return skip;
}


bool CoreChecks::PreCallValidateQueueSetPerfHintQCOM(VkQueue queue, const VkPerfHintInfoQCOM* pPerfHintInfo,
const ErrorObject& error_obj) const {
bool skip = false;
const auto queue_state = Get<vvl::Queue>(queue);

if (!queue_state->is_perf_hint_queue) {
skip |= LogError("VUID-vkQueueSetPerfHintQCOM-queue-12388", queue, error_obj.location,
"the queue with flags (%s) doesn't support queue performance hints.",
string_VkQueueFlags(queue_state->GetQueueFlags()).c_str());
}

if (pPerfHintInfo) {
if (pPerfHintInfo->type != VK_PERF_HINT_TYPE_FREQUENCY_SCALED_QCOM && pPerfHintInfo->scale != 0) {
const Location perf_hint_scale_loc = error_obj.location.pNext(Struct::VkPerfHintInfoQCOM, Field::scale);
skip |= LogError("VUID-VkPerfHintInfoQCOM-type-12389", queue, perf_hint_scale_loc,
"equals to (%" PRIu32 "), but VkPerfHintInfoQCOM::type is (%s).",
pPerfHintInfo->scale, string_VkPerfHintTypeQCOM(pPerfHintInfo->type));
}
if (pPerfHintInfo->scale > 100) {
const Location perf_hint_scale_loc = error_obj.location.pNext(Struct::VkPerfHintInfoQCOM, Field::scale);
skip |= LogError("VUID-VkPerfHintInfoQCOM-scale-12390", queue, perf_hint_scale_loc,
"equals to (%" PRIu32 ").",
pPerfHintInfo->scale);
}
}

return skip;
}
3 changes: 3 additions & 0 deletions layers/core_checks/core_validation.h
Original file line number Diff line number Diff line change
Expand Up @@ -3040,6 +3040,9 @@ class CoreChecks : public vvl::DeviceProxy {
bool ValidateBoundTileMemory(const vvl::Bindable& bindable, const vvl::CommandBuffer& cb_state,
const Location& loc) const override;

bool PreCallValidateQueueSetPerfHintQCOM(VkQueue queue, const VkPerfHintInfoQCOM* pPerfHintInfo,
const ErrorObject& error_obj) const override;

void Created(vvl::CommandBuffer& cb) override;
void Created(vvl::Queue& queue) override;

Expand Down
6 changes: 5 additions & 1 deletion layers/state_tracker/queue_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,12 @@ static inline std::chrono::time_point<std::chrono::steady_clock> GetCondWaitTime
class Queue : public StateObject, public SubStateManager<QueueSubState> {
public:
Queue(DeviceState& device_state, VkQueue handle, uint32_t family_index, uint32_t queue_index, VkDeviceQueueCreateFlags flags,
const VkQueueFamilyProperties& queue_family_properties)
const VkQueueFamilyProperties& queue_family_properties, VkQueueFlags perf_hint_supported_queues)
: StateObject(handle, kVulkanObjectTypeQueue),
queue_family_index(family_index),
queue_index(queue_index),
create_flags(flags),
is_perf_hint_queue((queue_family_properties.queueFlags & perf_hint_supported_queues) != 0),
device_state_(device_state),
queue_family_properties_(queue_family_properties) {}

Expand Down Expand Up @@ -193,6 +194,9 @@ class Queue : public StateObject, public SubStateManager<QueueSubState> {
bool is_used_for_presentation = false; // QueuePresent
bool is_used_for_regular_submits = false; // QueueSubmit and QueueBindSparse

// Set to true if the queuePerfHint feature is supported and current queueFlags is included in the supportedQueues
bool is_perf_hint_queue = false;

using LockGuard = std::unique_lock<std::mutex>;
LockGuard Lock() const { return LockGuard(lock_); }

Expand Down
22 changes: 18 additions & 4 deletions layers/state_tracker/state_tracker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1114,8 +1114,9 @@ VkFormatFeatureFlags2 DeviceState::GetPotentialFormatFeatures(VkFormat format) c

std::shared_ptr<Queue> DeviceState::CreateQueue(VkQueue handle, uint32_t family_index, uint32_t queue_index,
VkDeviceQueueCreateFlags flags,
const VkQueueFamilyProperties& queueFamilyProperties) {
return std::make_shared<Queue>(*this, handle, family_index, queue_index, flags, queueFamilyProperties);
const VkQueueFamilyProperties& queueFamilyProperties,
VkQueueFlags perf_hint_supported_queues) {
return std::make_shared<Queue>(*this, handle, family_index, queue_index, flags, queueFamilyProperties, perf_hint_supported_queues);
}

void DeviceState::FinishDeviceSetup(const VkDeviceCreateInfo* pCreateInfo, const Location& loc) {
Expand All @@ -1141,6 +1142,12 @@ void DeviceState::FinishDeviceSetup(const VkDeviceCreateInfo* pCreateInfo, const
std::vector<VkQueueFamilyProperties> queue_family_properties_list(num_queue_families);
DispatchGetPhysicalDeviceQueueFamilyProperties(physical_device, &num_queue_families, queue_family_properties_list.data());

VkPhysicalDeviceQueuePerfHintPropertiesQCOM queue_perf_hint_props = vku::InitStructHelper();
if (enabled_features.queuePerfHint) {
VkPhysicalDeviceProperties2 props2 = vku::InitStructHelper(&queue_perf_hint_props);
DispatchGetPhysicalDeviceProperties2(physical_device, &props2);
}

for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; ++i) {
const VkDeviceQueueCreateInfo& queue_create_info = pCreateInfo->pQueueCreateInfos[i];
queue_family_index_set.insert(queue_create_info.queueFamilyIndex);
Expand All @@ -1162,7 +1169,7 @@ void DeviceState::FinishDeviceSetup(const VkDeviceCreateInfo* pCreateInfo, const
}
assert(queue != VK_NULL_HANDLE);
Add(CreateQueue(queue, queue_info.queue_family_index, i, queue_info.flags,
queue_family_properties_list[queue_info.queue_family_index]));
queue_family_properties_list[queue_info.queue_family_index], queue_perf_hint_props.supportedQueues));
}
}
}
Expand Down Expand Up @@ -1787,7 +1794,14 @@ void DeviceState::RecordGetDeviceQueueState(uint32_t queue_family_index, uint32_
std::vector<VkQueueFamilyProperties> queue_family_properties_list(num_queue_families);
DispatchGetPhysicalDeviceQueueFamilyProperties(physical_device, &num_queue_families, queue_family_properties_list.data());

Add(CreateQueue(queue, queue_family_index, queue_index, flags, queue_family_properties_list[queue_family_index]));
VkPhysicalDeviceQueuePerfHintPropertiesQCOM queue_perf_hint_props = vku::InitStructHelper();
if (enabled_features.queuePerfHint) {
VkPhysicalDeviceProperties2 props2 = vku::InitStructHelper(&queue_perf_hint_props);
DispatchGetPhysicalDeviceProperties2(physical_device, &props2);
}

Add(CreateQueue(queue, queue_family_index, queue_index, flags, queue_family_properties_list[queue_family_index],
queue_perf_hint_props.supportedQueues));
}
}

Expand Down
3 changes: 2 additions & 1 deletion layers/state_tracker/state_tracker.h
Original file line number Diff line number Diff line change
Expand Up @@ -774,7 +774,8 @@ class DeviceState : public vvl::BaseDevice {

virtual std::shared_ptr<vvl::Queue> CreateQueue(VkQueue handle, uint32_t queue_family_index, uint32_t queue_index,
VkDeviceQueueCreateFlags flags,
const VkQueueFamilyProperties& queueFamilyProperties);
const VkQueueFamilyProperties& queueFamilyProperties,
VkQueueFlags perf_hint_supported_queues);

void PostCallRecordGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue,
const RecordObject& record_obj) override;
Expand Down
35 changes: 35 additions & 0 deletions layers/stateless/sl_queue.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/* Copyright (c) 2015-2026 The Khronos Group Inc.
* Copyright (c) 2015-2026 Valve Corporation
* Copyright (c) 2015-2026 LunarG, Inc.
* Copyright (C) 2026 Qualcomm Technologies, 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
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "stateless/stateless_validation.h"

namespace stateless {

bool Device::manual_PreCallValidateQueueSetPerfHintQCOM(VkQueue queue, const VkPerfHintInfoQCOM *pPerfHintInfo,
const Context &context) const {
bool skip = false;

if (!enabled_features.queuePerfHint) {
skip |= LogError("VUID-vkQueueSetPerfHintQCOM-queuePerfHint-12387", queue, context.error_obj.location,
"VkPhysicalDeviceQueuePerfHintFeaturesQCOM::queuePerfHint feature isn't enabled.");
}

return skip;
}

} // namespace stateless
2 changes: 2 additions & 0 deletions layers/stateless/stateless_validation.h
Original file line number Diff line number Diff line change
Expand Up @@ -1379,6 +1379,8 @@ class Device : public vvl::BaseDevice {
const Context &context) const;
bool manual_PreCallValidateCmdDispatchTileQCOM(VkCommandBuffer commandBuffer, const VkDispatchTileInfoQCOM* pDispatchTileInfo,
const Context& context) const;
bool manual_PreCallValidateQueueSetPerfHintQCOM(VkQueue queue, const VkPerfHintInfoQCOM *pPerfHintInfo,
const Context &context) const;

#include "generated/stateless_device_methods.h"
};
Expand Down
1 change: 1 addition & 0 deletions layers/vulkan/generated/stateless_validation_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24766,6 +24766,7 @@ bool Device::PreCallValidateQueueSetPerfHintQCOM(VkQueue queue, const VkPerfHint
skip |= context.ValidateRangedEnum(pPerfHintInfo_loc.dot(Field::type), vvl::Enum::VkPerfHintTypeQCOM, pPerfHintInfo->type,
"VUID-VkPerfHintInfoQCOM-type-parameter");
}
if (!skip) skip |= manual_PreCallValidateQueueSetPerfHintQCOM(queue, pPerfHintInfo, context);
return skip;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ def __init__(self,
'vkCmdBeginTransformFeedback2EXT',
'vkCmdBeginPerTileExecutionQCOM',
'vkCmdDispatchTileQCOM',
'vkQueueSetPerfHintQCOM',
]

# Commands to ignore
Expand Down
8 changes: 7 additions & 1 deletion tests/device_profiles/max_profile.json
Original file line number Diff line number Diff line change
Expand Up @@ -1815,6 +1815,12 @@
"VkPhysicalDeviceShaderMultipleWaitQueuesPropertiesQCOM": {
"maxShaderWaitQueues": 2
},
"VkPhysicalDeviceQueuePerfHintPropertiesQCOM": {
"supportedQueues": [
"VK_QUEUE_GRAPHICS_BIT",
"VK_QUEUE_COMPUTE_BIT"
]
},
"VkPhysicalDeviceTileMemoryHeapPropertiesQCOM": {
"queueSubmitBoundary": true,
"tileBufferTransfers": true
Expand Down Expand Up @@ -11322,4 +11328,4 @@
]
}
}
}
}
138 changes: 138 additions & 0 deletions tests/unit/device_queue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -604,3 +604,141 @@ TEST_F(NegativeDeviceQueue, MissingInternallySynchronizedQueuesFeature) {
vk::CreateDevice(Gpu(), &device_ci, nullptr, &test_device);
m_errorMonitor->VerifyFound();
}

TEST_F(NegativeDeviceQueue, QueuePerfHintFeatureNotEnabled) {
TEST_DESCRIPTION("Try to invoke vkQueueSetPerfHintQCOM API, but queuePerfHint feature isn't enabled.");
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredExtensions(VK_QCOM_QUEUE_PERF_HINT_EXTENSION_NAME);
RETURN_IF_SKIP(Init());

VkPerfHintInfoQCOM perf_hint_info = vku::InitStructHelper();
perf_hint_info.type = VK_PERF_HINT_TYPE_DEFAULT_QCOM;
perf_hint_info.scale = 0;

m_errorMonitor->SetDesiredError("VUID-vkQueueSetPerfHintQCOM-queuePerfHint-12387");
vk::QueueSetPerfHintQCOM(m_default_queue->handle(), &perf_hint_info);
m_errorMonitor->VerifyFound();
}

TEST_F(NegativeDeviceQueue, QueueNotInPerfHintSupportedQueues) {
TEST_DESCRIPTION("Try to invoke vkQueueSetPerfHintQCOM API, but the queue isn't in the perf-hint 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());

uint32_t bad_queue_family_index = std::numeric_limits<uint32_t>::max();
for (uint32_t index = 0; index < queue_family_count; ++index) {
if ((queue_family_props[index].queueFlags & supported_queues) == 0) {
bad_queue_family_index = index;
break;
}
}
if (bad_queue_family_index == std::numeric_limits<uint32_t>::max()) {
GTEST_SKIP() << "Failed to find the queue family that doesn't support queue perf-hint property, skipping test.";
}

RETURN_IF_SKIP(InitState());

VkQueue bad_queue = VK_NULL_HANDLE;
vk::GetDeviceQueue(device(), bad_queue_family_index, 0, &bad_queue);

VkPerfHintInfoQCOM perf_hint_info = vku::InitStructHelper();
perf_hint_info.type = VK_PERF_HINT_TYPE_DEFAULT_QCOM;
perf_hint_info.scale = 0;

m_errorMonitor->SetDesiredError("VUID-vkQueueSetPerfHintQCOM-queue-12388");
vk::QueueSetPerfHintQCOM(bad_queue, &perf_hint_info);
m_errorMonitor->VerifyFound();
}

TEST_F(NegativeDeviceQueue, MaxFrequencyPerfHintButNotZeroScale) {
TEST_DESCRIPTION("Try to invoke vkQueueSetPerfHintQCOM API with maximum frequency perf-hint, but the scale isn't zero.");
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());

uint32_t expected_queue_family_index = std::numeric_limits<uint32_t>::max();
for (uint32_t index = 0; index < queue_family_count; ++index) {
if ((queue_family_props[index].queueFlags & supported_queues) != 0) {
expected_queue_family_index = index;
break;
}
}
if (expected_queue_family_index == std::numeric_limits<uint32_t>::max()) {
GTEST_SKIP() << "Failed to find the queue family that supports queue perf-hint property, skipping test.";
}

RETURN_IF_SKIP(InitState());

VkQueue perf_hint_queue = VK_NULL_HANDLE;
vk::GetDeviceQueue(device(), expected_queue_family_index, 0, &perf_hint_queue);

VkPerfHintInfoQCOM perf_hint_info = vku::InitStructHelper();
perf_hint_info.type = VK_PERF_HINT_TYPE_FREQUENCY_MAX_QCOM;
perf_hint_info.scale = 100;

m_errorMonitor->SetDesiredError("VUID-VkPerfHintInfoQCOM-type-12389");
vk::QueueSetPerfHintQCOM(perf_hint_queue, &perf_hint_info);
m_errorMonitor->VerifyFound();
}

TEST_F(NegativeDeviceQueue, ScaledFrequencyPerfHintButInvalidScale) {
TEST_DESCRIPTION("Try to invoke vkQueueSetPerfHintQCOM API with scaled frequency perf-hint, but the scale is greater than 100.");
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());

uint32_t expected_queue_family_index = std::numeric_limits<uint32_t>::max();
for (uint32_t index = 0; index < queue_family_count; ++index) {
if ((queue_family_props[index].queueFlags & supported_queues) != 0) {
expected_queue_family_index = index;
break;
}
}
if (expected_queue_family_index == std::numeric_limits<uint32_t>::max()) {
GTEST_SKIP() << "Failed to find the queue family that supports queue perf-hint property, skipping test.";
}

RETURN_IF_SKIP(InitState());

VkQueue perf_hint_queue = VK_NULL_HANDLE;
vk::GetDeviceQueue(device(), expected_queue_family_index, 0, &perf_hint_queue);

VkPerfHintInfoQCOM perf_hint_info = vku::InitStructHelper();
perf_hint_info.type = VK_PERF_HINT_TYPE_FREQUENCY_SCALED_QCOM;
perf_hint_info.scale = 120;

m_errorMonitor->SetDesiredError("VUID-VkPerfHintInfoQCOM-scale-12390");
vk::QueueSetPerfHintQCOM(perf_hint_queue, &perf_hint_info);
m_errorMonitor->VerifyFound();
}
Loading
Loading