mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-01-28 13:05:02 -08:00
libs/vkd3d: Avoid vkCmdCopyQueryPoolResults() for not issued queries.
The Vulkan spec states: * "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." * "If queries will never finish (e.g. due to being reset but not issued), then vkGetQueryPoolResults may not return in finite time."
This commit is contained in:
parent
334c532401
commit
2ea8ffb554
@ -24,6 +24,8 @@
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
|
||||
|
||||
#define DIV_ROUND_UP(a, b) ((a) % (b) == 0 ? (a) / (b) : (a) / (b) + 1)
|
||||
|
||||
static inline size_t align(size_t addr, size_t alignment)
|
||||
{
|
||||
return (addr + (alignment - 1)) & ~(alignment - 1);
|
||||
|
@ -3305,6 +3305,8 @@ static void STDMETHODCALLTYPE d3d12_command_list_EndQuery(ID3D12GraphicsCommandL
|
||||
|
||||
TRACE("iface %p, heap %p, type %#x, index %u.\n", iface, heap, type, index);
|
||||
|
||||
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));
|
||||
@ -3320,11 +3322,12 @@ static void STDMETHODCALLTYPE d3d12_command_list_ResolveQueryData(ID3D12Graphics
|
||||
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_command_list *list = impl_from_ID3D12GraphicsCommandList(iface);
|
||||
struct d3d12_query_heap *query_heap = unsafe_impl_from_ID3D12QueryHeap(heap);
|
||||
struct d3d12_resource *buffer = unsafe_impl_from_ID3D12Resource(dst_buffer);
|
||||
const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
|
||||
VkDeviceSize stride = sizeof(uint64_t);
|
||||
unsigned int i;
|
||||
|
||||
TRACE("iface %p, heap %p, type %#x, start_index %u, query_count %u, "
|
||||
"dst_buffer %p, aligned_dst_buffer_offset %#"PRIx64".\n",
|
||||
@ -3350,9 +3353,28 @@ static void STDMETHODCALLTYPE d3d12_command_list_ResolveQueryData(ID3D12Graphics
|
||||
if (type == D3D12_QUERY_TYPE_PIPELINE_STATISTICS)
|
||||
stride = sizeof(struct D3D12_QUERY_DATA_PIPELINE_STATISTICS);
|
||||
|
||||
VK_CALL(vkCmdCopyQueryPoolResults(list->vk_command_buffer, query_heap->vk_query_pool,
|
||||
start_index, query_count, buffer->u.vk_buffer, aligned_dst_buffer_offset,
|
||||
stride, VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
|
||||
/* 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."
|
||||
*/
|
||||
for (i = 0; i < query_count; ++i)
|
||||
{
|
||||
const UINT64 offset = aligned_dst_buffer_offset + i * stride;
|
||||
const unsigned int query_index = start_index + i;
|
||||
|
||||
if (!d3d12_query_heap_is_result_available(query_heap, query_index))
|
||||
{
|
||||
VK_CALL(vkCmdFillBuffer(list->vk_command_buffer,
|
||||
buffer->u.vk_buffer, offset, stride, 0x00000000));
|
||||
continue;
|
||||
}
|
||||
|
||||
VK_CALL(vkCmdCopyQueryPoolResults(list->vk_command_buffer,
|
||||
query_heap->vk_query_pool, query_index, 1, buffer->u.vk_buffer,
|
||||
offset, stride, VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
|
||||
}
|
||||
}
|
||||
|
||||
static void STDMETHODCALLTYPE d3d12_command_list_SetPredication(ID3D12GraphicsCommandList *iface,
|
||||
|
@ -1871,14 +1871,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;
|
||||
|
||||
if (!(object = vkd3d_malloc(sizeof(*object))))
|
||||
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]))))
|
||||
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));
|
||||
|
||||
pool_info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
|
||||
pool_info.pNext = NULL;
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
@ -279,12 +280,33 @@ struct d3d12_query_heap
|
||||
VkQueryPool vk_query_pool;
|
||||
|
||||
struct d3d12_device *device;
|
||||
|
||||
uint64_t availability_mask[];
|
||||
};
|
||||
|
||||
HRESULT d3d12_query_heap_create(struct d3d12_device *device, const D3D12_QUERY_HEAP_DESC *desc,
|
||||
struct d3d12_query_heap **heap) DECLSPEC_HIDDEN;
|
||||
struct d3d12_query_heap *unsafe_impl_from_ID3D12QueryHeap(ID3D12QueryHeap *iface) DECLSPEC_HIDDEN;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
struct d3d12_root_descriptor_table_range
|
||||
{
|
||||
unsigned int offset;
|
||||
|
Loading…
x
Reference in New Issue
Block a user