It's technically correct in warning about overwriting the entire vec4 from the address of .x, if a bit overzealous. It's probably a good warning to keep enabled.
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- tests/d3d12.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/tests/d3d12.c b/tests/d3d12.c index 2507974f..b611448d 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -4737,7 +4737,7 @@ static void test_clear_render_target_view(void)
ID3D12Device_CreateRenderTargetView(device, resource, &rtv_desc, rtv_handle);
- ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, rtv_handle, &array_colors[i].x, 0, NULL); + ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, rtv_handle, (const float *)&array_colors[i], 0, NULL); }
transition_resource_state(command_list, resource, @@ -4768,7 +4768,7 @@ static void test_clear_render_target_view(void)
ID3D12Device_CreateRenderTargetView(device, resource, &rtv_desc, rtv_handle);
- ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, rtv_handle, &array_colors[i].x, 0, NULL); + ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, rtv_handle, (const float *)&array_colors[i], 0, NULL); }
transition_resource_state(command_list, resource, @@ -5703,7 +5703,7 @@ static void test_unknown_rtv_format(void) create_render_target(&context, &desc, &render_targets[1], &rtvs[2]);
for (i = 0; i < ARRAY_SIZE(rtvs); ++i) - ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, rtvs[i], &white.x, 0, NULL); + ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, rtvs[i], (const float *)&white, 0, NULL);
/* NULL RTV */ memset(&rtv_desc, 0, sizeof(rtv_desc)); @@ -14123,7 +14123,7 @@ static void test_gather(void) context.pipeline_state = create_pipeline_state(context.device, context.root_signature, desc.rt_format, NULL, &ps_gather4, NULL);
- ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, &white.x, 0, NULL); + ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, (const float *)&white, 0, NULL);
ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); @@ -14161,7 +14161,7 @@ static void test_gather(void) context.pipeline_state = create_pipeline_state(context.device, context.root_signature, desc.rt_format, NULL, &ps_gather4_offset, NULL);
- ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, &white.x, 0, NULL); + ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, (const float *)&white, 0, NULL);
ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); @@ -14199,7 +14199,7 @@ static void test_gather(void) context.pipeline_state = create_pipeline_state(context.device, context.root_signature, desc.rt_format, NULL, &ps_gather4_green, NULL);
- ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, &white.x, 0, NULL); + ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, (const float *)&white, 0, NULL);
ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); @@ -14237,7 +14237,7 @@ static void test_gather(void) context.pipeline_state = create_pipeline_state(context.device, context.root_signature, desc.rt_format, NULL, &ps_gather4_po, NULL);
- ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, &white.x, 0, NULL); + ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, (const float *)&white, 0, NULL);
ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); @@ -14273,7 +14273,7 @@ static void test_gather(void) constants.offset_x = 0; constants.offset_y = 0;
- ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, &white.x, 0, NULL); + ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, (const float *)&white, 0, NULL);
ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); @@ -14463,7 +14463,7 @@ static void test_gather_c(void) context.pipeline_state = create_pipeline_state(context.device, context.root_signature, desc.rt_format, NULL, &ps_gather4_c, NULL);
- ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, &white.x, 0, NULL); + ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, (const float *)&white, 0, NULL);
ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); @@ -14501,7 +14501,7 @@ static void test_gather_c(void) context.pipeline_state = create_pipeline_state(context.device, context.root_signature, desc.rt_format, NULL, &ps_gather4_po_c, NULL);
- ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, &white.x, 0, NULL); + ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, (const float *)&white, 0, NULL);
ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); @@ -14537,7 +14537,7 @@ static void test_gather_c(void) constants.offset_x = 0; constants.offset_y = 0;
- ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, &white.x, 0, NULL); + ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, (const float *)&white, 0, NULL);
ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); @@ -15388,7 +15388,7 @@ static void test_multisample_array_texture(void) rtv_desc.Texture2DMSArray.ArraySize = 1; ID3D12Device_CreateRenderTargetView(device, texture, &rtv_desc, cpu_handle);
- ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, cpu_handle, &colors[i].x, 0, NULL); + ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, cpu_handle, (const float *)&colors[i], 0, NULL); }
transition_resource_state(command_list, texture,
Based on a vkd3d-proton patch by Hans-Kristian Arntzen.
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- tests/d3d12.c | 30 ++++++++++++++++++++++++++++++ tests/d3d12_crosstest.h | 14 ++++++++++++++ 2 files changed, 44 insertions(+)
diff --git a/tests/d3d12.c b/tests/d3d12.c index b611448d..cb9fe5fb 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -36009,6 +36009,35 @@ done: destroy_test_context(&context); }
+static void test_clock_calibration(void) +{ + uint64_t cpu_times[2] = {0}, gpu_times[2] = {0}; + struct test_context context; + HRESULT hr; + + if (!init_test_context(&context, NULL)) + 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]); + + destroy_test_context(&context); +} + START_TEST(d3d12) { parse_args(argc, argv); @@ -36186,4 +36215,5 @@ START_TEST(d3d12) run_test(test_resource_arrays); run_test(test_unbounded_resource_arrays); run_test(test_unbounded_samplers); + run_test(test_clock_calibration); } diff --git a/tests/d3d12_crosstest.h b/tests/d3d12_crosstest.h index 0b77bdee..fc761809 100644 --- a/tests/d3d12_crosstest.h +++ b/tests/d3d12_crosstest.h @@ -60,6 +60,7 @@ typedef int HRESULT; #else # define VKD3D_UTILS_API_VERSION VKD3D_API_VERSION_1_2 # include <pthread.h> +# include <unistd.h> # include "vkd3d.h" # include "vkd3d_utils.h" #endif @@ -203,6 +204,19 @@ static inline bool join_thread(HANDLE untyped_thread) } #endif
+#ifdef _WIN32 +static inline void vkd3d_sleep(unsigned int ms) +{ + Sleep(ms); +} + +#else +static inline void vkd3d_sleep(unsigned int ms) +{ + usleep(1000 * ms); +} +#endif + static HRESULT wait_for_fence(ID3D12Fence *fence, uint64_t value) { unsigned int ret;
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Conor McCarthy cmccarthy@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]);
On Fri, 14 Jan 2022 at 16:18, Conor McCarthy cmccarthy@codeweavers.com wrote:
- 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;
- }
Is TICKSPERSEC something we should allow to be specified by vkd3d_create_instance() or vkd3d_create_device()? It seems like something that may be subject to future change.
+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;
It may be best to avoid VK_TIME_DOMAIN_MAX_ENUM_EXT; I'm not sure it's considered part of the API by Khronos. Note that e.g. VK_PIPELINE_BIND_POINT_RANGE_SIZE was simply removed at some point, and that the Wine Vulkan headers don't have VK_TIME_DOMAIN_MAX_ENUM_EXT. They do have VK_TIME_DOMAIN_EXT_MAX_ENUM instead, which may be a bug, but regardless.