From 16753bc2f1c77fae321f354dc381ac3aa1939360 Mon Sep 17 00:00:00 2001 From: Echo J Date: Tue, 19 Mar 2024 16:57:08 +0200 Subject: [PATCH] nvk: Implement calibrated timestamps This implementation is mostly a copy-paste from RADV Part-of: --- docs/features.txt | 4 +- src/nouveau/vulkan/nvk_device.c | 52 ++++++++++++++++++++++++ src/nouveau/vulkan/nvk_physical_device.c | 28 +++++++++++++ src/nouveau/winsys/nouveau_device.c | 10 +++++ src/nouveau/winsys/nouveau_device.h | 1 + 5 files changed, 93 insertions(+), 2 deletions(-) diff --git a/docs/features.txt b/docs/features.txt index 34ab79d8a10..f176605ee30 100644 --- a/docs/features.txt +++ b/docs/features.txt @@ -503,7 +503,7 @@ Khronos extensions that are not part of any Vulkan version: VK_KHR_acceleration_structure DONE (anv/gfx12.5+, lvp, radv/gfx10.3+) VK_KHR_android_surface not started - VK_KHR_calibrated_timestamps DONE (anv, radv) + VK_KHR_calibrated_timestamps DONE (anv, nvk, radv) VK_KHR_cooperative_matrix DONE (anv, radv/gfx11+) VK_KHR_deferred_host_operations DONE (anv, hasvk, lvp, radv) VK_KHR_display DONE (anv, nvk, pvr, radv, tu, v3dv) @@ -558,7 +558,7 @@ Khronos extensions that are not part of any Vulkan version: VK_EXT_attachment_feedback_loop_layout DONE (anv, lvp, nvk, radv, tu, v3dv, vn) VK_EXT_border_color_swizzle DONE (anv, hasvk, lvp, nvk, radv/gfx10+, tu, v3dv, vn) VK_EXT_buffer_device_address DONE (anv, hasvk, nvk, radv) - VK_EXT_calibrated_timestamps DONE (anv, hasvk, lvp, radv, vn) + VK_EXT_calibrated_timestamps DONE (anv, hasvk, nvk, lvp, radv, vn) VK_EXT_color_write_enable DONE (anv, hasvk, lvp, nvk, radv, tu, v3dv, vn) VK_EXT_conditional_rendering DONE (anv, hasvk, lvp, nvk, radv, tu, vn) VK_EXT_conservative_rasterization DONE (anv, radv, vn) diff --git a/src/nouveau/vulkan/nvk_device.c b/src/nouveau/vulkan/nvk_device.c index f1cddc0589a..bdba3f8218e 100644 --- a/src/nouveau/vulkan/nvk_device.c +++ b/src/nouveau/vulkan/nvk_device.c @@ -322,6 +322,58 @@ nvk_DestroyDevice(VkDevice _device, const VkAllocationCallbacks *pAllocator) vk_free(&dev->vk.alloc, dev); } +VKAPI_ATTR VkResult VKAPI_CALL +nvk_GetCalibratedTimestampsKHR(VkDevice _device, + uint32_t timestampCount, + const VkCalibratedTimestampInfoKHR *pTimestampInfos, + uint64_t *pTimestamps, + uint64_t *pMaxDeviation) +{ + VK_FROM_HANDLE(nvk_device, dev, _device); + struct nvk_physical_device *pdev = nvk_device_physical(dev); + uint64_t max_clock_period = 0; + uint64_t begin, end; + int d; + +#ifdef CLOCK_MONOTONIC_RAW + begin = vk_clock_gettime(CLOCK_MONOTONIC_RAW); +#else + begin = vk_clock_gettime(CLOCK_MONOTONIC); +#endif + + for (d = 0; d < timestampCount; d++) { + switch (pTimestampInfos[d].timeDomain) { + case VK_TIME_DOMAIN_DEVICE_KHR: + pTimestamps[d] = nouveau_ws_device_timestamp(pdev->ws_dev); + max_clock_period = MAX2(max_clock_period, 1); /* FIXME: Is timestamp period actually 1? */ + break; + case VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR: + pTimestamps[d] = vk_clock_gettime(CLOCK_MONOTONIC); + max_clock_period = MAX2(max_clock_period, 1); + break; + +#ifdef CLOCK_MONOTONIC_RAW + case VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR: + pTimestamps[d] = begin; + break; +#endif + default: + pTimestamps[d] = 0; + break; + } + } + +#ifdef CLOCK_MONOTONIC_RAW + end = vk_clock_gettime(CLOCK_MONOTONIC_RAW); +#else + end = vk_clock_gettime(CLOCK_MONOTONIC); +#endif + + *pMaxDeviation = vk_time_max_deviation(begin, end, max_clock_period); + + return VK_SUCCESS; +} + VkResult nvk_device_ensure_slm(struct nvk_device *dev, uint32_t bytes_per_thread) diff --git a/src/nouveau/vulkan/nvk_physical_device.c b/src/nouveau/vulkan/nvk_physical_device.c index 7c398196558..d0e5d715a4c 100644 --- a/src/nouveau/vulkan/nvk_physical_device.c +++ b/src/nouveau/vulkan/nvk_physical_device.c @@ -83,6 +83,7 @@ nvk_get_device_extensions(const struct nvk_instance *instance, .KHR_16bit_storage = true, .KHR_bind_memory2 = true, .KHR_buffer_device_address = true, + .KHR_calibrated_timestamps = true, .KHR_copy_commands2 = true, .KHR_create_renderpass2 = true, .KHR_dedicated_allocation = true, @@ -167,6 +168,7 @@ nvk_get_device_extensions(const struct nvk_instance *instance, .EXT_attachment_feedback_loop_layout = true, .EXT_border_color_swizzle = true, .EXT_buffer_device_address = true, + .EXT_calibrated_timestamps = true, .EXT_conditional_rendering = true, .EXT_color_write_enable = true, .EXT_custom_border_color = true, @@ -1412,6 +1414,32 @@ nvk_GetPhysicalDeviceQueueFamilyProperties2( } } +static const VkTimeDomainKHR nvk_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 +nvk_GetPhysicalDeviceCalibrateableTimeDomainsKHR( + VkPhysicalDevice physicalDevice, + uint32_t *pTimeDomainCount, + VkTimeDomainKHR *pTimeDomains) +{ + VK_OUTARRAY_MAKE_TYPED(VkTimeDomainKHR, out, pTimeDomains, pTimeDomainCount); + + for (int d = 0; d < ARRAY_SIZE(nvk_time_domains); d++) { + vk_outarray_append_typed(VkTimeDomainKHR, &out, i) { + *i = nvk_time_domains[d]; + } + } + + return vk_outarray_status(&out); +} + + VKAPI_ATTR void VKAPI_CALL nvk_GetPhysicalDeviceMultisamplePropertiesEXT( VkPhysicalDevice physicalDevice, diff --git a/src/nouveau/winsys/nouveau_device.c b/src/nouveau/winsys/nouveau_device.c index c752b954281..580cdf72b9c 100644 --- a/src/nouveau/winsys/nouveau_device.c +++ b/src/nouveau/winsys/nouveau_device.c @@ -445,3 +445,13 @@ nouveau_ws_device_vram_used(struct nouveau_ws_device *device) return used; } + +uint64_t +nouveau_ws_device_timestamp(struct nouveau_ws_device *device) +{ + uint64_t timestamp = 0; + if (nouveau_ws_param(device->fd, NOUVEAU_GETPARAM_PTIMER_TIME, ×tamp)) + return 0; + + return timestamp; +} diff --git a/src/nouveau/winsys/nouveau_device.h b/src/nouveau/winsys/nouveau_device.h index ad3c61d42cd..4ad91d32d48 100644 --- a/src/nouveau/winsys/nouveau_device.h +++ b/src/nouveau/winsys/nouveau_device.h @@ -65,6 +65,7 @@ struct nouveau_ws_device *nouveau_ws_device_new(struct _drmDevice *drm_device); void nouveau_ws_device_destroy(struct nouveau_ws_device *); uint64_t nouveau_ws_device_vram_used(struct nouveau_ws_device *); +uint64_t nouveau_ws_device_timestamp(struct nouveau_ws_device *device); #ifdef __cplusplus }