From f0a1e1411363da4c139fc75bcb9fcc0171cb5d32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zef=20Kucia?= Date: Mon, 16 Apr 2018 12:16:21 +0200 Subject: [PATCH] libs/vkd3d: Mark device as removed when command list in recording state is executed. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes a GPU hang in test_device_removed_reason() on RADV. Signed-off-by: Józef Kucia Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- include/private/vkd3d_debug.h | 3 +++ libs/vkd3d-common/debug.c | 17 ++++++++++++----- libs/vkd3d/command.c | 13 ++++++++++++- libs/vkd3d/device.c | 21 +++++++++++++++++++-- libs/vkd3d/vkd3d_private.h | 4 ++++ tests/d3d12.c | 4 ++-- 6 files changed, 52 insertions(+), 10 deletions(-) diff --git a/include/private/vkd3d_debug.h b/include/private/vkd3d_debug.h index b9d4bcde..e5e938db 100644 --- a/include/private/vkd3d_debug.h +++ b/include/private/vkd3d_debug.h @@ -21,6 +21,8 @@ #include "vkd3d_common.h" +#include + enum vkd3d_dbg_level { VKD3D_DBG_LEVEL_NONE, @@ -36,6 +38,7 @@ void vkd3d_dbg_printf(enum vkd3d_dbg_level level, const char *function, const char *fmt, ...) VKD3D_PRINTF_FUNC(3, 4) DECLSPEC_HIDDEN; const char *vkd3d_dbg_sprintf(const char *fmt, ...) VKD3D_PRINTF_FUNC(1, 2) DECLSPEC_HIDDEN; +const char *vkd3d_dbg_vsprintf(const char *fmt, va_list args) DECLSPEC_HIDDEN; const char *debugstr_a(const char *str) DECLSPEC_HIDDEN; const char *debugstr_w(const WCHAR *wstr, size_t wchar_size) DECLSPEC_HIDDEN; diff --git a/libs/vkd3d-common/debug.c b/libs/vkd3d-common/debug.c index 9cdf2a98..b8380457 100644 --- a/libs/vkd3d-common/debug.c +++ b/libs/vkd3d-common/debug.c @@ -20,7 +20,6 @@ #include #include -#include #include #include #include @@ -89,19 +88,27 @@ static char *get_buffer(void) return buffers[current_index]; } -const char *vkd3d_dbg_sprintf(const char *fmt, ...) +const char *vkd3d_dbg_vsprintf(const char *fmt, va_list args) { char *buffer; - va_list args; buffer = get_buffer(); - va_start(args, fmt); vsnprintf(buffer, VKD3D_DEBUG_BUFFER_SIZE, fmt, args); - va_end(args); buffer[VKD3D_DEBUG_BUFFER_SIZE - 1] = '\0'; return buffer; } +const char *vkd3d_dbg_sprintf(const char *fmt, ...) +{ + const char *buffer; + va_list args; + + va_start(args, fmt); + buffer = vkd3d_dbg_vsprintf(fmt, args); + va_end(args); + return buffer; +} + const char *debugstr_a(const char *str) { char *buffer, *ptr; diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index b7b774b2..82a99fda 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -4191,6 +4191,7 @@ static void STDMETHODCALLTYPE d3d12_command_queue_ExecuteCommandLists(ID3D12Comm { struct d3d12_command_queue *command_queue = impl_from_ID3D12CommandQueue(iface); const struct vkd3d_vk_device_procs *vk_procs; + struct d3d12_command_list *cmd_list; struct VkSubmitInfo submit_desc; VkCommandBuffer *buffers; VkQueue vk_queue; @@ -4210,7 +4211,17 @@ static void STDMETHODCALLTYPE d3d12_command_queue_ExecuteCommandLists(ID3D12Comm for (i = 0; i < command_list_count; ++i) { - buffers[i] = unsafe_impl_from_ID3D12CommandList(command_lists[i])->vk_command_buffer; + cmd_list = unsafe_impl_from_ID3D12CommandList(command_lists[i]); + + if (cmd_list->is_recording) + { + d3d12_device_mark_as_removed(command_queue->device, DXGI_ERROR_INVALID_CALL, + "Command list %p is in recording state.\n", command_lists[i]); + vkd3d_free(buffers); + return; + } + + buffers[i] = cmd_list->vk_command_buffer; } submit_desc.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 805d477f..48ad7c50 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -1943,9 +1943,11 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateFence(ID3D12Device *iface, static HRESULT STDMETHODCALLTYPE d3d12_device_GetDeviceRemovedReason(ID3D12Device *iface) { - FIXME("iface %p stub!\n", iface); + struct d3d12_device *device = impl_from_ID3D12Device(iface); - return S_OK; + TRACE("iface %p.\n", iface); + + return device->removed_reason; } static void STDMETHODCALLTYPE d3d12_device_GetCopyableFootprints(ID3D12Device *iface, @@ -2245,6 +2247,8 @@ static HRESULT d3d12_device_init(struct d3d12_device *device, if ((device->parent = create_info->parent)) IUnknown_AddRef(device->parent); + device->removed_reason = S_OK; + return S_OK; } @@ -2270,6 +2274,19 @@ HRESULT d3d12_device_create(struct vkd3d_instance *instance, return S_OK; } +void d3d12_device_mark_as_removed(struct d3d12_device *device, HRESULT reason, + const char *message, ...) +{ + va_list args; + + va_start(args, message); + WARN("Device %p is lost (reason %#x, message \"%s\").\n", + device, reason, vkd3d_dbg_vsprintf(message, args)); + va_end(args); + + device->removed_reason = reason; +} + IUnknown *vkd3d_get_device_parent(ID3D12Device *device) { struct d3d12_device *d3d12_device = impl_from_ID3D12Device(device); diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 246c42be..4a359dbf 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -683,10 +683,14 @@ struct d3d12_device IUnknown *parent; LUID adapter_luid; + + HRESULT removed_reason; }; HRESULT d3d12_device_create(struct vkd3d_instance *instance, const struct vkd3d_device_create_info *create_info, struct d3d12_device **device) DECLSPEC_HIDDEN; +void d3d12_device_mark_as_removed(struct d3d12_device *device, HRESULT reason, + const char *message, ...) VKD3D_PRINTF_FUNC(3, 4) DECLSPEC_HIDDEN; struct d3d12_device *unsafe_impl_from_ID3D12Device(ID3D12Device *iface) DECLSPEC_HIDDEN; HRESULT vkd3d_create_buffer(struct d3d12_device *device, diff --git a/tests/d3d12.c b/tests/d3d12.c index 7dfee875..ea7d24da 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -4598,7 +4598,7 @@ static void test_device_removed_reason(void) exec_command_list(queue, command_list); hr = ID3D12Device_GetDeviceRemovedReason(device); - todo(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); + ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); hr = ID3D12Device_CreateCommandQueue(device, &command_queue_desc, &IID_ID3D12CommandQueue, (void **)&tmp_queue); @@ -4607,7 +4607,7 @@ static void test_device_removed_reason(void) ID3D12CommandQueue_Release(tmp_queue); hr = ID3D12Device_GetDeviceRemovedReason(device); - todo(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); + ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); ID3D12GraphicsCommandList_Release(command_list); ID3D12CommandAllocator_Release(command_allocator);