vkd3d: Do not interrupt render pass for occlusion queries.

Signed-off-by: Philip Rebohle <philip.rebohle@tu-dortmund.de>
This commit is contained in:
Philip Rebohle 2020-12-04 17:38:23 +01:00 committed by Hans-Kristian Arntzen
parent 7711b9ba1a
commit c057e881dc
2 changed files with 172 additions and 27 deletions

View File

@ -2488,10 +2488,96 @@ static void d3d12_command_list_emit_render_pass_transition(struct d3d12_command_
j, vk_image_barriers));
}
static void d3d12_command_list_begin_active_query(struct d3d12_command_list *list,
struct vkd3d_active_query *query)
{
const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
assert(query->state == VKD3D_ACTIVE_QUERY_RESET);
VK_CALL(vkCmdBeginQuery(list->vk_command_buffer, query->vk_pool, query->index, query->flags));
query->state = VKD3D_ACTIVE_QUERY_BEGUN;
}
static void d3d12_command_list_end_active_query(struct d3d12_command_list *list,
struct vkd3d_active_query *query)
{
const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
assert(query->state == VKD3D_ACTIVE_QUERY_BEGUN);
VK_CALL(vkCmdEndQuery(list->vk_command_buffer, query->vk_pool, query->index));
query->state = VKD3D_ACTIVE_QUERY_ENDED;
}
static void d3d12_command_list_enable_query(struct d3d12_command_list *list,
VkQueryPool vk_query_pool, uint32_t index, VkQueryControlFlags flags)
{
struct vkd3d_active_query *query;
if (!vkd3d_array_reserve((void **)&list->active_queries, &list->active_queries_size,
list->active_queries_count + 1, sizeof(*list->active_queries)))
{
ERR("Failed to add query.\n");
return;
}
query = &list->active_queries[list->active_queries_count++];
query->vk_pool = vk_query_pool;
query->index = index;
query->flags = flags;
query->state = VKD3D_ACTIVE_QUERY_RESET;
}
static void d3d12_command_list_disable_query(struct d3d12_command_list *list,
VkQueryPool vk_query_pool, uint32_t index)
{
unsigned int i;
for (i = 0; i < list->active_queries_count; i++)
{
struct vkd3d_active_query *query = &list->active_queries[i];
if (query->vk_pool == vk_query_pool && query->index == index)
{
if (query->state == VKD3D_ACTIVE_QUERY_RESET)
d3d12_command_list_begin_active_query(list, query);
if (query->state == VKD3D_ACTIVE_QUERY_BEGUN)
d3d12_command_list_end_active_query(list, query);
*query = list->active_queries[--list->active_queries_count];
return;
}
}
WARN("Query (%#"PRIx64",%u) not active.\n", (uint64_t)vk_query_pool, index);
}
static void d3d12_command_list_handle_active_queries(struct d3d12_command_list *list, bool end)
{
unsigned int i;
for (i = 0; i < list->active_queries_count; i++)
{
struct vkd3d_active_query *query = &list->active_queries[i];
/* It is possible (although unexpected) that an app uses an occlusion
* query for multiple draw calls, which may require multiple render
* pass instances. In that case, we can only handle the first instance. */
if (query->state == VKD3D_ACTIVE_QUERY_ENDED && !end)
FIXME("Query (%#"PRIx64",%u) already ended.\n", (uint64_t)query->vk_pool, query->index);
if (query->state == VKD3D_ACTIVE_QUERY_RESET)
d3d12_command_list_begin_active_query(list, query);
if (query->state == VKD3D_ACTIVE_QUERY_BEGUN && end)
d3d12_command_list_end_active_query(list, query);
}
}
static void d3d12_command_list_end_current_render_pass(struct d3d12_command_list *list, bool suspend)
{
const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
d3d12_command_list_handle_active_queries(list, true);
if (list->xfb_enabled)
{
VK_CALL(vkCmdEndTransformFeedbackEXT(list->vk_command_buffer, 0, ARRAY_SIZE(list->so_counter_buffers),
@ -2899,6 +2985,7 @@ static ULONG STDMETHODCALLTYPE d3d12_command_list_Release(d3d12_command_list_ifa
vkd3d_free(list->init_transitions);
vkd3d_free(list->query_ranges);
vkd3d_free(list->active_queries);
vkd3d_free(list);
d3d12_device_release(device);
@ -3270,6 +3357,7 @@ static void d3d12_command_list_reset_state(struct d3d12_command_list *list,
list->init_transitions_count = 0;
list->query_ranges_count = 0;
list->active_queries_count = 0;
ID3D12GraphicsCommandList_SetPipelineState(iface, initial_pipeline_state);
}
@ -4079,7 +4167,10 @@ static bool d3d12_command_list_begin_render_pass(struct d3d12_command_list *list
d3d12_command_list_update_descriptors(list, VK_PIPELINE_BIND_POINT_GRAPHICS);
if (list->current_render_pass != VK_NULL_HANDLE)
{
d3d12_command_list_handle_active_queries(list, false);
return true;
}
vk_render_pass = list->pso_render_pass;
assert(vk_render_pass);
@ -4118,6 +4209,7 @@ static bool d3d12_command_list_begin_render_pass(struct d3d12_command_list *list
list->xfb_enabled = true;
}
d3d12_command_list_handle_active_queries(list, false);
return true;
}
@ -6744,39 +6836,67 @@ static void STDMETHODCALLTYPE d3d12_command_list_DiscardResource(d3d12_command_l
}
}
static inline bool d3d12_query_type_is_indexed(D3D12_QUERY_TYPE type)
{
return type >= D3D12_QUERY_TYPE_SO_STATISTICS_STREAM0 &&
type <= D3D12_QUERY_TYPE_SO_STATISTICS_STREAM3;
}
static inline bool d3d12_query_type_is_inline(D3D12_QUERY_TYPE type)
{
return type == D3D12_QUERY_TYPE_OCCLUSION ||
type == D3D12_QUERY_TYPE_BINARY_OCCLUSION;
}
static inline bool d3d12_query_type_is_scoped(D3D12_QUERY_TYPE type)
{
return type != D3D12_QUERY_TYPE_TIMESTAMP;
}
VkQueryControlFlags d3d12_query_type_get_vk_flags(D3D12_QUERY_TYPE type)
{
return type == D3D12_QUERY_TYPE_OCCLUSION
? VK_QUERY_CONTROL_PRECISE_BIT : 0;
}
static void STDMETHODCALLTYPE d3d12_command_list_BeginQuery(d3d12_command_list_iface *iface,
ID3D12QueryHeap *heap, D3D12_QUERY_TYPE type, UINT index)
{
struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList(iface);
struct d3d12_query_heap *query_heap = unsafe_impl_from_ID3D12QueryHeap(heap);
const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
VkQueryControlFlags flags = 0;
VkQueryControlFlags flags = d3d12_query_type_get_vk_flags(type);
TRACE("iface %p, heap %p, type %#x, index %u.\n", iface, heap, type, index);
if (type == D3D12_QUERY_TYPE_TIMESTAMP)
if (!d3d12_query_type_is_scoped(type))
{
WARN("Query type %u is not scoped.\n", type);
return;
}
d3d12_command_list_track_query_heap(list, query_heap);
d3d12_command_list_end_current_render_pass(list, true);
if (!d3d12_command_list_reset_query(list, query_heap->vk_query_pool, index))
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;
if (D3D12_QUERY_TYPE_SO_STATISTICS_STREAM0 <= type && type <= D3D12_QUERY_TYPE_SO_STATISTICS_STREAM3)
if (d3d12_query_type_is_inline(type))
{
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));
d3d12_command_list_enable_query(list, query_heap->vk_query_pool, index, flags);
}
else
VK_CALL(vkCmdBeginQuery(list->vk_command_buffer, query_heap->vk_query_pool, index, flags));
{
d3d12_command_list_end_current_render_pass(list, true);
if (!d3d12_command_list_reset_query(list, query_heap->vk_query_pool, index))
VK_CALL(vkCmdResetQueryPool(list->vk_command_buffer, query_heap->vk_query_pool, index, 1));
if (d3d12_query_type_is_indexed(type))
{
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));
}
else
VK_CALL(vkCmdBeginQuery(list->vk_command_buffer, query_heap->vk_query_pool, index, flags));
}
}
static void STDMETHODCALLTYPE d3d12_command_list_EndQuery(d3d12_command_list_iface *iface,
@ -6790,7 +6910,24 @@ static void STDMETHODCALLTYPE d3d12_command_list_EndQuery(d3d12_command_list_ifa
d3d12_command_list_track_query_heap(list, query_heap);
if (type == D3D12_QUERY_TYPE_TIMESTAMP)
if (d3d12_query_type_is_inline(type))
{
d3d12_command_list_disable_query(list, query_heap->vk_query_pool, index);
}
else if (d3d12_query_type_is_scoped(type))
{
d3d12_command_list_end_current_render_pass(list, true);
if (d3d12_query_type_is_indexed(type))
{
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));
}
else
VK_CALL(vkCmdEndQuery(list->vk_command_buffer, query_heap->vk_query_pool, index));
}
else if (type == D3D12_QUERY_TYPE_TIMESTAMP)
{
if (!d3d12_command_list_reset_query(list, query_heap->vk_query_pool, index))
{
@ -6802,18 +6939,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_EndQuery(d3d12_command_list_ifa
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, query_heap->vk_query_pool, index));
}
else
{
d3d12_command_list_end_current_render_pass(list, true);
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));
}
else
VK_CALL(vkCmdEndQuery(list->vk_command_buffer, query_heap->vk_query_pool, index));
}
FIXME("Unhandled query type %u.\n", type);
}
static size_t get_query_stride(D3D12_QUERY_TYPE type)

View File

@ -1274,6 +1274,21 @@ struct vkd3d_initial_transition
};
};
enum vkd3d_active_query_state
{
VKD3D_ACTIVE_QUERY_RESET,
VKD3D_ACTIVE_QUERY_BEGUN,
VKD3D_ACTIVE_QUERY_ENDED,
};
struct vkd3d_active_query
{
VkQueryPool vk_pool;
uint32_t index;
uint32_t flags;
enum vkd3d_active_query_state state;
};
enum vkd3d_query_range_flag
{
VKD3D_QUERY_RANGE_RESET = 0x1,
@ -1356,6 +1371,10 @@ struct d3d12_command_list
size_t query_ranges_size;
size_t query_ranges_count;
struct vkd3d_active_query *active_queries;
size_t active_queries_size;
size_t active_queries_count;
LONG *outstanding_submissions_count;
struct vkd3d_private_store private_store;