From: Józef Kucia jkucia@codeweavers.com
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- include/vkd3d_d3d12.idl | 6 ++++++ libs/vkd3d/command.c | 35 +++++++++++++++++++++++++++++++---- libs/vkd3d/device.c | 1 + libs/vkd3d/resource.c | 13 ++++++++++--- libs/vkd3d/vkd3d_private.h | 1 + tests/d3d12.c | 11 ++++++++--- 6 files changed, 57 insertions(+), 10 deletions(-)
diff --git a/include/vkd3d_d3d12.idl b/include/vkd3d_d3d12.idl index 8b2e70fdadcb..231123bd672f 100644 --- a/include/vkd3d_d3d12.idl +++ b/include/vkd3d_d3d12.idl @@ -1749,6 +1749,12 @@ typedef struct D3D12_QUERY_DATA_PIPELINE_STATISTICS UINT64 CSInvocations; } D3D12_QUERY_DATA_PIPELINE_STATISTICS;
+typedef struct D3D12_QUERY_DATA_SO_STATISTICS +{ + UINT64 NumPrimitivesWritten; + UINT64 PrimitivesStorageNeeded; +} D3D12_QUERY_DATA_SO_STATISTICS; + typedef enum D3D12_PREDICATION_OP { D3D12_PREDICATION_OP_EQUAL_ZERO = 0, diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index 7457ae3610fa..5b11c3c43d44 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -4080,10 +4080,19 @@ static void STDMETHODCALLTYPE d3d12_command_list_BeginQuery(ID3D12GraphicsComman
d3d12_command_list_end_current_render_pass(list);
+ VK_CALL(vkCmdResetQueryPool(list->vk_command_buffer, query_heap->vk_query_pool, index, 1)); + if (type == D3D12_QUERY_TYPE_OCCLUSION) flags = VK_QUERY_CONTROL_PRECISE_BIT;
- VK_CALL(vkCmdResetQueryPool(list->vk_command_buffer, query_heap->vk_query_pool, index, 1)); + if (D3D12_QUERY_TYPE_SO_STATISTICS_STREAM0 <= type && type <= D3D12_QUERY_TYPE_SO_STATISTICS_STREAM3) + { + unsigned int stream_index = type - D3D12_QUERY_TYPE_SO_STATISTICS_STREAM0; + VK_CALL(vkCmdBeginQueryIndexedEXT(list->vk_command_buffer, + query_heap->vk_query_pool, index, flags, stream_index)); + return; + } + VK_CALL(vkCmdBeginQuery(list->vk_command_buffer, query_heap->vk_query_pool, index, flags)); }
@@ -4110,9 +4119,28 @@ static void STDMETHODCALLTYPE d3d12_command_list_EndQuery(ID3D12GraphicsCommandL return; }
+ if (D3D12_QUERY_TYPE_SO_STATISTICS_STREAM0 <= type && type <= D3D12_QUERY_TYPE_SO_STATISTICS_STREAM3) + { + unsigned int stream_index = type - D3D12_QUERY_TYPE_SO_STATISTICS_STREAM0; + VK_CALL(vkCmdEndQueryIndexedEXT(list->vk_command_buffer, + query_heap->vk_query_pool, index, stream_index)); + return; + } + VK_CALL(vkCmdEndQuery(list->vk_command_buffer, query_heap->vk_query_pool, index)); }
+static size_t get_query_stride(D3D12_QUERY_TYPE type) +{ + if (type == D3D12_QUERY_TYPE_PIPELINE_STATISTICS) + return sizeof(D3D12_QUERY_DATA_PIPELINE_STATISTICS); + + if (D3D12_QUERY_TYPE_SO_STATISTICS_STREAM0 <= type && type <= D3D12_QUERY_TYPE_SO_STATISTICS_STREAM3) + return sizeof(D3D12_QUERY_DATA_SO_STATISTICS); + + return sizeof(uint64_t); +} + static void STDMETHODCALLTYPE d3d12_command_list_ResolveQueryData(ID3D12GraphicsCommandList *iface, ID3D12QueryHeap *heap, D3D12_QUERY_TYPE type, UINT start_index, UINT query_count, ID3D12Resource *dst_buffer, UINT64 aligned_dst_buffer_offset) @@ -4120,9 +4148,9 @@ static void STDMETHODCALLTYPE d3d12_command_list_ResolveQueryData(ID3D12Graphics const struct d3d12_query_heap *query_heap = unsafe_impl_from_ID3D12QueryHeap(heap); struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList(iface); struct d3d12_resource *buffer = unsafe_impl_from_ID3D12Resource(dst_buffer); - VkDeviceSize offset, stride = sizeof(uint64_t); const struct vkd3d_vk_device_procs *vk_procs; unsigned int i, first, count; + VkDeviceSize offset, stride;
TRACE("iface %p, heap %p, type %#x, start_index %u, query_count %u, " "dst_buffer %p, aligned_dst_buffer_offset %#"PRIx64".\n", @@ -4149,8 +4177,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_ResolveQueryData(ID3D12Graphics
d3d12_command_list_end_current_render_pass(list);
- if (type == D3D12_QUERY_TYPE_PIPELINE_STATISTICS) - stride = sizeof(struct D3D12_QUERY_DATA_PIPELINE_STATISTICS); + stride = get_query_stride(type);
count = 0; first = start_index; diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index df59a49dcc17..3d9b8c9aae8d 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -945,6 +945,7 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, vulkan_info->device_limits = device_properties2.properties.limits; vulkan_info->sparse_properties = device_properties2.properties.sparseProperties; vulkan_info->rasterization_stream = xfb_properties.transformFeedbackRasterizationStreamSelect; + vulkan_info->transform_feedback_queries = xfb_properties.transformFeedbackQueries; vulkan_info->max_vertex_attrib_divisor = max(vertex_divisor_properties.maxVertexAttribDivisor, 1);
device->feature_options.DoublePrecisionFloatShaderOps = features->shaderFloat64; diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index 34f558d6fda3..1176538f5c54 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -2835,9 +2835,16 @@ HRESULT d3d12_query_heap_create(struct d3d12_device *device, const D3D12_QUERY_H break;
case D3D12_QUERY_HEAP_TYPE_SO_STATISTICS: - FIXME("Unsupported query heap type SO_STATISTICS.\n"); - vkd3d_free(object); - return E_NOTIMPL; + if (!device->vk_info.transform_feedback_queries) + { + FIXME("Transform feedback queries are not supported by Vulkan implementation.\n"); + vkd3d_free(object); + return E_NOTIMPL; + } + + pool_info.queryType = VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT; + pool_info.pipelineStatistics = 0; + break;
default: WARN("Invalid query heap type %u.\n", desc->Type); diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index dee129e80e9e..9b2fbaf4abe0 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -93,6 +93,7 @@ struct vkd3d_vulkan_info bool EXT_vertex_attribute_divisor;
bool rasterization_stream; + bool transform_feedback_queries;
bool vertex_attrib_zero_divisor; unsigned int max_vertex_attrib_divisor; diff --git a/tests/d3d12.c b/tests/d3d12.c index 259f0cafa443..e83ea48fdb6a 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -19007,10 +19007,15 @@ static void test_create_query_heap(void) heap_desc.NodeMask = 0;
hr = ID3D12Device_CreateQueryHeap(device, &heap_desc, &IID_ID3D12QueryHeap, (void **)&query_heap); - todo ok(hr == S_OK, "Failed to create query heap, type %u, hr %#x.\n", heap_desc.Type, hr); - - if (hr == S_OK) + if (hr != E_NOTIMPL) + { + ok(hr == S_OK, "Failed to create query heap, type %u, hr %#x.\n", heap_desc.Type, hr); ID3D12QueryHeap_Release(query_heap); + } + else + { + skip("Stream output is not supported.\n"); + }
refcount = ID3D12Device_Release(device); ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount);