[PATCH v3 2/3] d3d9/tests: Add test for 'nrm' opcode.

Paul Gofman gofmanp at gmail.com
Thu Jun 13 05:17:25 CDT 2019


Signed-off-by: Paul Gofman <gofmanp at gmail.com>
---
v2:
    1. Encode max float / infinity values in nrm_c0. This should workaround output color clamp problem
        on testbot's llvmpipe gl renderer, and also reveals the behaviour more reliably for relevant cases.
        As per my local testing, llvmpipe outputs color 0 for big positive ps color output starting
        from color value of approximatrely 1e7 (1e6 still outputs 0xff as expected);
    2. Refined test revealed broken case on some of the warp drivers, added broken case handling.

v3:
    1. Encoded Inf value in nrm_c0 so that max_float does not get encoded.
    2. Added todo_wine for zero norm and non-zero 'w' cases.

 dlls/d3d9/tests/visual.c | 255 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 255 insertions(+)

diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c
index 1991c0a519..99913e3a73 100644
--- a/dlls/d3d9/tests/visual.c
+++ b/dlls/d3d9/tests/visual.c
@@ -34,6 +34,7 @@
 #define COBJMACROS
 #include <d3d9.h>
 #include "wine/test.h"
+#include "wine/heap.h"
 
 struct vec2
 {
@@ -25982,6 +25983,259 @@ static void test_sysmem_draw(void)
     DestroyWindow(window);
 }
 
+static void test_nrm_instruction(void)
+{
+    IDirect3DVertexDeclaration9 *vertex_declaration;
+    IDirect3DVertexShader9 *vertex_shader;
+    IDirect3DPixelShader9 *pixel_shader;
+    D3DADAPTER_IDENTIFIER9 identifier;
+    IDirect3DDevice9 *device;
+    unsigned int body_size;
+    IDirect3D9 *d3d;
+    D3DCOLOR colour;
+    unsigned int i;
+    DWORD *ps_code;
+    ULONG refcount;
+    D3DCAPS9 caps;
+    BOOL is_warp;
+    HWND window;
+    HRESULT hr;
+
+    static const D3DVERTEXELEMENT9 decl_elements[] =
+    {
+        {0,  0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
+        {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
+        {0, 20, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
+        D3DDECL_END()
+    };
+    static const struct
+    {
+        struct vec3 position;
+        struct vec2 t0;
+        struct vec4 t1;
+    }
+    quad[] =
+    {
+        {{-1.0f, -1.0f, 0.1f}, {1.0f, 1.0f}, {0.0f, 1.0f, 0.3f, 0.5f}},
+        {{ 1.0f, -1.0f, 0.1f}, {1.0f, 1.0f}, {0.0f, 1.0f, 0.3f, 0.5f}},
+        {{-1.0f,  1.0f, 0.1f}, {1.0f, 1.0f}, {0.0f, 1.0f, 0.3f, 0.5f}},
+        {{ 1.0f,  1.0f, 0.1f}, {1.0f, 1.0f}, {0.0f, 1.0f, 0.3f, 0.5f}},
+    };
+
+    static const DWORD vs_code[] =
+    {
+        0xfffe0300,                                     /* vs_3_0                 */
+        0x0200001f, 0x80000000, 0x900f0000,             /* dcl_position v0        */
+        0x0200001f, 0x80000005, 0x900f0001,             /* dcl_texcoord0 v1       */
+        0x0200001f, 0x80010005, 0x900f0002,             /* dcl_texcoord1 v2       */
+        0x0200001f, 0x80000000, 0xe00f0000,             /* dcl_position o0        */
+        0x0200001f, 0x80000005, 0xe00f0001,             /* dcl_texcoord0 o1       */
+        0x0200001f, 0x80010005, 0xe00f0002,             /* dcl_texcoord1 o2       */
+        0x0200001f, 0x80020005, 0xe00f0003,             /* dcl_texcoord2 o3       */
+        0x02000001, 0xe00f0000, 0x90e40000,             /* mov o0, v0             */
+        0x02000001, 0xe00f0001, 0x90e40001,             /* mov o1, v1             */
+        0x02000001, 0xe00f0002, 0x90e40002,             /* mov o2, v2             */
+        0x02000024, 0x800f0000, 0x90e40002,             /* nrm r0, v2             */
+        0x02000001, 0xe00f0003, 0x80e40000,             /* mov o3, r0             */
+        0x0000ffff,
+    };
+    static const DWORD ps_header[] =
+    {
+        0xffff0300,                                     /* ps_3_0                 */
+    };
+    static const DWORD ps_footer[] =
+    {
+        0x02000001, 0x800f0800, 0x80e40000,             /* mov oC0, r0            */
+        0x0000ffff,                                     /* end                    */
+    };
+    static const DWORD nrm_t0[] =
+    {
+        0x0200001f, 0x80000005, 0x90070001,             /* dcl_texcoord0 v0.xyz   */
+        0x02000024, 0x800f0000, 0x90e40001,             /* nrm r0, v0             */
+    };
+    static const DWORD nrm_xyz_t0[] =
+    {
+        0x0200001f, 0x80000005, 0x90070000,             /* dcl_texcoord0 v0.xyz   */
+        0x02000001, 0x800f0000, 0xa0e40000,             /* mov r0, c0             */
+        0x02000024, 0x80070000, 0x90e40000,             /* nrm r0.xyz, v0         */
+        0x02000001, 0x80040000, 0x80ff0000,             /* mov r0.z, r0.w         */
+    };
+    static const DWORD nrm_t1[] =
+    {
+        0x0200001f, 0x80010005, 0x900f0000,             /* dcl_texcoord1 v0.xyzw  */
+        0x02000024, 0x800f0000, 0x90e40000,             /* nrm r0, v0             */
+    };
+    static const DWORD nrm_vs_t1[] =
+    {
+        0x0200001f, 0x80020005, 0x900f0000,             /* dcl_texcoord2 v0.xyzw  */
+        0x02000001, 0x800f0000, 0x90e40000,             /* mov r0, v0             */
+    };
+    static const DWORD nrm_t1_xyz[] =
+    {
+        0x0200001f, 0x80010005, 0x900f0000,             /* dcl_texcoord1 v0.xyzw  */
+        0x02000001, 0x800f0000, 0xa0e40000,             /* mov r0, c0             */
+        0x02000024, 0x80070000, 0x90e40000,             /* nrm r0.xyz, t1         */
+        0x02000001, 0x80040000, 0x80ff0000,             /* mov r0.z, r0.w         */
+    };
+    static const DWORD nrm_t1_xy[] =
+    {
+        0x0200001f, 0x80010005, 0x900f0000,             /* dcl_texcoord1 v0.xyzw  */
+        0x02000001, 0x800f0000, 0xa0e40000,             /* mov r0, c0             */
+        0x02000024, 0x800f0000, 0x90540000,             /* nrm r0, v0.xy          */
+    };
+    static const DWORD nrm_xyz_t1_yw[] =
+    {
+        0x0200001f, 0x80010005, 0x900f0000,             /* dcl_texcoord1 v0.xyzw  */
+        0x02000001, 0x800f0000, 0xa0e40000,             /* mov r0, c0             */
+        0x02000024, 0x80070000, 0x90fd0000,             /* nrm r0.xyz, v0.yw      */
+    };
+    static const DWORD nrm_t1_dcl_xy[] =
+    {
+        0x0200001f, 0x80010005, 0x90030000,             /* dcl_texcoord1 v0.xy    */
+        0x02000001, 0x800f0000, 0xa0e40000,             /* mov r0, c0             */
+        0x02000024, 0x800f0000, 0x90540000,             /* nrm r0, v0             */
+    };
+    static const DWORD nrm_c0[] =
+    {
+        0x05000051, 0xa00f0001, 0x7f800000, 0xff800000, 0x3e99999a, 0x3ecccccd,
+                /* def c1, Inf, -Inf, 0.3, 0.4 */
+        0x02000024, 0x800f0000, 0xa0e40000,             /* nrm r0, c0             */
+        0x02000001, 0x80040000, 0x80ff0000,             /* mov r0.z, r0.w         */
+        0x02030029, 0x80aa0000, 0xa0000001,             /* if_ge r0.z, c1.x       */
+        0x02000001, 0x80040000, 0xa0aa0001,             /* mov r0.z, c1.z         */
+        0x0000002a,                                     /* else                   */
+        0x02060029, 0x80aa0000, 0xa0550001,             /* if_le r0.z, c1.y       */
+        0x02000001, 0x80040000, 0xa0ff0001,             /* mov r0.z, c1.w         */
+        0x0000002b,                                     /* endif                  */
+        0x0000002b,                                     /* endif                  */
+    };
+    static const DWORD nrm_c0_swizzle[] =
+    {
+        0x02000024, 0x800f0000, 0xa0390000,             /* nrm r0, c0.yzwx        */
+    };
+
+    static const struct
+    {
+        const char *name;
+        const DWORD *ops;
+        DWORD body_size;
+        struct vec4 c0;
+        D3DCOLOR expected_colour;
+        BOOL todo;
+        BOOL warp_broken;
+        D3DCOLOR expected_warp_broken_colour;
+    }
+    tests[] =
+    {
+        {"nrm_t0", nrm_t0, ARRAY_SIZE(nrm_t0), {0.0f}, 0x00b4b400},
+        {"nrm_xyz_t0", nrm_xyz_t0, ARRAY_SIZE(nrm_xyz_t0), {0.1f, 0.1f, 0.1f, 0.1f}, 0x00b4b419},
+        {"nrm_t1", nrm_t1, ARRAY_SIZE(nrm_t1), {0.0f}, 0x0000f449},
+        {"nrm_vs_t1", nrm_vs_t1, ARRAY_SIZE(nrm_vs_t1), {0.0f}, 0x0000f449},
+        {"nrm_t1_xyz", nrm_t1_xyz, ARRAY_SIZE(nrm_t1_xyz), {0.1f, 0.1f, 0.1f, 0.1f}, 0x0000f419},
+        {"nrm_t1_xy", nrm_t1_xy, ARRAY_SIZE(nrm_t1_xy), {0.1f, 0.1f, 0.1f, 0.1f}, 0x0000b4b4},
+        {"nrm_xyz_t1_yw", nrm_xyz_t1_yw, ARRAY_SIZE(nrm_xyz_t1_yw), {0.1f, 0.1f, 0.1f, 0.1f}, 0x00d06868},
+        {"nrm_t1_dcl_xy", nrm_t1_dcl_xy, ARRAY_SIZE(nrm_t1_dcl_xy), {0.1f, 0.1f, 0.1f, 0.1f}, 0x0000b4b4},
+        {"nrm_vec4(0.0, 0.0, 0.0, 0.5)", nrm_c0, ARRAY_SIZE(nrm_c0), {0.0f, 0.0f, 0.0f, 0.5f}, 0x0000004c,
+                TRUE, TRUE, 0x000000ff},
+        {"nrm_vec4(0.0, 0.0, 0.0, -0.5)", nrm_c0, ARRAY_SIZE(nrm_c0), {0.0f, 0.0f, 0.0f, -0.5f}, 0x00000066,
+                TRUE, TRUE, 0x00000000},
+        {"nrm_vec4(0.0, 0.0, 0.0, 0.0)", nrm_c0, ARRAY_SIZE(nrm_c0), {0.0f, 0.0f, 0.0f, 0.0f}, 0x00000000},
+        {"nrm_vec4(2.0, 0.0, 0.0, 0.5)", nrm_c0, ARRAY_SIZE(nrm_c0), {2.0f, 0.0f, 0.0f, 0.5f}, 0x00ff0040},
+        {"nrm_vec4(1.0)", nrm_c0, ARRAY_SIZE(nrm_c0), {1.0f, 1.0f, 1.0f, 1.0f}, 0x00939393},
+        {"nrm_vec4(1e36, 1e36, 1e36, 1e36)", nrm_c0, ARRAY_SIZE(nrm_c0),
+                {1e36f, 1e36f, 1e36f, 1e36f}, 0x00000000}, /* norm calculation is not overflow safe */
+        {"nrm_c0_swizzle", nrm_c0_swizzle, ARRAY_SIZE(nrm_c0_swizzle), {1.0f, 1.0f, 0.0f, 2.0f}, 0x007200e4},
+    };
+
+    window = create_window();
+    ok(!!window, "Failed to create a window.\n");
+
+    d3d = Direct3DCreate9(D3D_SDK_VERSION);
+    ok(!!d3d, "Failed to create a D3D object.\n");
+    if (!(device = create_device(d3d, window, window, TRUE)))
+    {
+        skip("Failed to create a D3D device, skipping tests.\n");
+        IDirect3D9_Release(d3d);
+        DestroyWindow(window);
+        return;
+    }
+
+    hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+    if (caps.PixelShaderVersion < D3DPS_VERSION(3, 0) || caps.VertexShaderVersion < D3DVS_VERSION(3, 0))
+    {
+        skip("No shader model 3 support, skipping tests.\n");
+        IDirect3DDevice9_Release(device);
+        IDirect3D9_Release(d3d);
+        DestroyWindow(window);
+        return;
+    }
+
+    hr = IDirect3D9_GetAdapterIdentifier(d3d, D3DADAPTER_DEFAULT, 0, &identifier);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+    is_warp = adapter_is_warp(&identifier);
+
+    body_size = 0;
+    for (i = 0; i < ARRAY_SIZE(tests); ++i)
+        body_size = max(body_size, tests[i].body_size);
+
+    ps_code = heap_alloc(sizeof(ps_header) + body_size * sizeof(*ps_code) + sizeof(ps_footer));
+    memcpy(ps_code, ps_header, sizeof(ps_header));
+
+    hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, FALSE);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+    hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_NONE);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+    hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+    hr = IDirect3DDevice9_CreateVertexShader(device, vs_code, &vertex_shader);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+    hr = IDirect3DDevice9_SetVertexShader(device, vertex_shader);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+    hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+    for (i = 0; i < ARRAY_SIZE(tests); ++i)
+    {
+        memcpy(ps_code + ARRAY_SIZE(ps_header), tests[i].ops, sizeof(*ps_code) * tests[i].body_size);
+        memcpy(ps_code + ARRAY_SIZE(ps_header) + tests[i].body_size, ps_footer, sizeof(ps_footer));
+
+        hr = IDirect3DDevice9_CreatePixelShader(device, ps_code, &pixel_shader);
+        ok(hr == D3D_OK, "Got unexpected hr %#x, test %s.\n", hr, tests[i].name);
+        hr = IDirect3DDevice9_BeginScene(device);
+        ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+        hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80808080, 0.0f, 0);
+        ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+        hr = IDirect3DDevice9_SetPixelShader(device, pixel_shader);
+        ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+        hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, &tests[i].c0.x, 1);
+        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);
+
+        colour = getPixelColor(device, 320, 240);
+        todo_wine_if(tests[i].todo)
+        ok(color_match(colour, tests[i].expected_colour, 1) || broken(is_warp && tests[i].warp_broken
+                && color_match(colour, tests[i].expected_warp_broken_colour, 1)),
+                "test %s, expected 0x%08x, got 0x%08x.\n",
+                tests[i].name, tests[i].expected_colour, colour);
+
+        IDirect3DPixelShader9_Release(pixel_shader);
+    }
+    hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+    heap_free(ps_code);
+    IDirect3DVertexShader9_Release(vertex_shader);
+    IDirect3DVertexDeclaration9_Release(vertex_declaration);
+    refcount = IDirect3DDevice9_Release(device);
+    ok(!refcount, "Device has %u references left.\n", refcount);
+    IDirect3D9_Release(d3d);
+    DestroyWindow(window);
+}
+
 START_TEST(visual)
 {
     D3DADAPTER_IDENTIFIER9 identifier;
@@ -26124,4 +26378,5 @@ START_TEST(visual)
     test_map_synchronisation();
     test_color_vertex();
     test_sysmem_draw();
+    test_nrm_instruction();
 }
-- 
2.21.0




More information about the wine-devel mailing list