[PATCH v4 8/8] d3d11: Implement ID3D11DeviceContext::ExecuteCommandList().
Zebediah Figura
z.figura12 at gmail.com
Thu May 27 11:14:35 CDT 2021
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
dlls/d3d11/device.c | 17 ++++-
dlls/d3d11/tests/d3d11.c | 30 ++++-----
dlls/wined3d/cs.c | 109 +++++++++++++++++++++++++++++++++
dlls/wined3d/device.c | 8 +++
dlls/wined3d/wined3d.spec | 1 +
dlls/wined3d/wined3d_private.h | 2 +
include/wine/wined3d.h | 2 +
7 files changed, 150 insertions(+), 19 deletions(-)
diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c
index 33ba1dc255e..850539e9da2 100644
--- a/dlls/d3d11/device.c
+++ b/dlls/d3d11/device.c
@@ -448,6 +448,14 @@ static const struct ID3D11CommandListVtbl d3d11_command_list_vtbl =
d3d11_command_list_GetContextFlags,
};
+static struct d3d11_command_list *unsafe_impl_from_ID3D11CommandList(ID3D11CommandList *iface)
+{
+ if (!iface)
+ return NULL;
+ assert(iface->lpVtbl == &d3d11_command_list_vtbl);
+ return impl_from_ID3D11CommandList(iface);
+}
+
static void d3d11_device_context_cleanup(struct d3d11_device_context *context)
{
wined3d_private_store_cleanup(&context->private_store);
@@ -1520,7 +1528,14 @@ static void STDMETHODCALLTYPE d3d11_device_context_ResolveSubresource(ID3D11Devi
static void STDMETHODCALLTYPE d3d11_device_context_ExecuteCommandList(ID3D11DeviceContext1 *iface,
ID3D11CommandList *command_list, BOOL restore_state)
{
- FIXME("iface %p, command_list %p, restore_state %#x stub!\n", iface, command_list, restore_state);
+ struct d3d11_device_context *context = impl_from_ID3D11DeviceContext1(iface);
+ struct d3d11_command_list *list_impl = unsafe_impl_from_ID3D11CommandList(command_list);
+
+ TRACE("iface %p, command_list %p, restore_state %#x.\n", iface, command_list, restore_state);
+
+ wined3d_mutex_lock();
+ wined3d_device_context_execute_command_list(context->wined3d_context, list_impl->wined3d_list, !!restore_state);
+ wined3d_mutex_unlock();
}
static void STDMETHODCALLTYPE d3d11_device_context_HSSetShaderResources(ID3D11DeviceContext1 *iface,
diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c
index 8da0cfaa8bf..408c0492cd2 100644
--- a/dlls/d3d11/tests/d3d11.c
+++ b/dlls/d3d11/tests/d3d11.c
@@ -32302,9 +32302,7 @@ static void test_deferred_context_state(void)
ID3D11DeviceContext_PSSetConstantBuffers(immediate, 0, 1, &green_buffer);
ID3D11DeviceContext_ExecuteCommandList(immediate, list1, FALSE);
ID3D11DeviceContext_PSGetConstantBuffers(immediate, 0, 1, &ret_buffer);
- todo_wine ok(!ret_buffer, "Got unexpected buffer %p.\n", ret_buffer);
- if (ret_buffer)
- ID3D11Buffer_Release(ret_buffer);
+ ok(!ret_buffer, "Got unexpected buffer %p.\n", ret_buffer);
ID3D11CommandList_Release(list2);
ID3D11CommandList_Release(list1);
@@ -32328,9 +32326,7 @@ static void test_deferred_context_state(void)
ID3D11DeviceContext_PSSetConstantBuffers(deferred, 0, 1, &blue_buffer);
ID3D11DeviceContext_ExecuteCommandList(deferred, list1, FALSE);
ID3D11DeviceContext_PSGetConstantBuffers(deferred, 0, 1, &ret_buffer);
- todo_wine ok(!ret_buffer, "Got unexpected buffer %p.\n", ret_buffer);
- if (ret_buffer)
- ID3D11Buffer_Release(ret_buffer);
+ ok(!ret_buffer, "Got unexpected buffer %p.\n", ret_buffer);
ID3D11CommandList_Release(list1);
ID3D11DeviceContext_Release(deferred2);
@@ -32488,12 +32484,12 @@ static void test_deferred_context_rendering(void)
ID3D11DeviceContext_ExecuteCommandList(immediate, list1, TRUE);
color = get_texture_color(test_context.backbuffer, 320, 240);
- todo_wine ok(color == 0xff00ff00, "Got unexpected color %#08x.\n", color);
+ ok(color == 0xff00ff00, "Got unexpected color %#08x.\n", color);
ID3D11DeviceContext_ClearRenderTargetView(immediate, test_context.backbuffer_rtv, &white.x);
ID3D11DeviceContext_ExecuteCommandList(immediate, list1, TRUE);
color = get_texture_color(test_context.backbuffer, 320, 240);
- todo_wine ok(color == 0xff00ff00, "Got unexpected color %#08x.\n", color);
+ ok(color == 0xff00ff00, "Got unexpected color %#08x.\n", color);
ID3D11DeviceContext_ClearRenderTargetView(immediate, test_context.backbuffer_rtv, &white.x);
ID3D11DeviceContext_ExecuteCommandList(immediate, list2, TRUE);
@@ -32509,7 +32505,7 @@ static void test_deferred_context_rendering(void)
ID3D11DeviceContext_ClearRenderTargetView(immediate, test_context.backbuffer_rtv, &white.x);
ID3D11DeviceContext_ExecuteCommandList(immediate, list2, TRUE);
color = get_texture_color(test_context.backbuffer, 320, 240);
- todo_wine ok(color == 0xff00ff00, "Got unexpected color %#08x.\n", color);
+ ok(color == 0xff00ff00, "Got unexpected color %#08x.\n", color);
ID3D11CommandList_Release(list2);
ID3D11CommandList_Release(list1);
@@ -32535,7 +32531,7 @@ static void test_deferred_context_rendering(void)
ID3D11DeviceContext_ClearRenderTargetView(immediate, rtv, blue);
ID3D11DeviceContext_ExecuteCommandList(immediate, list1, TRUE);
color = get_texture_color(test_context.backbuffer, 320, 240);
- todo_wine ok(color == 0xffff0000, "Got unexpected color %#08x.\n", color);
+ ok(color == 0xffff0000, "Got unexpected color %#08x.\n", color);
ID3D11CommandList_Release(list1);
ID3D11DeviceContext_Release(deferred);
@@ -32569,12 +32565,10 @@ static void test_deferred_context_rendering(void)
set_viewport(immediate, 0.0f, 0.0f, 640.0f, 480.0f, 0.0f, 1.0f);
draw_color_quad(&test_context, &white);
color = get_texture_color(test_context.backbuffer, 320, 240);
- todo_wine ok(color == 0xffffffff, "Got unexpected color %#08x.\n", color);
+ ok(color == 0xffffffff, "Got unexpected color %#08x.\n", color);
ID3D11DeviceContext_OMGetBlendState(immediate, &ret_blend, blend_factor, &sample_mask);
- todo_wine ok(!ret_blend, "Got unexpected blend state %p.\n", ret_blend);
- if (ret_blend)
- ID3D11BlendState_Release(ret_blend);
+ ok(!ret_blend, "Got unexpected blend state %p.\n", ret_blend);
ID3D11CommandList_Release(list1);
ID3D11DeviceContext_Release(deferred);
@@ -32602,7 +32596,7 @@ static void test_deferred_context_rendering(void)
ID3D11DeviceContext_OMSetBlendState(immediate, red_blend, NULL, D3D11_DEFAULT_SAMPLE_MASK);
ID3D11DeviceContext_ExecuteCommandList(immediate, list1, FALSE);
color = get_texture_color(test_context.backbuffer, 320, 240);
- todo_wine ok(color == 0xffffffff, "Got unexpected color %#08x.\n", color);
+ ok(color == 0xffffffff, "Got unexpected color %#08x.\n", color);
ID3D11CommandList_Release(list1);
@@ -32625,7 +32619,7 @@ static void test_deferred_context_rendering(void)
ID3D11DeviceContext_OMSetBlendState(immediate, red_blend, NULL, D3D11_DEFAULT_SAMPLE_MASK);
ID3D11DeviceContext_ExecuteCommandList(immediate, list1, FALSE);
color = get_texture_color(test_context.backbuffer, 320, 240);
- todo_wine ok(color == 0xff00ff00, "Got unexpected color %#08x.\n", color);
+ ok(color == 0xff00ff00, "Got unexpected color %#08x.\n", color);
ID3D11CommandList_Release(list1);
@@ -32658,7 +32652,7 @@ static void test_deferred_context_rendering(void)
ID3D11DeviceContext_OMSetBlendState(immediate, red_blend, NULL, D3D11_DEFAULT_SAMPLE_MASK);
ID3D11DeviceContext_ExecuteCommandList(immediate, list2, FALSE);
color = get_texture_color(test_context.backbuffer, 320, 240);
- todo_wine ok(color == 0xffffffff, "Got unexpected color %#08x.\n", color);
+ ok(color == 0xffffffff, "Got unexpected color %#08x.\n", color);
ID3D11CommandList_Release(list2);
@@ -32678,7 +32672,7 @@ static void test_deferred_context_rendering(void)
ID3D11DeviceContext_OMSetBlendState(immediate, red_blend, NULL, D3D11_DEFAULT_SAMPLE_MASK);
ID3D11DeviceContext_ExecuteCommandList(immediate, list2, FALSE);
color = get_texture_color(test_context.backbuffer, 320, 240);
- todo_wine ok(color == 0xff00ff00, "Got unexpected color %#08x.\n", color);
+ ok(color == 0xff00ff00, "Got unexpected color %#08x.\n", color);
ID3D11CommandList_Release(list2);
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index 1e082ce724d..50a08334dab 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -37,6 +37,12 @@ struct wined3d_command_list
SIZE_T resource_count;
struct wined3d_resource **resources;
+
+ /* List of command lists queued for execution on this command list. We might
+ * be the only thing holding a pointer to another command list, so we need
+ * to hold a reference here (and in wined3d_deferred_context) as well. */
+ SIZE_T command_list_count;
+ struct wined3d_command_list **command_lists;
};
static void wined3d_command_list_destroy_object(void *object)
@@ -70,6 +76,8 @@ ULONG CDECL wined3d_command_list_decref(struct wined3d_command_list *list)
{
SIZE_T i;
+ for (i = 0; i < list->command_list_count; ++i)
+ wined3d_command_list_decref(list->command_lists[i]);
for (i = 0; i < list->resource_count; ++i)
wined3d_resource_decref(list->resources[i]);
@@ -130,6 +138,7 @@ enum wined3d_cs_op
WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW,
WINED3D_CS_OP_COPY_UAV_COUNTER,
WINED3D_CS_OP_GENERATE_MIPMAPS,
+ WINED3D_CS_OP_EXECUTE_COMMAND_LIST,
WINED3D_CS_OP_STOP,
};
@@ -511,6 +520,12 @@ struct wined3d_cs_generate_mipmaps
struct wined3d_shader_resource_view *view;
};
+struct wined3d_cs_execute_command_list
+{
+ enum wined3d_cs_op opcode;
+ struct wined3d_command_list *list;
+};
+
struct wined3d_cs_stop
{
enum wined3d_cs_op opcode;
@@ -599,6 +614,7 @@ static const char *debug_cs_op(enum wined3d_cs_op op)
WINED3D_TO_STR(WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW);
WINED3D_TO_STR(WINED3D_CS_OP_COPY_UAV_COUNTER);
WINED3D_TO_STR(WINED3D_CS_OP_GENERATE_MIPMAPS);
+ WINED3D_TO_STR(WINED3D_CS_OP_EXECUTE_COMMAND_LIST);
WINED3D_TO_STR(WINED3D_CS_OP_STOP);
#undef WINED3D_TO_STR
}
@@ -2314,6 +2330,27 @@ static void wined3d_cs_issue_query(struct wined3d_device_context *context,
query->state = QUERY_SIGNALLED;
}
+static void wined3d_cs_execute_command_list(struct wined3d_device_context *context,
+ struct wined3d_command_list *list, bool restore_state)
+{
+ struct wined3d_cs_execute_command_list *op;
+ SIZE_T i;
+
+ op = wined3d_device_context_require_space(context, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT);
+ op->opcode = WINED3D_CS_OP_EXECUTE_COMMAND_LIST;
+ op->list = list;
+
+ for (i = 0; i < list->resource_count; ++i)
+ wined3d_resource_acquire(list->resources[i]);
+
+ wined3d_device_context_submit(context, WINED3D_CS_QUEUE_DEFAULT);
+
+ if (restore_state)
+ wined3d_device_context_set_state(context, context->state);
+ else
+ wined3d_device_context_reset_state(context);
+}
+
static void wined3d_cs_exec_preload_resource(struct wined3d_cs *cs, const void *data)
{
const struct wined3d_cs_preload_resource *op = data;
@@ -2777,6 +2814,8 @@ static void wined3d_cs_acquire_resource(struct wined3d_device_context *context,
wined3d_resource_acquire(resource);
}
+static void wined3d_cs_exec_execute_command_list(struct wined3d_cs *cs, const void *data);
+
static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) =
{
/* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop,
@@ -2828,8 +2867,32 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void
/* WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW */ wined3d_cs_exec_clear_unordered_access_view,
/* WINED3D_CS_OP_COPY_UAV_COUNTER */ wined3d_cs_exec_copy_uav_counter,
/* WINED3D_CS_OP_GENERATE_MIPMAPS */ wined3d_cs_exec_generate_mipmaps,
+ /* WINED3D_CS_OP_EXECUTE_COMMAND_LIST */ wined3d_cs_exec_execute_command_list,
};
+static void wined3d_cs_exec_execute_command_list(struct wined3d_cs *cs, const void *data)
+{
+ const struct wined3d_cs_execute_command_list *op = data;
+ size_t start = 0, end = op->list->data_size;
+ const BYTE *cs_data = op->list->data;
+
+ TRACE("Executing command list %p.\n", op->list);
+
+ while (start < end)
+ {
+ const struct wined3d_cs_packet *packet = (const struct wined3d_cs_packet *)&cs_data[start];
+ enum wined3d_cs_op opcode = *(const enum wined3d_cs_op *)packet->data;
+
+ if (opcode >= WINED3D_CS_OP_STOP)
+ ERR("Invalid opcode %#x.\n", opcode);
+ else
+ wined3d_cs_op_handlers[opcode](cs, packet->data);
+ TRACE("%s executed.\n", debug_cs_op(opcode));
+
+ start += offsetof(struct wined3d_cs_packet, data[packet->size]);
+ }
+}
+
static void *wined3d_cs_st_require_space(struct wined3d_device_context *context,
size_t size, enum wined3d_cs_queue_id queue_id)
{
@@ -2897,6 +2960,7 @@ static const struct wined3d_device_context_ops wined3d_cs_st_ops =
wined3d_cs_issue_query,
wined3d_cs_flush,
wined3d_cs_acquire_resource,
+ wined3d_cs_execute_command_list,
};
static BOOL wined3d_cs_queue_is_empty(const struct wined3d_cs *cs, const struct wined3d_cs_queue *queue)
@@ -3024,6 +3088,7 @@ static const struct wined3d_device_context_ops wined3d_cs_mt_ops =
wined3d_cs_issue_query,
wined3d_cs_flush,
wined3d_cs_acquire_resource,
+ wined3d_cs_execute_command_list,
};
static void poll_queries(struct wined3d_cs *cs)
@@ -3235,6 +3300,12 @@ struct wined3d_deferred_context
SIZE_T resource_count, resources_capacity;
struct wined3d_resource **resources;
+
+ /* List of command lists queued for execution on this context. A command
+ * list can be the only thing holding a pointer to another command list, so
+ * we need to hold a reference here and in wined3d_command_list as well. */
+ SIZE_T command_list_count, command_lists_capacity;
+ struct wined3d_command_list **command_lists;
};
static struct wined3d_deferred_context *wined3d_deferred_context_from_context(struct wined3d_device_context *context)
@@ -3332,6 +3403,30 @@ static void wined3d_deferred_context_acquire_resource(struct wined3d_device_cont
wined3d_resource_incref(resource);
}
+static void wined3d_deferred_context_execute_command_list(struct wined3d_device_context *context,
+ struct wined3d_command_list *list, bool restore_state)
+{
+ struct wined3d_deferred_context *deferred = wined3d_deferred_context_from_context(context);
+ struct wined3d_cs_execute_command_list *op;
+
+ op = wined3d_device_context_require_space(context, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT);
+ op->opcode = WINED3D_CS_OP_EXECUTE_COMMAND_LIST;
+ op->list = list;
+
+ if (restore_state)
+ wined3d_device_context_set_state(context, context->state);
+ else
+ wined3d_device_context_reset_state(context);
+
+ /* Grab a reference to the command list. Note that this implicitly prevents
+ * any dependent command lists or resources from being freed as well. */
+ if (!wined3d_array_reserve((void **)&deferred->command_lists, &deferred->command_lists_capacity,
+ deferred->command_list_count + 1, sizeof(*deferred->command_lists)))
+ return;
+
+ wined3d_command_list_incref(deferred->command_lists[deferred->command_list_count++] = list);
+}
+
static const struct wined3d_device_context_ops wined3d_deferred_context_ops =
{
wined3d_deferred_context_require_space,
@@ -3344,6 +3439,7 @@ static const struct wined3d_device_context_ops wined3d_deferred_context_ops =
wined3d_deferred_context_issue_query,
wined3d_deferred_context_flush,
wined3d_deferred_context_acquire_resource,
+ wined3d_deferred_context_execute_command_list,
};
HRESULT CDECL wined3d_deferred_context_create(struct wined3d_device *device, struct wined3d_device_context **context)
@@ -3419,8 +3515,21 @@ HRESULT CDECL wined3d_deferred_context_record_command_list(struct wined3d_device
memcpy(object->resources, deferred->resources, deferred->resource_count * sizeof(*object->resources));
/* Transfer our references to the resources to the command list. */
+ if (!(object->command_lists = heap_alloc(deferred->command_list_count * sizeof(*object->command_lists))))
+ {
+ heap_free(object->resources);
+ heap_free(object->data);
+ heap_free(object);
+ return E_OUTOFMEMORY;
+ }
+ object->command_list_count = deferred->command_list_count;
+ memcpy(object->command_lists, deferred->command_lists,
+ deferred->command_list_count * sizeof(*object->command_lists));
+ /* Transfer our references to the command lists to the command list. */
+
deferred->data_size = 0;
deferred->resource_count = 0;
+ deferred->command_list_count = 0;
/* This is in fact recorded into a subsequent command list. */
if (restore)
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 08f986dd5e2..c6b0c9f831e 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -4888,6 +4888,14 @@ void CDECL wined3d_device_context_issue_query(struct wined3d_device_context *con
context->ops->issue_query(context, query, flags);
}
+void CDECL wined3d_device_context_execute_command_list(struct wined3d_device_context *context,
+ struct wined3d_command_list *list, bool restore_state)
+{
+ TRACE("context %p, list %p, restore_state %d.\n", context, list, restore_state);
+
+ context->ops->execute_command_list(context, list, restore_state);
+}
+
struct wined3d_rendertarget_view * CDECL wined3d_device_context_get_rendertarget_view(
const struct wined3d_device_context *context, unsigned int view_idx)
{
diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec
index 6683b3bc30f..1369fd4cf90 100644
--- a/dlls/wined3d/wined3d.spec
+++ b/dlls/wined3d/wined3d.spec
@@ -95,6 +95,7 @@
@ cdecl wined3d_device_context_draw_indirect(ptr ptr long long)
@ cdecl wined3d_device_context_dispatch(ptr long long long)
@ cdecl wined3d_device_context_dispatch_indirect(ptr ptr long)
+@ cdecl wined3d_device_context_execute_command_list(ptr ptr long)
@ cdecl wined3d_device_context_flush(ptr)
@ cdecl wined3d_device_context_generate_mipmaps(ptr ptr)
@ cdecl wined3d_device_context_get_blend_state(ptr ptr ptr)
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index af9beffc142..8e3efccffc2 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -4693,6 +4693,8 @@ struct wined3d_device_context_ops
void (*issue_query)(struct wined3d_device_context *context, struct wined3d_query *query, unsigned int flags);
void (*flush)(struct wined3d_device_context *context);
void (*acquire_resource)(struct wined3d_device_context *context, struct wined3d_resource *resource);
+ void (*execute_command_list)(struct wined3d_device_context *context,
+ struct wined3d_command_list *list, bool restore_state);
};
struct wined3d_device_context
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index bb6bf58a822..7777e45ad21 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -2441,6 +2441,8 @@ void __cdecl wined3d_device_context_draw_indexed(struct wined3d_device_context *
unsigned int start_index, unsigned int index_count, unsigned int start_instance, unsigned int instance_count);
void __cdecl wined3d_device_context_draw_indirect(struct wined3d_device_context *context,
struct wined3d_buffer *buffer, unsigned int offset, bool indexed);
+void __cdecl wined3d_device_context_execute_command_list(struct wined3d_device_context *context,
+ struct wined3d_command_list *list, bool restore_state);
void __cdecl wined3d_device_context_flush(struct wined3d_device_context *context);
void __cdecl wined3d_device_context_generate_mipmaps(struct wined3d_device_context *context,
struct wined3d_shader_resource_view *view);
--
2.30.2
More information about the wine-devel
mailing list