d3d9 does not do instancing for not-indexed draw calls on Windows
Original issue in DXVK repo: https://github.com/doitsujin/dxvk/issues/3157
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=54570
-- v5: d3d9: Disable instancing for not-indexed drawing d3d9/tests: Add test for not-indexed instancing drawing
From: Illia Polishchuk illia.a.polishchuk@globallogic.com
d3d9 does not do instancing for not-indexed draw calls on Windows --- dlls/d3d9/tests/visual.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-)
diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c index 230f7deabb2..8132007a3d0 100644 --- a/dlls/d3d9/tests/visual.c +++ b/dlls/d3d9/tests/visual.c @@ -13090,6 +13090,35 @@ static void stream_test(void) hr = IDirect3DDevice9_SetStreamSource(device, act.strInstance, vb3, 0, sizeof(instancepos[0])); ok(SUCCEEDED(hr), "Failed to set stream source, hr %#lx.\n", hr);
+ /* Not indexed draw test. Instancing should not happen */ + hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 1); + ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr); + + hr = IDirect3DDevice9_EndScene(device); + ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr); + + /* Check that only single triangle without instansing has beed drawed with not-indexed draw + * Instancing should happens only with indexed draws for d3d9 */ + color = getPixelColor(device, 200, 340); + ok(color == act.color1, "has color 0x%08x, expected 0x%08x (case %i)\n", color, act.color1, i); + color = getPixelColor(device, 400, 340); + ok(color == 0x00ffffff, "has color 0x%08x, expected 0x%08x (case %i)\n", color, 0x00ffffff, i); + color = getPixelColor(device, 400, 180); + ok(color == 0x00ffffff, "has color 0x%08x, expected 0x%08x (case %i)\n", color, 0x00ffffff, i); + color = getPixelColor(device, 200, 180); + ok(color == 0x00ffffff, "has color 0x%08x, expected 0x%08x (case %i)\n", color, 0x00ffffff, i); + + + hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IDirect3DDevice9_BeginScene(device); + ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr); + + /* Indexed draw test. Instancing should happen */ hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0, 0, 4, 0, 2); ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr); hr = IDirect3DDevice9_EndScene(device); @@ -13120,7 +13149,7 @@ static void stream_test(void) ok(color == act.color3, "has color 0x%08x, expected 0x%08x (case %i)\n", color, act.color3, i); color = getPixelColor(device, 160, 120); ok(color == act.color4, "has color 0x%08x, expected 0x%08x (case %i)\n", color, act.color4, i); - + hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); ok(hr == S_OK, "Got hr %#lx.\n", hr); }
From: Illia Polishchuk illia.a.polishchuk@globallogic.com
d3d9 does not do instancing for not-indexed draw calls on Windows
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=54570 --- dlls/d3d9/device.c | 18 ++++++++++++++---- dlls/wined3d/adapter_vk.c | 2 -- dlls/wined3d/context_gl.c | 6 ------ dlls/wined3d/wined3d_private.h | 1 - 4 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index eddb2a0ebdd..8c0045cd2f5 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -3052,7 +3052,11 @@ static HRESULT WINAPI d3d9_device_DrawPrimitive(IDirect3DDevice9Ex *iface, d3d9_generate_auto_mipmaps(device); wined3d_device_context_set_primitive_type(device->immediate_context, wined3d_primitive_type_from_d3d(primitive_type), 0); - wined3d_device_context_draw(device->immediate_context, start_vertex, vertex_count, 0, 0); + + /* Windows D3D9 does not do non-indexed instanced draws. + * Set instance count to 1 for the not indexed draw */ + wined3d_device_context_draw(device->immediate_context, start_vertex, vertex_count, 0, 1); + d3d9_rts_flag_auto_gen_mipmap(device); wined3d_mutex_unlock();
@@ -3092,7 +3096,8 @@ static HRESULT WINAPI d3d9_device_DrawIndexedPrimitive(IDirect3DDevice9Ex *iface wined3d_primitive_type_from_d3d(primitive_type), 0); wined3d_device_apply_stateblock(device->wined3d_device, device->state); d3d9_device_upload_sysmem_index_buffer(device, &start_idx, index_count); - wined3d_device_context_draw_indexed(device->immediate_context, base_vertex_idx, start_idx, index_count, 0, 0); + wined3d_device_context_draw_indexed(device->immediate_context, base_vertex_idx, start_idx, index_count, 0, + wined3d_stateblock_get_state(device->state)->streams[0].frequency); d3d9_rts_flag_auto_gen_mipmap(device); wined3d_mutex_unlock();
@@ -3144,7 +3149,11 @@ static HRESULT WINAPI d3d9_device_DrawPrimitiveUP(IDirect3DDevice9Ex *iface, wined3d_device_context_set_primitive_type(device->immediate_context, wined3d_primitive_type_from_d3d(primitive_type), 0); wined3d_device_apply_stateblock(device->wined3d_device, device->state); - wined3d_device_context_draw(device->immediate_context, vb_pos / stride, vtx_count, 0, 0); + + /* Windows D3D9 does not do non-indexed instanced draws. + * Set instance count to 1 for the not indexed draw */ + wined3d_device_context_draw(device->immediate_context, vb_pos / stride, vtx_count, 0, 1); + wined3d_stateblock_set_stream_source(device->state, 0, NULL, 0, 0); d3d9_rts_flag_auto_gen_mipmap(device);
@@ -3211,7 +3220,8 @@ static HRESULT WINAPI d3d9_device_DrawIndexedPrimitiveUP(IDirect3DDevice9Ex *ifa wined3d_device_context_set_primitive_type(device->immediate_context, wined3d_primitive_type_from_d3d(primitive_type), 0); wined3d_device_context_draw_indexed(device->immediate_context, - vb_pos / vertex_stride - min_vertex_idx, ib_pos / idx_fmt_size, idx_count, 0, 0); + vb_pos / vertex_stride - min_vertex_idx, ib_pos / idx_fmt_size, idx_count, 0, + wined3d_stateblock_get_state(device->state)->streams[0].frequency);
wined3d_stateblock_set_stream_source(device->state, 0, NULL, 0, 0); wined3d_stateblock_set_index_buffer(device->state, NULL, WINED3DFMT_UNKNOWN); diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index cf8a7aec6dc..64f2ca369ee 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -1813,8 +1813,6 @@ static void adapter_vk_draw_primitive(struct wined3d_device *device, else { instance_count = parameters->u.direct.instance_count; - if (context_vk->c.instance_count) - instance_count = context_vk->c.instance_count; if (!instance_count) instance_count = 1;
diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c index 5574997bf05..27969f0b5c9 100644 --- a/dlls/wined3d/context_gl.c +++ b/dlls/wined3d/context_gl.c @@ -5321,8 +5321,6 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s else { unsigned int instance_count = parameters->u.direct.instance_count; - if (context->instance_count) - instance_count = context->instance_count;
if (context->use_immediate_mode_draw || emulation) draw_primitive_immediate_mode(wined3d_context_gl(context), state, stream_info, idx_data, @@ -5466,7 +5464,6 @@ static void wined3d_context_gl_load_vertex_data(struct wined3d_context_gl *conte
/* This is used for the fixed-function pipeline only, and the * fixed-function pipeline doesn't do instancing. */ - context_gl->c.instance_count = 0; current_bo = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0u : 0;
/* Blend data */ @@ -5680,7 +5677,6 @@ static void wined3d_context_gl_load_numbered_arrays(struct wined3d_context_gl *c unsigned int i;
/* Default to no instancing. */ - context->instance_count = 0; current_bo = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0u : 0;
if (stream_info->use_map & ~wined3d_mask_from_size(gl_info->limits.vertex_attribs)) @@ -5726,8 +5722,6 @@ static void wined3d_context_gl_load_numbered_arrays(struct wined3d_context_gl *c stream = &state->streams[element->stream_idx]; stream->buffer->bo_user.valid = true;
- if ((stream->flags & WINED3DSTREAMSOURCE_INSTANCEDATA) && !context->instance_count) - context->instance_count = state->streams[0].frequency;
if (gl_info->supported[ARB_INSTANCED_ARRAYS]) { diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 459ac7a19c8..c0a190cbc5c 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2307,7 +2307,6 @@ struct wined3d_context DWORD numbered_array_mask; enum fogsource fog_source;
- UINT instance_count;
void *shader_backend_data; void *fragment_pipe_data;
Note that this will still respect D3DSTREAMSOURCE_INSTANCEDATA for DrawPrimitive()/DrawPrimitiveUP(). That may very well be the correct behaviour, but something like "d3d9: Always draw only a single instance for non-indexed draws." would be a more accurate description of the commit.
- wined3d_device_context_draw_indexed(device->immediate_context, base_vertex_idx, start_idx, index_count, 0, 0); + wined3d_device_context_draw_indexed(device->immediate_context, base_vertex_idx, start_idx, index_count, 0, + wined3d_stateblock_get_state(device->state)->streams[0].frequency);
I think you should be able to use "device->stateblock_state" instead of "wined3d_stateblock_get_state(device->state)" here, as well as in d3d9_device_DrawIndexedPrimitiveUP().
There are a couple of places with trailing spaces in this series.