[PATCH v2 1/3] d3dcompiler/tests: Rewrite to use a separate d3d9 device for each test.

Matteo Bruni matteo.mystral at gmail.com
Tue Feb 25 11:30:19 CST 2020


On Tue, Feb 18, 2020 at 9:32 PM Zebediah Figura <z.figura12 at gmail.com> wrote:
>
> This brings the d3dcompiler tests more in line with existing d3d9 tests, and
> allows potentially running the tests in parallel.
>
> Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
> ---
>  dlls/d3dcompiler_43/tests/hlsl.c | 801 +++++++++++++++----------------
>  1 file changed, 384 insertions(+), 417 deletions(-)

This gives me some warnings:

In file included from /home/matteo/wine/include/d3d11shader.h:22,
                 from /home/matteo/wine/include/d3dcompiler.h:22,
                 from /home/matteo/wine/dlls/d3dcompiler_43/tests/hlsl.c:22:
/home/matteo/wine/dlls/d3dcompiler_43/tests/hlsl.c: In function ‘func_hlsl’:
../../../include/d3dcommon.h:120:12: warning: ‘ps_code’ may be used
uninitialized in this function [-Wmaybe-uninitialized]
  120 |     return This->lpVtbl->Release(This);
      |            ^~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/matteo/wine/dlls/d3dcompiler_43/tests/hlsl.c:523:17: note:
‘ps_code’ was declared here
  523 |     ID3D10Blob *ps_code;
      |                 ^~~~~~~

and similarly for the other calls to compile_shader(). It looks like
the compiler gets confused by the todo_wine and thinks that the
ps_code assignment might not happen. Initializing ps_code to NULL
works around. For reference, this is 32-bit mingw-w64 based on gcc
9.2.

Otherwise it looks pretty good. A few comments inline:

> -    hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, NULL,
> -            D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
> -    IDirect3D9_Release(d3d9_ptr);
> -    if (FAILED(hr))
> +    if (FAILED(hr = IDirect3DDevice9_CreateRenderTarget(device, 640, 480, D3DFMT_A32B32G32R32F,
> +            D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL)))
>      {
> -        skip("could not create Direct3D9 device\n");
> +        skip("Failed to create an A32B32G32R32F surface, hr %#x.\n", hr);
> +        IDirect3DDevice9_Release(device);
>          return NULL;
>      }
> +    ok(hr == D3D_OK, "Failed to create render target, hr %#x.\n", hr);

I'd just write "Got unexpected hr %#x.\n": technically this shouldn't
fail since if FAILED(CreateRenderTarget()) is handled by the if above,
so this would only catch S_FALSE or something similar.

> +    hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
> +    ok(hr == D3D_OK, "Failed to set render target, hr %#x.\n", hr);
> +    IDirect3DSurface9_Release(rt);
>
> -    /* Create the quad geometry */
> -    hr = IDirect3DDevice9_CreateVertexBuffer(device_ptr, 4 * sizeof(struct vertex),
> -            D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, quad_geometry, NULL);
> -    ok(SUCCEEDED(hr),
> -            "Could not create vertex buffer, IDirect3DDevice9_CreateVertexBuffer returned: %08x\n", hr);
> -
> -    hr = IDirect3DVertexBuffer9_Lock(*quad_geometry, 0, sizeof(quad_vertices), &temp_geometry_vertices, 0);
> -    ok(SUCCEEDED(hr), "IDirect3DVertexBuffer9_Lock returned: %08x\n", hr);
> -    memcpy(temp_geometry_vertices, quad_vertices, sizeof(quad_vertices));
> -    IDirect3DVertexBuffer9_Unlock(*quad_geometry);
> +    return device;
> +}
>
> -    hr = IDirect3DDevice9_CreateVertexDeclaration(device_ptr, vdeclelements, vdeclaration);
> -    ok(SUCCEEDED(hr), "Could not create vertex declaration: "
> -            "IDirect3DDevice9_CreateVertexDeclaration returned: %08x\n", hr);
> +#define draw_quad(device, ps_code) draw_quad_(__LINE__, device, ps_code)
> +static void draw_quad_(unsigned int line, IDirect3DDevice9 *device, ID3D10Blob *ps_code)

If we're not splitting d3d10+ tests to a separate file, this could use
a d3d9 specifier. Otherwise, I guess all the specifiers in the *other*
functions could go away.

> +{
> +    IDirect3DVertexDeclaration9 *vertex_declaration;
> +    IDirect3DVertexShader9 *vs;
> +    IDirect3DPixelShader9 *ps;
> +    ID3D10Blob *vs_code;
> +    HRESULT hr;
>
> -    hr = IDirect3DDevice9_SetVertexDeclaration(device_ptr, *vdeclaration);
> -    ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned: %08x\n", hr);
> +    static const D3DVERTEXELEMENT9 decl_elements[] =
> +    {
> +        {0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
> +        {0, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
> +        D3DDECL_END()
> +    };
>
> -    /* Create a simple vertex shader to just pass through the values */
> -    hr = ppD3DCompile(vshader_passthru_hlsl, strlen(vshader_passthru_hlsl), NULL,
> -            NULL, NULL, "vshader", "vs_1_1", 0, 0, &compiled, &errors);
> -    if (FAILED(hr))
> +    static const struct
>      {
> -        skip("not compiling vertex shader due to lacking wine HLSL support!\n");
> -        if (errors)
> -            ID3D10Blob_Release(errors);
> -        return NULL;
> +        struct vec2 position;
> +        struct vec2 t0;
>      }
> +    quad[] =
> +    {
> +        {{-1.0f, -1.0f}, {0.0f, 1.0f}},
> +        {{-1.0f,  1.0f}, {0.0f, 0.0f}},
> +        {{ 1.0f, -1.0f}, {1.0f, 1.0f}},
> +        {{ 1.0f,  1.0f}, {1.0f, 0.0f}},
> +    };
>
> -    hr = IDirect3DDevice9_CreateVertexShader(device_ptr, ID3D10Blob_GetBufferPointer(compiled),
> -            vshader_passthru);
> -    ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexShader returned: %08x\n", hr);
> -    ID3D10Blob_Release(compiled);
> +    static const char vs_source[] =
> +        "float4 main(float4 pos : POSITION, inout float2 texcoord : TEXCOORD0) : POSITION\n"
> +        "{\n"
> +        "   return pos;\n"
> +        "}";
>
> -    return device_ptr;
> -}
> +    hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
> +    ok_(__FILE__, line)(hr == D3D_OK, "Failed to create vertex declaration, hr %#x.\n", hr);
>
> -/* Convenience functions */
> -static void set_float4_d3d9(IDirect3DDevice9 *device, ID3DXConstantTable *constants, const char *name,
> -        float x, float y, float z, float w)
> -{
> -    D3DXVECTOR4 vector;
> -    vector.x = x;
> -    vector.y = y;
> -    vector.z = z;
> -    vector.w = w;
> -    ID3DXConstantTable_SetVector(constants, device, name, &vector);
> -}
> +    hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
> +    ok_(__FILE__, line)(hr == D3D_OK, "Failed to set vertex declaration, hr %#x.\n", hr);
>
> -/* Compile our pixel shader and get back the compiled version and a constant table */
> -static IDirect3DPixelShader9 *compile_pixel_shader9(IDirect3DDevice9 *device, const char *shader,
> -        const char *profile, ID3DXConstantTable **constants)
> -{
> -    ID3D10Blob *compiled = NULL;
> -    ID3D10Blob *errors = NULL;
> -    IDirect3DPixelShader9 *pshader;
> -    HRESULT hr;
> +    vs_code = compile_shader(vs_source, "vs_2_0");
> +
> +    hr = IDirect3DDevice9_CreateVertexShader(device, ID3D10Blob_GetBufferPointer(vs_code), &vs);
> +    ok_(__FILE__, line)(hr == D3D_OK, "Failed to create vertex shader, hr %#x.\n", hr);
> +
> +    hr = IDirect3DDevice9_SetVertexShader(device, vs);
> +    ok_(__FILE__, line)(hr == D3D_OK, "Failed to set vertex shader, hr %#x.\n", hr);
> +
> +    hr = IDirect3DDevice9_CreatePixelShader(device, ID3D10Blob_GetBufferPointer(ps_code), &ps);
> +    ok_(__FILE__, line)(hr == D3D_OK, "Failed to create pixel shader, hr %#x.\n", hr);
> +
> +    hr = IDirect3DDevice9_SetPixelShader(device, ps);
> +    ok_(__FILE__, line)(hr == D3D_OK, "Failed to set pixel shader, hr %#x.\n", hr);
> +
> +    hr = IDirect3DDevice9_BeginScene(device);
> +    ok_(__FILE__, line)(hr == D3D_OK, "Failed to draw, hr %#x.\n", hr);
>
> -    hr = ppD3DCompile(shader, strlen(shader), NULL, NULL,
> -            NULL, "test", profile, /* test is the name of the entry point of our shader */
> -            0, 0, &compiled, &errors);
> -    ok(hr == D3D_OK, "Pixel shader %s compilation failed: %s\n", shader,
> -            errors ? (char *)ID3D10Blob_GetBufferPointer(errors) : "");
> -    if (FAILED(hr)) return NULL;
> +    hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
> +    ok_(__FILE__, line)(hr == D3D_OK, "Failed to draw, hr %#x.\n", hr);
>
> -    hr = pD3DXGetShaderConstantTable(ID3D10Blob_GetBufferPointer(compiled), constants);
> -    ok(hr == D3D_OK, "Could not get constant table from compiled pixel shader\n");
> +    hr = IDirect3DDevice9_EndScene(device);
> +    ok_(__FILE__, line)(hr == D3D_OK, "Failed to draw, hr %#x.\n", hr);
>
> -    hr = IDirect3DDevice9_CreatePixelShader(device, ID3D10Blob_GetBufferPointer(compiled), &pshader);
> -    ok(SUCCEEDED(hr), "IDirect3DDevice9_CreatePixelShader returned: %08x\n", hr);
> -    ID3D10Blob_Release(compiled);
> -    return pshader;
> +    IDirect3DVertexShader9_Release(vs);
> +    IDirect3DPixelShader9_Release(ps);
> +    ID3D10Blob_Release(vs_code);

Missing release of the vertex declaration.

>  }
>
> -/* Draw a full screen quad */
> -static void draw_quad_with_shader9(IDirect3DDevice9 *device, IDirect3DVertexBuffer9 *quad_geometry)
> +static struct vec4 get_readback_vec4_d3d9(IDirect3DDevice9 *device, unsigned int x, unsigned int y)
>  {
> +    IDirect3DSurface9 *surface = NULL, *target = NULL;
> +    RECT rect = {x, y, x + 1, y + 1};
> +    D3DLOCKED_RECT locked_rect;
> +    D3DSURFACE_DESC desc;
> +    struct vec4 ret;
>      HRESULT hr;
> -    D3DXMATRIX projection_matrix;
>
> -    pD3DXMatrixOrthoLH(&projection_matrix, 2.0f, 2.0f, 0.0f, 1.0f);
> -    IDirect3DDevice9_SetTransform(device, D3DTS_PROJECTION, &projection_matrix);
> +    hr = IDirect3DDevice9Ex_GetRenderTarget(device, 0, &target);
> +    ok(hr == D3D_OK, "Failed to get render target, hr %#x.\n", hr);
>
> -    hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
> -    ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned: %08x\n", hr);
> +    hr = IDirect3DSurface9_GetDesc(target, &desc);
> +    ok(hr == D3D_OK, "Failed to get surface desc, hr %#x.\n", hr);
> +    hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurface(device, desc.Width, desc.Height,
> +            desc.Format, D3DPOOL_SYSTEMMEM, &surface, NULL);
> +    ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
>
> -    hr = IDirect3DDevice9_BeginScene(device);
> -    ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned: %08x\n", hr);
> +    hr = IDirect3DDevice9Ex_GetRenderTargetData(device, target, surface);
> +    ok(hr == D3D_OK, "Failed to get render target data, hr %#x.\n", hr);
>
> -    hr = IDirect3DDevice9_SetStreamSource(device, 0, quad_geometry, 0, sizeof(struct vertex));
> -    ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource returned: %08x\n", hr);
> -    hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
> -    ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive returned: %08x\n", hr);
> +    hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, D3DLOCK_READONLY);
> +    ok(hr == D3D_OK, "Failed to lock surface, hr %#x.\n", hr);
>
> -    hr = IDirect3DDevice9_EndScene(device);
> -    ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned: %08x\n", hr);
> +    ret = ((struct vec4 *)locked_rect.pBits)[0];
> +
> +    IDirect3DSurface9_UnlockRect(surface);
> +
> +    IDirect3DSurface9_Release(target);
> +    IDirect3DSurface9_Release(surface);
> +    return ret;
>  }

This isn't quite the get_readback_*() thing from the d3d tests: it
both maps / unmaps the texture and returns the value, so it's more
akin to a get_color(). The function is probably okay for now (it can
be reimplemented on top of an actual get_readback_*() and such if need
be) but I find the current naming a bit confusing.

>
> -static void setup_device9(IDirect3DDevice9 *device, IDirect3DSurface9 **render_target,
> -        IDirect3DSurface9 **readback, D3DFORMAT format, unsigned int width, unsigned int height,
> -        IDirect3DVertexShader9 *vshader, IDirect3DPixelShader9 *pshader)
> +#define set_float_d3d9(a, b, c, d) set_float_d3d9_(__LINE__, a, b, c, d)
> +static void set_float_d3d9_(unsigned int line, IDirect3DDevice9 *device, ID3D10Blob *blob, const char *name, float f)
>  {
> +    ID3DXConstantTable *constants;
>      HRESULT hr;
> -    hr = IDirect3DDevice9_CreateRenderTarget(device, width, height, format,
> -            D3DMULTISAMPLE_NONE, 0, FALSE, render_target, NULL);
> -    ok(hr == D3D_OK, "IDirect3DDevice9_CreateRenderTarget returned: %08x\n", hr);
> -
> -    /* The Direct3D 9 docs state that we cannot lock a render target surface,
> -       instead we must copy the render target onto this surface to lock it */
> -    hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, width, height, format,
> -            D3DPOOL_SYSTEMMEM, readback, NULL);
> -    ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned: %08x\n", hr);
> -
> -    hr = IDirect3DDevice9_SetRenderTarget(device, 0, *render_target);
> -    ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget returned: %08x\n", hr);
> -
> -    hr = IDirect3DDevice9_SetVertexShader(device, vshader);
> -    ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned: %08x\n", hr);
> -    hr = IDirect3DDevice9_SetPixelShader(device, pshader);
> -    ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned: %08x\n", hr);
> +
> +    hr = pD3DXGetShaderConstantTable(ID3D10Blob_GetBufferPointer(blob), &constants);
> +    ok_(__FILE__, line)(hr == D3D_OK, "Failed to get constant table, hr %#x.\n", hr);
> +
> +    hr = ID3DXConstantTable_SetFloat(constants, device, name, f);
> +    ok_(__FILE__, line)(hr == D3D_OK, "Failed to set constant, hr %#x.\n", hr);
> +
> +    ID3DXConstantTable_Release(constants);
>  }
>
> -static BOOL colors_match(D3DXCOLOR a, D3DXCOLOR b, float epsilon)
> +#define set_float4_d3d9(a, b, c, d, e, f, g) set_float4_d3d9_(__LINE__, a, b, c, d, e, f, g)
> +static void set_float4_d3d9_(unsigned int line, IDirect3DDevice9 *device, ID3D10Blob *blob,
> +        const char *name, float x, float y, float z, float w)
>  {
> -  return (fabs(a.r - b.r) < epsilon && fabs(a.g - b.g) < epsilon && fabs(a.b - b.b) < epsilon &&
> -          fabs(a.a - b.a) < epsilon);
> +    ID3DXConstantTable *constants;
> +    D3DXVECTOR4 v = {x, y, z, w};
> +    HRESULT hr;
> +
> +    hr = pD3DXGetShaderConstantTable(ID3D10Blob_GetBufferPointer(blob), &constants);
> +    ok_(__FILE__, line)(hr == D3D_OK, "Failed to get constant table, hr %#x.\n", hr);
> +
> +    hr = ID3DXConstantTable_SetVector(constants, device, name, &v);
> +    ok_(__FILE__, line)(hr == D3D_OK, "Failed to set constant, hr %#x.\n", hr);
> +
> +    ID3DXConstantTable_Release(constants);
>  }

It's a bit ugly and inefficient to redundantly create and destroy
ID3DXConstantTable objects for shaders with multiple constants that
need to be set, like in test_math(). I guess another option would be
to not use these helpers in those cases, but that would somewhat
defeat their purpose.
Maybe give this the "readback" treatment and introduce a helper that
only does the constant setting and reimplement this in terms of the
new one. Then for tests setting a single constant you would call this
and for the multiple constants case you would call the slimmer, new
helper (and probably manually create and destroy the constant table in
the test).

> +static HWND create_window(void)
> +{
> +    WNDCLASSA wc = {0};
> +    wc.lpfnWndProc = DefWindowProcA;
> +    wc.lpszClassName = "d3d9_test_wc";
> +    RegisterClassA(&wc);
>
> -    IDirect3DSurface9_Release(render_target);
> -    IDirect3DSurface9_Release(readback);
> +    return CreateWindowA("d3d9_test_wc", "d3d9_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
>  }

Nitpick, class and window names could mention d3dcompiler (and maybe d3d9).

> -static void test_conditionals(IDirect3DDevice9 *device, IDirect3DVertexBuffer9 *quad_geometry,
> -        IDirect3DVertexShader9 *vshader_passthru)
> +static void test_conditionals(void)
>  {
> -    static const struct hlsl_probe_info if_greater_probes[] =
> -    {
> -        { 0, 0, {0.9f, 0.8f, 0.7f, 0.6f}, 0.0001f, "if greater test"},
> -        { 5, 0, {0.9f, 0.8f, 0.7f, 0.6f}, 0.0001f, "if greater test"},
> -        {10, 0, {0.9f, 0.8f, 0.7f, 0.6f}, 0.0001f, "if greater test"},
> -        {15, 0, {0.9f, 0.8f, 0.7f, 0.6f}, 0.0001f, "if greater test"},
> -        {25, 0, {0.1f, 0.2f, 0.3f, 0.4f}, 0.0001f, "if greater test"},
> -        {30, 0, {0.1f, 0.2f, 0.3f, 0.4f}, 0.0001f, "if greater test"}
> -    };
> +    IDirect3DDevice9 *device;
> +    ID3D10Blob *ps_code;
> +    unsigned int i;
> +    struct vec4 v;
> +    HWND window;
>
> -    static const char *if_greater_shader =
> -        "float4 test(float2 pos: TEXCOORD0): COLOR\n"
> +    static const char ps_if_source[] =
> +        "float4 main(float2 pos : TEXCOORD0) : COLOR\n"
>          "{\n"
> -        "    if((pos.x * 32.0) > 20.0)\n"
> +        "    if((pos.x * 640.0) > 200.0)\n"
>          "        return float4(0.1, 0.2, 0.3, 0.4);\n"
>          "    else\n"
>          "        return float4(0.9, 0.8, 0.7, 0.6);\n"
>          "}";
>
> -    static const struct hlsl_probe_info ternary_operator_probes[] =
> -    {
> -        {0, 0, {0.50f, 0.25f, 0.50f, 0.75f}, 0.00001f, "ternary operator test"},
> -        {1, 0, {0.50f, 0.25f, 0.50f, 0.75f}, 0.00001f, "ternary operator test"},
> -        {2, 0, {0.50f, 0.25f, 0.50f, 0.75f}, 0.00001f, "ternary operator test"},
> -        {3, 0, {0.50f, 0.25f, 0.50f, 0.75f}, 0.00001f, "ternary operator test"},
> -        {4, 0, {0.60f, 0.80f, 0.10f, 0.20f}, 0.00001f, "ternary operator test"},
> -        {5, 0, {0.60f, 0.80f, 0.10f, 0.20f}, 0.00001f, "ternary operator test"},
> -        {6, 0, {0.60f, 0.80f, 0.10f, 0.20f}, 0.00001f, "ternary operator test"},
> -        {7, 0, {0.60f, 0.80f, 0.10f, 0.20f}, 0.00001f, "ternary operator test"}
> -    };
> -
> -    static const char *ternary_operator_shader =
> -        "float4 test(float2 pos: TEXCOORD0): COLOR\n"
> +    static const char ps_ternary_source[] =
> +        "float4 main(float2 pos : TEXCOORD0) : COLOR\n"
>          "{\n"
>          "    return (pos.x < 0.5?float4(0.5, 0.25, 0.5, 0.75):float4(0.6, 0.8, 0.1, 0.2));\n"
>          "}";

I guess you could add a few whitespaces in there while at it.

>
> -    ID3DXConstantTable *constants;
> -    IDirect3DPixelShader9 *pshader;
> +    window = create_window();
> +    ok(!!window, "Failed to create a window.\n");
> +
> +    if (!(device = create_d3d9_device(window)))
> +    {
> +        DestroyWindow(window);
> +        return;
> +    }
>
> -    pshader = compile_pixel_shader9(device, if_greater_shader, "ps_2_0", &constants);
> -    if (pshader != NULL)
> +    todo_wine ps_code = compile_shader(ps_if_source, "ps_2_0");
> +    if (ps_code)
>      {
> -        compute_shader_probe9(device, vshader_passthru, pshader, quad_geometry, if_greater_probes,
> -                ARRAY_SIZE(if_greater_probes), 32, 1, __LINE__);
> +        draw_quad(device, ps_code);
>
> -        ID3DXConstantTable_Release(constants);
> -        IDirect3DPixelShader9_Release(pshader);
> +        for (i = 0; i < 200; i += 40)
> +        {
> +            v = get_readback_vec4_d3d9(device, i, 0);
> +            ok(compare_vec4(&v, 0.9f, 0.8f, 0.7f, 0.6f, 0),
> +                    "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v.x, v.y, v.z, v.w);
> +        }
> +
> +        for (i = 240; i < 640; i += 40)
> +        {
> +            v = get_readback_vec4_d3d9(device, i, 0);
> +            ok(compare_vec4(&v, 0.1f, 0.2f, 0.3f, 0.4f, 0),
> +                    "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v.x, v.y, v.z, v.w);
> +        }
> +
> +        ID3D10Blob_Release(ps_code);
>      }
>
> -    pshader = compile_pixel_shader9(device, ternary_operator_shader, "ps_2_0", &constants);
> -    if (pshader != NULL)
> +    todo_wine ps_code = compile_shader(ps_ternary_source, "ps_2_0");
> +    if (ps_code)
>      {
> -        compute_shader_probe9(device, vshader_passthru, pshader, quad_geometry, ternary_operator_probes,
> -                ARRAY_SIZE(ternary_operator_probes), 8, 1, __LINE__);
> +        draw_quad(device, ps_code);
>
> -        ID3DXConstantTable_Release(constants);
> -        IDirect3DPixelShader9_Release(pshader);
> +        for (i = 0; i < 320; i += 40)
> +        {
> +            v = get_readback_vec4_d3d9(device, i, 0);
> +            ok(compare_vec4(&v, 0.5f, 0.25f, 0.5f, 0.75f, 0),
> +                    "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v.x, v.y, v.z, v.w);
> +        }
> +
> +        for (i = 360; i < 640; i += 40)
> +        {
> +            v = get_readback_vec4_d3d9(device, i, 0);
> +            ok(compare_vec4(&v, 0.6f, 0.8f, 0.1f, 0.2f, 0),
> +                    "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v.x, v.y, v.z, v.w);
> +        }

This test is a case where it would be nice to have actual
get_readback_*() functions and only map + unmap the texture once.

> +
> +        ID3D10Blob_Release(ps_code);
>      }
> +
> +    IDirect3DDevice9_Release(device);
> +    DestroyWindow(window);
>  }
>
> -static void test_float_vectors(IDirect3DDevice9 *device, IDirect3DVertexBuffer9 *quad_geometry,
> -        IDirect3DVertexShader9 *vshader_passthru)
> +static void test_float_vectors(void)
>  {
> -    static const struct hlsl_probe_info vec4_indexing_test1_probes[] =
> -    {
> -        {0, 0, {0.020f, 0.245f, 0.351f, 1.000f}, 0.0001f, "vec4 indexing test 1"}
> -    };
> +    ID3DXConstantTable *constants;
> +    IDirect3DDevice9 *device;
> +    ID3D10Blob *ps_code;
> +    struct vec4 v;
> +    HWND window;
> +    HRESULT hr;
>
> -    static const char *vec4_indexing_test1_shader =
> -        "float4 test(): COLOR\n"
> +    static const char ps_indexing_source[] =
> +        "float4 main() : COLOR\n"
>          "{\n"
>          "    float4 color;\n"
>          "    color[0] = 0.020;\n"
> @@ -458,15 +464,10 @@ static void test_float_vectors(IDirect3DDevice9 *device, IDirect3DVertexBuffer9
>          "    return color;\n"
>          "}";
>
> -    static const struct hlsl_probe_info vec4_indexing_test2_probes[] =
> -    {
> -        {0, 0, {0.5f, 0.3f, 0.8f, 0.2f}, 0.0001f, "vec4 indexing test 2"}
> -    };
> -
> -    /* We have this uniform i here so the compiler can't optimize */
> -    static const char *vec4_indexing_test2_shader =
> +    /* A uniform index is used so that the compiler can't optimize. */
> +    static const char ps_uniform_indexing_source[] =
>          "uniform int i;\n"
> -        "float4 test(): COLOR\n"
> +        "float4 main() : COLOR\n"
>          "{\n"
>          "    float4 color = float4(0.5, 0.4, 0.3, 0.2);\n"
>          "    color.g = color[i];\n"
> @@ -474,73 +475,58 @@ static void test_float_vectors(IDirect3DDevice9 *device, IDirect3DVertexBuffer9
>          "    return color;\n"
>          "}";
>
> -    ID3DXConstantTable *constants;
> -    IDirect3DPixelShader9 *pshader;
> +    window = create_window();
> +    ok(!!window, "Failed to create a window.\n");
>
> -    pshader = compile_pixel_shader9(device, vec4_indexing_test1_shader, "ps_2_0", &constants);
> -    if (pshader != NULL)
> +    if (!(device = create_d3d9_device(window)))
>      {
> -        compute_shader_probe9(device, vshader_passthru, pshader, quad_geometry, vec4_indexing_test1_probes,
> -                ARRAY_SIZE(vec4_indexing_test1_probes), 1, 1, __LINE__);
> -
> -        ID3DXConstantTable_Release(constants);
> -        IDirect3DPixelShader9_Release(pshader);
> +        DestroyWindow(window);
> +        return;
>      }
>
> -    pshader = compile_pixel_shader9(device, vec4_indexing_test2_shader, "ps_2_0", &constants);
> -    if (pshader != NULL)
> +    todo_wine ps_code = compile_shader(ps_indexing_source, "ps_2_0");
> +    if (ps_code)
>      {
> -        ID3DXConstantTable_SetInt(constants, device, "i", 2);
> +        draw_quad(device, ps_code);
> +
> +        v = get_readback_vec4_d3d9(device, 0, 0);
> +        ok(compare_vec4(&v, 0.02f, 0.245f, 0.351f, 1.0f, 0),
> +                "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v.x, v.y, v.z, v.w);

Something for a separate patch: this test could be extended to check
what happens if 'i' is outside of the valid range. If it turns out to
be undefined behavior, a small comment will suffice.



More information about the wine-devel mailing list