Avoid storing pointers to the CS data inside individual ops, so that we can reallocate the queue when appending data to a deferred context, or copy the queue contents to a command list.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/wined3d/cs.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-)
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 14076defaa9..8702ac08631 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -107,7 +107,7 @@ struct wined3d_cs_clear enum wined3d_cs_op opcode; DWORD flags; unsigned int rt_count; - struct wined3d_fb_state *fb; + struct wined3d_fb_state fb; RECT draw_rect; struct wined3d_color color; float depth; @@ -684,19 +684,19 @@ static void wined3d_cs_exec_clear(struct wined3d_cs *cs, const void *data) const struct wined3d_cs_clear *op = data; unsigned int i;
- device->blitter->ops->blitter_clear(device->blitter, device, op->rt_count, op->fb, + device->blitter->ops->blitter_clear(device->blitter, device, op->rt_count, &op->fb, op->rect_count, op->rects, &op->draw_rect, op->flags, &op->color, op->depth, op->stencil);
if (op->flags & WINED3DCLEAR_TARGET) { for (i = 0; i < op->rt_count; ++i) { - if (op->fb->render_targets[i]) - wined3d_resource_release(op->fb->render_targets[i]->resource); + if (op->fb.render_targets[i]) + wined3d_resource_release(op->fb.render_targets[i]->resource); } } if (op->flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL)) - wined3d_resource_release(op->fb->depth_stencil->resource); + wined3d_resource_release(op->fb.depth_stencil->resource); }
void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT *rects, @@ -715,7 +715,7 @@ void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT * op->opcode = WINED3D_CS_OP_CLEAR; op->flags = flags & (WINED3DCLEAR_TARGET | WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL); op->rt_count = rt_count; - op->fb = &cs->state.fb; + op->fb = state->fb; SetRect(&op->draw_rect, vp->x, vp->y, vp->x + vp->width, vp->y + vp->height); if (state->rasterizer_state && state->rasterizer_state->desc.scissor) IntersectRect(&op->draw_rect, &op->draw_rect, &state->scissor_rects[0]); @@ -746,24 +746,23 @@ void wined3d_device_context_emit_clear_rendertarget_view(struct wined3d_device_c struct wined3d_cs_clear *op; size_t size;
- size = FIELD_OFFSET(struct wined3d_cs_clear, rects[1]) + sizeof(struct wined3d_fb_state); + size = FIELD_OFFSET(struct wined3d_cs_clear, rects[1]); op = wined3d_device_context_require_space(context, size, WINED3D_CS_QUEUE_DEFAULT); - op->fb = (void *)&op->rects[1];
op->opcode = WINED3D_CS_OP_CLEAR; op->flags = flags & (WINED3DCLEAR_TARGET | WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL); if (flags & WINED3DCLEAR_TARGET) { op->rt_count = 1; - op->fb->render_targets[0] = view; - op->fb->depth_stencil = NULL; + op->fb.render_targets[0] = view; + op->fb.depth_stencil = NULL; op->color = *color; } else { op->rt_count = 0; - op->fb->render_targets[0] = NULL; - op->fb->depth_stencil = view; + op->fb.render_targets[0] = NULL; + op->fb.depth_stencil = view; op->depth = depth; op->stencil = stencil; }
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=42191 Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/d3d11/d3d11_private.h | 1 + dlls/d3d11/device.c | 83 +++++++++++++++++---- dlls/d3d11/tests/d3d11.c | 65 +++++++++-------- dlls/wined3d/cs.c | 146 +++++++++++++++++++++++++++++++++++++ dlls/wined3d/wined3d.spec | 3 + include/wine/wined3d.h | 3 + 6 files changed, 256 insertions(+), 45 deletions(-)
diff --git a/dlls/d3d11/d3d11_private.h b/dlls/d3d11/d3d11_private.h index 1a8cdc6d77c..2b5a51afbd1 100644 --- a/dlls/d3d11/d3d11_private.h +++ b/dlls/d3d11/d3d11_private.h @@ -547,6 +547,7 @@ struct d3d11_device_context ID3D11Multithread ID3D11Multithread_iface; LONG refcount;
+ D3D11_DEVICE_CONTEXT_TYPE type; struct wined3d_device_context *wined3d_context; struct d3d_device *device;
diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c index 2a012fce144..77485091b2b 100644 --- a/dlls/d3d11/device.c +++ b/dlls/d3d11/device.c @@ -330,6 +330,11 @@ static void d3d_device_context_state_init(struct d3d_device_context_state *state d3d_device_context_state_AddRef(&state->ID3DDeviceContextState_iface); }
+static void d3d11_device_context_cleanup(struct d3d11_device_context *context) +{ + wined3d_private_store_cleanup(&context->private_store); +} + /* ID3D11DeviceContext - immediate context methods */
static inline struct d3d11_device_context *impl_from_ID3D11DeviceContext1(ID3D11DeviceContext1 *iface) @@ -351,7 +356,7 @@ static HRESULT STDMETHODCALLTYPE d3d11_device_context_QueryInterface(ID3D11Devic { *out = &context->ID3D11DeviceContext1_iface; } - else if (IsEqualGUID(iid, &IID_ID3D11Multithread)) + else if (context->type == D3D11_DEVICE_CONTEXT_IMMEDIATE && IsEqualGUID(iid, &IID_ID3D11Multithread)) { *out = &context->ID3D11Multithread_iface; } @@ -390,6 +395,12 @@ static ULONG STDMETHODCALLTYPE d3d11_device_context_Release(ID3D11DeviceContext1
if (!refcount) { + if (context->type != D3D11_DEVICE_CONTEXT_IMMEDIATE) + { + wined3d_deferred_context_destroy(context->wined3d_context); + d3d11_device_context_cleanup(context); + heap_free(context); + } ID3D11Device2_Release(&context->device->ID3D11Device2_iface); }
@@ -2645,9 +2656,11 @@ static void STDMETHODCALLTYPE d3d11_device_context_Flush(ID3D11DeviceContext1 *i
static D3D11_DEVICE_CONTEXT_TYPE STDMETHODCALLTYPE d3d11_device_context_GetType(ID3D11DeviceContext1 *iface) { + struct d3d11_device_context *context = impl_from_ID3D11DeviceContext1(iface); + TRACE("iface %p.\n", iface);
- return D3D11_DEVICE_CONTEXT_IMMEDIATE; + return context->type; }
static UINT STDMETHODCALLTYPE d3d11_device_context_GetContextFlags(ID3D11DeviceContext1 *iface) @@ -2826,13 +2839,18 @@ static void STDMETHODCALLTYPE d3d11_device_context_SwapDeviceContextState(ID3D11
TRACE("iface %p, state %p, prev %p.\n", iface, state, prev);
- if (!state) + if (prev) + *prev = NULL; + + if (context->type != D3D11_DEVICE_CONTEXT_IMMEDIATE) { - if (prev) - *prev = NULL; + WARN("SwapDeviceContextState is not allowed on a deferred context.\n"); return; }
+ if (!state) + return; + wined3d_mutex_lock();
prev_impl = device->state; @@ -3082,11 +3100,13 @@ static const struct ID3D11MultithreadVtbl d3d11_multithread_vtbl = d3d11_multithread_GetMultithreadProtected, };
-static void d3d11_device_context_init(struct d3d11_device_context *context, struct d3d_device *device) +static void d3d11_device_context_init(struct d3d11_device_context *context, struct d3d_device *device, + D3D11_DEVICE_CONTEXT_TYPE type) { context->ID3D11DeviceContext1_iface.lpVtbl = &d3d11_device_context_vtbl; context->ID3D11Multithread_iface.lpVtbl = &d3d11_multithread_vtbl; context->refcount = 1; + context->type = type;
context->device = device; ID3D11Device2_AddRef(&device->ID3D11Device2_iface); @@ -3094,11 +3114,6 @@ static void d3d11_device_context_init(struct d3d11_device_context *context, stru wined3d_private_store_init(&context->private_store); }
-static void d3d11_device_context_destroy(struct d3d11_device_context *context) -{ - wined3d_private_store_cleanup(&context->private_store); -} - /* ID3D11Device methods */
static HRESULT STDMETHODCALLTYPE d3d11_device_QueryInterface(ID3D11Device2 *iface, REFIID iid, void **out) @@ -3575,13 +3590,49 @@ static HRESULT STDMETHODCALLTYPE d3d11_device_CreateCounter(ID3D11Device2 *iface return E_NOTIMPL; }
+static HRESULT d3d11_deferred_context_create(struct d3d_device *device, + UINT flags, struct d3d11_device_context **context) +{ + struct d3d11_device_context *object; + HRESULT hr; + + if (flags) + FIXME("Ignoring flags %#x.\n", flags); + + if (!(object = heap_alloc_zero(sizeof(*object)))) + return E_OUTOFMEMORY; + d3d11_device_context_init(object, device, D3D11_DEVICE_CONTEXT_DEFERRED); + + wined3d_mutex_lock(); + if (FAILED(hr = wined3d_deferred_context_create(device->wined3d_device, &object->wined3d_context))) + { + WARN("Failed to create wined3d deferred context, hr %#x.\n", hr); + heap_free(object); + wined3d_mutex_unlock(); + return hr; + } + wined3d_mutex_unlock(); + + TRACE("Created deferred context %p.\n", object); + *context = object; + + return S_OK; +} + static HRESULT STDMETHODCALLTYPE d3d11_device_CreateDeferredContext(ID3D11Device2 *iface, UINT flags, ID3D11DeviceContext **context) { - FIXME("iface %p, flags %#x, context %p stub!\n", iface, flags, context); + struct d3d_device *device = impl_from_ID3D11Device2(iface); + struct d3d11_device_context *object; + HRESULT hr;
- *context = NULL; - return E_NOTIMPL; + TRACE("iface %p, flags %#x, context %p.\n", iface, flags, context); + + if (FAILED(hr = d3d11_deferred_context_create(device, flags, &object))) + return hr; + + *context = (ID3D11DeviceContext *)&object->ID3D11DeviceContext1_iface; + return S_OK; }
static HRESULT STDMETHODCALLTYPE d3d11_device_OpenSharedResource(ID3D11Device2 *iface, HANDLE resource, REFIID iid, @@ -4302,7 +4353,7 @@ static ULONG STDMETHODCALLTYPE d3d_device_inner_Release(IUnknown *iface) d3d_device_context_state_remove_entry(device->context_states[i], device); } heap_free(device->context_states); - d3d11_device_context_destroy(&device->immediate_context); + d3d11_device_context_cleanup(&device->immediate_context); if (device->wined3d_device) { wined3d_mutex_lock(); @@ -6655,7 +6706,7 @@ void d3d_device_init(struct d3d_device *device, void *outer_unknown) device->d3d11_only = FALSE; device->state = NULL;
- d3d11_device_context_init(&device->immediate_context, device); + d3d11_device_context_init(&device->immediate_context, device, D3D11_DEVICE_CONTEXT_IMMEDIATE); ID3D11DeviceContext1_Release(&device->immediate_context.ID3D11DeviceContext1_iface);
wine_rb_init(&device->blend_states, d3d_blend_state_compare); diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c index 089755fd1ba..f415cbaad45 100644 --- a/dlls/d3d11/tests/d3d11.c +++ b/dlls/d3d11/tests/d3d11.c @@ -2266,6 +2266,8 @@ static void test_create_deferred_context(void)
hr = ID3D11Device_CreateDeferredContext(device, 0, &context); todo_wine ok(hr == DXGI_ERROR_INVALID_CALL, "Failed to create deferred context, hr %#x.\n", hr); + if (hr == S_OK) + ID3D11DeviceContext_Release(context);
refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); @@ -2278,9 +2280,7 @@ static void test_create_deferred_context(void)
expected_refcount = get_refcount(device) + 1; hr = ID3D11Device_CreateDeferredContext(device, 0, &context); - todo_wine ok(hr == S_OK, "Failed to create deferred context, hr %#x.\n", hr); - if (FAILED(hr)) - goto done; + ok(hr == S_OK, "Failed to create deferred context, hr %#x.\n", hr); refcount = get_refcount(device); ok(refcount == expected_refcount, "Got refcount %u, expected %u.\n", refcount, expected_refcount); refcount = get_refcount(context); @@ -2294,7 +2294,6 @@ static void test_create_deferred_context(void) refcount = ID3D11DeviceContext_Release(context); ok(!refcount, "Got unexpected refcount %u.\n", refcount);
-done: refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } @@ -32270,14 +32269,7 @@ static void test_deferred_context_state(void) ID3D11DeviceContext_PSSetConstantBuffers(immediate, 0, 1, &green_buffer);
hr = ID3D11Device_CreateDeferredContext(device, 0, &deferred); - todo_wine ok(hr == S_OK, "Failed to create deferred context, hr %#x.\n", hr); - if (hr != S_OK) - { - ID3D11Buffer_Release(blue_buffer); - ID3D11Buffer_Release(green_buffer); - release_test_context(&test_context); - return; - } + ok(hr == S_OK, "Failed to create deferred context, hr %#x.\n", hr);
ID3D11DeviceContext_PSGetConstantBuffers(deferred, 0, 1, &ret_buffer); ok(!ret_buffer, "Got unexpected buffer %p.\n", ret_buffer); @@ -32289,7 +32281,15 @@ static void test_deferred_context_state(void) ID3D11Buffer_Release(ret_buffer);
hr = ID3D11DeviceContext_FinishCommandList(deferred, TRUE, &list1); - ok(hr == S_OK, "Failed to create command list, hr %#x.\n", hr); + todo_wine ok(hr == S_OK, "Failed to create command list, hr %#x.\n", hr); + if (hr != S_OK) + { + ID3D11DeviceContext_Release(deferred); + ID3D11Buffer_Release(blue_buffer); + ID3D11Buffer_Release(green_buffer); + release_test_context(&test_context); + return; + }
ID3D11DeviceContext_PSGetConstantBuffers(deferred, 0, 1, &ret_buffer); ok(ret_buffer == blue_buffer, "Got unexpected buffer %p.\n", ret_buffer); @@ -32468,12 +32468,7 @@ static void test_deferred_context_rendering(void) immediate = test_context.immediate_context;
hr = ID3D11Device_CreateDeferredContext(device, 0, &deferred); - todo_wine ok(hr == S_OK, "Failed to create deferred context, hr %#x.\n", hr); - if (hr != S_OK) - { - release_test_context(&test_context); - return; - } + ok(hr == S_OK, "Failed to create deferred context, hr %#x.\n", hr);
memset(&blend_desc, 0, sizeof(blend_desc));
@@ -32492,7 +32487,16 @@ static void test_deferred_context_rendering(void) ID3D11DeviceContext_ClearRenderTargetView(deferred, test_context.backbuffer_rtv, green);
hr = ID3D11DeviceContext_FinishCommandList(deferred, TRUE, &list1); - ok(hr == S_OK, "Failed to create command list, hr %#x.\n", hr); + todo_wine ok(hr == S_OK, "Failed to create command list, hr %#x.\n", hr); + if (hr != S_OK) + { + ID3D11BlendState_Release(red_blend); + ID3D11BlendState_Release(green_blend); + ID3D11BlendState_Release(blue_blend); + ID3D11DeviceContext_Release(deferred); + release_test_context(&test_context); + return; + }
hr = ID3D11DeviceContext_FinishCommandList(deferred, TRUE, &list2); ok(hr == S_OK, "Failed to create command list, hr %#x.\n", hr); @@ -32729,12 +32733,7 @@ static void test_deferred_context_map(void) immediate = test_context.immediate_context;
hr = ID3D11Device_CreateDeferredContext(device, 0, &deferred); - todo_wine ok(hr == S_OK, "Failed to create deferred context, hr %#x.\n", hr); - if (hr != S_OK) - { - release_test_context(&test_context); - return; - } + ok(hr == S_OK, "Failed to create deferred context, hr %#x.\n", hr);
for (i = 0; i < ARRAY_SIZE(data); ++i) data[i] = i; @@ -32758,13 +32757,21 @@ static void test_deferred_context_map(void) ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
hr = ID3D11DeviceContext_Map(deferred, (ID3D11Resource *)buffer, 0, D3D11_MAP_WRITE, 0, &map_desc); - ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); + todo_wine ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
hr = ID3D11DeviceContext_Map(deferred, (ID3D11Resource *)buffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &map_desc); - ok(hr == D3D11_ERROR_DEFERRED_CONTEXT_MAP_WITHOUT_INITIAL_DISCARD, "Got unexpected hr %#x.\n", hr); + todo_wine ok(hr == D3D11_ERROR_DEFERRED_CONTEXT_MAP_WITHOUT_INITIAL_DISCARD, "Got unexpected hr %#x.\n", hr);
hr = ID3D11DeviceContext_Map(deferred, (ID3D11Resource *)buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map_desc); - ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + if (hr != S_OK) + { + ID3D11Buffer_Release(buffer2); + ID3D11Buffer_Release(buffer); + ID3D11DeviceContext_Release(deferred); + release_test_context(&test_context); + return; + } map_data = map_desc.pData; /* The previous contents of map_data are undefined and may in practice be * uninitialized garbage. */ diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 8702ac08631..3f05d593b7c 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -3162,3 +3162,149 @@ void wined3d_cs_destroy(struct wined3d_cs *cs) heap_free(cs->data); heap_free(cs); } + +struct wined3d_deferred_context +{ + struct wined3d_device_context c; + + SIZE_T data_size, data_capacity; + void *data; +}; + +static struct wined3d_deferred_context *wined3d_deferred_context_from_context(struct wined3d_device_context *context) +{ + return CONTAINING_RECORD(context, struct wined3d_deferred_context, c); +} + +static void *wined3d_deferred_context_require_space(struct wined3d_device_context *context, + size_t size, enum wined3d_cs_queue_id queue_id) +{ + struct wined3d_deferred_context *deferred = wined3d_deferred_context_from_context(context); + struct wined3d_cs_packet *packet; + size_t header_size, packet_size; + + assert(queue_id == WINED3D_CS_QUEUE_DEFAULT); + + header_size = offsetof(struct wined3d_cs_packet, data[0]); + packet_size = offsetof(struct wined3d_cs_packet, data[size]); + packet_size = (packet_size + header_size - 1) & ~(header_size - 1); + + if (!wined3d_array_reserve(&deferred->data, &deferred->data_capacity, deferred->data_size + packet_size, 1)) + return NULL; + + packet = (struct wined3d_cs_packet *)((BYTE *)deferred->data + deferred->data_size); + TRACE("size was %zu, adding %zu\n", (size_t)deferred->data_size, packet_size); + deferred->data_size += packet_size; + packet->size = packet_size - header_size; + return &packet->data; +} + +static void wined3d_deferred_context_submit(struct wined3d_device_context *context, enum wined3d_cs_queue_id queue_id) +{ + assert(queue_id == WINED3D_CS_QUEUE_DEFAULT); + + /* Nothing to do. */ +} + +static void wined3d_deferred_context_finish(struct wined3d_device_context *context, enum wined3d_cs_queue_id queue_id) +{ + /* This should not happen; we cannot meaningfully finish a deferred context. */ + ERR("Ignoring finish() on a deferred context.\n"); +} + +static void wined3d_deferred_context_push_constants(struct wined3d_device_context *context, + enum wined3d_push_constants p, unsigned int start_idx, unsigned int count, const void *constants) +{ + FIXME("context %p, p %#x, start_idx %u, count %u, constants %p, stub!\n", context, p, start_idx, count, constants); +} + +static HRESULT wined3d_deferred_context_map(struct wined3d_device_context *context, + struct wined3d_resource *resource, unsigned int sub_resource_idx, + struct wined3d_map_desc *map_desc, const struct wined3d_box *box, unsigned int flags) +{ + FIXME("context %p, resource %p, sub_resource_idx %u, map_desc %p, box %p, flags %#x, stub!\n", + context, resource, sub_resource_idx, map_desc, box, flags); + return E_NOTIMPL; +} + +static HRESULT wined3d_deferred_context_unmap(struct wined3d_device_context *context, + struct wined3d_resource *resource, unsigned int sub_resource_idx) +{ + FIXME("context %p, resource %p, sub_resource_idx %u, stub!\n", context, resource, sub_resource_idx); + return E_NOTIMPL; +} + +static void wined3d_deferred_context_update_sub_resource(struct wined3d_device_context *context, + struct wined3d_resource *resource, unsigned int sub_resource_idx, const struct wined3d_box *box, + const void *data, unsigned int row_pitch, unsigned int slice_pitch) +{ + FIXME("context %p, resource %p, sub_resource_idx %u, box %s, data %p, row_pitch %u, slice_pitch %u, stub!\n", + context, resource, sub_resource_idx, debug_box(box), data, row_pitch, slice_pitch); +} + +static void wined3d_deferred_context_issue_query(struct wined3d_device_context *context, + struct wined3d_query *query, unsigned int flags) +{ + FIXME("context %p, query %p, flags %#x, stub!\n", context, query, flags); +} + +static void wined3d_deferred_context_flush(struct wined3d_device_context *context) +{ + FIXME("context %p, stub!\n", context); +} + +static void wined3d_deferred_context_acquire_resource(struct wined3d_device_context *context, + struct wined3d_resource *resource) +{ + FIXME("context %p, resource %p, stub!\n", context, resource); +} + +static const struct wined3d_device_context_ops wined3d_deferred_context_ops = +{ + wined3d_deferred_context_require_space, + wined3d_deferred_context_submit, + wined3d_deferred_context_finish, + wined3d_deferred_context_push_constants, + wined3d_deferred_context_map, + wined3d_deferred_context_unmap, + wined3d_deferred_context_update_sub_resource, + wined3d_deferred_context_issue_query, + wined3d_deferred_context_flush, + wined3d_deferred_context_acquire_resource, +}; + +HRESULT CDECL wined3d_deferred_context_create(struct wined3d_device *device, struct wined3d_device_context **context) +{ + struct wined3d_deferred_context *object; + HRESULT hr; + + TRACE("device %p, context %p.\n", device, context); + + if (!(object = heap_alloc_zero(sizeof(*object)))) + return E_OUTOFMEMORY; + + if (FAILED(hr = wined3d_state_create(device, &device->cs->c.state->feature_level, 1, &object->c.state))) + { + heap_free(object); + return hr; + } + + object->c.ops = &wined3d_deferred_context_ops; + object->c.device = device; + + TRACE("Created deferred context %p.\n", object); + *context = &object->c; + + return S_OK; +} + +void CDECL wined3d_deferred_context_destroy(struct wined3d_device_context *context) +{ + struct wined3d_deferred_context *deferred = wined3d_deferred_context_from_context(context); + + TRACE("context %p.\n", context); + + wined3d_state_destroy(deferred->c.state); + heap_free(deferred->data); + heap_free(deferred); +} diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index 9f3dfed7ef8..901e9bee621 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -33,6 +33,9 @@ @ cdecl wined3d_buffer_get_resource(ptr) @ cdecl wined3d_buffer_incref(ptr)
+@ cdecl wined3d_deferred_context_create(ptr ptr) +@ cdecl wined3d_deferred_context_destroy(ptr) + @ cdecl wined3d_depth_stencil_state_create(ptr ptr ptr ptr ptr) @ cdecl wined3d_depth_stencil_state_decref(ptr) @ cdecl wined3d_depth_stencil_state_get_parent(ptr) diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 2ee18bcaaed..0be192b0f01 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2340,6 +2340,9 @@ void * __cdecl wined3d_buffer_get_parent(const struct wined3d_buffer *buffer); struct wined3d_resource * __cdecl wined3d_buffer_get_resource(struct wined3d_buffer *buffer); ULONG __cdecl wined3d_buffer_incref(struct wined3d_buffer *buffer);
+HRESULT __cdecl wined3d_deferred_context_create(struct wined3d_device *device, struct wined3d_device_context **context); +void __cdecl wined3d_deferred_context_destroy(struct wined3d_device_context *context); + HRESULT __cdecl wined3d_depth_stencil_state_create(struct wined3d_device *device, const struct wined3d_depth_stencil_state_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_depth_stencil_state **state);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=91349
Your paranoid android.
=== w1064v1809 (32 bit report) ===
d3d11: d3d11.c:5810: Test failed: Got unexpected IAVertices count: 0. d3d11.c:5811: Test failed: Got unexpected IAPrimitives count: 0. d3d11.c:5812: Test failed: Got unexpected VSInvocations count: 0. d3d11.c:5815: Test failed: Got unexpected CInvocations count: 0. d3d11.c:5816: Test failed: Got unexpected CPrimitives count: 0.
=== w10pro64 (32 bit report) ===
d3d11: d3d11.c:5810: Test failed: Got unexpected IAVertices count: 0. d3d11.c:5811: Test failed: Got unexpected IAPrimitives count: 0. d3d11.c:5812: Test failed: Got unexpected VSInvocations count: 0. d3d11.c:5815: Test failed: Got unexpected CInvocations count: 0. d3d11.c:5816: Test failed: Got unexpected CPrimitives count: 0.
=== debiant2 (32 bit report) ===
d3d11: d3d11.c:9660: Test failed: d3d11.c:15112: Test marked todo: Got hr 0 for WRITE_NO_OVERWRITE.
=== debiant2 (32 bit Chinese:China report) ===
d3d11: d3d11.c:9660: Test failed: d3d11.c:15021: Test marked todo: Got hr 0 for WRITE.
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=41636 Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/d3d11/device.c | 12 ++++++++++-- dlls/d3d11/tests/d3d11.c | 5 +---- 2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c index 77485091b2b..38b0f18da56 100644 --- a/dlls/d3d11/device.c +++ b/dlls/d3d11/device.c @@ -4078,9 +4078,17 @@ static void STDMETHODCALLTYPE d3d11_device_GetImmediateContext1(ID3D11Device2 *i static HRESULT STDMETHODCALLTYPE d3d11_device_CreateDeferredContext1(ID3D11Device2 *iface, UINT flags, ID3D11DeviceContext1 **context) { - FIXME("iface %p, flags %#x, context %p stub!\n", iface, flags, context); + struct d3d_device *device = impl_from_ID3D11Device2(iface); + struct d3d11_device_context *object; + HRESULT hr;
- return E_NOTIMPL; + TRACE("iface %p, flags %#x, context %p.\n", iface, flags, context); + + if (FAILED(hr = d3d11_deferred_context_create(device, flags, &object))) + return hr; + + *context = &object->ID3D11DeviceContext1_iface; + return S_OK; }
static HRESULT STDMETHODCALLTYPE d3d11_device_CreateBlendState1(ID3D11Device2 *iface, diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c index f415cbaad45..d799bed25f4 100644 --- a/dlls/d3d11/tests/d3d11.c +++ b/dlls/d3d11/tests/d3d11.c @@ -32410,9 +32410,7 @@ static void test_deferred_context_swap_state(void) ID3D11DeviceContext1_PSSetConstantBuffers(immediate, 0, 1, &green_buffer);
hr = ID3D11Device1_CreateDeferredContext1(device, 0, &deferred); - todo_wine ok(hr == S_OK, "Failed to create deferred context, hr %#x.\n", hr); - if (hr != S_OK) - goto out; + ok(hr == S_OK, "Failed to create deferred context, hr %#x.\n", hr);
feature_level = ID3D11Device1_GetFeatureLevel(device); hr = ID3D11Device1_CreateDeviceContextState(device, 0, &feature_level, 1, D3D11_SDK_VERSION, @@ -32433,7 +32431,6 @@ static void test_deferred_context_swap_state(void) ID3DDeviceContextState_Release(state); ID3D11DeviceContext1_Release(deferred);
-out: ID3D11Buffer_Release(green_buffer); ID3D11DeviceContext1_Release(immediate); ID3D11Device1_Release(device);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=91350
Your paranoid android.
=== debiant2 (32 bit Arabic:Morocco report) ===
d3d11: d3d11.c:9660: Test failed: d3d11.c:15112: Test marked todo: Got hr 0 for WRITE.
=== debiant2 (32 bit French report) ===
d3d11: d3d11.c:19759: Test failed: Got 0xdeadbeef, expected 0x80706050 or 0x7f706050 at 80, uvec4 0x50, 0x60, 0x70, 0x80.
=== debiant2 (32 bit Hindi:India report) ===
d3d11: d3d11.c:9660: Test failed: d3d11.c:15043: Test marked todo: Got hr 0 for WRITE_DISCARD.
=== debiant2 (64 bit WoW report) ===
d3d11: d3d11.c:9660: Test failed: d3d11.c:15021: Test marked todo: Got hr 0 for WRITE.
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/wined3d/cs.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 3f05d593b7c..77d40801414 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -3169,6 +3169,9 @@ struct wined3d_deferred_context
SIZE_T data_size, data_capacity; void *data; + + SIZE_T resource_count, resources_capacity; + struct wined3d_resource **resources; };
static struct wined3d_deferred_context *wined3d_deferred_context_from_context(struct wined3d_device_context *context) @@ -3256,7 +3259,14 @@ static void wined3d_deferred_context_flush(struct wined3d_device_context *contex static void wined3d_deferred_context_acquire_resource(struct wined3d_device_context *context, struct wined3d_resource *resource) { - FIXME("context %p, resource %p, stub!\n", context, resource); + struct wined3d_deferred_context *deferred = wined3d_deferred_context_from_context(context); + + if (!wined3d_array_reserve((void **)&deferred->resources, &deferred->resources_capacity, + deferred->resource_count + 1, sizeof(*deferred->resources))) + return; + + deferred->resources[deferred->resource_count++] = resource; + wined3d_resource_incref(resource); }
static const struct wined3d_device_context_ops wined3d_deferred_context_ops = @@ -3301,9 +3311,14 @@ HRESULT CDECL wined3d_deferred_context_create(struct wined3d_device *device, str void CDECL wined3d_deferred_context_destroy(struct wined3d_device_context *context) { struct wined3d_deferred_context *deferred = wined3d_deferred_context_from_context(context); + SIZE_T i;
TRACE("context %p.\n", context);
+ for (i = 0; i < deferred->resource_count; ++i) + wined3d_resource_decref(deferred->resources[i]); + heap_free(deferred->resources); + wined3d_state_destroy(deferred->c.state); heap_free(deferred->data); heap_free(deferred);
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Specifically, tweak and make use of the already existing WINED3D_CS_OP_RESET_STATE.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/d3d11/device.c | 40 +--------------------------------- dlls/wined3d/cs.c | 16 +++++++++++--- dlls/wined3d/device.c | 13 +++++++++-- dlls/wined3d/wined3d.spec | 1 + dlls/wined3d/wined3d_private.h | 2 +- include/wine/wined3d.h | 1 + 6 files changed, 28 insertions(+), 45 deletions(-)
diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c index 38b0f18da56..2afdbf48ade 100644 --- a/dlls/d3d11/device.c +++ b/dlls/d3d11/device.c @@ -2597,49 +2597,11 @@ static void STDMETHODCALLTYPE d3d11_device_context_CSGetConstantBuffers(ID3D11De static void STDMETHODCALLTYPE d3d11_device_context_ClearState(ID3D11DeviceContext1 *iface) { struct d3d11_device_context *context = impl_from_ID3D11DeviceContext1(iface); - static const float blend_factor[] = {1.0f, 1.0f, 1.0f, 1.0f}; - unsigned int i, j;
TRACE("iface %p.\n", iface);
wined3d_mutex_lock(); - for (i = 0; i < WINED3D_SHADER_TYPE_COUNT; ++i) - { - wined3d_device_context_set_shader(context->wined3d_context, i, NULL); - for (j = 0; j < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; ++j) - wined3d_device_context_set_constant_buffer(context->wined3d_context, i, j, NULL); - for (j = 0; j < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; ++j) - wined3d_device_context_set_shader_resource_view(context->wined3d_context, i, j, NULL); - for (j = 0; j < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++j) - wined3d_device_context_set_sampler(context->wined3d_context, i, j, NULL); - } - for (i = 0; i < D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; ++i) - { - wined3d_device_context_set_stream_source(context->wined3d_context, i, NULL, 0, 0); - } - wined3d_device_context_set_index_buffer(context->wined3d_context, NULL, WINED3DFMT_UNKNOWN, 0); - wined3d_device_context_set_vertex_declaration(context->wined3d_context, NULL); - wined3d_device_context_set_primitive_type(context->wined3d_context, WINED3D_PT_UNDEFINED, 0); - for (i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) - { - wined3d_device_context_set_rendertarget_view(context->wined3d_context, i, NULL, FALSE); - } - wined3d_device_context_set_depth_stencil_view(context->wined3d_context, NULL); - for (i = 0; i < WINED3D_PIPELINE_COUNT; ++i) - { - for (j = 0; j < D3D11_PS_CS_UAV_REGISTER_COUNT; ++j) - wined3d_device_context_set_unordered_access_view(context->wined3d_context, i, j, NULL, ~0u); - } - ID3D11DeviceContext1_OMSetDepthStencilState(iface, NULL, 0); - ID3D11DeviceContext1_OMSetBlendState(iface, NULL, blend_factor, D3D11_DEFAULT_SAMPLE_MASK); - ID3D11DeviceContext1_RSSetViewports(iface, 0, NULL); - ID3D11DeviceContext1_RSSetScissorRects(iface, 0, NULL); - ID3D11DeviceContext1_RSSetState(iface, NULL); - for (i = 0; i < D3D11_SO_BUFFER_SLOT_COUNT; ++i) - { - wined3d_device_context_set_stream_output(context->wined3d_context, i, NULL, 0); - } - wined3d_device_context_set_predication(context->wined3d_context, NULL, FALSE); + wined3d_device_context_reset_state(context->wined3d_context); wined3d_mutex_unlock(); }
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 77d40801414..b55bfdab866 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -359,6 +359,7 @@ struct wined3d_cs_push_constants struct wined3d_cs_reset_state { enum wined3d_cs_op opcode; + bool invalidate; };
struct wined3d_cs_callback @@ -2143,18 +2144,27 @@ static void wined3d_cs_mt_push_constants(struct wined3d_device_context *context,
static void wined3d_cs_exec_reset_state(struct wined3d_cs *cs, const void *data) { + const struct wined3d_cs_reset_state *op = data; + unsigned int state; + state_cleanup(&cs->state); wined3d_state_reset(&cs->state, &cs->c.device->adapter->d3d_info); + if (op->invalidate) + { + for (state = 0; state <= STATE_HIGHEST; ++state) + device_invalidate_state(cs->c.device, state); + } }
-void wined3d_cs_emit_reset_state(struct wined3d_cs *cs) +void wined3d_device_context_emit_reset_state(struct wined3d_device_context *context, bool invalidate) { struct wined3d_cs_reset_state *op;
- op = wined3d_device_context_require_space(&cs->c, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT); + op = wined3d_device_context_require_space(context, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT); op->opcode = WINED3D_CS_OP_RESET_STATE; + op->invalidate = invalidate;
- wined3d_device_context_submit(&cs->c, WINED3D_CS_QUEUE_DEFAULT); + wined3d_device_context_submit(context, WINED3D_CS_QUEUE_DEFAULT); }
static void wined3d_cs_exec_callback(struct wined3d_cs *cs, const void *data) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 2c8ebba8844..08f986dd5e2 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -1169,7 +1169,7 @@ void wined3d_device_uninit_3d(struct wined3d_device *device) wined3d_texture_decref(texture); }
- wined3d_cs_emit_reset_state(device->cs); + wined3d_device_context_emit_reset_state(&device->cs->c, false); state_cleanup(state);
wine_rb_clear(&device->samplers, device_free_sampler, NULL); @@ -1649,6 +1649,15 @@ void CDECL wined3d_device_context_get_scissor_rects(const struct wined3d_device_ *rect_count = state->scissor_rect_count; }
+void CDECL wined3d_device_context_reset_state(struct wined3d_device_context *context) +{ + TRACE("context %p.\n", context); + + state_cleanup(context->state); + wined3d_state_reset(context->state, &context->device->adapter->d3d_info); + wined3d_device_context_emit_reset_state(context, true); +} + void CDECL wined3d_device_context_set_state(struct wined3d_device_context *context, struct wined3d_state *state) { const struct wined3d_light_info *light; @@ -5417,7 +5426,7 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, if (reset_state) { TRACE("Resetting state.\n"); - wined3d_cs_emit_reset_state(device->cs); + wined3d_device_context_emit_reset_state(&device->cs->c, false); state_cleanup(state);
LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry) diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index 901e9bee621..84412515c39 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -114,6 +114,7 @@ @ cdecl wined3d_device_context_get_viewports(ptr ptr ptr) @ cdecl wined3d_device_context_issue_query(ptr ptr long) @ cdecl wined3d_device_context_map(ptr ptr long ptr ptr long) +@ cdecl wined3d_device_context_reset_state(ptr) @ cdecl wined3d_device_context_resolve_sub_resource(ptr ptr long ptr long long) @ cdecl wined3d_device_context_set_blend_state(ptr ptr ptr long) @ cdecl wined3d_device_context_set_constant_buffer(ptr long long ptr) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index fadad706af4..af9beffc142 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4737,7 +4737,6 @@ void wined3d_device_context_emit_clear_uav_uint(struct wined3d_device_context *c void wined3d_cs_emit_preload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain, const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, unsigned int swap_interval, DWORD flags) DECLSPEC_HIDDEN; -void wined3d_cs_emit_reset_state(struct wined3d_cs *cs) DECLSPEC_HIDDEN; void wined3d_cs_emit_set_color_key(struct wined3d_cs *cs, struct wined3d_texture *texture, WORD flags, const struct wined3d_color_key *color_key) DECLSPEC_HIDDEN; void wined3d_cs_emit_set_render_state(struct wined3d_cs *cs, @@ -4775,6 +4774,7 @@ void wined3d_device_context_emit_draw(struct wined3d_device_context *context, bool indexed) DECLSPEC_HIDDEN; void wined3d_device_context_emit_generate_mipmaps(struct wined3d_device_context *context, struct wined3d_shader_resource_view *view) DECLSPEC_HIDDEN; +void wined3d_device_context_emit_reset_state(struct wined3d_device_context *context, bool invalidate) DECLSPEC_HIDDEN; void wined3d_device_context_emit_set_blend_state(struct wined3d_device_context *context, struct wined3d_blend_state *state, const struct wined3d_color *blend_factor, unsigned int sample_mask) DECLSPEC_HIDDEN; diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 0be192b0f01..812c042cdd7 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2480,6 +2480,7 @@ void __cdecl wined3d_device_context_issue_query(struct wined3d_device_context *c HRESULT __cdecl wined3d_device_context_map(struct wined3d_device_context *context, struct wined3d_resource *resource, unsigned int sub_resource_idx, struct wined3d_map_desc *map_desc, const struct wined3d_box *box, unsigned int flags); +void __cdecl wined3d_device_context_reset_state(struct wined3d_device_context *context); void __cdecl wined3d_device_context_resolve_sub_resource(struct wined3d_device_context *context, struct wined3d_resource *dst_resource, unsigned int dst_sub_resource_idx, struct wined3d_resource *src_resource, unsigned int src_sub_resource_idx, enum wined3d_format_id format_id);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=91352
Your paranoid android.
=== debiant2 (32 bit report) ===
d3d11: d3d11.c:9660: Test failed: d3d11.c:15140: Test marked todo: Got hr 0 for WRITE_DISCARD.
=== debiant2 (32 bit Chinese:China report) ===
d3d11: d3d11.c:9660: Test failed: d3d11.c:15021: Test marked todo: Test 60: Got unexpected color 0xff00ff00 at (2, 0). d3d11.c:9660: Test failed: d3d11.c:15043: Test marked todo: Got hr 0 for WRITE_DISCARD. d3d11.c:9660: Test failed: Got hr 0 for WRITE.
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/d3d11/d3d11_private.h | 10 +++ dlls/d3d11/device.c | 155 ++++++++++++++++++++++++++++++++++++- dlls/wined3d/cs.c | 103 ++++++++++++++++++++++++ dlls/wined3d/wined3d.spec | 4 + include/wine/wined3d.h | 6 ++ 5 files changed, 277 insertions(+), 1 deletion(-)
diff --git a/dlls/d3d11/d3d11_private.h b/dlls/d3d11/d3d11_private.h index 2b5a51afbd1..afbde9a4bfb 100644 --- a/dlls/d3d11/d3d11_private.h +++ b/dlls/d3d11/d3d11_private.h @@ -583,6 +583,16 @@ struct d3d_device SIZE_T context_state_count; };
+struct d3d11_command_list +{ + ID3D11CommandList ID3D11CommandList_iface; + LONG refcount; + + ID3D11Device2 *device; + struct wined3d_command_list *wined3d_list; + struct wined3d_private_store private_store; +}; + static inline struct d3d_device *impl_from_ID3D11Device(ID3D11Device *iface) { return CONTAINING_RECORD((ID3D11Device2 *)iface, struct d3d_device, ID3D11Device2_iface); diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c index 2afdbf48ade..33ba1dc255e 100644 --- a/dlls/d3d11/device.c +++ b/dlls/d3d11/device.c @@ -330,6 +330,124 @@ static void d3d_device_context_state_init(struct d3d_device_context_state *state d3d_device_context_state_AddRef(&state->ID3DDeviceContextState_iface); }
+/* ID3D11CommandList methods */ + +static inline struct d3d11_command_list *impl_from_ID3D11CommandList(ID3D11CommandList *iface) +{ + return CONTAINING_RECORD(iface, struct d3d11_command_list, ID3D11CommandList_iface); +} + +static HRESULT STDMETHODCALLTYPE d3d11_command_list_QueryInterface(ID3D11CommandList *iface, REFIID iid, void **out) +{ + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_ID3D11CommandList) + || IsEqualGUID(iid, &IID_ID3D11DeviceChild) + || IsEqualGUID(iid, &IID_IUnknown)) + { + ID3D11CommandList_AddRef(iface); + *out = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + *out = NULL; + + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE d3d11_command_list_AddRef(ID3D11CommandList *iface) +{ + struct d3d11_command_list *list = impl_from_ID3D11CommandList(iface); + ULONG refcount = InterlockedIncrement(&list->refcount); + + TRACE("%p increasing refcount to %u.\n", list, refcount); + + return refcount; +} + +static ULONG STDMETHODCALLTYPE d3d11_command_list_Release(ID3D11CommandList *iface) +{ + struct d3d11_command_list *list = impl_from_ID3D11CommandList(iface); + ULONG refcount = InterlockedDecrement(&list->refcount); + + TRACE("%p decreasing refcount to %u.\n", list, refcount); + + if (!refcount) + { + wined3d_mutex_lock(); + wined3d_command_list_decref(list->wined3d_list); + wined3d_mutex_unlock(); + wined3d_private_store_cleanup(&list->private_store); + ID3D11Device2_Release(list->device); + heap_free(list); + } + + return refcount; +} + +static void STDMETHODCALLTYPE d3d11_command_list_GetDevice(ID3D11CommandList *iface, ID3D11Device **device) +{ + struct d3d11_command_list *list = impl_from_ID3D11CommandList(iface); + + TRACE("iface %p, device %p.\n", iface, device); + + *device = (ID3D11Device *)list->device; + ID3D11Device2_AddRef(list->device); +} + +static HRESULT STDMETHODCALLTYPE d3d11_command_list_GetPrivateData(ID3D11CommandList *iface, REFGUID guid, + UINT *data_size, void *data) +{ + struct d3d11_command_list *list = impl_from_ID3D11CommandList(iface); + + TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data); + + return d3d_get_private_data(&list->private_store, guid, data_size, data); +} + +static HRESULT STDMETHODCALLTYPE d3d11_command_list_SetPrivateData(ID3D11CommandList *iface, REFGUID guid, + UINT data_size, const void *data) +{ + struct d3d11_command_list *list = impl_from_ID3D11CommandList(iface); + + TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data); + + return d3d_set_private_data(&list->private_store, guid, data_size, data); +} + +static HRESULT STDMETHODCALLTYPE d3d11_command_list_SetPrivateDataInterface(ID3D11CommandList *iface, + REFGUID guid, const IUnknown *data) +{ + struct d3d11_command_list *list = impl_from_ID3D11CommandList(iface); + + TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data); + + return d3d_set_private_data_interface(&list->private_store, guid, data); +} + +static UINT STDMETHODCALLTYPE d3d11_command_list_GetContextFlags(ID3D11CommandList *iface) +{ + TRACE("iface %p.\n", iface); + + return 0; +} + +static const struct ID3D11CommandListVtbl d3d11_command_list_vtbl = +{ + /* IUnknown methods */ + d3d11_command_list_QueryInterface, + d3d11_command_list_AddRef, + d3d11_command_list_Release, + /* ID3D11DeviceChild methods */ + d3d11_command_list_GetDevice, + d3d11_command_list_GetPrivateData, + d3d11_command_list_SetPrivateData, + d3d11_command_list_SetPrivateDataInterface, + /* ID3D11CommandList methods */ + d3d11_command_list_GetContextFlags, +}; + static void d3d11_device_context_cleanup(struct d3d11_device_context *context) { wined3d_private_store_cleanup(&context->private_store); @@ -2635,9 +2753,44 @@ static UINT STDMETHODCALLTYPE d3d11_device_context_GetContextFlags(ID3D11DeviceC static HRESULT STDMETHODCALLTYPE d3d11_device_context_FinishCommandList(ID3D11DeviceContext1 *iface, BOOL restore, ID3D11CommandList **command_list) { + struct d3d11_device_context *context = impl_from_ID3D11DeviceContext1(iface); + struct d3d11_command_list *object; + HRESULT hr; + TRACE("iface %p, restore %#x, command_list %p.\n", iface, restore, command_list);
- return DXGI_ERROR_INVALID_CALL; + if (context->type == D3D11_DEVICE_CONTEXT_IMMEDIATE) + { + WARN("Attempt to record command list on an immediate context; returning DXGI_ERROR_INVALID_CALL.\n"); + return DXGI_ERROR_INVALID_CALL; + } + + if (!(object = heap_alloc_zero(sizeof(*object)))) + return E_OUTOFMEMORY; + + wined3d_mutex_lock(); + + if (FAILED(hr = wined3d_deferred_context_record_command_list(context->wined3d_context, + !!restore, &object->wined3d_list))) + { + WARN("Failed to record wined3d command list, hr %#x.\n", hr); + heap_free(object); + return hr; + } + + wined3d_mutex_unlock(); + + object->ID3D11CommandList_iface.lpVtbl = &d3d11_command_list_vtbl; + object->refcount = 1; + object->device = &context->device->ID3D11Device2_iface; + wined3d_private_store_init(&object->private_store); + + ID3D11Device2_AddRef(object->device); + + TRACE("Created command list %p.\n", object); + *command_list = &object->ID3D11CommandList_iface; + + return S_OK; }
static void STDMETHODCALLTYPE d3d11_device_context_CopySubresourceRegion1(ID3D11DeviceContext1 *iface, diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index b55bfdab866..db1c811a1f1 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -26,6 +26,59 @@ WINE_DECLARE_DEBUG_CHANNEL(fps);
#define WINED3D_INITIAL_CS_SIZE 4096
+struct wined3d_command_list +{ + LONG refcount; + + struct wined3d_device *device; + + SIZE_T data_size; + void *data; + + SIZE_T resource_count; + struct wined3d_resource **resources; +}; + +static void wined3d_command_list_destroy_object(void *object) +{ + struct wined3d_command_list *list = object; + + TRACE("list %p.\n", list); + + heap_free(list->resources); + heap_free(list->data); + heap_free(list); +} + +ULONG CDECL wined3d_command_list_incref(struct wined3d_command_list *list) +{ + ULONG refcount = InterlockedIncrement(&list->refcount); + + TRACE("%p increasing refcount to %u.\n", list, refcount); + + return refcount; +} + +ULONG CDECL wined3d_command_list_decref(struct wined3d_command_list *list) +{ + ULONG refcount = InterlockedDecrement(&list->refcount); + struct wined3d_device *device = list->device; + + TRACE("%p decreasing refcount to %u.\n", list, refcount); + + if (!refcount) + { + SIZE_T i; + + for (i = 0; i < list->resource_count; ++i) + wined3d_resource_decref(list->resources[i]); + + wined3d_cs_destroy_object(device->cs, wined3d_command_list_destroy_object, list); + } + + return refcount; +} + enum wined3d_cs_op { WINED3D_CS_OP_NOP, @@ -3333,3 +3386,53 @@ void CDECL wined3d_deferred_context_destroy(struct wined3d_device_context *conte heap_free(deferred->data); heap_free(deferred); } + +HRESULT CDECL wined3d_deferred_context_record_command_list(struct wined3d_device_context *context, + bool restore, struct wined3d_command_list **list) +{ + struct wined3d_deferred_context *deferred = wined3d_deferred_context_from_context(context); + struct wined3d_command_list *object; + + TRACE("context %p, list %p.\n", context, list); + + if (restore) + { + FIXME("Restoring context state is not implemented.\n"); + return E_NOTIMPL; + } + + if (!(object = heap_alloc_zero(sizeof(*object)))) + return E_OUTOFMEMORY; + + object->refcount = 1; + object->device = deferred->c.device; + + if (!(object->data = heap_alloc(deferred->data_size))) + { + heap_free(object); + return E_OUTOFMEMORY; + } + object->data_size = deferred->data_size; + memcpy(object->data, deferred->data, deferred->data_size); + + if (!(object->resources = heap_alloc(deferred->resource_count * sizeof(*object->resources)))) + { + heap_free(object->data); + heap_free(object); + return E_OUTOFMEMORY; + } + object->resource_count = deferred->resource_count; + memcpy(object->resources, deferred->resources, deferred->resource_count * sizeof(*object->resources)); + /* Transfer our references to the resources to the command list. */ + + deferred->data_size = 0; + deferred->resource_count = 0; + + /* This is in fact recorded into a subsequent command list. */ + wined3d_device_context_reset_state(&deferred->c); + + TRACE("Created command list %p.\n", object); + *list = object; + + return S_OK; +} diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index 84412515c39..6683b3bc30f 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -33,8 +33,12 @@ @ cdecl wined3d_buffer_get_resource(ptr) @ cdecl wined3d_buffer_incref(ptr)
+@ cdecl wined3d_command_list_decref(ptr) +@ cdecl wined3d_command_list_incref(ptr) + @ cdecl wined3d_deferred_context_create(ptr ptr) @ cdecl wined3d_deferred_context_destroy(ptr) +@ cdecl wined3d_deferred_context_record_command_list(ptr long ptr)
@ cdecl wined3d_depth_stencil_state_create(ptr ptr ptr ptr ptr) @ cdecl wined3d_depth_stencil_state_decref(ptr) diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 812c042cdd7..bb6bf58a822 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2221,6 +2221,7 @@ struct wined3d; struct wined3d_adapter; struct wined3d_blend_state; struct wined3d_buffer; +struct wined3d_command_list; struct wined3d_depth_stencil_state; struct wined3d_device; struct wined3d_device_context; @@ -2340,8 +2341,13 @@ void * __cdecl wined3d_buffer_get_parent(const struct wined3d_buffer *buffer); struct wined3d_resource * __cdecl wined3d_buffer_get_resource(struct wined3d_buffer *buffer); ULONG __cdecl wined3d_buffer_incref(struct wined3d_buffer *buffer);
+ULONG __cdecl wined3d_command_list_decref(struct wined3d_command_list *list); +ULONG __cdecl wined3d_command_list_incref(struct wined3d_command_list *list); + HRESULT __cdecl wined3d_deferred_context_create(struct wined3d_device *device, struct wined3d_device_context **context); void __cdecl wined3d_deferred_context_destroy(struct wined3d_device_context *context); +HRESULT __cdecl wined3d_deferred_context_record_command_list(struct wined3d_device_context *context, + bool restore, struct wined3d_command_list **list);
HRESULT __cdecl wined3d_depth_stencil_state_create(struct wined3d_device *device, const struct wined3d_depth_stencil_state_desc *desc, void *parent,
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=91353
Your paranoid android.
=== debiant2 (32 bit report) ===
d3d11: d3d11: Timeout
=== debiant2 (32 bit Chinese:China report) ===
d3d11: d3d11: Timeout
=== debiant2 (32 bit WoW report) ===
d3d11: d3d11: Timeout
=== debiant2 (64 bit WoW report) ===
d3d11: d3d11: Timeout
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/d3d11/tests/d3d11.c | 39 +++++++++++++-------------------------- dlls/wined3d/cs.c | 11 ++++------- 2 files changed, 17 insertions(+), 33 deletions(-)
diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c index d799bed25f4..8da0cfaa8bf 100644 --- a/dlls/d3d11/tests/d3d11.c +++ b/dlls/d3d11/tests/d3d11.c @@ -32281,15 +32281,7 @@ static void test_deferred_context_state(void) ID3D11Buffer_Release(ret_buffer);
hr = ID3D11DeviceContext_FinishCommandList(deferred, TRUE, &list1); - todo_wine ok(hr == S_OK, "Failed to create command list, hr %#x.\n", hr); - if (hr != S_OK) - { - ID3D11DeviceContext_Release(deferred); - ID3D11Buffer_Release(blue_buffer); - ID3D11Buffer_Release(green_buffer); - release_test_context(&test_context); - return; - } + ok(hr == S_OK, "Failed to create command list, hr %#x.\n", hr);
ID3D11DeviceContext_PSGetConstantBuffers(deferred, 0, 1, &ret_buffer); ok(ret_buffer == blue_buffer, "Got unexpected buffer %p.\n", ret_buffer); @@ -32310,7 +32302,9 @@ 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); - ok(!ret_buffer, "Got unexpected buffer %p.\n", ret_buffer); + todo_wine ok(!ret_buffer, "Got unexpected buffer %p.\n", ret_buffer); + if (ret_buffer) + ID3D11Buffer_Release(ret_buffer);
ID3D11CommandList_Release(list2); ID3D11CommandList_Release(list1); @@ -32484,16 +32478,7 @@ static void test_deferred_context_rendering(void) ID3D11DeviceContext_ClearRenderTargetView(deferred, test_context.backbuffer_rtv, green);
hr = ID3D11DeviceContext_FinishCommandList(deferred, TRUE, &list1); - todo_wine ok(hr == S_OK, "Failed to create command list, hr %#x.\n", hr); - if (hr != S_OK) - { - ID3D11BlendState_Release(red_blend); - ID3D11BlendState_Release(green_blend); - ID3D11BlendState_Release(blue_blend); - ID3D11DeviceContext_Release(deferred); - release_test_context(&test_context); - return; - } + ok(hr == S_OK, "Failed to create command list, hr %#x.\n", hr);
hr = ID3D11DeviceContext_FinishCommandList(deferred, TRUE, &list2); ok(hr == S_OK, "Failed to create command list, hr %#x.\n", hr); @@ -32503,12 +32488,12 @@ static void test_deferred_context_rendering(void)
ID3D11DeviceContext_ExecuteCommandList(immediate, list1, TRUE); color = get_texture_color(test_context.backbuffer, 320, 240); - ok(color == 0xff00ff00, "Got unexpected color %#08x.\n", color); + todo_wine 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); - ok(color == 0xff00ff00, "Got unexpected color %#08x.\n", color); + todo_wine ok(color == 0xff00ff00, "Got unexpected color %#08x.\n", color);
ID3D11DeviceContext_ClearRenderTargetView(immediate, test_context.backbuffer_rtv, &white.x); ID3D11DeviceContext_ExecuteCommandList(immediate, list2, TRUE); @@ -32524,7 +32509,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); - ok(color == 0xff00ff00, "Got unexpected color %#08x.\n", color); + todo_wine ok(color == 0xff00ff00, "Got unexpected color %#08x.\n", color);
ID3D11CommandList_Release(list2); ID3D11CommandList_Release(list1); @@ -32550,7 +32535,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); - ok(color == 0xffff0000, "Got unexpected color %#08x.\n", color); + todo_wine ok(color == 0xffff0000, "Got unexpected color %#08x.\n", color);
ID3D11CommandList_Release(list1); ID3D11DeviceContext_Release(deferred); @@ -32584,10 +32569,12 @@ 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); - ok(color == 0xffffffff, "Got unexpected color %#08x.\n", color); + todo_wine ok(color == 0xffffffff, "Got unexpected color %#08x.\n", color);
ID3D11DeviceContext_OMGetBlendState(immediate, &ret_blend, blend_factor, &sample_mask); - ok(!ret_blend, "Got unexpected blend state %p.\n", ret_blend); + todo_wine ok(!ret_blend, "Got unexpected blend state %p.\n", ret_blend); + if (ret_blend) + ID3D11BlendState_Release(ret_blend);
ID3D11CommandList_Release(list1); ID3D11DeviceContext_Release(deferred); diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index db1c811a1f1..1e082ce724d 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -3395,12 +3395,6 @@ HRESULT CDECL wined3d_deferred_context_record_command_list(struct wined3d_device
TRACE("context %p, list %p.\n", context, list);
- if (restore) - { - FIXME("Restoring context state is not implemented.\n"); - return E_NOTIMPL; - } - if (!(object = heap_alloc_zero(sizeof(*object)))) return E_OUTOFMEMORY;
@@ -3429,7 +3423,10 @@ HRESULT CDECL wined3d_deferred_context_record_command_list(struct wined3d_device deferred->resource_count = 0;
/* This is in fact recorded into a subsequent command list. */ - wined3d_device_context_reset_state(&deferred->c); + if (restore) + wined3d_device_context_set_state(&deferred->c, deferred->c.state); + else + wined3d_device_context_reset_state(&deferred->c);
TRACE("Created command list %p.\n", object); *list = object;
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=91354
Your paranoid android.
=== w1064v1809 (32 bit report) ===
d3d11: d3d11.c:5810: Test failed: Got unexpected IAVertices count: 0. d3d11.c:5811: Test failed: Got unexpected IAPrimitives count: 0. d3d11.c:5812: Test failed: Got unexpected VSInvocations count: 0. d3d11.c:5815: Test failed: Got unexpected CInvocations count: 0. d3d11.c:5816: Test failed: Got unexpected CPrimitives count: 0.
=== w10pro64 (32 bit report) ===
d3d11: d3d11.c:5657: Test failed: Got unexpected query result 0x0000000000000000. d3d11.c:5810: Test failed: Got unexpected IAVertices count: 0. d3d11.c:5811: Test failed: Got unexpected IAPrimitives count: 0. d3d11.c:5812: Test failed: Got unexpected VSInvocations count: 0. d3d11.c:5815: Test failed: Got unexpected CInvocations count: 0. d3d11.c:5816: Test failed: Got unexpected CPrimitives count: 0.
=== debiant2 (32 bit French report) ===
d3d11: d3d11.c:9660: Test failed: d3d11.c:15043: Test marked todo: Got hr 0 for WRITE_DISCARD.
=== debiant2 (32 bit Chinese:China report) ===
d3d11: d3d11.c:9660: Test failed: d3d11.c:15043: Test marked todo: Got hr 0 for WRITE_DISCARD.
=== debiant2 (32 bit WoW report) ===
d3d11: d3d11.c:9660: Test failed: d3d11.c:15043: Test marked todo: Got hr 0 for WRITE_DISCARD.
=== debiant2 (64 bit WoW report) ===
d3d11: d3d11.c:5816: Test failed: d3d11.c:6143: Test marked todo: Got unexpected PrimitivesStorageNeeded: 2. d3d11.c:19759: Test failed: d3d11.c:23386: Tests skipped: Got {0x00000000, 0x00000000, 0x00000000, 0x00000000}, expected {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff} at (0, 0), sub-resource 0.
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura z.figura12@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);
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=91355
Your paranoid android.
=== w1064v1809 (32 bit report) ===
d3d11: d3d11.c:5810: Test failed: Got unexpected IAVertices count: 0. d3d11.c:5811: Test failed: Got unexpected IAPrimitives count: 0. d3d11.c:5812: Test failed: Got unexpected VSInvocations count: 0. d3d11.c:5815: Test failed: Got unexpected CInvocations count: 0. d3d11.c:5816: Test failed: Got unexpected CPrimitives count: 0.
=== w10pro64 (32 bit report) ===
d3d11: d3d11.c:5810: Test failed: Got unexpected IAVertices count: 0. d3d11.c:5811: Test failed: Got unexpected IAPrimitives count: 0. d3d11.c:5812: Test failed: Got unexpected VSInvocations count: 0. d3d11.c:5815: Test failed: Got unexpected CInvocations count: 0. d3d11.c:5816: Test failed: Got unexpected CPrimitives count: 0. d3d11.c:5657: Test failed: Got unexpected query result 0x0000000000000000.