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
-- v3: 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 instanced for not-indexed draw calls
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=54570 --- dlls/d3d9/device.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+)
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index eddb2a0ebdd..8aba3288513 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -3033,7 +3033,9 @@ static HRESULT WINAPI d3d9_device_DrawPrimitive(IDirect3DDevice9Ex *iface, D3DPRIMITIVETYPE primitive_type, UINT start_vertex, UINT primitive_count) { struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); + const struct wined3d_stateblock_state *state; unsigned int vertex_count; + UINT saved_flags, saved_freq;
TRACE("iface %p, primitive_type %#x, start_vertex %u, primitive_count %u.\n", iface, primitive_type, start_vertex, primitive_count); @@ -3045,6 +3047,17 @@ static HRESULT WINAPI d3d9_device_DrawPrimitive(IDirect3DDevice9Ex *iface, WARN("Called without a valid vertex declaration set.\n"); return D3DERR_INVALIDCALL; } + + /* Windows D3D9 does not do non-indexed instanced draws. + * Set instance count to 1 for the not indexed draw */ + state = wined3d_stateblock_get_state(device->state); + saved_freq = state->streams[0].frequency; + if(saved_freq > 1) + { + saved_flags = state->streams[0].flags; + wined3d_stateblock_set_stream_source_freq(device->update_state, 0, saved_flags | 1); + } + wined3d_device_apply_stateblock(device->wined3d_device, device->state); vertex_count = vertex_count_from_primitive_count(primitive_type, primitive_count); d3d9_device_upload_managed_textures(device); @@ -3053,6 +3066,11 @@ static HRESULT WINAPI d3d9_device_DrawPrimitive(IDirect3DDevice9Ex *iface, 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); + + /* Restore instance count to previous value */ + if(saved_freq > 1) + wined3d_stateblock_set_stream_source_freq(device->update_state, 0, saved_flags | saved_freq); + d3d9_rts_flag_auto_gen_mipmap(device); wined3d_mutex_unlock();
@@ -3103,8 +3121,10 @@ static HRESULT WINAPI d3d9_device_DrawPrimitiveUP(IDirect3DDevice9Ex *iface, D3DPRIMITIVETYPE primitive_type, UINT primitive_count, const void *data, UINT stride) { struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); + const struct wined3d_stateblock_state *state; UINT vtx_count = vertex_count_from_primitive_count(primitive_type, primitive_count); UINT size = vtx_count * stride; + UINT saved_flags, saved_freq; unsigned int vb_pos; HRESULT hr;
@@ -3143,8 +3163,24 @@ static HRESULT WINAPI d3d9_device_DrawPrimitiveUP(IDirect3DDevice9Ex *iface, d3d9_device_upload_managed_textures(device); wined3d_device_context_set_primitive_type(device->immediate_context, wined3d_primitive_type_from_d3d(primitive_type), 0); + + /* Windows D3D9 does not do non-indexed instanced draws. + * Set instance count to 1 for the not indexed draw */ + state = wined3d_stateblock_get_state(device->state); + saved_freq = state->streams[0].frequency; + if(saved_freq > 1) + { + saved_flags = state->streams[0].flags; + wined3d_stateblock_set_stream_source_freq(device->update_state, 0, saved_flags | 1); + } + wined3d_device_apply_stateblock(device->wined3d_device, device->state); wined3d_device_context_draw(device->immediate_context, vb_pos / stride, vtx_count, 0, 0); + + /* Restore instance count to previous value */ + if(saved_freq > 1) + wined3d_stateblock_set_stream_source_freq(device->update_state, 0, saved_flags | saved_freq); + wined3d_stateblock_set_stream_source(device->state, 0, NULL, 0, 0); d3d9_rts_flag_auto_gen_mipmap(device);
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=129990
Your paranoid android.
=== debian11 (32 bit report) ===
urlmon: url.c:1259: Test failed: dwResponseCode=502, expected 200 url.c:1468: Test failed: progress 13: status = 502 url.c:1468: Test failed: progress 4: status = 502 url.c:1468: Test failed: progress 6: status = 502 url.c:1259: Test failed: dwResponseCode=502, expected 200 url.c:1468: Test failed: progress 13: status = 502 url.c:1468: Test failed: progress 4: status = 502 url.c:1468: Test failed: progress 6: status = 502