From c48141457203d4cdfcd8315c0735748ba3b9fda2 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Wed, 17 Sep 2025 08:52:27 +0200 Subject: [PATCH] vkd3d: Implement d3d12_device_CreateCommandList1(). Signed-off-by: Nikolay Sivov --- libs/vkd3d/command.c | 107 ++++++++++++++----------------------- libs/vkd3d/device.c | 24 +++++++-- libs/vkd3d/vkd3d_private.h | 5 +- tests/d3d12.c | 23 ++++++++ 4 files changed, 87 insertions(+), 72 deletions(-) diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index 4d3372439..69f42280e 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -2688,39 +2688,12 @@ static void d3d12_command_list_reset_state(struct d3d12_command_list *list, static HRESULT STDMETHODCALLTYPE d3d12_command_list_Reset(ID3D12GraphicsCommandList6 *iface, ID3D12CommandAllocator *allocator, ID3D12PipelineState *initial_pipeline_state) { - struct d3d12_command_allocator *allocator_impl = unsafe_impl_from_ID3D12CommandAllocator(allocator); struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList6(iface); - HRESULT hr; TRACE("iface %p, allocator %p, initial_pipeline_state %p.\n", iface, allocator, initial_pipeline_state); - if (!allocator_impl) - { - WARN("Command allocator is NULL.\n"); - return E_INVALIDARG; - } - - if (allocator_impl->type != list->type) - { - WARN("Command list types do not match (allocator %#x, list %#x).\n", - allocator_impl->type, list->type); - return E_INVALIDARG; - } - - if (list->is_recording) - { - WARN("Command list is in the recording state.\n"); - return E_FAIL; - } - - if (SUCCEEDED(hr = d3d12_command_allocator_allocate_command_buffer(allocator_impl, list))) - { - list->allocator = allocator_impl; - d3d12_command_list_reset_state(list, initial_pipeline_state); - } - - return hr; + return d3d12_command_list_reset(list, allocator, initial_pipeline_state); } static void STDMETHODCALLTYPE d3d12_command_list_ClearState(ID3D12GraphicsCommandList6 *iface, @@ -6412,9 +6385,8 @@ static struct d3d12_command_list *unsafe_impl_from_ID3D12CommandList(ID3D12Comma return CONTAINING_RECORD(iface, struct d3d12_command_list, ID3D12GraphicsCommandList6_iface); } -static HRESULT d3d12_command_list_init(struct d3d12_command_list *list, struct d3d12_device *device, - D3D12_COMMAND_LIST_TYPE type, struct d3d12_command_allocator *allocator, - ID3D12PipelineState *initial_pipeline_state) +static HRESULT d3d12_command_list_init(struct d3d12_command_list *list, + struct d3d12_device *device, D3D12_COMMAND_LIST_TYPE type) { HRESULT hr; @@ -6428,52 +6400,21 @@ static HRESULT d3d12_command_list_init(struct d3d12_command_list *list, struct d d3d12_device_add_ref(list->device = device); - list->allocator = allocator; - - list->descriptor_heap_count = 0; - - if (SUCCEEDED(hr = d3d12_command_allocator_allocate_command_buffer(allocator, list))) - { - list->pipeline_bindings[VKD3D_PIPELINE_BIND_POINT_GRAPHICS].vk_uav_counter_views = NULL; - list->pipeline_bindings[VKD3D_PIPELINE_BIND_POINT_COMPUTE].vk_uav_counter_views = NULL; - d3d12_command_list_reset_state(list, initial_pipeline_state); - } - else - { - vkd3d_private_store_destroy(&list->private_store); - d3d12_device_release(device); - } - return hr; } -HRESULT d3d12_command_list_create(struct d3d12_device *device, - UINT node_mask, D3D12_COMMAND_LIST_TYPE type, ID3D12CommandAllocator *allocator_iface, - ID3D12PipelineState *initial_pipeline_state, struct d3d12_command_list **list) +HRESULT d3d12_command_list_create(struct d3d12_device *device, UINT node_mask, + D3D12_COMMAND_LIST_TYPE type, struct d3d12_command_list **list) { - struct d3d12_command_allocator *allocator; struct d3d12_command_list *object; HRESULT hr; - if (!(allocator = unsafe_impl_from_ID3D12CommandAllocator(allocator_iface))) - { - WARN("Command allocator is NULL.\n"); - return E_INVALIDARG; - } - - if (allocator->type != type) - { - WARN("Command list types do not match (allocator %#x, list %#x).\n", - allocator->type, type); - return E_INVALIDARG; - } - debug_ignored_node_mask(node_mask); - if (!(object = vkd3d_malloc(sizeof(*object)))) + if (!(object = vkd3d_calloc(1, sizeof(*object)))) return E_OUTOFMEMORY; - if (FAILED(hr = d3d12_command_list_init(object, device, type, allocator, initial_pipeline_state))) + if (FAILED(hr = d3d12_command_list_init(object, device, type))) { vkd3d_free(object); return hr; @@ -6486,6 +6427,40 @@ HRESULT d3d12_command_list_create(struct d3d12_device *device, return S_OK; } +HRESULT d3d12_command_list_reset(struct d3d12_command_list *list, ID3D12CommandAllocator *allocator_iface, + ID3D12PipelineState *initial_pipeline_state) +{ + struct d3d12_command_allocator *allocator; + HRESULT hr; + + if (!(allocator = unsafe_impl_from_ID3D12CommandAllocator(allocator_iface))) + { + WARN("Command allocator is NULL.\n"); + return E_INVALIDARG; + } + + if (allocator->type != list->type) + { + WARN("Command list types do not match (allocator %#x, list %#x).\n", + allocator->type, list->type); + return E_INVALIDARG; + } + + if (list->is_recording) + { + WARN("Command list is in the recording state.\n"); + return E_FAIL; + } + + if (SUCCEEDED(hr = d3d12_command_allocator_allocate_command_buffer(allocator, list))) + { + list->allocator = allocator; + d3d12_command_list_reset_state(list, initial_pipeline_state); + } + + return hr; +} + /* ID3D12CommandQueue */ static inline struct d3d12_command_queue *impl_from_ID3D12CommandQueue(ID3D12CommandQueue *iface) { diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 67f84aafa..6af5e2a5c 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -3271,10 +3271,15 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandList(ID3D12Device9 *i iface, node_mask, type, command_allocator, initial_pipeline_state, debugstr_guid(riid), command_list); - if (FAILED(hr = d3d12_command_list_create(device, node_mask, type, command_allocator, - initial_pipeline_state, &object))) + if (FAILED(hr = d3d12_command_list_create(device, node_mask, type, &object))) return hr; + if (FAILED(hr = d3d12_command_list_reset(object, command_allocator, initial_pipeline_state))) + { + ID3D12GraphicsCommandList6_Release(&object->ID3D12GraphicsCommandList6_iface); + return hr; + } + return return_interface(&object->ID3D12GraphicsCommandList6_iface, &IID_ID3D12GraphicsCommandList6, riid, command_list); } @@ -5082,10 +5087,21 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandList1(ID3D12Device9 * UINT node_mask, D3D12_COMMAND_LIST_TYPE type, D3D12_COMMAND_LIST_FLAGS flags, REFIID iid, void **command_list) { - FIXME("iface %p, node_mask 0x%08x, type %#x, flags %#x, iid %s, command_list %p stub!\n", + struct d3d12_device *device = impl_from_ID3D12Device9(iface); + struct d3d12_command_list *object; + HRESULT hr; + + TRACE("iface %p, node_mask 0x%08x, type %#x, flags %#x, iid %s, command_list %p.\n", iface, node_mask, type, flags, debugstr_guid(iid), command_list); - return E_NOTIMPL; + if (flags) + FIXME("Ignoring flags %#x.\n", flags); + + if (FAILED(hr = d3d12_command_list_create(device, node_mask, type, &object))) + return hr; + + return return_interface(&object->ID3D12GraphicsCommandList6_iface, + &IID_ID3D12GraphicsCommandList6, iid, command_list); } static HRESULT STDMETHODCALLTYPE d3d12_device_CreateProtectedResourceSession(ID3D12Device9 *iface, diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index bc5406c45..4317d8afd 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -1327,8 +1327,9 @@ struct d3d12_command_list }; HRESULT d3d12_command_list_create(struct d3d12_device *device, - UINT node_mask, D3D12_COMMAND_LIST_TYPE type, ID3D12CommandAllocator *allocator_iface, - ID3D12PipelineState *initial_pipeline_state, struct d3d12_command_list **list); + UINT node_mask, D3D12_COMMAND_LIST_TYPE type, struct d3d12_command_list **list); +HRESULT d3d12_command_list_reset(struct d3d12_command_list *list, + ID3D12CommandAllocator *allocator_iface, ID3D12PipelineState *initial_pipeline_state); struct vkd3d_queue { diff --git a/tests/d3d12.c b/tests/d3d12.c index 12f4ff72c..7363e6ca0 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -1327,8 +1327,10 @@ static void test_create_command_allocator(void) static void test_create_command_list(void) { ID3D12CommandAllocator *command_allocator; + ID3D12GraphicsCommandList *command_list2; ID3D12Device *device, *tmp_device; ID3D12CommandList *command_list; + ID3D12Device4 *device4; ULONG refcount; HRESULT hr; @@ -1425,6 +1427,27 @@ static void test_create_command_list(void) refcount = ID3D12CommandAllocator_Release(command_allocator); ok(!refcount, "ID3D12CommandAllocator has %u references left.\n", (unsigned int)refcount); + if (SUCCEEDED(ID3D12Device_QueryInterface(device, &IID_ID3D12Device4, (void **)&device4))) + { + hr = ID3D12Device4_CreateCommandList1(device4, 0, D3D12_COMMAND_LIST_TYPE_DIRECT, + D3D12_COMMAND_LIST_FLAG_NONE, &IID_ID3D12GraphicsCommandList, (void **)&command_list2); + ok(SUCCEEDED(hr), "Failed to create command list, hr %#x.\n", hr); + + hr = ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_DIRECT, + &IID_ID3D12CommandAllocator, (void **)&command_allocator); + ok(SUCCEEDED(hr), "Failed to create command allocator, hr %#x.\n", hr); + + hr = ID3D12GraphicsCommandList_Reset(command_list2, command_allocator, NULL); + ok(SUCCEEDED(hr), "Failed to reset command list, hr %#x.\n", hr); + + refcount = ID3D12CommandAllocator_Release(command_allocator); + ok(!refcount, "ID3D12CommandAllocator has %u references left.\n", (unsigned int)refcount); + refcount = ID3D12GraphicsCommandList_Release(command_list2); + ok(!refcount, "ID3D12CommandList has %u references left.\n", (unsigned int)refcount); + + ID3D12Device4_Release(device4); + } + refcount = ID3D12Device_Release(device); ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount); }