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
42 changes: 41 additions & 1 deletion layers/core_checks/cc_spirv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "core_validation.h"
#include "generated/spirv_grammar_helper.h"
#include "generated/spirv_validation_helper.h"
#include "generated/dispatch_functions.h"
#include "state_tracker/shader_instruction.h"
#include "state_tracker/shader_module.h"
#include "state_tracker/shader_stage_state.h"
Expand Down Expand Up @@ -3227,9 +3228,48 @@ bool CoreChecks::ValidateDataGraphConstants(const spirv::Module &module_spirv, c
return skip;
}

const VkQueueFamilyDataGraphPropertiesARM tosa_1_0_property {
VK_STRUCTURE_TYPE_QUEUE_FAMILY_DATA_GRAPH_PROPERTIES_ARM,
nullptr,
{VK_PHYSICAL_DEVICE_DATA_GRAPH_PROCESSING_ENGINE_TYPE_DEFAULT_ARM, false},
{VK_PHYSICAL_DEVICE_DATA_GRAPH_OPERATION_TYPE_SPIRV_EXTENDED_INSTRUCTION_SET_ARM, "TOSA.001000.1", 0}
};

bool CoreChecks::ValidateDataGraphOperations(const vvl::Pipeline& pipeline, uint32_t queueFamilyIndex, const Location& loc) const {
bool skip = false;
// TODO - https://github.com/KhronosGroup/Vulkan-ValidationLayers/pull/11713

const ShaderStageState *stage_state_ptr = GetDataGraphShaderStage(pipeline);
if (!stage_state_ptr) {
return skip;
}
const spirv::EntryPoint *entry_point = stage_state_ptr->entrypoint.get();
if (!entry_point) {
return skip;
}

// this checks only the ARM operation type with TOSA, not any of the other operation types (QCOM).

if (!entry_point->uses_tosa_1_0) {
return skip;
}

bool queue_uses_tosa_1_0 = false;
for (const auto& p : physical_device_state->queue_family_data_graph_properties.at(queueFamilyIndex)) {
if (CompareVkQueueFamilyDataGraphPropertiesARM(tosa_1_0_property, p)) {
queue_uses_tosa_1_0 = true;
break;
}
}

if (!queue_uses_tosa_1_0) {
skip |=
LogError("VUID-vkCmdDispatchDataGraphARM-commandBuffer-09941", device, loc,
"Entrypoint %s includes \"TOSA.001000.1\" instructions but the queue associated with the command buffer does not include the required property:\n%s"
"vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM for queueFamilyIndex %u returned:\n%s",
entry_point->name.c_str(), string_VkQueueFamilyDataGraphPropertiesARM(tosa_1_0_property).c_str(), queueFamilyIndex,
string_VkQueueFamilyDataGraphPropertiesARM(physical_device_state->queue_family_data_graph_properties.at(queueFamilyIndex)).c_str());
}

return skip;
}

Expand Down
19 changes: 19 additions & 0 deletions layers/state_tracker/device_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,24 @@ const std::vector<VkQueueFamilyProperties> PhysicalDevice::GetQueueFamilyProps(V
return result;
}

const std::unordered_map<uint32_t, std::vector<VkQueueFamilyDataGraphPropertiesARM>> PhysicalDevice::GetQueueFamilyDataGraphProps(VkPhysicalDevice phys_dev) {
uint32_t n_families = static_cast<uint32_t>(queue_family_properties.size());
if (n_families == 0) {
// queue_family_properties not yet initialized. We should've done it before now, this is just in case
DispatchGetPhysicalDeviceQueueFamilyProperties(phys_dev, &n_families, nullptr);
}

std::unordered_map<uint32_t, std::vector<VkQueueFamilyDataGraphPropertiesARM>> all_properties;
for (uint32_t i = 0; i < n_families; i++) {
uint32_t n_properties = 0;
assert(VK_SUCCESS == DispatchGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM(phys_dev, i, &n_properties, nullptr));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this crashes locally because my machine doesn't have this function, you are going to need to warp this with

const std::unordered_map<uint32_t, std::vector<VkQueueFamilyDataGraphPropertiesARM>> PhysicalDevice::GetQueueFamilyDataGraphProps(VkPhysicalDevice phys_dev) {
    std::unordered_map<uint32_t, std::vector<VkQueueFamilyDataGraphPropertiesARM>> all_properties;
    if (has_arm_tensors) {

    }
    return all_properties;
}

... see PhysicalDevice::has_maintenance9 as an example

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

copying what we do with has_maintenance9 doesn't work, it gets initialize after we pass through here.
Is there another way to check if an extension is supported at this stage?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and how can DispatchGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM be undefined? It's in the generated vulkan code, layers/vulkan/generated/dispatch_functions.h.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function is just null, there is no implementation in my driver, so it crashes

What we can do is just cache it, the first time someone calls it in the command buffer it gets the value, the 2nd time, it just reads from it

Copy link
Contributor Author

@stefano-bucciarelli-arm stefano-bucciarelli-arm Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pushed something to check if the function is not null in the dispatch table, does this work?
Is there a simple way to make the mock ICD emulate the issue for testing, i.e. force dispatch_table.GetPhysicalDeviceQueueFamilyDataGraphPropertiesARM == nullptr?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stefano-bucciarelli-arm just remove it from TestICD and try to run any test, it will crash quite quickly

diff --git a/layers/vulkan/generated/test_icd_helper.h b/layers/vulkan/generated/test_icd_helper.h
index 8b34680c1..66fcb94e5 100644
--- a/layers/vulkan/generated/test_icd_helper.h
+++ b/layers/vulkan/generated/test_icd_helper.h
@@ -2140,9 +2140,6 @@ static VKAPI_ATTR VkResult VKAPI_CALL GetDataGraphPipelinePropertiesARM(VkDevice
                                                                         const VkDataGraphPipelineInfoARM* pPipelineInfo,
                                                                         uint32_t propertiesCount,
                                                                         VkDataGraphPipelinePropertyQueryResultARM* pProperties);
-static VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceQueueFamilyDataGraphPropertiesARM(
-    VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, uint32_t* pQueueFamilyDataGraphPropertyCount,
-    VkQueueFamilyDataGraphPropertiesARM* pQueueFamilyDataGraphProperties);
 static VKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM(
     VkPhysicalDevice physicalDevice,
     const VkPhysicalDeviceQueueFamilyDataGraphProcessingEngineInfoARM* pQueueFamilyDataGraphProcessingEngineInfo,
@@ -3094,7 +3091,6 @@ static const std::unordered_map<std::string, void*> name_to_func_ptr_map = {
     {"vkCmdDispatchDataGraphARM", (void*)CmdDispatchDataGraphARM},
     {"vkGetDataGraphPipelineAvailablePropertiesARM", (void*)GetDataGraphPipelineAvailablePropertiesARM},
     {"vkGetDataGraphPipelinePropertiesARM", (void*)GetDataGraphPipelinePropertiesARM},
-    {"vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM", (void*)GetPhysicalDeviceQueueFamilyDataGraphPropertiesARM},
     {"vkGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM",
      (void*)GetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM},
     {"vkCmdSetAttachmentFeedbackLoopEnableEXT", (void*)CmdSetAttachmentFeedbackLoopEnableEXT},
diff --git a/tests/icd/test_icd.cpp b/tests/icd/test_icd.cpp
index 924d5c888..7d647e76f 100644
--- a/tests/icd/test_icd.cpp
+++ b/tests/icd/test_icd.cpp
@@ -1454,20 +1454,6 @@ static VKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceExternalTensorPropertiesARM(
     }
 }
 
-static VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceQueueFamilyDataGraphPropertiesARM(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, uint32_t *pQueueFamilyDataGraphPropertyCount, VkQueueFamilyDataGraphPropertiesARM* pQueueFamilyDataGraphProperties) {
-
-    // TODO: Need a way for test to decide to support or not support various engines
-
-    if (pQueueFamilyDataGraphProperties == nullptr) {
-        *pQueueFamilyDataGraphPropertyCount = 1;
-    } else {
-        pQueueFamilyDataGraphProperties[0].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_DATA_GRAPH_PROPERTIES_ARM;
-        pQueueFamilyDataGraphProperties[0].engine = { VK_PHYSICAL_DEVICE_DATA_GRAPH_PROCESSING_ENGINE_TYPE_DEFAULT_ARM, false };
-        pQueueFamilyDataGraphProperties[0].operation = { VK_PHYSICAL_DEVICE_DATA_GRAPH_OPERATION_TYPE_SPIRV_EXTENDED_INSTRUCTION_SET_ARM, "TOSA.001000.1", 0 };
-    }
-    return VK_SUCCESS;
-}
-
 static VKAPI_ATTR VkResult VKAPI_CALL
 GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo,
                                         VkImageFormatProperties2* pImageFormatProperties) {

std::vector<VkQueueFamilyDataGraphPropertiesARM> family_properties(n_properties, vku::InitStruct<VkQueueFamilyDataGraphPropertiesARM>());
assert(VK_SUCCESS == DispatchGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM(phys_dev, i, &n_properties, family_properties.data()));
all_properties.try_emplace(i, std::move(family_properties));
}
return all_properties;
}

VkQueueFlags PhysicalDevice::GetSupportedQueues() {
VkQueueFlags flags = 0;
for (const auto& prop : queue_family_properties) {
Expand All @@ -65,6 +83,7 @@ VkQueueFlags PhysicalDevice::GetSupportedQueues() {
PhysicalDevice::PhysicalDevice(VkPhysicalDevice handle)
: StateObject(handle, kVulkanObjectTypePhysicalDevice),
queue_family_properties(GetQueueFamilyProps(handle)),
queue_family_data_graph_properties(GetQueueFamilyDataGraphProps(handle)),
supported_queues(GetSupportedQueues()) {}

} // namespace vvl
4 changes: 4 additions & 0 deletions layers/state_tracker/device_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ class PhysicalDevice : public StateObject {
public:
uint32_t queue_family_known_count = 1; // spec implies one QF must always be supported
const std::vector<VkQueueFamilyProperties> queue_family_properties;
const std::unordered_map<uint32_t, std::vector<VkQueueFamilyDataGraphPropertiesARM>> queue_family_data_graph_properties;

const VkQueueFlags supported_queues;
uint32_t display_plane_property_count = 0;
uint32_t surface_formats_count = 0;
Expand Down Expand Up @@ -77,6 +79,8 @@ class PhysicalDevice : public StateObject {
vvl::unordered_map<Func, CallState> call_state_;

const std::vector<VkQueueFamilyProperties> GetQueueFamilyProps(VkPhysicalDevice phys_dev);
const std::unordered_map<uint32_t, std::vector<VkQueueFamilyDataGraphPropertiesARM>> GetQueueFamilyDataGraphProps(VkPhysicalDevice phys_dev);

VkQueueFlags GetSupportedQueues();
};

Expand Down
6 changes: 0 additions & 6 deletions layers/vulkan/generated/test_icd_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -5969,12 +5969,6 @@ static VKAPI_ATTR VkResult VKAPI_CALL GetDataGraphPipelinePropertiesARM(VkDevice
return VK_SUCCESS;
}

static VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceQueueFamilyDataGraphPropertiesARM(
VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, uint32_t* pQueueFamilyDataGraphPropertyCount,
VkQueueFamilyDataGraphPropertiesARM* pQueueFamilyDataGraphProperties) {
return VK_SUCCESS;
}

static VKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM(
VkPhysicalDevice physicalDevice,
const VkPhysicalDeviceQueueFamilyDataGraphProcessingEngineInfoARM* pQueueFamilyDataGraphProcessingEngineInfo,
Expand Down
1 change: 1 addition & 0 deletions scripts/generators/test_icd_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ def __init__(self):
'vkGetPhysicalDeviceExternalSemaphoreProperties',
'vkGetPhysicalDeviceExternalFenceProperties',
'vkGetPhysicalDeviceExternalBufferProperties',
'vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM',
'vkGetBufferMemoryRequirements',
'vkGetBufferMemoryRequirements2',
'vkGetDeviceBufferMemoryRequirements',
Expand Down
14 changes: 14 additions & 0 deletions tests/icd/test_icd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1454,6 +1454,20 @@ static VKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceExternalTensorPropertiesARM(
}
}

static VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceQueueFamilyDataGraphPropertiesARM(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, uint32_t *pQueueFamilyDataGraphPropertyCount, VkQueueFamilyDataGraphPropertiesARM* pQueueFamilyDataGraphProperties) {

// TODO: Need a way for test to decide to support or not support various engines

if (pQueueFamilyDataGraphProperties == nullptr) {
*pQueueFamilyDataGraphPropertyCount = 1;
} else {
pQueueFamilyDataGraphProperties[0].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_DATA_GRAPH_PROPERTIES_ARM;
pQueueFamilyDataGraphProperties[0].engine = { VK_PHYSICAL_DEVICE_DATA_GRAPH_PROCESSING_ENGINE_TYPE_DEFAULT_ARM, false };
pQueueFamilyDataGraphProperties[0].operation = { VK_PHYSICAL_DEVICE_DATA_GRAPH_OPERATION_TYPE_SPIRV_EXTENDED_INSTRUCTION_SET_ARM, "TOSA.001000.1", 0 };
}
return VK_SUCCESS;
}

static VKAPI_ATTR VkResult VKAPI_CALL
GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo,
VkImageFormatProperties2* pImageFormatProperties) {
Expand Down
68 changes: 68 additions & 0 deletions tests/unit/data_graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "descriptor_helper.h"
#include "data_graph_objects.h"
#include "generated/pnext_chain_extraction.h"
#include "../layers/utils/vk_struct_compare.h"
#include <vector>

class NegativeDataGraph : public DataGraphTest {};
Expand Down Expand Up @@ -2371,3 +2372,70 @@ TEST_F(NegativeDataGraph, BindWrongBindPoint) {
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_DATA_GRAPH_ARM, pipeline);
m_errorMonitor->VerifyFound();
}

TEST_F(NegativeDataGraph, CmdDispatchWrongQueue) {
TEST_DESCRIPTION("Try to create a datagraph where the command buffer is allocated on a queue that does not support TOSA 1.0");
InitBasicDataGraph();
RETURN_IF_SKIP(Init());

// find a queue family that does NOT support TOSA
const VkQueueFamilyDataGraphPropertiesARM tosa_1_0_property {
VK_STRUCTURE_TYPE_QUEUE_FAMILY_DATA_GRAPH_PROPERTIES_ARM,
nullptr,
{VK_PHYSICAL_DEVICE_DATA_GRAPH_PROCESSING_ENGINE_TYPE_DEFAULT_ARM, false},
{VK_PHYSICAL_DEVICE_DATA_GRAPH_OPERATION_TYPE_SPIRV_EXTENDED_INSTRUCTION_SET_ARM, "TOSA.001000.1", 0}
};
uint32_t queue_without_tosa_1_0_idx = UINT32_MAX;
uint32_t n_queue_families;
vk::GetPhysicalDeviceQueueFamilyProperties(Gpu(), &n_queue_families, nullptr);
for (uint32_t qfi = 0; qfi < n_queue_families; qfi++) {
uint32_t n_properties;
ASSERT_TRUE(VK_SUCCESS == vk::GetPhysicalDeviceQueueFamilyDataGraphPropertiesARM(Gpu(), qfi, &n_properties, nullptr));
std::vector<VkQueueFamilyDataGraphPropertiesARM> properties(n_properties, {VK_STRUCTURE_TYPE_QUEUE_FAMILY_DATA_GRAPH_PROPERTIES_ARM});
ASSERT_TRUE(VK_SUCCESS == vk::GetPhysicalDeviceQueueFamilyDataGraphPropertiesARM(Gpu(), qfi, &n_properties, properties.data()));

bool queue_supports_tosa_1_0 = false;
for (const auto& p : properties) {
if (CompareVkQueueFamilyDataGraphPropertiesARM(tosa_1_0_property, p)) {
queue_supports_tosa_1_0 = true;
break;
}
}
if (!queue_supports_tosa_1_0) {
queue_without_tosa_1_0_idx = qfi;
break;
}
}

if (UINT32_MAX == queue_without_tosa_1_0_idx) {
GTEST_SKIP() << "All queues support TOSA, impossible to create the error condition, skip.";
}

vkt::dg::DataGraphPipelineHelper pipeline(*this);
pipeline.CreateDataGraphPipeline();

VkDataGraphPipelineSessionCreateInfoARM session_ci = vku::InitStructHelper();
session_ci.dataGraphPipeline = pipeline;
vkt::DataGraphPipelineSession session(*m_device, session_ci);
session.GetMemoryReqs();
CheckSessionMemory(session);

auto &bind_point_reqs = session.BindPointReqs();
std::vector<vkt::DeviceMemory> device_mem(bind_point_reqs.size());
session.AllocSessionMem(device_mem);
auto session_bind_infos = InitSessionBindInfo(session, device_mem);
vk::BindDataGraphPipelineSessionMemoryARM(*m_device, session_bind_infos.size(), session_bind_infos.data());

pipeline.descriptor_set_->WriteDescriptorTensorInfo(0, &pipeline.tensor_views_[0]->handle(), 0);
pipeline.descriptor_set_->WriteDescriptorTensorInfo(1, &pipeline.tensor_views_[1]->handle(), 0);
pipeline.descriptor_set_->UpdateDescriptorSets();

m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_DATA_GRAPH_ARM, pipeline);
vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_DATA_GRAPH_ARM, pipeline.pipeline_layout_, 0, 1,
&pipeline.descriptor_set_.get()->set_, 0, nullptr);
m_errorMonitor->SetDesiredError("VUID-vkCmdDispatchDataGraphARM-commandBuffer-09941");
vk::CmdDispatchDataGraphARM(m_command_buffer, session, nullptr);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
Loading