From 4d5f0f6ee28892d2625efdba65502d34682e26aa Mon Sep 17 00:00:00 2001 From: Christoph Pillmayer Date: Wed, 7 May 2025 09:15:41 +0000 Subject: [PATCH] panvk: Implement VK_KHR_calibrated_timestamps Add entrypoints for calibrated timestamps. Co-authored-by: Mary Guillemard Reviewed-by: Lars-Ivar Hesselberg Simonsen Part-of: --- src/panfrost/vulkan/panvk_physical_device.c | 32 ++++++++++ src/panfrost/vulkan/panvk_vX_device.c | 68 +++++++++++++++++++++ 2 files changed, 100 insertions(+) diff --git a/src/panfrost/vulkan/panvk_physical_device.c b/src/panfrost/vulkan/panvk_physical_device.c index 9bdb1161795..f56f965f131 100644 --- a/src/panfrost/vulkan/panvk_physical_device.c +++ b/src/panfrost/vulkan/panvk_physical_device.c @@ -1258,3 +1258,35 @@ panvk_GetPhysicalDeviceExternalBufferProperties( .compatibleHandleTypes = handle_types, }; } + +static const VkTimeDomainKHR panvk_time_domains[] = { + VK_TIME_DOMAIN_DEVICE_KHR, + VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR, +#ifdef CLOCK_MONOTONIC_RAW + VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR, +#endif +}; + +VKAPI_ATTR VkResult VKAPI_CALL +panvk_GetPhysicalDeviceCalibrateableTimeDomainsKHR( + VkPhysicalDevice physicalDevice, uint32_t *pTimeDomainCount, + VkTimeDomainKHR *pTimeDomains) +{ + VK_FROM_HANDLE(panvk_physical_device, pdev, physicalDevice); + VK_OUTARRAY_MAKE_TYPED(VkTimeDomainKHR, out, pTimeDomains, pTimeDomainCount); + + int d = 0; + + /* If GPU query timestamp isn't supported, skip device domain */ + if (!pdev->kmod.props.gpu_can_query_timestamp) + d++; + + for (; d < ARRAY_SIZE(panvk_time_domains); d++) { + vk_outarray_append_typed(VkTimeDomainKHR, &out, i) + { + *i = panvk_time_domains[d]; + } + } + + return vk_outarray_status(&out); +} diff --git a/src/panfrost/vulkan/panvk_vX_device.c b/src/panfrost/vulkan/panvk_vX_device.c index 5357b6dcb79..2483cfae715 100644 --- a/src/panfrost/vulkan/panvk_vX_device.c +++ b/src/panfrost/vulkan/panvk_vX_device.c @@ -609,3 +609,71 @@ panvk_per_arch(GetRenderingAreaGranularityKHR)( { *pGranularity = (VkExtent2D){32, 32}; } + +VKAPI_ATTR VkResult VKAPI_CALL +panvk_per_arch(GetCalibratedTimestampsKHR)( + VkDevice _device, uint32_t timestampCount, + const VkCalibratedTimestampInfoKHR *pTimestampInfos, uint64_t *pTimestamps, + uint64_t *pMaxDeviation) +{ + VK_FROM_HANDLE(panvk_device, device, _device); + struct panvk_physical_device *pdev = + to_panvk_physical_device(device->vk.physical); + + bool requested_domain[] = { + [VK_TIME_DOMAIN_DEVICE_KHR] = false, + [VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR] = false, + [VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR] = false, + }; + uint64_t timestamps[] = { + [VK_TIME_DOMAIN_DEVICE_KHR] = 0, + [VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR] = 0, + [VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR] = 0, + }; + uint64_t max_period = 0; + + for (uint32_t idx = 0; idx < timestampCount; ++idx) + requested_domain[pTimestampInfos[idx].timeDomain] |= true; + + uint64_t begin, end; +#ifdef CLOCK_MONOTONIC_RAW + requested_domain[VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR] = true; + begin = vk_clock_gettime(CLOCK_MONOTONIC_RAW); +#else + requested_domain[VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR] = true; + begin = vk_clock_gettime(CLOCK_MONOTONIC); +#endif + + if (requested_domain[VK_TIME_DOMAIN_DEVICE_KHR]) { + timestamps[VK_TIME_DOMAIN_DEVICE_KHR] = + pan_kmod_query_timestamp(pdev->kmod.dev); + max_period = MAX2(max_period, panvk_get_gpu_system_timestamp_period(pdev)); + } + + if (requested_domain[VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR]) { + timestamps[VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR] = + vk_clock_gettime(CLOCK_MONOTONIC); + max_period = MAX2(max_period, 1); + } + +#ifdef CLOCK_MONOTONIC_RAW + if (requested_domain[VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR]) { + timestamps[VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR] = + vk_clock_gettime(CLOCK_MONOTONIC_RAW); + max_period = MAX2(max_period, 1); + } +#endif + +#ifdef CLOCK_MONOTONIC_RAW + end = timestamps[VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR]; +#else + end = timestamps[VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR]; +#endif + + for (uint32_t idx = 0; idx < timestampCount; ++idx) + pTimestamps[idx] = timestamps[pTimestampInfos[idx].timeDomain]; + + *pMaxDeviation = vk_time_max_deviation(begin, end, max_period); + + return VK_SUCCESS; +}