diff --git a/src/virtio/vulkan/vn_physical_device.c b/src/virtio/vulkan/vn_physical_device.c index bc7a428d0a4..98eec8c74f5 100644 --- a/src/virtio/vulkan/vn_physical_device.c +++ b/src/virtio/vulkan/vn_physical_device.c @@ -738,6 +738,8 @@ vn_physical_device_init_properties(struct vn_physical_device *physical_dev) } memcpy(vk10_props->deviceName, device_name, device_name_len + 1); + /* store renderer VkDriverId for implementation specific workarounds */ + physical_dev->renderer_driver_id = vk12_props->driverID; VN_SET_CORE_VALUE(vk12_props, driverID, VK_DRIVER_ID_MESA_VENUS); snprintf(vk12_props->driverName, sizeof(vk12_props->driverName), "venus"); diff --git a/src/virtio/vulkan/vn_physical_device.h b/src/virtio/vulkan/vn_physical_device.h index 729bd18fd5c..1915d9d7a9a 100644 --- a/src/virtio/vulkan/vn_physical_device.h +++ b/src/virtio/vulkan/vn_physical_device.h @@ -117,6 +117,7 @@ struct vn_physical_device { struct vn_physical_device_features features; struct vn_physical_device_properties properties; + enum VkDriverId renderer_driver_id; VkQueueFamilyProperties2 *queue_family_properties; uint32_t queue_family_count; diff --git a/src/virtio/vulkan/vn_query_pool.c b/src/virtio/vulkan/vn_query_pool.c index 3973f3020d4..e8bca85a8bf 100644 --- a/src/virtio/vulkan/vn_query_pool.c +++ b/src/virtio/vulkan/vn_query_pool.c @@ -14,6 +14,7 @@ #include "vn_device.h" #include "vn_feedback.h" +#include "vn_physical_device.h" /* query pool commands */ @@ -100,6 +101,26 @@ vn_CreateQueryPool(VkDevice device, } } + /* Venus has to handle overflow behavior with query feedback to keep + * consistency between vkCmdCopyQueryPoolResults and vkGetQueryPoolResults. + * The default query feedback behavior is to wrap on overflow. However, per + * spec: + * + * If an unsigned integer query’s value overflows the result type, the + * value may either wrap or saturate. + * + * We detect the renderer side implementation to align with the + * implementation specific behavior. + */ + switch (dev->physical_device->renderer_driver_id) { + case VK_DRIVER_ID_ARM_PROPRIETARY: + case VK_DRIVER_ID_MESA_TURNIP: + pool->saturate_on_overflow = true; + break; + default: + break; + }; + VkQueryPool pool_handle = vn_query_pool_to_handle(pool); vn_async_vkCreateQueryPool(dev->instance, device, pCreateInfo, NULL, &pool_handle); @@ -205,8 +226,13 @@ vn_get_query_pool_feedback(struct vn_query_pool *pool, const uint32_t avail = (uint32_t)src[src_index + pool->result_array_size]; if (avail) { - for (uint32_t j = 0; j < pool->result_array_size; j++) - dst[dst_index + j] = (uint32_t)src[src_index + j]; + for (uint32_t j = 0; j < pool->result_array_size; j++) { + const uint64_t src_val = src[src_index + j]; + dst[dst_index + j] = + src_val > UINT32_MAX && pool->saturate_on_overflow + ? UINT32_MAX + : (uint32_t)src_val; + } } else { result = VK_NOT_READY; /* valid to return result of 0 if partial bit is set */ diff --git a/src/virtio/vulkan/vn_query_pool.h b/src/virtio/vulkan/vn_query_pool.h index efaad02734b..9246b7d3c86 100644 --- a/src/virtio/vulkan/vn_query_pool.h +++ b/src/virtio/vulkan/vn_query_pool.h @@ -23,6 +23,7 @@ struct vn_query_pool { /* non-NULL if VN_PERF_NO_QUERY_FEEDBACK is disabled */ struct vn_feedback_buffer *feedback; uint32_t result_array_size; + bool saturate_on_overflow; }; VK_DEFINE_NONDISP_HANDLE_CASTS(vn_query_pool, base.base,