[PATCH vkd3d 3/3] vkd3d: Implement ID3D12CommandQueue_GetClockCalibration().
Conor McCarthy
cmccarthy at codeweavers.com
Fri Jan 14 09:17:20 CST 2022
Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
---
libs/vkd3d/command.c | 60 ++++++++++++++++++++++++++++++++++++--
libs/vkd3d/device.c | 53 +++++++++++++++++++++++++++++++++
libs/vkd3d/vkd3d_private.h | 2 ++
libs/vkd3d/vulkan_procs.h | 6 ++++
tests/d3d12.c | 4 ---
5 files changed, 119 insertions(+), 6 deletions(-)
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c
index 3e252aee..919b0584 100644
--- a/libs/vkd3d/command.c
+++ b/libs/vkd3d/command.c
@@ -6238,13 +6238,69 @@ static HRESULT STDMETHODCALLTYPE d3d12_command_queue_GetTimestampFrequency(ID3D1
return S_OK;
}
+#define TICKSPERSEC 10000000
+
static HRESULT STDMETHODCALLTYPE d3d12_command_queue_GetClockCalibration(ID3D12CommandQueue *iface,
UINT64 *gpu_timestamp, UINT64 *cpu_timestamp)
{
- FIXME("iface %p, gpu_timestamp %p, cpu_timestamp %p stub!\n",
+ struct d3d12_command_queue *command_queue = impl_from_ID3D12CommandQueue(iface);
+ struct d3d12_device *device = command_queue->device;
+ const struct vkd3d_vk_device_procs *vk_procs;
+ VkCalibratedTimestampInfoEXT infos[2];
+ uint64_t timestamps[2];
+ uint64_t deviations[2];
+ VkResult vr;
+
+ TRACE("iface %p, gpu_timestamp %p, cpu_timestamp %p.\n",
iface, gpu_timestamp, cpu_timestamp);
- return E_NOTIMPL;
+ if (!command_queue->vkd3d_queue->timestamp_bits)
+ {
+ WARN("Timestamp queries not supported.\n");
+ return E_FAIL;
+ }
+
+ if (!gpu_timestamp || !cpu_timestamp)
+ return E_INVALIDARG;
+
+ if (!device->vk_info.EXT_calibrated_timestamps || device->vk_host_time_domain == VK_TIME_DOMAIN_MAX_ENUM_EXT)
+ {
+ WARN(!device->vk_info.EXT_calibrated_timestamps
+ ? "VK_EXT_calibrated_timestamps was not found. Setting timestamps to zero.\n"
+ : "Device and/or host time domain is not available. Setting timestamps to zero.\n");
+ *gpu_timestamp = 0;
+ *cpu_timestamp = 0;
+ return S_OK;
+ }
+
+ vk_procs = &device->vk_procs;
+
+ infos[0].sType = VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT;
+ infos[0].pNext = NULL;
+ infos[0].timeDomain = VK_TIME_DOMAIN_DEVICE_EXT;
+ infos[1].sType = VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT;
+ infos[1].pNext = NULL;
+ infos[1].timeDomain = device->vk_host_time_domain;
+
+ memset(timestamps, 0, sizeof(timestamps));
+ if ((vr = VK_CALL(vkGetCalibratedTimestampsEXT(command_queue->device->vk_device,
+ ARRAY_SIZE(infos), infos, timestamps, deviations))) < 0)
+ {
+ WARN("Failed to get calibrated timestamps, vr %d.\n", vr);
+ return E_FAIL;
+ }
+
+ if (infos[1].timeDomain == VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT
+ || infos[1].timeDomain == VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT)
+ {
+ /* Convert monotonic clock to match Wine's RtlQueryPerformanceFrequency(). */
+ timestamps[1] /= 1000000000 / TICKSPERSEC;
+ }
+
+ *gpu_timestamp = timestamps[0];
+ *cpu_timestamp = timestamps[1];
+
+ return S_OK;
}
static D3D12_COMMAND_QUEUE_DESC * STDMETHODCALLTYPE d3d12_command_queue_GetDesc(ID3D12CommandQueue *iface,
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index 661ca1d9..a37f8c52 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -130,6 +130,7 @@ static const struct vkd3d_optional_extension_info optional_device_extensions[] =
VK_EXTENSION(KHR_PUSH_DESCRIPTOR, KHR_push_descriptor),
VK_EXTENSION(KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE, KHR_sampler_mirror_clamp_to_edge),
/* EXT extensions */
+ VK_EXTENSION(EXT_CALIBRATED_TIMESTAMPS, EXT_calibrated_timestamps),
VK_EXTENSION(EXT_CONDITIONAL_RENDERING, EXT_conditional_rendering),
VK_EXTENSION(EXT_DEBUG_MARKER, EXT_debug_marker),
VK_EXTENSION(EXT_DEPTH_CLIP_ENABLE, EXT_depth_clip_enable),
@@ -2349,6 +2350,57 @@ static void vkd3d_gpu_descriptor_allocator_cleanup(struct vkd3d_gpu_descriptor_a
pthread_mutex_destroy(&allocator->mutex);
}
+static bool have_vk_time_domain(VkTimeDomainEXT *domains, unsigned int count, VkTimeDomainEXT domain)
+{
+ unsigned int i;
+
+ for (i = 0; i < count; ++i)
+ if (domains[i] == domain)
+ return true;
+
+ return false;
+}
+
+static void vkd3d_time_domains_init(struct d3d12_device *device)
+{
+ const struct vkd3d_vk_instance_procs *vk_procs = &device->vkd3d_instance->vk_procs;
+ VkTimeDomainEXT domains[8];
+ uint32_t count;
+ VkResult vr;
+
+ device->vk_host_time_domain = VK_TIME_DOMAIN_MAX_ENUM_EXT;
+
+ if (!device->vk_info.EXT_calibrated_timestamps)
+ return;
+
+ count = ARRAY_SIZE(domains);
+ if ((vr = VK_CALL(vkGetPhysicalDeviceCalibrateableTimeDomainsEXT(device->vk_physical_device,
+ &count, domains))) == VK_SUCCESS || vr == VK_INCOMPLETE)
+ {
+ if (vr == VK_INCOMPLETE)
+ FIXME("Calibrated time domain list is incomplete.\n");
+
+ if (!have_vk_time_domain(domains, count, VK_TIME_DOMAIN_DEVICE_EXT))
+ {
+ WARN("Device time domain not found. Calibrated timestamps will not be available.\n");
+ return;
+ }
+
+ if (have_vk_time_domain(domains, count, VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT))
+ device->vk_host_time_domain = VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT;
+ else if (have_vk_time_domain(domains, count, VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT))
+ device->vk_host_time_domain = VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT;
+ else if (have_vk_time_domain(domains, count, VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT))
+ device->vk_host_time_domain = VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT;
+ else
+ WARN("Found no acceptable host time domain. Calibrated timestamps will not be available.\n");
+ }
+ else
+ {
+ WARN("Failed to get calibrated time domains, vr %d.\n", vr);
+ }
+}
+
/* ID3D12Device */
static inline struct d3d12_device *impl_from_ID3D12Device(ID3D12Device *iface)
{
@@ -3910,6 +3962,7 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
vkd3d_render_pass_cache_init(&device->render_pass_cache);
vkd3d_gpu_descriptor_allocator_init(&device->gpu_descriptor_allocator);
vkd3d_gpu_va_allocator_init(&device->gpu_va_allocator);
+ vkd3d_time_domains_init(device);
for (i = 0; i < ARRAY_SIZE(device->desc_mutex); ++i)
pthread_mutex_init(&device->desc_mutex[i], NULL);
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index 047f4a29..6441ba1a 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -108,6 +108,7 @@ struct vkd3d_vulkan_info
bool KHR_push_descriptor;
bool KHR_sampler_mirror_clamp_to_edge;
/* EXT device extensions */
+ bool EXT_calibrated_timestamps;
bool EXT_conditional_rendering;
bool EXT_debug_marker;
bool EXT_depth_clip_enable;
@@ -1195,6 +1196,7 @@ struct d3d12_device
struct vkd3d_queue *copy_queue;
uint32_t queue_family_indices[VKD3D_MAX_QUEUE_FAMILY_COUNT];
unsigned int queue_family_count;
+ VkTimeDomainEXT vk_host_time_domain;
struct vkd3d_instance *vkd3d_instance;
diff --git a/libs/vkd3d/vulkan_procs.h b/libs/vkd3d/vulkan_procs.h
index ec29eb45..60556735 100644
--- a/libs/vkd3d/vulkan_procs.h
+++ b/libs/vkd3d/vulkan_procs.h
@@ -55,6 +55,9 @@ VK_INSTANCE_EXT_PFN(vkGetPhysicalDeviceProperties2KHR)
VK_INSTANCE_EXT_PFN(vkCreateDebugReportCallbackEXT)
VK_INSTANCE_EXT_PFN(vkDestroyDebugReportCallbackEXT)
+/* VK_EXT_calibrated_timestamps */
+VK_INSTANCE_EXT_PFN(vkGetPhysicalDeviceCalibrateableTimeDomainsEXT)
+
/* Device functions (obtained by vkGetDeviceProcAddr). */
VK_DEVICE_PFN(vkDestroyDevice) /* Load vkDestroyDevice() first. */
VK_DEVICE_PFN(vkAllocateCommandBuffers)
@@ -192,6 +195,9 @@ VK_DEVICE_EXT_PFN(vkGetDescriptorSetLayoutSupportKHR)
/* VK_KHR_push_descriptor */
VK_DEVICE_EXT_PFN(vkCmdPushDescriptorSetKHR)
+/* VK_EXT_calibrated_timestamps */
+VK_DEVICE_EXT_PFN(vkGetCalibratedTimestampsEXT)
+
/* VK_EXT_conditional_rendering */
VK_DEVICE_EXT_PFN(vkCmdBeginConditionalRenderingEXT)
VK_DEVICE_EXT_PFN(vkCmdEndConditionalRenderingEXT)
diff --git a/tests/d3d12.c b/tests/d3d12.c
index cb9fe5fb..5b61e498 100644
--- a/tests/d3d12.c
+++ b/tests/d3d12.c
@@ -36019,19 +36019,15 @@ static void test_clock_calibration(void)
return;
hr = ID3D12CommandQueue_GetClockCalibration(context.queue, &gpu_times[0], &cpu_times[0]);
- todo
ok(hr == S_OK, "Failed to retrieve calibrated timestamps, hr %#x.\n", hr);
vkd3d_sleep(100);
hr = ID3D12CommandQueue_GetClockCalibration(context.queue, &gpu_times[1], &cpu_times[1]);
- todo
ok(hr == S_OK, "Failed to retrieve calibrated timestamps, hr %#x.\n", hr);
- todo
ok(gpu_times[1] > gpu_times[0], "Inconsistent GPU timestamps %"PRIu64" and %"PRIu64".\n",
gpu_times[0], gpu_times[1]);
- todo
ok(cpu_times[1] > cpu_times[0], "Inconsistent CPU timestamps %"PRIu64" and %"PRIu64".\n",
cpu_times[0], cpu_times[1]);
--
2.34.1
More information about the wine-devel
mailing list