[PATCH 1/5] d3d9/tests: Add a basic Fetch4 sampling test.

Henri Verbeet hverbeet at codeweavers.com
Wed Mar 6 07:00:12 CST 2019


From: Daniel Ansorregui <mailszeros at gmail.com>

Signed-off-by: Henri Verbeet <hverbeet at 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();
-- 
2.11.0




More information about the wine-devel mailing list