From: Daniel Ansorregui mailszeros@gmail.com
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com --- dlls/d3d9/tests/visual.c | 275 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 275 insertions(+)
diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c index 69cd4418bd2..adb04c14de1 100644 --- a/dlls/d3d9/tests/visual.c +++ b/dlls/d3d9/tests/visual.c @@ -15396,6 +15396,280 @@ done: DestroyWindow(window); }
+static void test_fetch4(void) +{ + static const DWORD vs_code[] = + { + 0xfffe0300, /* vs_3_0 */ + 0x0200001f, 0x80000000, 0x900f0000, /* dcl_position v0 */ + 0x0200001f, 0x80000005, 0x900f0001, /* dcl_texcoord v1 */ + 0x0200001f, 0x80000000, 0xe00f0000, /* dcl_position o0 */ + 0x0200001f, 0x80000005, 0xe00f0001, /* dcl_texcoord o1 */ + 0x02000001, 0xe00f0000, 0x90e40000, /* mov o0, v0 */ + 0x02000001, 0xe00f0001, 0x90e40001, /* mov o1, v1 */ + 0x0000ffff, + }; + static const DWORD ps_code_texld[] = + { + 0xffff0300, /* ps_3_0 */ + 0x0200001f, 0x80000005, 0x900f0000, /* dcl_texcoord v0 */ + 0x0200001f, 0x90000000, 0xa00f0800, /* dcl_2d s0 */ + 0x03000042, 0x800f0000, 0x90e40000, 0xa0e40800, /* texld r0, v0, s0 */ + 0x02000001, 0x800f0800, 0x80e40000, /* mov oC0, r0 */ + 0x0000ffff, /* end */ + }; + /* AMD and Wine use the projection on Fetch4, Intel UHD ignores it. */ + static const DWORD ps_code_texldp[] = + { + 0xffff0300, /* ps_3_0 */ + 0x0200001f, 0x80000005, 0x900f0000, /* dcl_texcoord v0 */ + 0x0200001f, 0x90000000, 0xa00f0800, /* dcl_2d s0 */ + /* The idea here is that if we project from .z, we get a 4x zoom. From + * .w a 2x zoom. */ + 0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x40800000, 0x40000000, /* def c0, 0.0, 0.0, 4.0, 2.0 */ + 0x02000001, 0x80030000, 0x90f40000, /* mov r0.xy, v0.xyww */ + 0x02000001, 0x800c0000, 0xa0e00000, /* mov r0.zw, c0.xxzw */ + 0x03010042, 0x800f0000, 0x80e40000, 0xa0e40800, /* texldp r0, r0, s0 */ + 0x02000001, 0x800f0800, 0x80e40000, /* mov oC0, r0 */ + 0x0000ffff, /* end */ + }; + static const DWORD ps_code_swizzle[] = + { + /* Test texld when sampling with a .yzwx swizzle. */ + 0xffff0300, /* ps_3_0 */ + 0x0200001f, 0x80000005, 0x900f0000, /* dcl_texcoord v0 */ + 0x0200001f, 0x90000000, 0xa00f0800, /* dcl_2d s0 */ + 0x03000042, 0x800f0000, 0x90e40000, 0xa0390800, /* texld r0, v0, s0.yzwx */ + 0x02000001, 0x800f0800, 0x80e40000, /* mov oC0, r0 */ + 0x0000ffff, /* end */ + }; + + static const struct + { + struct vec3 position; + struct vec4 texcoord; + } + quad[] = + { + {{-1.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 4.0f, 2.0f}}, + {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 4.0f, 2.0f}}, + {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f, 4.0f, 2.0f}}, + {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 4.0f, 2.0f}}, + }; + + static const struct + { + unsigned int x[4], y[4]; + D3DCOLOR colour_amd[16]; + D3DCOLOR colour_intel[16]; + D3DCOLOR colour_fetch4_off[16]; + } + expected_colours = + { + /* Sample positions. */ + {40, 200, 360, 520}, + {30, 150, 270, 390}, + /* AMD implementation (-0.5 texel offsets). */ + {0x131202f2, 0x1211f2f1, 0x1110f101, 0x10100101, + 0x02f204f4, 0xf2f1f4f3, 0xf101f303, 0x01010303, + 0x04f42322, 0xf4f32221, 0xf3032120, 0x03032020, + 0x23222322, 0x22212221, 0x21202120, 0x20202020}, + /* Intel UHD 620 implementation (no texel offsets). + * We treat the Intel results as broken. */ + {0x13131313, 0x12131312, 0x11121211, 0x10111110, + 0x13021302, 0x120213f2, 0x11f212f1, 0x10f11101, + 0x02040204, 0xf20402f4, 0xf1f4f2f3, 0x01f3f103, + 0x04230423, 0xf4230422, 0xf322f421, 0x0321f320}, + /* Fetch4 off on 2D textures. */ + {0x13131313, 0x12121212, 0x11111111, 0x10101010, + 0x02020202, 0xf2f2f2f2, 0xf1f1f1f1, 0x01010101, + 0x04040404, 0xf4f4f4f4, 0xf3f3f3f3, 0x03030303, + 0x23232323, 0x22222222, 0x21212121, 0x20202020}, + }; + + static const DWORD fetch4_data[] = {0x10111213, 0x01f1f202, 0x03f3f404, 0x20212223}; + + static const struct + { + const char *name; + const DWORD *ps_code; + unsigned int projection; + BOOL swizzled; + DWORD ttff_flags; + } + shaders[] = + { + {"FFP", NULL, 0, FALSE, 0}, + {"texld", ps_code_texld, 0, FALSE, 0}, + {"texldp", ps_code_texldp, 2, FALSE, 0}, + {"texld_yzwx", ps_code_swizzle, 0, TRUE , 0}, + {"FFP_proj", NULL, 2, FALSE, D3DTTFF_PROJECTED}, + {"FFP_proj3", NULL, 4, FALSE, D3DTTFF_COUNT3 | D3DTTFF_PROJECTED}, + }; + + D3DCOLOR colour, colour_amd, colour_intel, colour_off; + IDirect3DPixelShader9 *ps[ARRAY_SIZE(shaders)]; + IDirect3DSurface9 *original_rt; + struct surface_readback rb; + IDirect3DVertexShader9 *vs; + IDirect3DTexture9 *texture; + IDirect3DDevice9 *device; + unsigned int i, j, x, y; + D3DLOCKED_RECT lr; + IDirect3D9 *d3d; + ULONG refcount; + D3DCAPS9 caps; + HWND window; + HRESULT hr; + + window = create_window(); + d3d = Direct3DCreate9(D3D_SDK_VERSION); + ok(!!d3d, "Failed to create a D3D object.\n"); + if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, + D3DFMT_X8R8G8B8, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, MAKEFOURCC('D','F','2','4')))) + { + skip("No DF24 support, skipping Fetch4 test.\n"); + goto done; + } + if (!(device = create_device(d3d, window, window, TRUE))) + { + skip("Failed to create a D3D device, skipping tests.\n"); + goto done; + } + + hr = IDirect3DDevice9_GetDeviceCaps(device, &caps); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + if (caps.PixelShaderVersion < D3DPS_VERSION(3, 0)) + { + skip("No pixel shader 3.0 support, skipping FETCH4 test.\n"); + IDirect3DDevice9_Release(device); + goto done; + } + hr = IDirect3DDevice9_GetRenderTarget(device, 0, &original_rt); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 1, 0, D3DFMT_L8, D3DPOOL_MANAGED, &texture, NULL); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + for (i = 0; i < ARRAY_SIZE(fetch4_data); ++i) + memcpy((BYTE *)lr.pBits + i * lr.Pitch, &fetch4_data[i], sizeof(fetch4_data[i])); + hr = IDirect3DTexture9_UnlockRect(texture, 0); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + hr = IDirect3DDevice9_CreateVertexShader(device, vs_code, &vs); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + for (i = 0; i < ARRAY_SIZE(shaders); ++i) + { + if (!shaders[i].ps_code) + { + ps[i] = NULL; + continue; + } + + hr = IDirect3DDevice9_CreatePixelShader(device, shaders[i].ps_code, &ps[i]); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + } + + hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE4(0)); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_ALWAYS); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + /* According to the documentation, Fetch4 is enabled when + * D3DSAMP_MIPMAPLODBIAS == GET4 and D3DSAMP_MAGFILTER == D3DTEXF_POINT. + * In practice, it seems that only GET4 is required. + * + * AMD r500 hardware always uses POINT filtering with Fetch4. The driver + * later on corrected this by adding a -0.5 texel offset. */ + hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPMAPLODBIAS, MAKEFOURCC('G','E','T','4')); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + /* Fetch4 should work with any texture wrapping mode, and does in Wine. + * However, AMD RX 580 devices force clamping when fetch4 is on. + * No other driver/hardware does this, but to avoid problems, we test with + * CLAMP on. */ + hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSW, D3DTADDRESS_CLAMP); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + /* Test basic Fetch4 sampling. */ + for (i = 0; i < ARRAY_SIZE(shaders); ++i) + { + hr = IDirect3DDevice9_SetVertexShader(device, ps[i] ? vs : NULL); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice9_SetPixelShader(device, ps[i]); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, shaders[i].ttff_flags); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0, 0.0f, 0); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice9_BeginScene(device); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad)); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice9_EndScene(device); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + get_rt_readback(original_rt, &rb); + for (j = 0; j < ARRAY_SIZE(expected_colours.colour_amd); ++j) + { + unsigned int projection = shaders[i].projection; + + x = expected_colours.x[j % 4]; + y = expected_colours.y[j / 4]; + colour_amd = expected_colours.colour_amd[j]; + if (projection) + colour_amd = expected_colours.colour_amd[j / 4 / projection * 4 + (j % 4) / projection]; + if (shaders[i].swizzled) + colour_amd = (colour_amd << 8) | (colour_amd >> 24); + colour_intel = expected_colours.colour_intel[j]; + colour_off = expected_colours.colour_fetch4_off[j]; + colour = get_readback_color(&rb, x, y); + + ok(color_match(colour, colour_amd, 1) || broken(color_match(colour, colour_intel, 1)) + || broken(color_match(colour, colour_off, 1)), + "Test %s: Got unexpected colour 0x%08x at (%u, %u).\n", + shaders[i].name, colour, x, y); + } + release_surface_readback(&rb); + + hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + } + + IDirect3DTexture9_Release(texture); + for (i = 0; i < ARRAY_SIZE(ps); ++i) + { + if (ps[i]) + IDirect3DPixelShader9_Release(ps[i]); + } + IDirect3DVertexShader9_Release(vs); + IDirect3DSurface9_Release(original_rt); + refcount = IDirect3DDevice9_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); +done: + IDirect3D9_Release(d3d); + DestroyWindow(window); +} + static void shadow_test(void) { static const DWORD ps_code[] = @@ -24895,6 +25169,7 @@ START_TEST(visual) depth_buffer2_test(); depth_blit_test(); intz_test(); + test_fetch4(); shadow_test(); fp_special_test(); depth_bounds_test();
Hi,
While running your changed tests on Windows, 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=48845
Your paranoid android.
=== w1064 (64 bit report) ===
d3d9: visual.c:8750: Test failed: Got unexpected color 0x00008080 for quad 2 (different colors).