Commit d0052d91 authored by Zebediah Figura's avatar Zebediah Figura Committed by Alexandre Julliard

d3d11: Implement ID3D11DeviceContext::ExecuteCommandList().

parent 55511718
......@@ -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,
......
......@@ -32289,9 +32289,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);
......@@ -32315,9 +32313,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);
......@@ -32475,12 +32471,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);
......@@ -32496,7 +32492,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);
......@@ -32522,7 +32518,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);
......@@ -32556,12 +32552,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);
......@@ -32589,7 +32583,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);
......@@ -32612,7 +32606,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);
......@@ -32645,7 +32639,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);
......@@ -32665,7 +32659,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);
......@@ -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)
......
......@@ -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)
{
......
......@@ -96,6 +96,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)
......
......@@ -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
......
......@@ -2442,6 +2442,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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment