vkd3d: Avoid vkResetCommandPool if there are pending command buffers.
Works around an app-bug in SotTR, where the command pool is reset before the command buffer completes. Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
This commit is contained in:
parent
334b1cab8d
commit
09af24e69b
|
@ -1038,6 +1038,7 @@ static HRESULT d3d12_command_allocator_allocate_command_buffer(struct d3d12_comm
|
||||||
}
|
}
|
||||||
|
|
||||||
allocator->current_command_list = list;
|
allocator->current_command_list = list;
|
||||||
|
list->outstanding_submissions_count = &allocator->outstanding_submissions_count;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -1500,6 +1501,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_command_allocator_Reset(ID3D12CommandAllo
|
||||||
const struct vkd3d_vk_device_procs *vk_procs;
|
const struct vkd3d_vk_device_procs *vk_procs;
|
||||||
struct d3d12_command_list *list;
|
struct d3d12_command_list *list;
|
||||||
struct d3d12_device *device;
|
struct d3d12_device *device;
|
||||||
|
LONG pending;
|
||||||
VkResult vr;
|
VkResult vr;
|
||||||
|
|
||||||
TRACE("iface %p.\n", iface);
|
TRACE("iface %p.\n", iface);
|
||||||
|
@ -1515,6 +1517,23 @@ static HRESULT STDMETHODCALLTYPE d3d12_command_allocator_Reset(ID3D12CommandAllo
|
||||||
TRACE("Resetting command list %p.\n", list);
|
TRACE("Resetting command list %p.\n", list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((pending = atomic_add_fetch(&allocator->outstanding_submissions_count, 0)) != 0)
|
||||||
|
{
|
||||||
|
/* HACK: There are currently command lists waiting to be submitted to the queue in the submission threads.
|
||||||
|
* Buggy application, but work around this by not resetting the command pool this time.
|
||||||
|
* To be perfectly safe, we can only reset after the fence timeline is signalled,
|
||||||
|
* however, this is enough to workaround SotTR which resets the command list right
|
||||||
|
* after calling ID3D12CommandQueue::ExecuteCommandLists().
|
||||||
|
* Only happens once or twice on bootup and doesn't cause memory leaks over time
|
||||||
|
* since the command pool is eventually reset.
|
||||||
|
* Game does not seem to care if E_FAIL is returned, which is the correct thing to do here.
|
||||||
|
*
|
||||||
|
* TODO: Guard this with actual timeline semaphores from vkQueueSubmit(). */
|
||||||
|
ERR("There are still %u pending command lists awaiting execution from command allocator iface %p!\n",
|
||||||
|
(unsigned int)pending, iface);
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
device = allocator->device;
|
device = allocator->device;
|
||||||
vk_procs = &device->vk_procs;
|
vk_procs = &device->vk_procs;
|
||||||
|
|
||||||
|
@ -1595,7 +1614,7 @@ static HRESULT d3d12_command_allocator_init(struct d3d12_command_allocator *allo
|
||||||
|
|
||||||
allocator->ID3D12CommandAllocator_iface.lpVtbl = &d3d12_command_allocator_vtbl;
|
allocator->ID3D12CommandAllocator_iface.lpVtbl = &d3d12_command_allocator_vtbl;
|
||||||
allocator->refcount = 1;
|
allocator->refcount = 1;
|
||||||
|
allocator->outstanding_submissions_count = 0;
|
||||||
allocator->type = type;
|
allocator->type = type;
|
||||||
allocator->vk_queue_flags = queue->vk_queue_flags;
|
allocator->vk_queue_flags = queue->vk_queue_flags;
|
||||||
|
|
||||||
|
@ -6081,6 +6100,7 @@ static void STDMETHODCALLTYPE d3d12_command_queue_ExecuteCommandLists(ID3D12Comm
|
||||||
struct d3d12_command_queue_submission sub;
|
struct d3d12_command_queue_submission sub;
|
||||||
struct d3d12_command_list *cmd_list;
|
struct d3d12_command_list *cmd_list;
|
||||||
VkCommandBuffer *buffers;
|
VkCommandBuffer *buffers;
|
||||||
|
LONG **outstanding;
|
||||||
unsigned int i, j;
|
unsigned int i, j;
|
||||||
|
|
||||||
TRACE("iface %p, command_list_count %u, command_lists %p.\n",
|
TRACE("iface %p, command_list_count %u, command_lists %p.\n",
|
||||||
|
@ -6092,6 +6112,12 @@ static void STDMETHODCALLTYPE d3d12_command_queue_ExecuteCommandLists(ID3D12Comm
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(outstanding = vkd3d_calloc(command_list_count, sizeof(*outstanding))))
|
||||||
|
{
|
||||||
|
ERR("Failed to allocate outstanding submissions count.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < command_list_count; ++i)
|
for (i = 0; i < command_list_count; ++i)
|
||||||
{
|
{
|
||||||
cmd_list = unsafe_impl_from_ID3D12CommandList(command_lists[i]);
|
cmd_list = unsafe_impl_from_ID3D12CommandList(command_lists[i]);
|
||||||
|
@ -6104,6 +6130,9 @@ static void STDMETHODCALLTYPE d3d12_command_queue_ExecuteCommandLists(ID3D12Comm
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
outstanding[i] = cmd_list->outstanding_submissions_count;
|
||||||
|
InterlockedIncrement(outstanding[i]);
|
||||||
|
|
||||||
for (j = 0; j < cmd_list->descriptor_updates_count; j++)
|
for (j = 0; j < cmd_list->descriptor_updates_count; j++)
|
||||||
d3d12_deferred_descriptor_set_update_resolve(cmd_list, &cmd_list->descriptor_updates[j]);
|
d3d12_deferred_descriptor_set_update_resolve(cmd_list, &cmd_list->descriptor_updates[j]);
|
||||||
buffers[i] = cmd_list->vk_command_buffer;
|
buffers[i] = cmd_list->vk_command_buffer;
|
||||||
|
@ -6112,6 +6141,7 @@ static void STDMETHODCALLTYPE d3d12_command_queue_ExecuteCommandLists(ID3D12Comm
|
||||||
sub.type = VKD3D_SUBMISSION_EXECUTE;
|
sub.type = VKD3D_SUBMISSION_EXECUTE;
|
||||||
sub.u.execute.cmd = buffers;
|
sub.u.execute.cmd = buffers;
|
||||||
sub.u.execute.count = command_list_count;
|
sub.u.execute.count = command_list_count;
|
||||||
|
sub.u.execute.outstanding_submissions_count = outstanding;
|
||||||
d3d12_command_queue_add_submission(command_queue, &sub);
|
d3d12_command_queue_add_submission(command_queue, &sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6470,6 +6500,8 @@ static void *d3d12_command_queue_submission_worker_main(void *userdata)
|
||||||
{
|
{
|
||||||
struct d3d12_command_queue_submission submission;
|
struct d3d12_command_queue_submission submission;
|
||||||
struct d3d12_command_queue *queue = userdata;
|
struct d3d12_command_queue *queue = userdata;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
vkd3d_set_thread_name("vkd3d_queue");
|
vkd3d_set_thread_name("vkd3d_queue");
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
|
@ -6499,6 +6531,10 @@ static void *d3d12_command_queue_submission_worker_main(void *userdata)
|
||||||
case VKD3D_SUBMISSION_EXECUTE:
|
case VKD3D_SUBMISSION_EXECUTE:
|
||||||
d3d12_command_queue_execute(queue, submission.u.execute.cmd, submission.u.execute.count);
|
d3d12_command_queue_execute(queue, submission.u.execute.cmd, submission.u.execute.count);
|
||||||
vkd3d_free(submission.u.execute.cmd);
|
vkd3d_free(submission.u.execute.cmd);
|
||||||
|
/* TODO: The correct place to do this would be in a fence handler, but this is good enough for now. */
|
||||||
|
for (i = 0; i < submission.u.execute.count; i++)
|
||||||
|
InterlockedDecrement(submission.u.execute.outstanding_submissions_count[i]);
|
||||||
|
vkd3d_free(submission.u.execute.outstanding_submissions_count);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VKD3D_SUBMISSION_DRAIN:
|
case VKD3D_SUBMISSION_DRAIN:
|
||||||
|
|
|
@ -1032,6 +1032,8 @@ struct d3d12_command_allocator
|
||||||
size_t command_buffers_size;
|
size_t command_buffers_size;
|
||||||
size_t command_buffer_count;
|
size_t command_buffer_count;
|
||||||
|
|
||||||
|
LONG outstanding_submissions_count;
|
||||||
|
|
||||||
struct d3d12_command_list *current_command_list;
|
struct d3d12_command_list *current_command_list;
|
||||||
struct d3d12_device *device;
|
struct d3d12_device *device;
|
||||||
|
|
||||||
|
@ -1164,6 +1166,8 @@ struct d3d12_command_list
|
||||||
size_t descriptor_updates_size;
|
size_t descriptor_updates_size;
|
||||||
size_t descriptor_updates_count;
|
size_t descriptor_updates_count;
|
||||||
|
|
||||||
|
LONG *outstanding_submissions_count;
|
||||||
|
|
||||||
struct vkd3d_private_store private_store;
|
struct vkd3d_private_store private_store;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1214,6 +1218,7 @@ struct d3d12_command_queue_submission_signal
|
||||||
struct d3d12_command_queue_submission_execute
|
struct d3d12_command_queue_submission_execute
|
||||||
{
|
{
|
||||||
VkCommandBuffer *cmd;
|
VkCommandBuffer *cmd;
|
||||||
|
LONG **outstanding_submissions_count;
|
||||||
UINT count;
|
UINT count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue