[PATCH vkd3d 5/5] vkd3d: Introduce command list type bundle.
Conor McCarthy
cmccarthy at codeweavers.com
Fri Sep 3 09:58:59 CDT 2021
Only DrawInstanced() is supported in this patch.
Modern compilers use a binary search for switch statements, so the
performance impact will be not too great when all valid command
list methods are handled.
Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
---
Makefile.am | 1 +
libs/vkd3d/bundle.c | 1102 ++++++++++++++++++++++++++++++++++++
libs/vkd3d/command.c | 60 +-
libs/vkd3d/device.c | 47 +-
libs/vkd3d/vkd3d_private.h | 76 +++
tests/d3d12.c | 9 +-
6 files changed, 1275 insertions(+), 20 deletions(-)
create mode 100644 libs/vkd3d/bundle.c
diff --git a/Makefile.am b/Makefile.am
index f51233c2..9a0b868f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -200,6 +200,7 @@ libvkd3d_la_SOURCES = \
include/vkd3d_d3d12.idl \
include/vkd3d_d3dcommon.idl \
include/vkd3d_unknown.idl \
+ libs/vkd3d/bundle.c \
libs/vkd3d/command.c \
libs/vkd3d/device.c \
libs/vkd3d/resource.c \
diff --git a/libs/vkd3d/bundle.c b/libs/vkd3d/bundle.c
new file mode 100644
index 00000000..dd3aadf7
--- /dev/null
+++ b/libs/vkd3d/bundle.c
@@ -0,0 +1,1102 @@
+/*
+ * Copyright 2021 Conor McCarthy for CodeWeavers.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "vkd3d_private.h"
+
+static void d3d12_bundle_command_buffer_reset(struct d3d12_bundle_command_buffer *command_buffer)
+{
+ command_buffer->commands = NULL;
+ command_buffer->size = 0;
+ command_buffer->count = 0;
+}
+
+static bool d3d12_bundle_command_buffer_reserve(struct d3d12_bundle_command_buffer *command_buffer,
+ size_t count, enum vkd3d_command_list_command_id id)
+{
+ size_t new_count = command_buffer->count + 1 + count;
+
+ if (!vkd3d_array_reserve((void **)&command_buffer->commands, &command_buffer->size,
+ max(new_count, 32), sizeof(*command_buffer->commands)))
+ {
+ ERR("Out of memory. Cannot record bundle command %#x.\n", id);
+ return false;
+ }
+
+ command_buffer->commands[command_buffer->count].header.count = count;
+ command_buffer->commands[command_buffer->count++].header.id = id;
+
+ return true;
+}
+
+static void d3d12_bundle_begin_command_buffer(struct d3d12_bundle *bundle)
+{
+ bundle->is_recording = true;
+ bundle->is_valid = true;
+}
+
+static void d3d12_bundle_allocator_destroyed(struct d3d12_bundle *bundle)
+{
+ TRACE("bundle %p.\n", bundle);
+
+ bundle->allocator = NULL;
+ d3d12_bundle_command_buffer_reset(&bundle->command_buffer);
+}
+
+/* ID3D12CommandAllocator */
+static inline struct d3d12_bundle_allocator *impl_from_ID3D12CommandAllocator(ID3D12CommandAllocator *iface)
+{
+ return CONTAINING_RECORD(iface, struct d3d12_bundle_allocator, ID3D12CommandAllocator_iface);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_bundle_allocator_QueryInterface(ID3D12CommandAllocator *iface,
+ REFIID riid, void **object)
+{
+ TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
+
+ if (IsEqualGUID(riid, &IID_ID3D12CommandAllocator)
+ || IsEqualGUID(riid, &IID_ID3D12Pageable)
+ || IsEqualGUID(riid, &IID_ID3D12DeviceChild)
+ || IsEqualGUID(riid, &IID_ID3D12Object)
+ || IsEqualGUID(riid, &IID_IUnknown))
+ {
+ ID3D12CommandAllocator_AddRef(iface);
+ *object = iface;
+ return S_OK;
+ }
+
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+ *object = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_bundle_allocator_AddRef(ID3D12CommandAllocator *iface)
+{
+ struct d3d12_bundle_allocator *allocator = impl_from_ID3D12CommandAllocator(iface);
+ ULONG refcount = InterlockedIncrement(&allocator->refcount);
+
+ TRACE("%p increasing refcount to %u.\n", allocator, refcount);
+
+ return refcount;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_bundle_allocator_Release(ID3D12CommandAllocator *iface)
+{
+ struct d3d12_bundle_allocator *allocator = impl_from_ID3D12CommandAllocator(iface);
+ ULONG refcount = InterlockedDecrement(&allocator->refcount);
+
+ TRACE("%p decreasing refcount to %u.\n", allocator, refcount);
+
+ if (!refcount)
+ {
+ struct d3d12_device *device = allocator->device;
+ size_t i;
+
+ vkd3d_private_store_destroy(&allocator->private_store);
+
+ if (allocator->current_bundle)
+ d3d12_bundle_allocator_destroyed(allocator->current_bundle);
+
+ for (i = 0; i < allocator->arg_buffer_count; ++i)
+ vkd3d_free(allocator->arg_buffers[i]);
+ vkd3d_free(allocator->arg_buffers);
+
+ vkd3d_free(allocator);
+
+ d3d12_device_release(device);
+ }
+
+ return refcount;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_bundle_allocator_GetPrivateData(ID3D12CommandAllocator *iface,
+ REFGUID guid, UINT *data_size, void *data)
+{
+ struct d3d12_bundle_allocator *allocator = impl_from_ID3D12CommandAllocator(iface);
+
+ TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_get_private_data(&allocator->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_bundle_allocator_SetPrivateData(ID3D12CommandAllocator *iface,
+ REFGUID guid, UINT data_size, const void *data)
+{
+ struct d3d12_bundle_allocator *allocator = impl_from_ID3D12CommandAllocator(iface);
+
+ TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_set_private_data(&allocator->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_bundle_allocator_SetPrivateDataInterface(ID3D12CommandAllocator *iface,
+ REFGUID guid, const IUnknown *data)
+{
+ struct d3d12_bundle_allocator *allocator = impl_from_ID3D12CommandAllocator(iface);
+
+ TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
+
+ return vkd3d_set_private_data_interface(&allocator->private_store, guid, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_bundle_allocator_SetName(ID3D12CommandAllocator *iface, const WCHAR *name)
+{
+ struct d3d12_bundle_allocator *allocator = impl_from_ID3D12CommandAllocator(iface);
+
+ TRACE("iface %p, name %s.\n", iface, debugstr_w(name, allocator->device->wchar_size));
+
+ return name ? S_OK : E_INVALIDARG;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_bundle_allocator_GetDevice(ID3D12CommandAllocator *iface, REFIID iid, void **device)
+{
+ struct d3d12_bundle_allocator *allocator = impl_from_ID3D12CommandAllocator(iface);
+
+ TRACE("iface %p, iid %s, device %p.\n", iface, debugstr_guid(iid), device);
+
+ return d3d12_device_query_interface(allocator->device, iid, device);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_bundle_allocator_Reset(ID3D12CommandAllocator *iface)
+{
+ struct d3d12_bundle_allocator *allocator = impl_from_ID3D12CommandAllocator(iface);
+ struct d3d12_bundle *bundle;
+ size_t i;
+
+ TRACE("iface %p.\n", iface);
+
+ if ((bundle = allocator->current_bundle))
+ {
+ if (bundle->is_recording)
+ {
+ WARN("A command list using this allocator is in the recording state.\n");
+ return E_FAIL;
+ }
+
+ TRACE("Resetting command list %p.\n", bundle);
+ }
+
+ for (i = 0; i < allocator->arg_buffer_count; ++i)
+ vkd3d_free(allocator->arg_buffers[i]);
+ allocator->arg_buffer_count = 0;
+
+ return S_OK;
+}
+
+static const struct ID3D12CommandAllocatorVtbl d3d12_bundle_allocator_vtbl =
+{
+ /* IUnknown methods */
+ d3d12_bundle_allocator_QueryInterface,
+ d3d12_bundle_allocator_AddRef,
+ d3d12_bundle_allocator_Release,
+ /* ID3D12Object methods */
+ d3d12_bundle_allocator_GetPrivateData,
+ d3d12_bundle_allocator_SetPrivateData,
+ d3d12_bundle_allocator_SetPrivateDataInterface,
+ d3d12_bundle_allocator_SetName,
+ /* ID3D12DeviceChild methods */
+ d3d12_bundle_allocator_GetDevice,
+ /* ID3D12CommandAllocator methods */
+ d3d12_bundle_allocator_Reset,
+};
+
+static struct d3d12_bundle_allocator *checked_impl_from_ID3D12CommandAllocator(ID3D12CommandAllocator *iface)
+{
+ if (iface->lpVtbl != &d3d12_bundle_allocator_vtbl)
+ return NULL;
+ return impl_from_ID3D12CommandAllocator(iface);
+}
+
+HRESULT d3d12_bundle_allocator_create(struct d3d12_device *device, struct d3d12_bundle_allocator **allocator)
+{
+ struct d3d12_bundle_allocator *object;
+ HRESULT hr;
+
+ if (!(object = vkd3d_calloc(1, sizeof(*object))))
+ return E_OUTOFMEMORY;
+
+ object->ID3D12CommandAllocator_iface.lpVtbl = &d3d12_bundle_allocator_vtbl;
+ object->refcount = 1;
+
+ if (FAILED(hr = vkd3d_private_store_init(&object->private_store)))
+ {
+ vkd3d_free(object);
+ return hr;
+ }
+
+ d3d12_device_add_ref(object->device = device);
+
+ TRACE("Created command allocator %p.\n", object);
+
+ *allocator = object;
+
+ return S_OK;
+}
+
+static HRESULT d3d12_bundle_allocator_init_command_buffer(struct d3d12_bundle_allocator *allocator,
+ struct d3d12_bundle *bundle)
+{
+ TRACE("allocator %p, bundle %p.\n", allocator, bundle);
+
+ if (allocator->current_bundle)
+ {
+ WARN("Command allocator is already in use.\n");
+ return E_INVALIDARG;
+ }
+
+ d3d12_bundle_command_buffer_reset(&bundle->command_buffer);
+
+ d3d12_bundle_begin_command_buffer(bundle);
+
+ allocator->current_bundle = bundle;
+
+ return S_OK;
+}
+
+static HRESULT d3d12_bundle_allocator_free_command_buffer(struct d3d12_bundle_allocator *allocator,
+ struct d3d12_bundle *bundle)
+{
+ TRACE("allocator %p, bundle %p.\n", allocator, bundle);
+
+ if (allocator->current_bundle == bundle)
+ allocator->current_bundle = NULL;
+
+ if (!vkd3d_array_reserve((void **)&allocator->arg_buffers, &allocator->arg_buffers_size,
+ allocator->arg_buffer_count + 1, sizeof(*allocator->arg_buffers)))
+ {
+ WARN("Failed to add command buffer.\n");
+ vkd3d_free(bundle->command_buffer.commands);
+ return E_OUTOFMEMORY;
+ }
+
+ allocator->arg_buffers[allocator->arg_buffer_count++] = bundle->command_buffer.commands;
+
+ return S_OK;
+}
+
+/* ID3D12GraphicsCommandList */
+static inline struct d3d12_bundle *impl_from_ID3D12GraphicsCommandList2(ID3D12GraphicsCommandList2 *iface)
+{
+ return CONTAINING_RECORD(iface, struct d3d12_bundle, ID3D12GraphicsCommandList2_iface);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_bundle_QueryInterface(ID3D12GraphicsCommandList2 *iface,
+ REFIID iid, void **object)
+{
+ TRACE("iface %p, iid %s, object %p.\n", iface, debugstr_guid(iid), object);
+
+ if (IsEqualGUID(iid, &IID_ID3D12GraphicsCommandList2)
+ || IsEqualGUID(iid, &IID_ID3D12GraphicsCommandList1)
+ || IsEqualGUID(iid, &IID_ID3D12GraphicsCommandList)
+ || IsEqualGUID(iid, &IID_ID3D12CommandList)
+ || IsEqualGUID(iid, &IID_ID3D12DeviceChild)
+ || IsEqualGUID(iid, &IID_ID3D12Object)
+ || IsEqualGUID(iid, &IID_IUnknown))
+ {
+ ID3D12GraphicsCommandList2_AddRef(iface);
+ *object = iface;
+ return S_OK;
+ }
+
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
+
+ *object = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_bundle_AddRef(ID3D12GraphicsCommandList2 *iface)
+{
+ struct d3d12_bundle *bundle = impl_from_ID3D12GraphicsCommandList2(iface);
+ ULONG refcount = InterlockedIncrement(&bundle->refcount);
+
+ TRACE("%p increasing refcount to %u.\n", bundle, refcount);
+
+ return refcount;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_bundle_Release(ID3D12GraphicsCommandList2 *iface)
+{
+ struct d3d12_bundle *bundle = impl_from_ID3D12GraphicsCommandList2(iface);
+ ULONG refcount = InterlockedDecrement(&bundle->refcount);
+
+ TRACE("%p decreasing refcount to %u.\n", bundle, refcount);
+
+ if (!refcount)
+ {
+ struct d3d12_device *device = bundle->device;
+
+ vkd3d_private_store_destroy(&bundle->private_store);
+
+ if (bundle->allocator)
+ d3d12_bundle_allocator_free_command_buffer(bundle->allocator, bundle);
+
+ vkd3d_free(bundle);
+
+ d3d12_device_release(device);
+ }
+
+ return refcount;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_bundle_GetPrivateData(ID3D12GraphicsCommandList2 *iface,
+ REFGUID guid, UINT *data_size, void *data)
+{
+ struct d3d12_bundle *bundle = impl_from_ID3D12GraphicsCommandList2(iface);
+
+ TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_get_private_data(&bundle->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_bundle_SetPrivateData(ID3D12GraphicsCommandList2 *iface,
+ REFGUID guid, UINT data_size, const void *data)
+{
+ struct d3d12_bundle *bundle = impl_from_ID3D12GraphicsCommandList2(iface);
+
+ TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_set_private_data(&bundle->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_bundle_SetPrivateDataInterface(ID3D12GraphicsCommandList2 *iface,
+ REFGUID guid, const IUnknown *data)
+{
+ struct d3d12_bundle *bundle = impl_from_ID3D12GraphicsCommandList2(iface);
+
+ TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
+
+ return vkd3d_set_private_data_interface(&bundle->private_store, guid, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_bundle_SetName(ID3D12GraphicsCommandList2 *iface, const WCHAR *name)
+{
+ struct d3d12_bundle *bundle = impl_from_ID3D12GraphicsCommandList2(iface);
+
+ TRACE("iface %p, name %s.\n", iface, debugstr_w(name, bundle->device->wchar_size));
+
+ return name ? S_OK : E_INVALIDARG;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_bundle_GetDevice(ID3D12GraphicsCommandList2 *iface, REFIID iid, void **device)
+{
+ struct d3d12_bundle *bundle = impl_from_ID3D12GraphicsCommandList2(iface);
+
+ TRACE("iface %p, iid %s, device %p.\n", iface, debugstr_guid(iid), device);
+
+ return d3d12_device_query_interface(bundle->device, iid, device);
+}
+
+static D3D12_COMMAND_LIST_TYPE STDMETHODCALLTYPE d3d12_bundle_GetType(ID3D12GraphicsCommandList2 *iface)
+{
+ TRACE("iface %p.\n", iface);
+
+ return D3D12_COMMAND_LIST_TYPE_BUNDLE;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_bundle_Close(ID3D12GraphicsCommandList2 *iface)
+{
+ struct d3d12_bundle *bundle = impl_from_ID3D12GraphicsCommandList2(iface);
+ HRESULT hr = S_OK;
+
+ TRACE("iface %p.\n", iface);
+
+ if (!bundle->is_recording)
+ {
+ WARN("Command list is not in the recording state.\n");
+ return E_FAIL;
+ }
+
+ if (bundle->allocator)
+ {
+ hr = d3d12_bundle_allocator_free_command_buffer(bundle->allocator, bundle);
+ bundle->allocator = NULL;
+ }
+
+ bundle->is_recording = false;
+
+ if (!bundle->is_valid)
+ {
+ WARN("Error occurred during command list recording.\n");
+ return E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+static void d3d12_bundle_init_state(struct d3d12_bundle *bundle, ID3D12PipelineState *initial_pipeline_state)
+{
+ ID3D12GraphicsCommandList2 *iface = &bundle->ID3D12GraphicsCommandList2_iface;
+
+ ID3D12GraphicsCommandList2_SetPipelineState(iface, initial_pipeline_state);
+ ID3D12GraphicsCommandList2_IASetPrimitiveTopology(iface, D3D_PRIMITIVE_TOPOLOGY_UNDEFINED);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_bundle_Reset(ID3D12GraphicsCommandList2 *iface,
+ ID3D12CommandAllocator *allocator_iface, ID3D12PipelineState *initial_pipeline_state)
+{
+ struct d3d12_bundle *bundle = impl_from_ID3D12GraphicsCommandList2(iface);
+ struct d3d12_bundle_allocator *allocator;
+ HRESULT hr;
+
+ if (!allocator_iface)
+ {
+ WARN("Command allocator is NULL.\n");
+ return E_INVALIDARG;
+ }
+
+ if (!(allocator = checked_impl_from_ID3D12CommandAllocator(allocator_iface)))
+ {
+ WARN("Command allocator is not of type D3D12_COMMAND_LIST_TYPE_BUNDLE.\n");
+ return E_INVALIDARG;
+ }
+
+ if (bundle->is_recording)
+ {
+ WARN("Command list is in the recording state.\n");
+ return E_FAIL;
+ }
+
+ if (SUCCEEDED(hr = d3d12_bundle_allocator_init_command_buffer(allocator, bundle)))
+ {
+ bundle->allocator = allocator;
+ d3d12_bundle_init_state(bundle, initial_pipeline_state);
+ }
+
+ return hr;
+}
+
+static void d3d12_bundle_mark_as_invalid(ID3D12GraphicsCommandList2 *iface)
+{
+ impl_from_ID3D12GraphicsCommandList2(iface)->is_valid = false;
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_ClearState(ID3D12GraphicsCommandList2 *iface,
+ ID3D12PipelineState *pipeline_state)
+{
+ ERR("iface %p, pipline_state %p command invalid for bundles.\n", iface, pipeline_state);
+
+ d3d12_bundle_mark_as_invalid(iface);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_DrawInstanced(ID3D12GraphicsCommandList2 *iface,
+ UINT vertex_count_per_instance, UINT instance_count, UINT start_vertex_location,
+ UINT start_instance_location)
+{
+ struct d3d12_bundle *bundle = impl_from_ID3D12GraphicsCommandList2(iface);
+ struct d3d12_bundle_command_buffer *buffer = &bundle->command_buffer;
+
+ TRACE("iface %p, vertex_count_per_instance %u, instance_count %u, start_vertex_location %u, "
+ "start_instance_location %u.\n", iface, vertex_count_per_instance, instance_count,
+ start_vertex_location, start_instance_location);
+
+ if (!d3d12_bundle_command_buffer_reserve(buffer, 4, VKD3D_COMMAND_DRAW_INSTANCED))
+ return;
+
+ buffer->commands[buffer->count++].uint_arg = vertex_count_per_instance;
+ buffer->commands[buffer->count++].uint_arg = instance_count;
+ buffer->commands[buffer->count++].uint_arg = start_vertex_location;
+ buffer->commands[buffer->count++].uint_arg = start_instance_location;
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_DrawIndexedInstanced(ID3D12GraphicsCommandList2 *iface,
+ UINT index_count_per_instance, UINT instance_count, UINT start_vertex_location,
+ INT base_vertex_location, UINT start_instance_location)
+{
+ FIXME("iface %p, index_count_per_instance %u, instance_count %u, start_vertex_location %u, "
+ "base_vertex_location %d, start_instance_location %u stub!\n", iface, index_count_per_instance,
+ instance_count, start_vertex_location, base_vertex_location, start_instance_location);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_Dispatch(ID3D12GraphicsCommandList2 *iface,
+ UINT x, UINT y, UINT z)
+{
+ FIXME("iface %p, x %u, y %u, z %u stub!\n", iface, x, y, z);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_CopyBufferRegion(ID3D12GraphicsCommandList2 *iface,
+ ID3D12Resource *dst, UINT64 dst_offset, ID3D12Resource *src, UINT64 src_offset, UINT64 byte_count)
+{
+ ERR("iface %p, dst_resource %p, dst_offset %#"PRIx64", src_resource %p, "
+ "src_offset %#"PRIx64", byte_count %#"PRIx64" command invalid for bundles.\n",
+ iface, dst, dst_offset, src, src_offset, byte_count);
+
+ d3d12_bundle_mark_as_invalid(iface);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_CopyTextureRegion(ID3D12GraphicsCommandList2 *iface,
+ const D3D12_TEXTURE_COPY_LOCATION *dst, UINT dst_x, UINT dst_y, UINT dst_z,
+ const D3D12_TEXTURE_COPY_LOCATION *src, const D3D12_BOX *src_box)
+{
+ ERR("iface %p, dst %p, dst_x %u, dst_y %u, dst_z %u, src %p, src_box %p command invalid for bundles.\n",
+ iface, dst, dst_x, dst_y, dst_z, src, src_box);
+
+ d3d12_bundle_mark_as_invalid(iface);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_CopyResource(ID3D12GraphicsCommandList2 *iface,
+ ID3D12Resource *dst, ID3D12Resource *src)
+{
+ ERR("iface %p, dst_resource %p, src_resource %p command invalid for bundles.\n", iface, dst, src);
+
+ d3d12_bundle_mark_as_invalid(iface);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_CopyTiles(ID3D12GraphicsCommandList2 *iface,
+ ID3D12Resource *tiled_resource, const D3D12_TILED_RESOURCE_COORDINATE *tile_region_start_coordinate,
+ const D3D12_TILE_REGION_SIZE *tile_region_size, ID3D12Resource *buffer, UINT64 buffer_offset,
+ D3D12_TILE_COPY_FLAGS flags)
+{
+ ERR("iface %p, tiled_resource %p, tile_region_start_coordinate %p, tile_region_size %p, "
+ "buffer %p, buffer_offset %#"PRIx64", flags %#x command invalid for bundles.\n",
+ iface, tiled_resource, tile_region_start_coordinate, tile_region_size,
+ buffer, buffer_offset, flags);
+
+ d3d12_bundle_mark_as_invalid(iface);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_ResolveSubresource(ID3D12GraphicsCommandList2 *iface,
+ ID3D12Resource *dst, UINT dst_sub_resource_idx,
+ ID3D12Resource *src, UINT src_sub_resource_idx, DXGI_FORMAT format)
+{
+ ERR("iface %p, dst_resource %p, dst_sub_resource_idx %u, src_resource %p, src_sub_resource_idx %u, format %#x "
+ "command invalid for bundles.\n", iface, dst, dst_sub_resource_idx, src, src_sub_resource_idx, format);
+
+ d3d12_bundle_mark_as_invalid(iface);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_IASetPrimitiveTopology(ID3D12GraphicsCommandList2 *iface,
+ D3D12_PRIMITIVE_TOPOLOGY topology)
+{
+ FIXME("iface %p, topology %#x stub!\n", iface, topology);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_RSSetViewports(ID3D12GraphicsCommandList2 *iface,
+ UINT viewport_count, const D3D12_VIEWPORT *viewports)
+{
+ ERR("iface %p, viewport_count %u, viewports %p command invalid for bundles.\n", iface, viewport_count, viewports);
+
+ d3d12_bundle_mark_as_invalid(iface);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_RSSetScissorRects(ID3D12GraphicsCommandList2 *iface,
+ UINT rect_count, const D3D12_RECT *rects)
+{
+ ERR("iface %p, rect_count %u, rects %p command invalid for bundles.\n", iface, rect_count, rects);
+
+ d3d12_bundle_mark_as_invalid(iface);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_OMSetBlendFactor(ID3D12GraphicsCommandList2 *iface,
+ const FLOAT blend_factor[4])
+{
+ FIXME("iface %p, blend_factor %p stub!\n", iface, blend_factor);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_OMSetStencilRef(ID3D12GraphicsCommandList2 *iface, UINT stencil_ref)
+{
+ FIXME("iface %p, stencil_ref %u stub!\n", iface, stencil_ref);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_SetPipelineState(ID3D12GraphicsCommandList2 *iface,
+ ID3D12PipelineState *pipeline_state)
+{
+ FIXME("iface %p, pipeline_state %p stub!\n", iface, pipeline_state);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_ResourceBarrier(ID3D12GraphicsCommandList2 *iface,
+ UINT barrier_count, const D3D12_RESOURCE_BARRIER *barriers)
+{
+ ERR("iface %p, barrier_count %u, barriers %p command invalid for bundles.\n", iface, barrier_count, barriers);
+
+ d3d12_bundle_mark_as_invalid(iface);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_ExecuteBundle(ID3D12GraphicsCommandList2 *iface,
+ ID3D12GraphicsCommandList *bundle_iface)
+{
+ ERR("iface %p, bundle_iface %p command invalid for bundles.\n", iface, bundle_iface);
+
+ d3d12_bundle_mark_as_invalid(iface);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_SetDescriptorHeaps(ID3D12GraphicsCommandList2 *iface,
+ UINT heap_count, ID3D12DescriptorHeap *const *heaps)
+{
+ TRACE("iface %p, heap_count %u, heaps %p.\n", iface, heap_count, heaps);
+
+ /* Our current implementation does not need this method.
+ *
+ * The D3D12 documentation states it is valid for bundles if the heaps are the same as
+ * those already set in the executing command list. ExecuteBundle() could validate this
+ * but we do not have an equivalent of the D3D12 Debug Layer. */
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_SetComputeRootSignature(ID3D12GraphicsCommandList2 *iface,
+ ID3D12RootSignature *root_signature)
+{
+ FIXME("iface %p, root_signature %p stub!\n", iface, root_signature);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_SetGraphicsRootSignature(ID3D12GraphicsCommandList2 *iface,
+ ID3D12RootSignature *root_signature)
+{
+ FIXME("iface %p, root_signature %p stub!\n", iface, root_signature);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_SetComputeRootDescriptorTable(ID3D12GraphicsCommandList2 *iface,
+ UINT root_parameter_index, D3D12_GPU_DESCRIPTOR_HANDLE base_descriptor)
+{
+ FIXME("iface %p, root_parameter_index %u, base_descriptor %#"PRIx64" stub!\n",
+ iface, root_parameter_index, base_descriptor.ptr);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_SetGraphicsRootDescriptorTable(ID3D12GraphicsCommandList2 *iface,
+ UINT root_parameter_index, D3D12_GPU_DESCRIPTOR_HANDLE base_descriptor)
+{
+ FIXME("iface %p, root_parameter_index %u, base_descriptor %#"PRIx64" stub!\n",
+ iface, root_parameter_index, base_descriptor.ptr);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_SetComputeRoot32BitConstant(ID3D12GraphicsCommandList2 *iface,
+ UINT root_parameter_index, UINT data, UINT dst_offset)
+{
+ FIXME("iface %p, root_parameter_index %u, data 0x%08x, dst_offset %u stub!\n",
+ iface, root_parameter_index, data, dst_offset);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_SetGraphicsRoot32BitConstant(ID3D12GraphicsCommandList2 *iface,
+ UINT root_parameter_index, UINT data, UINT dst_offset)
+{
+ FIXME("iface %p, root_parameter_index %u, data 0x%08x, dst_offset %u stub!\n",
+ iface, root_parameter_index, data, dst_offset);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_SetComputeRoot32BitConstants(ID3D12GraphicsCommandList2 *iface,
+ UINT root_parameter_index, UINT constant_count, const void *data, UINT dst_offset)
+{
+ FIXME("iface %p, root_parameter_index %u, constant_count %u, data %p, dst_offset %u stub!\n",
+ iface, root_parameter_index, constant_count, data, dst_offset);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_SetGraphicsRoot32BitConstants(ID3D12GraphicsCommandList2 *iface,
+ UINT root_parameter_index, UINT constant_count, const void *data, UINT dst_offset)
+{
+ FIXME("iface %p, root_parameter_index %u, constant_count %u, data %p, dst_offset %u stub!\n",
+ iface, root_parameter_index, constant_count, data, dst_offset);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_SetComputeRootConstantBufferView(
+ ID3D12GraphicsCommandList2 *iface, UINT root_parameter_index, D3D12_GPU_VIRTUAL_ADDRESS address)
+{
+ FIXME("iface %p, root_parameter_index %u, address %#"PRIx64" stub!\n", iface, root_parameter_index, address);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_SetGraphicsRootConstantBufferView(
+ ID3D12GraphicsCommandList2 *iface, UINT root_parameter_index, D3D12_GPU_VIRTUAL_ADDRESS address)
+{
+ FIXME("iface %p, root_parameter_index %u, address %#"PRIx64" stub!\n", iface, root_parameter_index, address);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_SetComputeRootShaderResourceView(
+ ID3D12GraphicsCommandList2 *iface, UINT root_parameter_index, D3D12_GPU_VIRTUAL_ADDRESS address)
+{
+ FIXME("iface %p, root_parameter_index %u, address %#"PRIx64" stub!\n", iface, root_parameter_index, address);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_SetGraphicsRootShaderResourceView(
+ ID3D12GraphicsCommandList2 *iface, UINT root_parameter_index, D3D12_GPU_VIRTUAL_ADDRESS address)
+{
+ FIXME("iface %p, root_parameter_index %u, address %#"PRIx64" stub!\n", iface, root_parameter_index, address);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_SetComputeRootUnorderedAccessView(
+ ID3D12GraphicsCommandList2 *iface, UINT root_parameter_index, D3D12_GPU_VIRTUAL_ADDRESS address)
+{
+ FIXME("iface %p, root_parameter_index %u, address %#"PRIx64" stub!\n", iface, root_parameter_index, address);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_SetGraphicsRootUnorderedAccessView(
+ ID3D12GraphicsCommandList2 *iface, UINT root_parameter_index, D3D12_GPU_VIRTUAL_ADDRESS address)
+{
+ FIXME("iface %p, root_parameter_index %u, address %#"PRIx64" stub!\n", iface, root_parameter_index, address);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_IASetIndexBuffer(ID3D12GraphicsCommandList2 *iface,
+ const D3D12_INDEX_BUFFER_VIEW *view)
+{
+ FIXME("iface %p, view %p stub!\n", iface, view);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_IASetVertexBuffers(ID3D12GraphicsCommandList2 *iface,
+ UINT start_slot, UINT view_count, const D3D12_VERTEX_BUFFER_VIEW *views)
+{
+ FIXME("iface %p, start_slot %u, view_count %u, views %p stub!\n", iface, start_slot, view_count, views);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_SOSetTargets(ID3D12GraphicsCommandList2 *iface,
+ UINT start_slot, UINT view_count, const D3D12_STREAM_OUTPUT_BUFFER_VIEW *views)
+{
+ ERR("iface %p, start_slot %u, view_count %u, views %p command invalid for bundles.\n",
+ iface, start_slot, view_count, views);
+
+ d3d12_bundle_mark_as_invalid(iface);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_OMSetRenderTargets(ID3D12GraphicsCommandList2 *iface,
+ UINT render_target_descriptor_count, const D3D12_CPU_DESCRIPTOR_HANDLE *render_target_descriptors,
+ BOOL single_descriptor_handle, const D3D12_CPU_DESCRIPTOR_HANDLE *depth_stencil_descriptor)
+{
+ ERR("iface %p, render_target_descriptor_count %u, render_target_descriptors %p, "
+ "single_descriptor_handle %#x, depth_stencil_descriptor %p command invalid for bundles.\n",
+ iface, render_target_descriptor_count, render_target_descriptors,
+ single_descriptor_handle, depth_stencil_descriptor);
+
+ d3d12_bundle_mark_as_invalid(iface);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_ClearDepthStencilView(ID3D12GraphicsCommandList2 *iface,
+ D3D12_CPU_DESCRIPTOR_HANDLE dsv, D3D12_CLEAR_FLAGS flags, float depth, UINT8 stencil,
+ UINT rect_count, const D3D12_RECT *rects)
+{
+ ERR("iface %p, dsv %#lx, flags %#x, depth %.8e, stencil 0x%02x, rect_count %u, rects %p "
+ "command invalid for bundles.\n", iface, dsv.ptr, flags, depth, stencil, rect_count, rects);
+
+ d3d12_bundle_mark_as_invalid(iface);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_ClearRenderTargetView(ID3D12GraphicsCommandList2 *iface,
+ D3D12_CPU_DESCRIPTOR_HANDLE rtv, const FLOAT color[4], UINT rect_count, const D3D12_RECT *rects)
+{
+ ERR("iface %p, rtv %#lx, color %p, rect_count %u, rects %p command invalid for bundles.\n",
+ iface, rtv.ptr, color, rect_count, rects);
+
+ d3d12_bundle_mark_as_invalid(iface);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_ClearUnorderedAccessViewUint(ID3D12GraphicsCommandList2 *iface,
+ D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle, D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle, ID3D12Resource *resource,
+ const UINT values[4], UINT rect_count, const D3D12_RECT *rects)
+{
+ ERR("iface %p, gpu_handle %#"PRIx64", cpu_handle %lx, resource %p, values %p, rect_count %u, rects %p command "
+ "invalid for bundles.\n", iface, gpu_handle.ptr, cpu_handle.ptr, resource, values, rect_count, rects);
+
+ d3d12_bundle_mark_as_invalid(iface);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_ClearUnorderedAccessViewFloat(ID3D12GraphicsCommandList2 *iface,
+ D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle, D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle, ID3D12Resource *resource,
+ const float values[4], UINT rect_count, const D3D12_RECT *rects)
+{
+ ERR("iface %p, gpu_handle %#"PRIx64", cpu_handle %lx, resource %p, values %p, rect_count %u, rects %p command "
+ "invalid for bundles.\n", iface, gpu_handle.ptr, cpu_handle.ptr, resource, values, rect_count, rects);
+
+ d3d12_bundle_mark_as_invalid(iface);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_DiscardResource(ID3D12GraphicsCommandList2 *iface,
+ ID3D12Resource *resource, const D3D12_DISCARD_REGION *region)
+{
+ ERR("iface %p, resource %p, region %p command invalid for bundles.\n", iface, resource, region);
+
+ d3d12_bundle_mark_as_invalid(iface);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_BeginQuery(ID3D12GraphicsCommandList2 *iface,
+ ID3D12QueryHeap *heap, D3D12_QUERY_TYPE type, UINT index)
+{
+ ERR("iface %p, heap %p, type %#x, index %u command invalid for bundles.\n", iface, heap, type, index);
+
+ d3d12_bundle_mark_as_invalid(iface);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_EndQuery(ID3D12GraphicsCommandList2 *iface,
+ ID3D12QueryHeap *heap, D3D12_QUERY_TYPE type, UINT index)
+{
+ ERR("iface %p, heap %p, type %#x, index %u command invalid for bundles.\n", iface, heap, type, index);
+
+ d3d12_bundle_mark_as_invalid(iface);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_ResolveQueryData(ID3D12GraphicsCommandList2 *iface,
+ ID3D12QueryHeap *heap, D3D12_QUERY_TYPE type, UINT start_index, UINT query_count,
+ ID3D12Resource *dst_buffer, UINT64 aligned_dst_buffer_offset)
+{
+ ERR("iface %p, heap %p, type %#x, start_index %u, query_count %u, "
+ "dst_buffer %p, aligned_dst_buffer_offset %#"PRIx64" command invalid for bundles.\n",
+ iface, heap, type, start_index, query_count, dst_buffer, aligned_dst_buffer_offset);
+
+ d3d12_bundle_mark_as_invalid(iface);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_SetPredication(ID3D12GraphicsCommandList2 *iface,
+ ID3D12Resource *buffer, UINT64 aligned_buffer_offset, D3D12_PREDICATION_OP operation)
+{
+ ERR("iface %p, buffer %p, aligned_buffer_offset %#"PRIx64", operation %#x command invalid for bundles.\n",
+ iface, buffer, aligned_buffer_offset, operation);
+
+ d3d12_bundle_mark_as_invalid(iface);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_SetMarker(ID3D12GraphicsCommandList2 *iface,
+ UINT metadata, const void *data, UINT size)
+{
+ /* Undocumented function used by Microsoft's PIX event runtime. Validity for bundles unknown. */
+ FIXME("iface %p, metadata %#x, data %p, size %u stub!\n", iface, metadata, data, size);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_BeginEvent(ID3D12GraphicsCommandList2 *iface,
+ UINT metadata, const void *data, UINT size)
+{
+ /* Undocumented function used by Microsoft's PIX event runtime. Validity for bundles unknown. */
+ FIXME("iface %p, metadata %#x, data %p, size %u stub!\n", iface, metadata, data, size);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_EndEvent(ID3D12GraphicsCommandList2 *iface)
+{
+ /* Undocumented function used by Microsoft's PIX event runtime. Validity for bundles unknown. */
+ FIXME("iface %p stub!\n", iface);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_ExecuteIndirect(ID3D12GraphicsCommandList2 *iface,
+ ID3D12CommandSignature *command_signature, UINT max_command_count, ID3D12Resource *arg_buffer,
+ UINT64 arg_buffer_offset, ID3D12Resource *count_buffer, UINT64 count_buffer_offset)
+{
+ FIXME("iface %p, command_signature %p, max_command_count %u, arg_buffer %p, "
+ "arg_buffer_offset %#"PRIx64", count_buffer %p, count_buffer_offset %#"PRIx64" stub!\n",
+ iface, command_signature, max_command_count, arg_buffer, arg_buffer_offset,
+ count_buffer, count_buffer_offset);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_AtomicCopyBufferUINT(ID3D12GraphicsCommandList2 *iface,
+ ID3D12Resource *dst_buffer, UINT64 dst_offset,
+ ID3D12Resource *src_buffer, UINT64 src_offset,
+ UINT dependent_resource_count, ID3D12Resource * const *dependent_resources,
+ const D3D12_SUBRESOURCE_RANGE_UINT64 *dependent_sub_resource_ranges)
+{
+ ERR("iface %p, dst_resource %p, dst_offset %#"PRIx64", src_resource %p, "
+ "src_offset %#"PRIx64", dependent_resource_count %u, "
+ "dependent_resources %p, dependent_sub_resource_ranges %p command invalid for bundles.\n",
+ iface, dst_buffer, dst_offset, src_buffer, src_offset,
+ dependent_resource_count, dependent_resources, dependent_sub_resource_ranges);
+
+ d3d12_bundle_mark_as_invalid(iface);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_AtomicCopyBufferUINT64(ID3D12GraphicsCommandList2 *iface,
+ ID3D12Resource *dst_buffer, UINT64 dst_offset,
+ ID3D12Resource *src_buffer, UINT64 src_offset,
+ UINT dependent_resource_count, ID3D12Resource * const *dependent_resources,
+ const D3D12_SUBRESOURCE_RANGE_UINT64 *dependent_sub_resource_ranges)
+{
+ ERR("iface %p, dst_resource %p, dst_offset %#"PRIx64", src_resource %p, "
+ "src_offset %#"PRIx64", dependent_resource_count %u, "
+ "dependent_resources %p, dependent_sub_resource_ranges %p command invalid for bundles.\n",
+ iface, dst_buffer, dst_offset, src_buffer, src_offset,
+ dependent_resource_count, dependent_resources, dependent_sub_resource_ranges);
+
+ d3d12_bundle_mark_as_invalid(iface);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_OMSetDepthBounds(ID3D12GraphicsCommandList2 *iface,
+ FLOAT min, FLOAT max)
+{
+ FIXME("iface %p, min %.8e, max %.8e stub!\n", iface, min, max);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_SetSamplePositions(ID3D12GraphicsCommandList2 *iface,
+ UINT sample_count, UINT pixel_count, D3D12_SAMPLE_POSITION *sample_positions)
+{
+ FIXME("iface %p, sample_count %u, pixel_count %u, sample_positions %p stub!\n",
+ iface, sample_count, pixel_count, sample_positions);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_ResolveSubresourceRegion(ID3D12GraphicsCommandList2 *iface,
+ ID3D12Resource *dst_resource, UINT dst_sub_resource_idx, UINT dst_x, UINT dst_y,
+ ID3D12Resource *src_resource, UINT src_sub_resource_idx,
+ D3D12_RECT *src_rect, DXGI_FORMAT format, D3D12_RESOLVE_MODE mode)
+{
+ ERR("iface %p, dst_resource %p, dst_sub_resource_idx %u, "
+ "dst_x %u, dst_y %u, src_resource %p, src_sub_resource_idx %u, "
+ "src_rect %p, format %#x, mode %#x command invalid for bundles.\n",
+ iface, dst_resource, dst_sub_resource_idx, dst_x, dst_y,
+ src_resource, src_sub_resource_idx, src_rect, format, mode);
+
+ d3d12_bundle_mark_as_invalid(iface);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_SetViewInstanceMask(ID3D12GraphicsCommandList2 *iface, UINT mask)
+{
+ FIXME("iface %p, mask %#x stub!\n", iface, mask);
+}
+
+static void STDMETHODCALLTYPE d3d12_bundle_WriteBufferImmediate(ID3D12GraphicsCommandList2 *iface,
+ UINT count, const D3D12_WRITEBUFFERIMMEDIATE_PARAMETER *parameters,
+ const D3D12_WRITEBUFFERIMMEDIATE_MODE *modes)
+{
+ FIXME("iface %p, count %u, parameters %p, modes %p stub!\n", iface, count, parameters, modes);
+}
+
+static const struct ID3D12GraphicsCommandList2Vtbl d3d12_bundle_vtbl =
+{
+ /* IUnknown methods */
+ d3d12_bundle_QueryInterface,
+ d3d12_bundle_AddRef,
+ d3d12_bundle_Release,
+ /* ID3D12Object methods */
+ d3d12_bundle_GetPrivateData,
+ d3d12_bundle_SetPrivateData,
+ d3d12_bundle_SetPrivateDataInterface,
+ d3d12_bundle_SetName,
+ /* ID3D12DeviceChild methods */
+ d3d12_bundle_GetDevice,
+ /* ID3D12CommandList methods */
+ d3d12_bundle_GetType,
+ /* ID3D12GraphicsCommandList methods */
+ d3d12_bundle_Close,
+ d3d12_bundle_Reset,
+ d3d12_bundle_ClearState,
+ d3d12_bundle_DrawInstanced,
+ d3d12_bundle_DrawIndexedInstanced,
+ d3d12_bundle_Dispatch,
+ d3d12_bundle_CopyBufferRegion,
+ d3d12_bundle_CopyTextureRegion,
+ d3d12_bundle_CopyResource,
+ d3d12_bundle_CopyTiles,
+ d3d12_bundle_ResolveSubresource,
+ d3d12_bundle_IASetPrimitiveTopology,
+ d3d12_bundle_RSSetViewports,
+ d3d12_bundle_RSSetScissorRects,
+ d3d12_bundle_OMSetBlendFactor,
+ d3d12_bundle_OMSetStencilRef,
+ d3d12_bundle_SetPipelineState,
+ d3d12_bundle_ResourceBarrier,
+ d3d12_bundle_ExecuteBundle,
+ d3d12_bundle_SetDescriptorHeaps,
+ d3d12_bundle_SetComputeRootSignature,
+ d3d12_bundle_SetGraphicsRootSignature,
+ d3d12_bundle_SetComputeRootDescriptorTable,
+ d3d12_bundle_SetGraphicsRootDescriptorTable,
+ d3d12_bundle_SetComputeRoot32BitConstant,
+ d3d12_bundle_SetGraphicsRoot32BitConstant,
+ d3d12_bundle_SetComputeRoot32BitConstants,
+ d3d12_bundle_SetGraphicsRoot32BitConstants,
+ d3d12_bundle_SetComputeRootConstantBufferView,
+ d3d12_bundle_SetGraphicsRootConstantBufferView,
+ d3d12_bundle_SetComputeRootShaderResourceView,
+ d3d12_bundle_SetGraphicsRootShaderResourceView,
+ d3d12_bundle_SetComputeRootUnorderedAccessView,
+ d3d12_bundle_SetGraphicsRootUnorderedAccessView,
+ d3d12_bundle_IASetIndexBuffer,
+ d3d12_bundle_IASetVertexBuffers,
+ d3d12_bundle_SOSetTargets,
+ d3d12_bundle_OMSetRenderTargets,
+ d3d12_bundle_ClearDepthStencilView,
+ d3d12_bundle_ClearRenderTargetView,
+ d3d12_bundle_ClearUnorderedAccessViewUint,
+ d3d12_bundle_ClearUnorderedAccessViewFloat,
+ d3d12_bundle_DiscardResource,
+ d3d12_bundle_BeginQuery,
+ d3d12_bundle_EndQuery,
+ d3d12_bundle_ResolveQueryData,
+ d3d12_bundle_SetPredication,
+ d3d12_bundle_SetMarker,
+ d3d12_bundle_BeginEvent,
+ d3d12_bundle_EndEvent,
+ d3d12_bundle_ExecuteIndirect,
+ /* ID3D12GraphicsCommandList1 methods */
+ d3d12_bundle_AtomicCopyBufferUINT,
+ d3d12_bundle_AtomicCopyBufferUINT64,
+ d3d12_bundle_OMSetDepthBounds,
+ d3d12_bundle_SetSamplePositions,
+ d3d12_bundle_ResolveSubresourceRegion,
+ d3d12_bundle_SetViewInstanceMask,
+ /* ID3D12GraphicsCommandList2 methods */
+ d3d12_bundle_WriteBufferImmediate,
+};
+
+struct d3d12_bundle *bundle_impl_from_ID3D12GraphicsCommandList(ID3D12GraphicsCommandList *iface)
+{
+ if (!iface || iface->lpVtbl != (struct ID3D12GraphicsCommandListVtbl *)&d3d12_bundle_vtbl)
+ return NULL;
+
+ return impl_from_ID3D12GraphicsCommandList2((ID3D12GraphicsCommandList2 *)iface);
+}
+
+static HRESULT d3d12_bundle_init(struct d3d12_bundle *bundle, struct d3d12_device *device,
+ struct d3d12_bundle_allocator *allocator, ID3D12PipelineState *initial_pipeline_state)
+{
+ HRESULT hr;
+
+ bundle->ID3D12GraphicsCommandList2_iface.lpVtbl = &d3d12_bundle_vtbl;
+ bundle->refcount = 1;
+
+ if (FAILED(hr = vkd3d_private_store_init(&bundle->private_store)))
+ return hr;
+
+ bundle->allocator = allocator;
+
+ if (SUCCEEDED(hr = d3d12_bundle_allocator_init_command_buffer(allocator, bundle)))
+ {
+ d3d12_device_add_ref(bundle->device = device);
+ d3d12_bundle_init_state(bundle, initial_pipeline_state);
+ }
+ else
+ {
+ vkd3d_private_store_destroy(&bundle->private_store);
+ }
+
+ return hr;
+}
+
+HRESULT d3d12_bundle_create(struct d3d12_device *device,
+ UINT node_mask, D3D12_COMMAND_LIST_TYPE type, ID3D12CommandAllocator *allocator_iface,
+ ID3D12PipelineState *initial_pipeline_state, struct d3d12_bundle **bundle)
+{
+ struct d3d12_bundle_allocator *allocator;
+ struct d3d12_bundle *object;
+ HRESULT hr;
+
+ if (!allocator_iface)
+ {
+ WARN("Command allocator is NULL.\n");
+ return E_INVALIDARG;
+ }
+
+ if (!(allocator = checked_impl_from_ID3D12CommandAllocator(allocator_iface)))
+ {
+ WARN("Command allocator is not of type D3D12_COMMAND_LIST_TYPE_BUNDLE.\n");
+ return E_INVALIDARG;
+ }
+
+ debug_ignored_node_mask(node_mask);
+
+ if (!(object = vkd3d_calloc(1, sizeof(*object))))
+ return E_OUTOFMEMORY;
+
+ if (FAILED(hr = d3d12_bundle_init(object, device, allocator, initial_pipeline_state)))
+ {
+ vkd3d_free(object);
+ return hr;
+ }
+
+ TRACE("Created command list %p.\n", object);
+
+ *bundle = object;
+
+ return S_OK;
+}
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c
index 253b9128..2a6d0b76 100644
--- a/libs/vkd3d/command.c
+++ b/libs/vkd3d/command.c
@@ -4049,10 +4049,51 @@ static void STDMETHODCALLTYPE d3d12_command_list_ResourceBarrier(ID3D12GraphicsC
WARN("Issuing split barrier(s) on D3D12_RESOURCE_BARRIER_FLAG_END_ONLY.\n");
}
+static void d3d12_bundle_command_execute(unsigned int id, const union d3d12_bundle_command_arg *args,
+ ID3D12GraphicsCommandList2 *list);
+
static void STDMETHODCALLTYPE d3d12_command_list_ExecuteBundle(ID3D12GraphicsCommandList2 *iface,
- ID3D12GraphicsCommandList *command_list)
+ ID3D12GraphicsCommandList *bundle_iface)
{
- FIXME("iface %p, command_list %p stub!\n", iface, command_list);
+ const struct d3d12_bundle *bundle = bundle_impl_from_ID3D12GraphicsCommandList(bundle_iface);
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ const union d3d12_bundle_command_arg *commands;
+ enum vkd3d_command_list_command_id id;
+ unsigned int count;
+ size_t i;
+
+ TRACE("iface %p, bundle_iface %p.\n", iface, bundle_iface);
+
+ if (!bundle)
+ {
+ WARN("bundle_iface is not a bundle.\n");
+ list->is_valid = false;
+ return;
+ }
+
+ if (!bundle->is_valid)
+ {
+ WARN("Error occurred during bundle recording.\n");
+ list->is_valid = false;
+ return;
+ }
+
+ if (bundle->is_recording)
+ {
+ WARN("Bundle is in the recording state.\n");
+ list->is_valid = false;
+ return;
+ }
+
+ commands = bundle->command_buffer.commands;
+
+ for (i = 0; i < bundle->command_buffer.count; i += count)
+ {
+ count = commands[i].header.count;
+ id = commands[i++].header.id;
+ d3d12_bundle_command_execute(id, &commands[i], iface);
+ }
+ assert(i == bundle->command_buffer.count);
}
static void STDMETHODCALLTYPE d3d12_command_list_SetDescriptorHeaps(ID3D12GraphicsCommandList2 *iface,
@@ -5614,6 +5655,21 @@ static struct d3d12_command_list *unsafe_impl_from_ID3D12CommandList(ID3D12Comma
return CONTAINING_RECORD(iface, struct d3d12_command_list, ID3D12GraphicsCommandList2_iface);
}
+static void d3d12_bundle_command_execute(enum vkd3d_command_list_command_id id,
+ const union d3d12_bundle_command_arg *args, ID3D12GraphicsCommandList2 *list)
+{
+ switch (id)
+ {
+ case VKD3D_COMMAND_DRAW_INSTANCED:
+ d3d12_command_list_DrawInstanced(list, args[0].uint_arg, args[1].uint_arg,
+ args[2].uint_arg, args[3].uint_arg);
+ break;
+ default:
+ FIXME("Unhandled command %u.\n", id);
+ break;
+ }
+}
+
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)
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index 0fadb521..3ff1affb 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -2314,17 +2314,29 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandAllocator(ID3D12Devic
D3D12_COMMAND_LIST_TYPE type, REFIID riid, void **command_allocator)
{
struct d3d12_device *device = impl_from_ID3D12Device(iface);
- struct d3d12_command_allocator *object;
HRESULT hr;
TRACE("iface %p, type %#x, riid %s, command_allocator %p.\n",
iface, type, debugstr_guid(riid), command_allocator);
- if (FAILED(hr = d3d12_command_allocator_create(device, type, &object)))
- return hr;
+ if (type == D3D12_COMMAND_LIST_TYPE_BUNDLE)
+ {
+ struct d3d12_bundle_allocator *object;
+ if (FAILED(hr = d3d12_bundle_allocator_create(device, &object)))
+ return hr;
- return return_interface(&object->ID3D12CommandAllocator_iface, &IID_ID3D12CommandAllocator,
- riid, command_allocator);
+ return return_interface(&object->ID3D12CommandAllocator_iface,
+ &IID_ID3D12CommandAllocator, riid, command_allocator);
+ }
+ else
+ {
+ struct d3d12_command_allocator *object;
+ if (FAILED(hr = d3d12_command_allocator_create(device, type, &object)))
+ return hr;
+
+ return return_interface(&object->ID3D12CommandAllocator_iface,
+ &IID_ID3D12CommandAllocator, riid, command_allocator);
+ }
}
static HRESULT STDMETHODCALLTYPE d3d12_device_CreateGraphicsPipelineState(ID3D12Device *iface,
@@ -2366,7 +2378,6 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandList(ID3D12Device *if
ID3D12PipelineState *initial_pipeline_state, REFIID riid, void **command_list)
{
struct d3d12_device *device = impl_from_ID3D12Device(iface);
- struct d3d12_command_list *object;
HRESULT hr;
TRACE("iface %p, node_mask 0x%08x, type %#x, command_allocator %p, "
@@ -2374,12 +2385,26 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandList(ID3D12Device *if
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)))
- return hr;
+ if (type == D3D12_COMMAND_LIST_TYPE_BUNDLE)
+ {
+ struct d3d12_bundle *object;
+ if (FAILED(hr = d3d12_bundle_create(device, node_mask, type, command_allocator,
+ initial_pipeline_state, &object)))
+ return hr;
- return return_interface(&object->ID3D12GraphicsCommandList2_iface,
- &IID_ID3D12GraphicsCommandList2, riid, command_list);
+ return return_interface(&object->ID3D12GraphicsCommandList2_iface,
+ &IID_ID3D12GraphicsCommandList2, riid, command_list);
+ }
+ else
+ {
+ struct d3d12_command_list *object;
+ if (FAILED(hr = d3d12_command_list_create(device, node_mask, type, command_allocator,
+ initial_pipeline_state, &object)))
+ return hr;
+
+ return return_interface(&object->ID3D12GraphicsCommandList2_iface,
+ &IID_ID3D12GraphicsCommandList2, riid, command_list);
+ }
}
/* Direct3D feature levels restrict which formats can be optionally supported. */
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index 0b326b11..1d5fab65 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -987,6 +987,82 @@ 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);
+enum vkd3d_command_list_command_id
+{
+ VKD3D_COMMAND_DRAW_INSTANCED,
+};
+
+struct d3d12_bundle_command_header
+{
+ unsigned int count;
+ enum vkd3d_command_list_command_id id;
+};
+
+union d3d12_bundle_command_arg
+{
+ struct d3d12_bundle_command_header header;
+ D3D12_GPU_DESCRIPTOR_HANDLE gpu_descriptor_handle;
+ D3D12_GPU_VIRTUAL_ADDRESS gpu_address;
+ D3D12_PRIMITIVE_TOPOLOGY topology;
+ float float_arg;
+ ID3D12CommandSignature *command_signature;
+ ID3D12PipelineState *pipeline_state;
+ ID3D12Resource *resource;
+ ID3D12RootSignature *root_signature;
+ int int_arg;
+ uint64_t uint64_arg;
+ unsigned int uint_arg;
+};
+
+#define d3d12_bundle_command_arg_count_from_sizeof(size) \
+ (((size) + sizeof(union d3d12_bundle_command_arg) - 1) / sizeof(union d3d12_bundle_command_arg))
+
+struct d3d12_bundle_command_buffer
+{
+ union d3d12_bundle_command_arg *commands;
+ size_t size;
+ size_t count;
+};
+
+struct d3d12_bundle_allocator
+{
+ ID3D12CommandAllocator ID3D12CommandAllocator_iface;
+ LONG refcount;
+
+ union d3d12_bundle_command_arg **arg_buffers;
+ size_t arg_buffers_size;
+ size_t arg_buffer_count;
+
+ struct d3d12_bundle *current_bundle;
+ struct d3d12_device *device;
+
+ struct vkd3d_private_store private_store;
+};
+
+HRESULT d3d12_bundle_allocator_create(struct d3d12_device *device,
+ struct d3d12_bundle_allocator **allocator);
+
+struct d3d12_bundle
+{
+ ID3D12GraphicsCommandList2 ID3D12GraphicsCommandList2_iface;
+ LONG refcount;
+
+ bool is_recording;
+ bool is_valid;
+ struct d3d12_bundle_command_buffer command_buffer;
+
+ struct d3d12_device *device;
+ struct d3d12_bundle_allocator *allocator;
+
+ struct vkd3d_private_store private_store;
+};
+
+struct d3d12_bundle *bundle_impl_from_ID3D12GraphicsCommandList(ID3D12GraphicsCommandList *iface);
+
+HRESULT d3d12_bundle_create(struct d3d12_device *device,
+ UINT node_mask, D3D12_COMMAND_LIST_TYPE type, ID3D12CommandAllocator *allocator_iface,
+ ID3D12PipelineState *initial_pipeline_state, struct d3d12_bundle **bundle);
+
struct vkd3d_queue
{
/* Access to VkQueue must be externally synchronized. */
diff --git a/tests/d3d12.c b/tests/d3d12.c
index 1e895dcd..f723dbaa 100644
--- a/tests/d3d12.c
+++ b/tests/d3d12.c
@@ -7380,13 +7380,6 @@ static void test_bundle_state_inheritance(void)
unsigned int x, y;
HRESULT hr;
- if (!vkd3d_test_platform_is_windows())
- {
- /* FIXME: Avoid 2048 test todos. */
- skip("Bundles are not implemented yet.\n");
- return;
- }
-
if (use_warp_device)
{
skip("Bundle state inheritance test crashes on WARP.\n");
@@ -7569,6 +7562,7 @@ static void test_bundle_state_inheritance(void)
transition_resource_state(command_list, context.render_target,
D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE);
+ todo
check_sub_resource_uint(context.render_target, 0, queue, command_list, 0xff00ff00, 0);
reset_command_list(command_list, context.allocator);
@@ -7594,6 +7588,7 @@ static void test_bundle_state_inheritance(void)
transition_resource_state(command_list, context.render_target,
D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE);
+ todo
check_sub_resource_uint(context.render_target, 0, queue, command_list, 0xff00ff00, 0);
ID3D12CommandAllocator_Release(bundle_allocator);
--
2.32.0
More information about the wine-devel
mailing list