From: Józef Kucia jkucia@codeweavers.com
Fixes a GPU hang in test_device_removed_reason() on RADV.
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- 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 b9d4bcde0a92..e5e938dbb3f3 100644 --- a/include/private/vkd3d_debug.h +++ b/include/private/vkd3d_debug.h @@ -21,6 +21,8 @@
#include "vkd3d_common.h"
+#include <stdarg.h> + 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 9cdf2a98e851..b8380457058d 100644 --- a/libs/vkd3d-common/debug.c +++ b/libs/vkd3d-common/debug.c @@ -20,7 +20,6 @@
#include <assert.h> #include <ctype.h> -#include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -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 b7b774b284de..82a99fda2511 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 805d477f89b0..48ad7c506c34 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 246c42bed937..4a359dbf7632 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 7dfee875ab0b..ea7d24da57be 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);