vkd3d: Implement virtual query allocation.

Signed-off-by: Philip Rebohle <philip.rebohle@tu-dortmund.de>
This commit is contained in:
Philip Rebohle 2021-01-13 13:34:13 +01:00 committed by Philip Rebohle
parent 634d8fd0fa
commit 16f5cff061
3 changed files with 206 additions and 0 deletions

View File

@ -1549,7 +1549,11 @@ static ULONG STDMETHODCALLTYPE d3d12_command_allocator_Release(ID3D12CommandAllo
for (i = 0; i < allocator->scratch_buffer_count; i++)
d3d12_device_return_scratch_buffer(device, &allocator->scratch_buffers[i]);
for (i = 0; i < allocator->query_pool_count; i++)
d3d12_device_return_query_pool(device, &allocator->query_pools[i]);
vkd3d_free(allocator->scratch_buffers);
vkd3d_free(allocator->query_pools);
vkd3d_free(allocator);
d3d12_device_release(device);
@ -1670,6 +1674,13 @@ static HRESULT STDMETHODCALLTYPE d3d12_command_allocator_Reset(ID3D12CommandAllo
d3d12_device_return_scratch_buffer(device, &allocator->scratch_buffers[i]);
allocator->scratch_buffer_count = 0;
/* Return query pools to the device */
for (i = 0; i < allocator->query_pool_count; i++)
d3d12_device_return_query_pool(device, &allocator->query_pools[i]);
allocator->query_pool_count = 0;
memset(&allocator->active_query_pools, 0, sizeof(allocator->active_query_pools));
return S_OK;
}
@ -1779,6 +1790,11 @@ static HRESULT d3d12_command_allocator_init(struct d3d12_command_allocator *allo
allocator->scratch_buffers_size = 0;
allocator->scratch_buffer_count = 0;
allocator->query_pools = NULL;
allocator->query_pools_size = 0;
allocator->query_pool_count = 0;
memset(&allocator->active_query_pools, 0, sizeof(allocator->active_query_pools));
allocator->current_command_list = NULL;
d3d12_device_add_ref(allocator->device = device);
@ -1870,6 +1886,58 @@ static bool d3d12_command_allocator_allocate_scratch_memory(struct d3d12_command
return true;
}
static struct vkd3d_query_pool *d3d12_command_allocator_find_active_query_pool(struct d3d12_command_allocator *allocator,
D3D12_QUERY_HEAP_TYPE heap_type)
{
uint32_t i;
static const struct
{
D3D12_QUERY_HEAP_TYPE heap_type;
uint32_t index;
}
map[] =
{
{ D3D12_QUERY_HEAP_TYPE_OCCLUSION, VKD3D_QUERY_TYPE_INDEX_OCCLUSION },
{ D3D12_QUERY_HEAP_TYPE_PIPELINE_STATISTICS, VKD3D_QUERY_TYPE_INDEX_PIPELINE_STATISTICS },
{ D3D12_QUERY_HEAP_TYPE_SO_STATISTICS, VKD3D_QUERY_TYPE_INDEX_TRANSFORM_FEEDBACK },
};
for (i = 0; i < ARRAY_SIZE(map); i++)
{
if (map[i].heap_type == heap_type)
return &allocator->active_query_pools[map[i].index];
}
ERR("Unhandled query heap type %u.\n", heap_type);
return NULL;
}
static bool d3d12_command_allocator_allocate_query(struct d3d12_command_allocator *allocator,
D3D12_QUERY_HEAP_TYPE heap_type, VkQueryPool *query_pool, uint32_t *query_index)
{
struct vkd3d_query_pool *pool = d3d12_command_allocator_find_active_query_pool(allocator, heap_type);
if (!pool)
return false;
if (pool->next_index >= pool->query_count)
{
if (FAILED(d3d12_device_get_query_pool(allocator->device, heap_type, pool)))
return false;
if (vkd3d_array_reserve((void**)&allocator->query_pools, &allocator->query_pools_size,
allocator->query_pool_count + 1, sizeof(*allocator->query_pools)))
allocator->query_pools[allocator->query_pool_count++] = *pool;
else
ERR("Failed to add query pool.\n");
}
*query_pool = pool->vk_query_pool;
*query_index = pool->next_index++;
return true;
}
/* ID3D12CommandList */
static inline struct d3d12_command_list *impl_from_ID3D12GraphicsCommandList(d3d12_command_list_iface *iface)
{

View File

@ -2364,6 +2364,115 @@ void d3d12_device_return_scratch_buffer(struct d3d12_device *device, const struc
}
}
static HRESULT d3d12_device_create_query_pool(struct d3d12_device *device, D3D12_QUERY_HEAP_TYPE heap_type, struct vkd3d_query_pool *pool)
{
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
VkQueryPoolCreateInfo pool_info;
VkResult vr;
TRACE("device %p, heap_type %u, pool %p.\n", device, heap_type, pool);
pool_info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
pool_info.pNext = NULL;
pool_info.flags = 0;
pool_info.pipelineStatistics = 0;
switch (heap_type)
{
case D3D12_QUERY_HEAP_TYPE_OCCLUSION:
/* Expect a large number of occlusion queries
* to be used within a single command list */
pool_info.queryType = VK_QUERY_TYPE_OCCLUSION;
pool_info.queryCount = 4096;
break;
case D3D12_QUERY_HEAP_TYPE_PIPELINE_STATISTICS:
pool_info.queryType = VK_QUERY_TYPE_PIPELINE_STATISTICS;
pool_info.queryCount = 128;
pool_info.pipelineStatistics =
VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT |
VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT |
VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT |
VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT |
VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT |
VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT |
VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT |
VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT |
VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT |
VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT |
VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT;
break;
case D3D12_QUERY_HEAP_TYPE_SO_STATISTICS:
pool_info.queryType = VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT;
pool_info.queryCount = 128;
break;
default:
ERR("Unhandled query type %u.\n", heap_type);
return E_INVALIDARG;
}
if ((vr = VK_CALL(vkCreateQueryPool(device->vk_device, &pool_info, NULL, &pool->vk_query_pool))) < 0)
{
ERR("Failed to create query pool, vr %u.\n", vr);
return hresult_from_vk_result(vr);
}
pool->heap_type = heap_type;
pool->query_count = pool_info.queryCount;
pool->next_index = 0;
return S_OK;
}
static void d3d12_device_destroy_query_pool(struct d3d12_device *device, const struct vkd3d_query_pool *pool)
{
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
TRACE("device %p, pool %p.\n", device, pool);
VK_CALL(vkDestroyQueryPool(device->vk_device, pool->vk_query_pool, NULL));
}
HRESULT d3d12_device_get_query_pool(struct d3d12_device *device, D3D12_QUERY_HEAP_TYPE heap_type, struct vkd3d_query_pool *pool)
{
size_t i;
pthread_mutex_lock(&device->mutex);
for (i = 0; i < device->query_pool_count; i++)
{
if (device->query_pools[i].heap_type == heap_type)
{
*pool = device->query_pools[i];
pool->next_index = 0;
if (--device->query_pool_count != i)
device->query_pools[i] = device->query_pools[device->query_pool_count];
pthread_mutex_unlock(&device->mutex);
return S_OK;
}
}
pthread_mutex_unlock(&device->mutex);
return d3d12_device_create_query_pool(device, heap_type, pool);
}
void d3d12_device_return_query_pool(struct d3d12_device *device, const struct vkd3d_query_pool *pool)
{
pthread_mutex_lock(&device->mutex);
if (device->query_pool_count < VKD3D_VIRTUAL_QUERY_POOL_COUNT)
{
device->query_pools[device->query_pool_count++] = *pool;
pthread_mutex_unlock(&device->mutex);
}
else
{
pthread_mutex_unlock(&device->mutex);
d3d12_device_destroy_query_pool(device, pool);
}
}
/* ID3D12Device */
static inline struct d3d12_device *impl_from_ID3D12Device(d3d12_device_iface *iface)
{
@ -2414,6 +2523,9 @@ static void d3d12_device_destroy(struct d3d12_device *device)
for (i = 0; i < device->scratch_buffer_count; i++)
d3d12_device_destroy_scratch_buffer(device, &device->scratch_buffers[i]);
for (i = 0; i < device->query_pool_count; i++)
d3d12_device_destroy_query_pool(device, &device->query_pools[i]);
vkd3d_private_store_destroy(&device->private_store);
vkd3d_cleanup_format_info(device);

View File

@ -1127,6 +1127,20 @@ struct vkd3d_scratch_buffer
VkDeviceAddress va;
};
#define VKD3D_QUERY_TYPE_INDEX_OCCLUSION (0u)
#define VKD3D_QUERY_TYPE_INDEX_PIPELINE_STATISTICS (1u)
#define VKD3D_QUERY_TYPE_INDEX_TRANSFORM_FEEDBACK (2u)
#define VKD3D_VIRTUAL_QUERY_TYPE_COUNT (3u)
#define VKD3D_VIRTUAL_QUERY_POOL_COUNT (128u)
struct vkd3d_query_pool
{
D3D12_QUERY_HEAP_TYPE heap_type;
VkQueryPool vk_query_pool;
uint32_t query_count;
uint32_t next_index;
};
/* ID3D12CommandAllocator */
struct d3d12_command_allocator
{
@ -1164,6 +1178,12 @@ struct d3d12_command_allocator
size_t scratch_buffers_size;
size_t scratch_buffer_count;
struct vkd3d_query_pool *query_pools;
size_t query_pools_size;
size_t query_pool_count;
struct vkd3d_query_pool active_query_pools[VKD3D_VIRTUAL_QUERY_TYPE_COUNT];
LONG outstanding_submissions_count;
struct d3d12_command_list *current_command_list;
@ -2087,6 +2107,9 @@ struct d3d12_device
struct vkd3d_scratch_buffer scratch_buffers[VKD3D_SCRATCH_BUFFER_COUNT];
size_t scratch_buffer_count;
struct vkd3d_query_pool query_pools[VKD3D_VIRTUAL_QUERY_POOL_COUNT];
size_t query_pool_count;
HRESULT removed_reason;
const struct vkd3d_format *depth_stencil_formats;
@ -2113,6 +2136,9 @@ struct d3d12_device *unsafe_impl_from_ID3D12Device(d3d12_device_iface *iface);
HRESULT d3d12_device_get_scratch_buffer(struct d3d12_device *device, VkDeviceSize min_size, struct vkd3d_scratch_buffer *scratch);
void d3d12_device_return_scratch_buffer(struct d3d12_device *device, const struct vkd3d_scratch_buffer *scratch);
HRESULT d3d12_device_get_query_pool(struct d3d12_device *device, D3D12_QUERY_HEAP_TYPE heap_type, struct vkd3d_query_pool *pool);
void d3d12_device_return_query_pool(struct d3d12_device *device, const struct vkd3d_query_pool *pool);
static inline HRESULT d3d12_device_query_interface(struct d3d12_device *device, REFIID iid, void **object)
{
return ID3D12Device6_QueryInterface(&device->ID3D12Device_iface, iid, object);