vkd3d: Rework query pool initialization.
Ensures that queries are always available and initialized in the correct order on the GPU timeline. Signed-off-by: Philip Rebohle <philip.rebohle@tu-dortmund.de>
This commit is contained in:
parent
bb9d0f2741
commit
215989f6d5
|
@ -2642,6 +2642,10 @@ static void d3d12_command_list_add_transition(struct d3d12_command_list *list, s
|
|||
skip = list->init_transitions[i - 1].resource.resource == transition->resource.resource;
|
||||
break;
|
||||
|
||||
case VKD3D_INITIAL_TRANSITION_TYPE_QUERY_HEAP:
|
||||
skip = list->init_transitions[i - 1].query_heap == transition->query_heap;
|
||||
break;
|
||||
|
||||
default:
|
||||
ERR("Unhandled transition type %u.\n", transition->type);
|
||||
continue;
|
||||
|
@ -2665,6 +2669,10 @@ static void d3d12_command_list_add_transition(struct d3d12_command_list *list, s
|
|||
transition->resource.resource, transition->resource.perform_initial_transition ? "yes" : "no");
|
||||
break;
|
||||
|
||||
case VKD3D_INITIAL_TRANSITION_TYPE_QUERY_HEAP:
|
||||
TRACE("Adding initialization for query heap %p.\n", transition->query_heap);
|
||||
break;
|
||||
|
||||
default:
|
||||
ERR("Unhandled transition type %u.\n", transition->type);
|
||||
}
|
||||
|
@ -2689,6 +2697,19 @@ static void d3d12_command_list_track_resource_usage(struct d3d12_command_list *l
|
|||
}
|
||||
}
|
||||
|
||||
static void d3d12_command_list_track_query_heap(struct d3d12_command_list *list,
|
||||
struct d3d12_query_heap *heap)
|
||||
{
|
||||
struct vkd3d_initial_transition transition;
|
||||
|
||||
if (!vkd3d_atomic_uint32_load_explicit(&heap->initialized, vkd3d_memory_order_relaxed))
|
||||
{
|
||||
transition.type = VKD3D_INITIAL_TRANSITION_TYPE_QUERY_HEAP;
|
||||
transition.query_heap = heap;
|
||||
d3d12_command_list_add_transition(list, &transition);
|
||||
}
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE d3d12_command_list_QueryInterface(d3d12_command_list_iface *iface,
|
||||
REFIID iid, void **object)
|
||||
{
|
||||
|
@ -6201,13 +6222,12 @@ static void STDMETHODCALLTYPE d3d12_command_list_BeginQuery(d3d12_command_list_i
|
|||
{
|
||||
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;
|
||||
const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
|
||||
VkQueryControlFlags flags = 0;
|
||||
|
||||
TRACE("iface %p, heap %p, type %#x, index %u.\n", iface, heap, type, index);
|
||||
|
||||
vk_procs = &list->device->vk_procs;
|
||||
|
||||
d3d12_command_list_track_query_heap(list, query_heap);
|
||||
d3d12_command_list_end_current_render_pass(list, true);
|
||||
|
||||
VK_CALL(vkCmdResetQueryPool(list->vk_command_buffer, query_heap->vk_query_pool, index, 1));
|
||||
|
@ -6231,16 +6251,13 @@ static void STDMETHODCALLTYPE d3d12_command_list_EndQuery(d3d12_command_list_ifa
|
|||
{
|
||||
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;
|
||||
const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
|
||||
|
||||
TRACE("iface %p, heap %p, type %#x, index %u.\n", iface, heap, type, index);
|
||||
|
||||
vk_procs = &list->device->vk_procs;
|
||||
|
||||
d3d12_command_list_track_query_heap(list, query_heap);
|
||||
d3d12_command_list_end_current_render_pass(list, true);
|
||||
|
||||
d3d12_query_heap_mark_result_as_available(query_heap, index);
|
||||
|
||||
if (type == D3D12_QUERY_TYPE_TIMESTAMP)
|
||||
{
|
||||
VK_CALL(vkCmdResetQueryPool(list->vk_command_buffer, query_heap->vk_query_pool, index, 1));
|
||||
|
@ -6275,19 +6292,17 @@ static void STDMETHODCALLTYPE d3d12_command_list_ResolveQueryData(d3d12_command_
|
|||
ID3D12QueryHeap *heap, D3D12_QUERY_TYPE type, UINT start_index, UINT query_count,
|
||||
ID3D12Resource *dst_buffer, UINT64 aligned_dst_buffer_offset)
|
||||
{
|
||||
const struct d3d12_query_heap *query_heap = unsafe_impl_from_ID3D12QueryHeap(heap);
|
||||
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);
|
||||
const struct vkd3d_vk_device_procs *vk_procs;
|
||||
unsigned int i, first, count;
|
||||
VkDeviceSize offset, stride;
|
||||
const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
|
||||
|
||||
TRACE("iface %p, heap %p, type %#x, start_index %u, query_count %u, "
|
||||
"dst_buffer %p, aligned_dst_buffer_offset %#"PRIx64".\n",
|
||||
iface, heap, type, start_index, query_count,
|
||||
dst_buffer, aligned_dst_buffer_offset);
|
||||
|
||||
vk_procs = &list->device->vk_procs;
|
||||
d3d12_command_list_track_query_heap(list, query_heap);
|
||||
|
||||
/* Vulkan is less strict than D3D12 here. Vulkan implementations are free
|
||||
* to return any non-zero result for binary occlusion with at least one
|
||||
|
@ -6307,49 +6322,9 @@ static void STDMETHODCALLTYPE d3d12_command_list_ResolveQueryData(d3d12_command_
|
|||
|
||||
d3d12_command_list_end_current_render_pass(list, true);
|
||||
|
||||
stride = get_query_stride(type);
|
||||
|
||||
count = 0;
|
||||
first = start_index;
|
||||
offset = aligned_dst_buffer_offset;
|
||||
for (i = 0; i < query_count; ++i)
|
||||
{
|
||||
if (d3d12_query_heap_is_result_available(query_heap, start_index + i))
|
||||
{
|
||||
++count;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (count)
|
||||
{
|
||||
VK_CALL(vkCmdCopyQueryPoolResults(list->vk_command_buffer,
|
||||
query_heap->vk_query_pool, first, count, buffer->vk_buffer,
|
||||
buffer->heap_offset + offset, stride, VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
|
||||
}
|
||||
count = 0;
|
||||
first = start_index + i;
|
||||
offset = aligned_dst_buffer_offset + i * stride;
|
||||
|
||||
/* We cannot copy query results if a query was not issued:
|
||||
*
|
||||
* "If the query does not become available in a finite amount of
|
||||
* time (e.g. due to not issuing a query since the last reset),
|
||||
* a VK_ERROR_DEVICE_LOST error may occur."
|
||||
*/
|
||||
VK_CALL(vkCmdFillBuffer(list->vk_command_buffer,
|
||||
buffer->vk_buffer, buffer->heap_offset + offset, stride, 0x00000000));
|
||||
|
||||
++first;
|
||||
offset += stride;
|
||||
}
|
||||
}
|
||||
|
||||
if (count)
|
||||
{
|
||||
VK_CALL(vkCmdCopyQueryPoolResults(list->vk_command_buffer,
|
||||
query_heap->vk_query_pool, first, count, buffer->vk_buffer,
|
||||
buffer->heap_offset + offset, stride, VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
|
||||
}
|
||||
VK_CALL(vkCmdCopyQueryPoolResults(list->vk_command_buffer, query_heap->vk_query_pool,
|
||||
start_index, query_count, buffer->vk_buffer, buffer->heap_offset + aligned_dst_buffer_offset,
|
||||
get_query_stride(type), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
|
||||
}
|
||||
|
||||
static void STDMETHODCALLTYPE d3d12_command_list_SetPredication(d3d12_command_list_iface *iface,
|
||||
|
@ -7826,6 +7801,10 @@ struct d3d12_command_queue_transition_pool
|
|||
VkImageMemoryBarrier *barriers;
|
||||
size_t barriers_size;
|
||||
size_t barriers_count;
|
||||
|
||||
const struct d3d12_query_heap **query_heaps;
|
||||
size_t query_heaps_size;
|
||||
size_t query_heaps_count;
|
||||
};
|
||||
|
||||
static HRESULT d3d12_command_queue_transition_pool_init(struct d3d12_command_queue_transition_pool *pool,
|
||||
|
@ -7883,6 +7862,8 @@ static void d3d12_command_queue_transition_pool_deinit(struct d3d12_command_queu
|
|||
d3d12_command_queue_transition_pool_wait(pool, device, pool->timeline_value);
|
||||
VK_CALL(vkDestroyCommandPool(device->vk_device, pool->pool, NULL));
|
||||
VK_CALL(vkDestroySemaphore(device->vk_device, pool->timeline, NULL));
|
||||
vkd3d_free(pool->barriers);
|
||||
vkd3d_free(pool->query_heaps);
|
||||
}
|
||||
|
||||
static void d3d12_command_queue_transition_pool_add_barrier(struct d3d12_command_queue_transition_pool *pool,
|
||||
|
@ -7922,6 +7903,53 @@ static void d3d12_command_queue_transition_pool_add_barrier(struct d3d12_command
|
|||
resource, barrier->oldLayout, barrier->newLayout);
|
||||
}
|
||||
|
||||
static void d3d12_command_queue_transition_pool_add_query_heap(struct d3d12_command_queue_transition_pool *pool,
|
||||
const struct d3d12_query_heap *heap)
|
||||
{
|
||||
if (!vkd3d_array_reserve((void**)&pool->query_heaps, &pool->query_heaps_size,
|
||||
pool->query_heaps_count + 1, sizeof(*pool->query_heaps)))
|
||||
{
|
||||
ERR("Failed to allocate query heap list.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pool->query_heaps[pool->query_heaps_count++] = heap;
|
||||
|
||||
TRACE("Initialization for query heap %p.\n", heap);
|
||||
}
|
||||
|
||||
static void d3d12_command_queue_init_query_heap(struct d3d12_device *device, VkCommandBuffer vk_cmd_buffer,
|
||||
const struct d3d12_query_heap *heap)
|
||||
{
|
||||
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
||||
unsigned int i;
|
||||
|
||||
VK_CALL(vkCmdResetQueryPool(vk_cmd_buffer, heap->vk_query_pool, 0, heap->desc.Count));
|
||||
|
||||
for (i = 0; i < heap->desc.Count; i++)
|
||||
{
|
||||
switch (heap->desc.Type)
|
||||
{
|
||||
case D3D12_QUERY_HEAP_TYPE_OCCLUSION:
|
||||
case D3D12_QUERY_HEAP_TYPE_SO_STATISTICS:
|
||||
case D3D12_QUERY_HEAP_TYPE_PIPELINE_STATISTICS:
|
||||
VK_CALL(vkCmdBeginQuery(vk_cmd_buffer, heap->vk_query_pool, i, 0));
|
||||
VK_CALL(vkCmdEndQuery(vk_cmd_buffer, heap->vk_query_pool, i));
|
||||
break;
|
||||
|
||||
case D3D12_QUERY_HEAP_TYPE_TIMESTAMP:
|
||||
case D3D12_QUERY_HEAP_TYPE_COPY_QUEUE_TIMESTAMP:
|
||||
VK_CALL(vkCmdWriteTimestamp(vk_cmd_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||
heap->vk_query_pool, i));
|
||||
break;
|
||||
|
||||
default:
|
||||
ERR("Unhandled query pool type %u.\n", heap->desc.Type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void d3d12_command_queue_transition_pool_build(struct d3d12_command_queue_transition_pool *pool,
|
||||
struct d3d12_device *device, const struct vkd3d_initial_transition *transitions, size_t count,
|
||||
VkCommandBuffer *vk_cmd_buffer, uint64_t *timeline_value)
|
||||
|
@ -7934,6 +7962,7 @@ static void d3d12_command_queue_transition_pool_build(struct d3d12_command_queue
|
|||
size_t i;
|
||||
|
||||
pool->barriers_count = 0;
|
||||
pool->query_heaps_count = 0;
|
||||
|
||||
if (!count)
|
||||
{
|
||||
|
@ -7958,12 +7987,17 @@ static void d3d12_command_queue_transition_pool_build(struct d3d12_command_queue
|
|||
d3d12_command_queue_transition_pool_add_barrier(pool, transition->resource.resource);
|
||||
break;
|
||||
|
||||
case VKD3D_INITIAL_TRANSITION_TYPE_QUERY_HEAP:
|
||||
if (!vkd3d_atomic_uint32_exchange_explicit(&transition->query_heap->initialized, 1, vkd3d_memory_order_relaxed))
|
||||
d3d12_command_queue_transition_pool_add_query_heap(pool, transition->query_heap);
|
||||
break;
|
||||
|
||||
default:
|
||||
ERR("Unhandled transition type %u.\n", transition->type);
|
||||
}
|
||||
}
|
||||
|
||||
if (!pool->barriers_count)
|
||||
if (!pool->barriers_count && !pool->query_heaps_count)
|
||||
{
|
||||
*vk_cmd_buffer = VK_NULL_HANDLE;
|
||||
return;
|
||||
|
@ -7984,6 +8018,8 @@ static void d3d12_command_queue_transition_pool_build(struct d3d12_command_queue
|
|||
VK_CALL(vkCmdPipelineBarrier(pool->cmd[command_index],
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
|
||||
0, 0, NULL, 0, NULL, pool->barriers_count, pool->barriers));
|
||||
for (i = 0; i < pool->query_heaps_count; i++)
|
||||
d3d12_command_queue_init_query_heap(device, pool->cmd[command_index], pool->query_heaps[i]);
|
||||
VK_CALL(vkEndCommandBuffer(pool->cmd[command_index]));
|
||||
|
||||
*vk_cmd_buffer = pool->cmd[command_index];
|
||||
|
|
|
@ -5892,18 +5892,17 @@ HRESULT d3d12_query_heap_create(struct d3d12_device *device, const D3D12_QUERY_H
|
|||
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
||||
struct d3d12_query_heap *object;
|
||||
VkQueryPoolCreateInfo pool_info;
|
||||
unsigned int element_count;
|
||||
VkResult vr;
|
||||
HRESULT hr;
|
||||
|
||||
element_count = DIV_ROUND_UP(desc->Count, sizeof(*object->availability_mask) * CHAR_BIT);
|
||||
if (!(object = vkd3d_malloc(offsetof(struct d3d12_query_heap, availability_mask[element_count]))))
|
||||
if (!(object = vkd3d_malloc(sizeof(*object))))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
object->ID3D12QueryHeap_iface.lpVtbl = &d3d12_query_heap_vtbl;
|
||||
object->refcount = 1;
|
||||
object->device = device;
|
||||
memset(object->availability_mask, 0, element_count * sizeof(*object->availability_mask));
|
||||
object->desc = *desc;
|
||||
object->initialized = 0;
|
||||
|
||||
pool_info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
|
||||
pool_info.pNext = NULL;
|
||||
|
|
|
@ -763,38 +763,19 @@ struct d3d12_query_heap
|
|||
ID3D12QueryHeap ID3D12QueryHeap_iface;
|
||||
LONG refcount;
|
||||
|
||||
D3D12_QUERY_HEAP_DESC desc;
|
||||
VkQueryPool vk_query_pool;
|
||||
uint32_t initialized;
|
||||
|
||||
struct d3d12_device *device;
|
||||
|
||||
struct vkd3d_private_store private_store;
|
||||
|
||||
uint64_t availability_mask[];
|
||||
};
|
||||
|
||||
HRESULT d3d12_query_heap_create(struct d3d12_device *device, const D3D12_QUERY_HEAP_DESC *desc,
|
||||
struct d3d12_query_heap **heap);
|
||||
struct d3d12_query_heap *unsafe_impl_from_ID3D12QueryHeap(ID3D12QueryHeap *iface);
|
||||
|
||||
/* A Vulkan query has to be issued at least one time before the result is
|
||||
* available. In D3D12 it is legal to get query reults for not issued queries.
|
||||
*/
|
||||
static inline bool d3d12_query_heap_is_result_available(const struct d3d12_query_heap *heap,
|
||||
unsigned int query_index)
|
||||
{
|
||||
unsigned int index = query_index / (sizeof(*heap->availability_mask) * CHAR_BIT);
|
||||
unsigned int shift = query_index % (sizeof(*heap->availability_mask) * CHAR_BIT);
|
||||
return heap->availability_mask[index] & ((uint64_t)1 << shift);
|
||||
}
|
||||
|
||||
static inline void d3d12_query_heap_mark_result_as_available(struct d3d12_query_heap *heap,
|
||||
unsigned int query_index)
|
||||
{
|
||||
unsigned int index = query_index / (sizeof(*heap->availability_mask) * CHAR_BIT);
|
||||
unsigned int shift = query_index % (sizeof(*heap->availability_mask) * CHAR_BIT);
|
||||
heap->availability_mask[index] |= (uint64_t)1 << shift;
|
||||
}
|
||||
|
||||
enum vkd3d_root_signature_flag
|
||||
{
|
||||
VKD3D_ROOT_SIGNATURE_USE_ROOT_DESCRIPTOR_SET = 0x00000001u,
|
||||
|
@ -1255,6 +1236,7 @@ struct vkd3d_clear_state
|
|||
enum vkd3d_initial_transition_type
|
||||
{
|
||||
VKD3D_INITIAL_TRANSITION_TYPE_RESOURCE,
|
||||
VKD3D_INITIAL_TRANSITION_TYPE_QUERY_HEAP,
|
||||
};
|
||||
|
||||
struct vkd3d_initial_transition
|
||||
|
@ -1267,6 +1249,7 @@ struct vkd3d_initial_transition
|
|||
struct d3d12_resource *resource;
|
||||
bool perform_initial_transition;
|
||||
} resource;
|
||||
struct d3d12_query_heap *query_heap;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue