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@codeweavers.com --- dlls/d3dcompiler_43/tests/hlsl.c | 801 +++++++++++++++---------------- 1 file changed, 384 insertions(+), 417 deletions(-)
diff --git a/dlls/d3dcompiler_43/tests/hlsl.c b/dlls/d3dcompiler_43/tests/hlsl.c index 868693838cc..9114ec98e1d 100644 --- a/dlls/d3dcompiler_43/tests/hlsl.c +++ b/dlls/d3dcompiler_43/tests/hlsl.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Travis Athougies + * Copyright (C) 2020 Zebediah Figura * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,290 +26,265 @@ static pD3DCompile ppD3DCompile;
static HRESULT (WINAPI *pD3DXGetShaderConstantTable)(const DWORD *byte_code, ID3DXConstantTable **constant_table); -static D3DMATRIX *(WINAPI *pD3DXMatrixOrthoLH)(D3DXMATRIX *pout, FLOAT w, FLOAT h, FLOAT zn, FLOAT zf);
-struct vertex +struct vec2 { - float x, y, z; - float tx, ty; + float x, y; };
-/* Tells compute_shader_probe* which pixels should be what colors */ -struct hlsl_probe_info +struct vec4 { - unsigned int x, y; - /* The expected values in this region */ - D3DXCOLOR c; - /* The max error for any value */ - float epsilon; - /* An error message to print if this test fails */ - const char *message; + float x, y, z, w; };
-static HWND create_window(void) +#define compile_shader(a, b) compile_shader_(__LINE__, a, b) +static ID3D10Blob *compile_shader_(unsigned int line, const char *source, const char *target) { - WNDCLASSA wc = {0}; - wc.lpfnWndProc = DefWindowProcA; - wc.lpszClassName = "d3d9_test_wc"; - RegisterClassA(&wc); + ID3D10Blob *blob = NULL, *errors = NULL; + HRESULT hr;
- return CreateWindowA("d3d9_test_wc", "d3d9_test", 0, 0, 0, 0, 0, 0, 0, 0, 0); + hr = ppD3DCompile(source, strlen(source), NULL, NULL, NULL, "main", target, 0, 0, &blob, &errors); + ok_(__FILE__, line)(hr == D3D_OK, "Failed to compile shader, hr %#x.\n", hr); + if (errors) + { + if (winetest_debug > 1) + trace_(__FILE__, line)("%s\n", (char *)ID3D10Blob_GetBufferPointer(errors)); + ID3D10Blob_Release(errors); + } + return blob; }
-static IDirect3DDevice9 *init_d3d9(IDirect3DVertexDeclaration9 **vdeclaration, - IDirect3DVertexBuffer9 **quad_geometry, IDirect3DVertexShader9 **vshader_passthru) +static IDirect3DDevice9 *create_d3d9_device(HWND window) { - static const struct vertex quad_vertices[4] = + D3DPRESENT_PARAMETERS present_parameters = { - {-1.0f, -1.0f, 0.0f, 0.0f, 1.0f}, - {-1.0f, 1.0f, 0.0f, 0.0f, 0.0f}, - { 1.0f, -1.0f, 0.0f, 1.0f, 1.0f}, - { 1.0f, 1.0f, 0.0f, 1.0f, 0.0f} + .Windowed = TRUE, + .hDeviceWindow = window, + .SwapEffect = D3DSWAPEFFECT_DISCARD, + .BackBufferWidth = 640, + .BackBufferHeight = 480, + .BackBufferFormat = D3DFMT_A8R8G8B8, }; - - static const D3DVERTEXELEMENT9 vdeclelements[] = - { - {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, - {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, - D3DDECL_END() - }; - - static const char *vshader_passthru_hlsl = - "float4 vshader(float4 pos: POSITION, inout float2 texcoord: TEXCOORD0): POSITION\n" - "{\n" - " return pos;\n" - "}"; - - IDirect3D9 *d3d9_ptr; - IDirect3DDevice9 *device_ptr = NULL; - D3DPRESENT_PARAMETERS present_parameters; - - void *temp_geometry_vertices; - - ID3D10Blob *compiled = NULL; - ID3D10Blob *errors = NULL; - + IDirect3DDevice9 *device; + IDirect3DSurface9 *rt; + IDirect3D9 *d3d; + D3DCAPS9 caps; HRESULT hr;
- d3d9_ptr = Direct3DCreate9(D3D_SDK_VERSION); - if (!d3d9_ptr) + d3d = Direct3DCreate9(D3D_SDK_VERSION); + ok(!!d3d, "Failed to create a D3D object.\n"); + + hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window, + D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device); + IDirect3D9_Release(d3d); + if (FAILED(hr)) { - skip("could not create D3D9\n"); + skip("Failed to create a 3D device, hr %#x.\n", hr); return NULL; }
- hr = IDirect3D9_CheckDeviceFormat(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, - 0, D3DRTYPE_SURFACE, D3DFMT_A32B32G32R32F); - if (FAILED(hr)) + hr = IDirect3DDevice9_GetDeviceCaps(device, &caps); + ok(hr == D3D_OK, "Failed to get device caps, hr %#x.\n", hr); + if (caps.PixelShaderVersion < D3DPS_VERSION(2, 0) || caps.VertexShaderVersion < D3DVS_VERSION(2, 0)) { - skip("A32B32G32R32F format not available on this device\n"); - IDirect3D9_Release(d3d9_ptr); + skip("No shader model 2 support.\n"); + IDirect3DDevice9_Release(device); return NULL; }
- ZeroMemory(&present_parameters, sizeof(present_parameters)); - present_parameters.Windowed = TRUE; - present_parameters.hDeviceWindow = create_window(); - present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD; - - 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); + 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) +{ + 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); }
-/* 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; }
-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); }
-/* Compute a shader on a width by height buffer and probes certain locations - to see if they are as expected. */ -static void compute_shader_probe9(IDirect3DDevice9 *device, IDirect3DVertexShader9 *vshader, - IDirect3DPixelShader9 *pshader, IDirect3DVertexBuffer9 *quad_geometry, - const struct hlsl_probe_info *probes, unsigned int count, - unsigned int width, unsigned int height, unsigned int line_number) +static BOOL compare_float(float f, float g, unsigned int ulps) { - IDirect3DSurface9 *render_target; - IDirect3DSurface9 *readback; + int x = *(int *)&f; + int y = *(int *)&g;
- HRESULT hr; - D3DLOCKED_RECT lr; - D3DXCOLOR *pbits_data; - unsigned int i; + if (x < 0) + x = INT_MIN - x; + if (y < 0) + y = INT_MIN - y;
- setup_device9(device, &render_target, &readback, D3DFMT_A32B32G32R32F, - width, height, vshader, pshader); - - /* Draw the quad with the shader and read back the data */ - draw_quad_with_shader9(device, quad_geometry); - IDirect3DDevice9_GetRenderTargetData(device, render_target, readback); - hr = IDirect3DSurface9_LockRect(readback, &lr, NULL, D3DLOCK_READONLY); - ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned: %08x\n", hr); - pbits_data = lr.pBits; - - /* Now go through the probes and check each one */ - for (i = 0; i < count; i++, probes++) { - int index = probes->x + (probes->y * lr.Pitch / sizeof(D3DXCOLOR)); - ok(colors_match(probes->c, pbits_data[index], probes->epsilon), - "Line %d: At (%d, %d): %s: Expected (%.04f,%.04f,%.04f, %.04f), got " - "(%.04f,%.04f,%.04f,%.04f)\n", line_number, probes->x, probes->y, probes->message, - probes->c.r, probes->c.g, probes->c.b, probes->c.a, pbits_data[index].r, - pbits_data[index].g, pbits_data[index].b, pbits_data[index].a); - } + if (abs(x - y) > ulps) + return FALSE;
- hr = IDirect3DSurface9_UnlockRect(readback); - ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect returned: %08x\n", hr); + return TRUE; +} + +static BOOL compare_vec4(const struct vec4 *vec, float x, float y, float z, float w, unsigned int ulps) +{ + return compare_float(vec->x, x, ulps) + && compare_float(vec->y, y, ulps) + && compare_float(vec->z, z, ulps) + && compare_float(vec->w, w, ulps); +}
- /* We now present the scene. This is mostly for debugging purposes, since GetRenderTargetData - also waits for drawing commands to complete. The reason this call is here and not in a - draw function is because the contents of the render target surface are invalidated after - this call. */ - hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); - ok(hr == D3D_OK, "IDirect3DDevice9_Present returned: %08x\n", hr); +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); }
-/* Now the actual test functions */ -static void test_swizzle(IDirect3DDevice9 *device, IDirect3DVertexBuffer9 *quad_geometry, - IDirect3DVertexShader9 *vshader_passthru) +static void test_swizzle(void) { - static const struct hlsl_probe_info probes[] = - { - {0, 0, {0.0101f, 0.0303f, 0.0202f, 0.0404f}, 0.0001f, "swizzle_test"} - }; + IDirect3DDevice9 *device; + ID3D10Blob *ps_code; + struct vec4 v; + HWND window;
- static const char *swizzle_test_shader = + static const char ps_source[] = "uniform float4 color;\n" - "float4 test(): COLOR\n" + "float4 main() : COLOR\n" "{\n" " float4 ret = color;\n" " ret.gb = ret.ra;\n" @@ -316,36 +292,40 @@ static void test_swizzle(IDirect3DDevice9 *device, IDirect3DVertexBuffer9 *quad_ " return ret;\n" "}";
- ID3DXConstantTable *constants; - IDirect3DPixelShader9 *pshader; + window = create_window(); + ok(!!window, "Failed to create a window.\n");
- pshader = compile_pixel_shader9(device, swizzle_test_shader, "ps_2_0", &constants); - if (pshader != NULL) + if (!(device = create_d3d9_device(window))) { - set_float4_d3d9(device, constants, "color", 0.0303f, 0.0f, 0.0f, 0.0202f); + DestroyWindow(window); + return; + } + + todo_wine ps_code = compile_shader(ps_source, "ps_2_0"); + if (ps_code) + { + set_float4_d3d9(device, ps_code, "color", 0.0303f, 0.0f, 0.0f, 0.0202f); + draw_quad(device, ps_code);
- compute_shader_probe9(device, vshader_passthru, pshader, quad_geometry, - probes, ARRAY_SIZE(probes), 1, 1, __LINE__); + v = get_readback_vec4_d3d9(device, 0, 0); + ok(compare_vec4(&v, 0.0101f, 0.0303f, 0.0202f, 0.0404f, 0), + "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v.x, v.y, v.z, v.w);
- ID3DXConstantTable_Release(constants); - IDirect3DPixelShader9_Release(pshader); + ID3D10Blob_Release(ps_code); } + IDirect3DDevice9_Release(device); + DestroyWindow(window); }
-static void test_math(IDirect3DDevice9 *device, IDirect3DVertexBuffer9 *quad_geometry, - IDirect3DVertexShader9 *vshader_passthru) +static void test_math(void) { - /* Tests order of operations */ - static const float u = 2.5f, v = 0.3f, w = 0.2f, x = 0.7f, y = 0.1f, z = 1.5f; - - static const struct hlsl_probe_info probes[] = - { - {0, 0, {-12.4300f, 9.8333f, 1.6000f, 34.9999f}, 0.0001f, - "order of operations test"} - }; + IDirect3DDevice9 *device; + ID3D10Blob *ps_code; + struct vec4 v; + HWND window;
- static const char *order_of_operations_shader = - "float4 test(uniform float u, uniform float v, uniform float w, uniform float x,\n" + static const char ps_source[] = + "float4 main(uniform float u, uniform float v, uniform float w, uniform float x,\n" " uniform float y, uniform float z): COLOR\n" "{\n" " return float4(x * y - z / w + --u / -v,\n" @@ -354,101 +334,127 @@ static void test_math(IDirect3DDevice9 *device, IDirect3DVertexBuffer9 *quad_geo " x / y / w);\n" "}";
- ID3DXConstantTable *constants; - IDirect3DPixelShader9 *pshader; + window = create_window(); + ok(!!window, "Failed to create a window.\n");
- pshader = compile_pixel_shader9(device, order_of_operations_shader, "ps_2_0", &constants); - if (pshader != NULL) + if (!(device = create_d3d9_device(window))) { - ID3DXConstantTable_SetFloat(constants, device, "$u", u); - ID3DXConstantTable_SetFloat(constants, device, "$v", v); - ID3DXConstantTable_SetFloat(constants, device, "$w", w); - ID3DXConstantTable_SetFloat(constants, device, "$x", x); - ID3DXConstantTable_SetFloat(constants, device, "$y", y); - ID3DXConstantTable_SetFloat(constants, device, "$z", z); - - compute_shader_probe9(device, vshader_passthru, pshader, quad_geometry, - probes, ARRAY_SIZE(probes), 1, 1, __LINE__); + DestroyWindow(window); + return; + }
- ID3DXConstantTable_Release(constants); - IDirect3DPixelShader9_Release(pshader); + todo_wine ps_code = compile_shader(ps_source, "ps_2_0"); + if (ps_code) + { + set_float_d3d9(device, ps_code, "$u", 2.5f); + set_float_d3d9(device, ps_code, "$v", 0.3f); + set_float_d3d9(device, ps_code, "$w", 0.2f); + set_float_d3d9(device, ps_code, "$x", 0.7f); + set_float_d3d9(device, ps_code, "$y", 0.1f); + set_float_d3d9(device, ps_code, "$z", 1.5f); + draw_quad(device, ps_code); + + v = get_readback_vec4_d3d9(device, 0, 0); + ok(compare_vec4(&v, -12.43f, 9.833333f, 1.6f, 35.0f, 1), + "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v.x, v.y, v.z, v.w); + + ID3D10Blob_Release(ps_code); } + IDirect3DDevice9_Release(device); + DestroyWindow(window); }
-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" "}";
- 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); + } + + 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);
- compute_shader_probe9(device, vshader_passthru, pshader, quad_geometry, vec4_indexing_test2_probes, - ARRAY_SIZE(vec4_indexing_test2_probes), 32, 1, __LINE__); + ID3D10Blob_Release(ps_code); + }
+ todo_wine ps_code = compile_shader(ps_uniform_indexing_source, "ps_2_0"); + if (ps_code) + { + hr = pD3DXGetShaderConstantTable(ID3D10Blob_GetBufferPointer(ps_code), &constants); + ok(hr == D3D_OK, "Failed to get constants, hr %#x.\n", hr); + hr = ID3DXConstantTable_SetInt(constants, device, "i", 2); + ok(hr == D3D_OK, "Failed to set constant, hr %#x.\n", hr); ID3DXConstantTable_Release(constants); - IDirect3DPixelShader9_Release(pshader); + draw_quad(device, ps_code); + + v = get_readback_vec4_d3d9(device, 0, 0); + ok(compare_vec4(&v, 0.5f, 0.3f, 0.8f, 0.2f, 0), + "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v.x, v.y, v.z, v.w); + + ID3D10Blob_Release(ps_code); } + + IDirect3DDevice9_Release(device); + DestroyWindow(window); }
-static void test_trig(IDirect3DDevice9 *device, IDirect3DVertexBuffer9 *quad_geometry, - IDirect3DVertexShader9 *vshader_passthru) +static void test_trig(void) { - static const struct hlsl_probe_info sincos_probes[] = - { - {0, 0, {0.5000f, 1.0000f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {1, 0, {0.5975f, 0.9904f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {2, 0, {0.6913f, 0.9620f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {3, 0, {0.7778f, 0.9160f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {4, 0, {0.8536f, 0.8536f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {5, 0, {0.9157f, 0.7778f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {6, 0, {0.9620f, 0.6913f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {7, 0, {0.9904f, 0.5975f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {8, 0, {1.0000f, 0.5000f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {9, 0, {0.9904f, 0.4025f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {10, 0, {0.9619f, 0.3087f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {11, 0, {0.9157f, 0.2222f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {12, 0, {0.8536f, 0.1464f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {13, 0, {0.7778f, 0.0843f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {14, 0, {0.6913f, 0.0381f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {15, 0, {0.5975f, 0.0096f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {16, 0, {0.5000f, 0.0000f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {17, 0, {0.4025f, 0.0096f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {18, 0, {0.3087f, 0.0381f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {19, 0, {0.2222f, 0.0843f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {20, 0, {0.1464f, 0.1464f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {21, 0, {0.0843f, 0.2222f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {22, 0, {0.0381f, 0.3087f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {23, 0, {0.0096f, 0.4025f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {24, 0, {0.0000f, 0.5000f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {25, 0, {0.0096f, 0.5975f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {26, 0, {0.0381f, 0.6913f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {27, 0, {0.0843f, 0.7778f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {28, 0, {0.1464f, 0.8536f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {29, 0, {0.2222f, 0.9157f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {30, 0, {0.3087f, 0.9619f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - {31, 0, {0.4025f, 0.9904f, 0.0f, 0.0f}, 0.001f, "sin/cos test"}, - }; + IDirect3DDevice9 *device; + ID3D10Blob *ps_code; + unsigned int i; + struct vec4 v; + HWND window;
- static const char *sincos_shader = - "float4 test(float x: TEXCOORD0): COLOR\n" + static const char ps_source[] = + "float4 main(float x : TEXCOORD0) : COLOR\n" "{\n" " const float pi2 = 6.2831853;\n" " float calcd_sin = (sin(x * pi2) + 1)/2;\n" @@ -548,22 +534,37 @@ static void test_trig(IDirect3DDevice9 *device, IDirect3DVertexBuffer9 *quad_geo " return float4(calcd_sin, calcd_cos, 0, 0);\n" "}";
- 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, sincos_shader, "ps_2_0", &constants); - if (pshader != NULL) + todo_wine ps_code = compile_shader(ps_source, "ps_2_0"); + if (ps_code) { - compute_shader_probe9(device, vshader_passthru, pshader, quad_geometry, sincos_probes, - ARRAY_SIZE(sincos_probes), 32, 1, __LINE__); + draw_quad(device, ps_code);
- ID3DXConstantTable_Release(constants); - IDirect3DPixelShader9_Release(pshader); + for (i = 0; i < 32; ++i) + { + float expect_x = (sinf(i * 2 * M_PI / 32) + 1.0f) / 2.0f; + float expect_y = (cosf(i * 2 * M_PI / 32) + 1.0f) / 2.0f; + v = get_readback_vec4_d3d9(device, i * 640 / 32, 0); + ok(compare_vec4(&v, expect_x, expect_y, 0.0f, 0.0f, 4096), + "Test %u: Got {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n", + i, v.x, v.y, v.z, v.w, expect_x, expect_y, 0.0f, 0.0f); + } + + ID3D10Blob_Release(ps_code); } + IDirect3DDevice9_Release(device); + DestroyWindow(window); }
-static void test_fail(IDirect3DDevice9 *device, IDirect3DVertexBuffer9 *qquad_geometry, - IDirect3DVertexShader9 *vshader_passthru) +static void test_fail(void) { static const char *tests[] = { @@ -619,10 +620,11 @@ static void test_fail(IDirect3DDevice9 *device, IDirect3DVertexBuffer9 *qquad_ge { compiled = errors = NULL; hr = ppD3DCompile(tests[i], strlen(tests[i]), NULL, NULL, NULL, "test", "ps_2_0", 0, 0, &compiled, &errors); - ok(hr == E_FAIL, "Test %u, got unexpected hr %#x.\n", i, hr); - ok(!!errors, "Test %u, expected non-NULL error blob.\n", i); + todo_wine ok(hr == E_FAIL, "Test %u, got unexpected hr %#x.\n", i, hr); + todo_wine_if (i == 1) ok(!!errors, "Test %u, expected non-NULL error blob.\n", i); ok(!compiled, "Test %u, expected no compiled shader blob.\n", i); - ID3D10Blob_Release(errors); + if (errors) + ID3D10Blob_Release(errors); } }
@@ -642,12 +644,6 @@ static BOOL load_d3dcompiler(void)
START_TEST(hlsl) { - D3DCAPS9 caps; - ULONG refcount; - IDirect3DDevice9 *device; - IDirect3DVertexDeclaration9 *vdeclaration; - IDirect3DVertexBuffer9 *quad_geometry; - IDirect3DVertexShader9 *vshader_passthru; HMODULE mod;
if (!load_d3dcompiler()) @@ -662,40 +658,11 @@ START_TEST(hlsl) return; } pD3DXGetShaderConstantTable = (void *)GetProcAddress(mod, "D3DXGetShaderConstantTable"); - pD3DXMatrixOrthoLH = (void *)GetProcAddress(mod, "D3DXMatrixOrthoLH"); - - device = init_d3d9(&vdeclaration, &quad_geometry, &vshader_passthru); - if (!device) return; - - /* Make sure we support pixel shaders, before trying to compile them! */ - /* Direct3D 9 (Shader model 1-3 tests) */ - IDirect3DDevice9_GetDeviceCaps(device, &caps); - if (caps.PixelShaderVersion >= D3DPS_VERSION(2, 0)) - { - todo_wine - { - test_swizzle(device, quad_geometry, vshader_passthru); - test_math(device, quad_geometry, vshader_passthru); - test_conditionals(device, quad_geometry, vshader_passthru); - test_float_vectors(device, quad_geometry, vshader_passthru); - test_trig(device, quad_geometry, vshader_passthru); - test_fail(device, quad_geometry, vshader_passthru); - } - } else skip("no pixel shader support\n"); - - /* Reference counting sanity checks */ - if (vshader_passthru) - { - refcount = IDirect3DVertexShader9_Release(vshader_passthru); - ok(!refcount, "Pass-through vertex shader has %u references left\n", refcount); - } - - refcount = IDirect3DVertexBuffer9_Release(quad_geometry); - ok(!refcount, "Vertex buffer has %u references left\n", refcount); - - refcount = IDirect3DVertexDeclaration9_Release(vdeclaration); - ok(!refcount, "Vertex declaration has %u references left\n", refcount);
- refcount = IDirect3DDevice9_Release(device); - ok(!refcount, "Device has %u references left\n", refcount); + test_swizzle(); + test_math(); + test_conditionals(); + test_float_vectors(); + test_trig(); + test_fail(); }
In particular, port those for which there is an interesting difference in code generation.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- It might make more sense to put this in a separate file, à la ddraw, since almost no code is shared between d3d9 and d3d11 parts.
dlls/d3dcompiler_43/tests/hlsl.c | 484 ++++++++++++++++++++++++++++++- 1 file changed, 468 insertions(+), 16 deletions(-)
diff --git a/dlls/d3dcompiler_43/tests/hlsl.c b/dlls/d3dcompiler_43/tests/hlsl.c index 9114ec98e1d..5cb64253e88 100644 --- a/dlls/d3dcompiler_43/tests/hlsl.c +++ b/dlls/d3dcompiler_43/tests/hlsl.c @@ -20,6 +20,7 @@ #include "wine/test.h" #include "d3dx9.h" #include "d3dcompiler.h" +#include "d3d11.h"
#include <math.h>
@@ -27,6 +28,10 @@ static pD3DCompile ppD3DCompile;
static HRESULT (WINAPI *pD3DXGetShaderConstantTable)(const DWORD *byte_code, ID3DXConstantTable **constant_table);
+static HRESULT (WINAPI *pD3D11CreateDevice)(IDXGIAdapter *adapter, D3D_DRIVER_TYPE driver_type, HMODULE swrast, UINT flags, + const D3D_FEATURE_LEVEL *feature_levels, UINT levels, UINT sdk_version, ID3D11Device **device_out, + D3D_FEATURE_LEVEL *obtained_feature_level, ID3D11DeviceContext **immediate_context); + struct vec2 { float x, y; @@ -568,63 +573,68 @@ static void test_fail(void) { static const char *tests[] = { - "float4 test(float2 pos: TEXCOORD0) : COLOR\n" + "float4 test() : SV_TARGET\n" "{\n" " return y;\n" "}",
- "float4 test(float2 pos: TEXCOORD0) : COLOR\n" + "float4 test() : SV_TARGET\n" "{\n" " float4 x = float4(0, 0, 0, 0);\n" " x.xzzx = float4(1, 2, 3, 4);\n" " return x;\n" "}",
- "float4 test(float2 pos: TEXCOORD0) : COLOR\n" + "float4 test(float2 pos: TEXCOORD0) : SV_TARGET\n" "{\n" " float4 x = pos;\n" " return x;\n" "}",
- "float4 test(float2 pos, TEXCOORD0) ; COLOR\n" + "float4 test(float2 pos, TEXCOORD0) ; SV_TARGET\n" "{\n" " pos = float4 x;\n" " mul(float4(5, 4, 3, 2), mvp) = x;\n" " return float4;\n" "}",
- "float4 563r(float2 45s: TEXCOORD0) : COLOR\n" + "float4 563r(float2 45s: TEXCOORD0) : SV_TARGET\n" "{\n" " float2 x = 45s;\n" " return float4(x.x, x.y, 0, 0);\n" "}",
- "float4 test(float2 pos: TEXCOORD0) : COLOR\n" + "float4 test() : SV_TARGET\n" "{\n" " struct { int b,c; } x = {0};\n" " return y;\n" "}",
- "float4 test(float2 pos: TEXCOORD0) : COLOR\n" + "float4 test() : SV_TARGET\n" "{\n" " struct {} x = {};\n" " return y;\n" "}", };
+ static const char *targets[] = {"ps_2_0", "ps_3_0", "ps_4_0"}; + ID3D10Blob *compiled, *errors; - unsigned int i; + unsigned int i, j; HRESULT hr;
- for (i = 0; i < ARRAY_SIZE(tests); ++i) + for (j = 0; j < ARRAY_SIZE(targets); ++j) { - compiled = errors = NULL; - hr = ppD3DCompile(tests[i], strlen(tests[i]), NULL, NULL, NULL, "test", "ps_2_0", 0, 0, &compiled, &errors); - todo_wine ok(hr == E_FAIL, "Test %u, got unexpected hr %#x.\n", i, hr); - todo_wine_if (i == 1) ok(!!errors, "Test %u, expected non-NULL error blob.\n", i); - ok(!compiled, "Test %u, expected no compiled shader blob.\n", i); - if (errors) - ID3D10Blob_Release(errors); + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + compiled = errors = NULL; + hr = ppD3DCompile(tests[i], strlen(tests[i]), NULL, NULL, NULL, "test", targets[j], 0, 0, &compiled, &errors); + todo_wine ok(hr == E_FAIL, "Test %u, target %s, got unexpected hr %#x.\n", i, targets[j], hr); + todo_wine_if (i == 1) ok(!!errors, "Test %u, target %s, expected non-NULL error blob.\n", i, targets[j]); + ok(!compiled, "Test %u, target %s, expected no compiled shader blob.\n", i, targets[j]); + if (errors) + ID3D10Blob_Release(errors); + } } }
@@ -642,6 +652,436 @@ static BOOL load_d3dcompiler(void) return TRUE; }
+struct d3d11_test_context +{ + ID3D11Device *device; + HWND window; + IDXGISwapChain *swapchain; + ID3D11Texture2D *rt; + ID3D11RenderTargetView *rtv; + ID3D11DeviceContext *immediate_context; + + ID3D11InputLayout *input_layout; + ID3D11VertexShader *vs; + const DWORD *vs_code; + ID3D11Buffer *vs_cb; + ID3D11Buffer *vb; + + ID3D11PixelShader *ps; + ID3D11Buffer *ps_cb; +}; + +static ID3D11Device *create_device(void) +{ + static const D3D_FEATURE_LEVEL feature_level[] = + { + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, + }; + ID3D11Device *device; + + if (SUCCEEDED(pD3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, + feature_level, ARRAY_SIZE(feature_level), D3D11_SDK_VERSION, &device, NULL, NULL))) + return device; + if (SUCCEEDED(pD3D11CreateDevice(NULL, D3D_DRIVER_TYPE_WARP, NULL, 0, + feature_level, ARRAY_SIZE(feature_level), D3D11_SDK_VERSION, &device, NULL, NULL))) + return device; + if (SUCCEEDED(pD3D11CreateDevice(NULL, D3D_DRIVER_TYPE_REFERENCE, NULL, 0, + feature_level, ARRAY_SIZE(feature_level), D3D11_SDK_VERSION, &device, NULL, NULL))) + return device; + + return NULL; +} + +static IDXGISwapChain *create_swapchain(ID3D11Device *device, HWND window) +{ + DXGI_SWAP_CHAIN_DESC dxgi_desc; + IDXGISwapChain *swapchain; + IDXGIDevice *dxgi_device; + IDXGIAdapter *adapter; + IDXGIFactory *factory; + HRESULT hr; + + hr = ID3D11Device_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device); + ok(SUCCEEDED(hr), "Failed to get DXGI device, hr %#x.\n", hr); + hr = IDXGIDevice_GetAdapter(dxgi_device, &adapter); + ok(SUCCEEDED(hr), "Failed to get adapter, hr %#x.\n", hr); + IDXGIDevice_Release(dxgi_device); + hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory); + ok(SUCCEEDED(hr), "Failed to get factory, hr %#x.\n", hr); + IDXGIAdapter_Release(adapter); + + dxgi_desc.BufferDesc.Width = 640; + dxgi_desc.BufferDesc.Height = 480; + dxgi_desc.BufferDesc.RefreshRate.Numerator = 60; + dxgi_desc.BufferDesc.RefreshRate.Denominator = 1; + dxgi_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + dxgi_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + dxgi_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + dxgi_desc.SampleDesc.Count = 1; + dxgi_desc.SampleDesc.Quality = 0; + dxgi_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + dxgi_desc.BufferCount = 1; + dxgi_desc.OutputWindow = window; + dxgi_desc.Windowed = TRUE; + dxgi_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + dxgi_desc.Flags = 0; + + hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &dxgi_desc, &swapchain); + ok(SUCCEEDED(hr), "Failed to create swapchain, hr %#x.\n", hr); + IDXGIFactory_Release(factory); + + return swapchain; +} + +#define init_d3d11_test_context(a) init_d3d11_test_context_(__LINE__, a) +static BOOL init_d3d11_test_context_(unsigned int line, struct d3d11_test_context *context) +{ + const D3D11_TEXTURE2D_DESC texture_desc = + { + .Width = 640, + .Height = 480, + .MipLevels = 1, + .ArraySize = 1, + .Format = DXGI_FORMAT_R32G32B32A32_FLOAT, + .SampleDesc.Count = 1, + .Usage = D3D11_USAGE_DEFAULT, + .BindFlags = D3D11_BIND_RENDER_TARGET, + }; + unsigned int rt_width, rt_height; + D3D11_VIEWPORT vp; + HRESULT hr; + RECT rect; + + memset(context, 0, sizeof(*context)); + + if (!(context->device = create_device())) + { + skip_(__FILE__, line)("Failed to create device.\n"); + return FALSE; + } + + rt_width = 640; + rt_height = 480; + SetRect(&rect, 0, 0, rt_width, rt_height); + AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE); + context->window = CreateWindowA("static", "d3d11_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 0, 0, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, NULL, NULL); + context->swapchain = create_swapchain(context->device, context->window); + + hr = ID3D11Device_CreateTexture2D(context->device, &texture_desc, NULL, &context->rt); + ok_(__FILE__, line)(hr == S_OK, "Failed to create texture, hr %#x.\n", hr); + + hr = ID3D11Device_CreateRenderTargetView(context->device, (ID3D11Resource *)context->rt, NULL, &context->rtv); + ok_(__FILE__, line)(hr == S_OK, "Failed to create rendertarget view, hr %#x.\n", hr); + + ID3D11Device_GetImmediateContext(context->device, &context->immediate_context); + + ID3D11DeviceContext_OMSetRenderTargets(context->immediate_context, 1, &context->rtv, NULL); + + vp.TopLeftX = 0.0f; + vp.TopLeftY = 0.0f; + vp.Width = rt_width; + vp.Height = rt_height; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + ID3D11DeviceContext_RSSetViewports(context->immediate_context, 1, &vp); + + return TRUE; +} + +#define release_d3d11_test_context(context) release_d3d11_test_context_(__LINE__, context) +static void release_d3d11_test_context_(unsigned int line, struct d3d11_test_context *context) +{ + ULONG ref; + + if (context->input_layout) + ID3D11InputLayout_Release(context->input_layout); + if (context->vs) + ID3D11VertexShader_Release(context->vs); + if (context->vs_cb) + ID3D11Buffer_Release(context->vs_cb); + if (context->vb) + ID3D11Buffer_Release(context->vb); + if (context->ps) + ID3D11PixelShader_Release(context->ps); + if (context->ps_cb) + ID3D11Buffer_Release(context->ps_cb); + + ID3D11DeviceContext_Release(context->immediate_context); + ID3D11RenderTargetView_Release(context->rtv); + ID3D11Texture2D_Release(context->rt); + IDXGISwapChain_Release(context->swapchain); + DestroyWindow(context->window); + + ref = ID3D11Device_Release(context->device); + ok_(__FILE__, line)(!ref, "Device has %u references left.\n", ref); +} + +#define create_buffer(a, b, c, d) create_buffer_(__LINE__, a, b, c, d) +static ID3D11Buffer *create_buffer_(unsigned int line, ID3D11Device *device, + unsigned int bind_flags, unsigned int size, const void *data) +{ + D3D11_SUBRESOURCE_DATA resource_data = {.pSysMem = data}; + D3D11_BUFFER_DESC buffer_desc = + { + .ByteWidth = size, + .Usage = D3D11_USAGE_DEFAULT, + .BindFlags = bind_flags, + }; + ID3D11Buffer *buffer; + HRESULT hr; + + hr = ID3D11Device_CreateBuffer(device, &buffer_desc, data ? &resource_data : NULL, &buffer); + ok_(__FILE__, line)(hr == S_OK, "Failed to create buffer, hr %#x.\n", hr); + return buffer; +} + +#define draw_quad_d3d11(context, ps_code) draw_quad_d3d11_(__LINE__, context, ps_code) +static void draw_quad_d3d11_(unsigned int line, struct d3d11_test_context *context, ID3D10Blob *ps_code) +{ + static const D3D11_INPUT_ELEMENT_DESC default_layout_desc[] = + { + {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, + }; + + static const char vs_source[] = + "float4 main(float4 position : POSITION) : SV_POSITION\n" + "{\n" + " return position;\n" + "}"; + + static const struct vec2 quad[] = + { + {-1.0f, -1.0f}, + {-1.0f, 1.0f}, + { 1.0f, -1.0f}, + { 1.0f, 1.0f}, + }; + + ID3D11Device *device = context->device; + unsigned int stride, offset; + ID3D11PixelShader *ps; + HRESULT hr; + + if (!context->vs) + { + ID3D10Blob *vs_code = compile_shader_(line, vs_source, "vs_4_0"); + + hr = ID3D11Device_CreateInputLayout(device, default_layout_desc, ARRAY_SIZE(default_layout_desc), + ID3D10Blob_GetBufferPointer(vs_code), ID3D10Blob_GetBufferSize(vs_code), &context->input_layout); + ok_(__FILE__, line)(hr == S_OK, "Failed to create input layout, hr %#x.\n", hr); + + hr = ID3D11Device_CreateVertexShader(device, ID3D10Blob_GetBufferPointer(vs_code), + ID3D10Blob_GetBufferSize(vs_code), NULL, &context->vs); + ok_(__FILE__, line)(hr == S_OK, "Failed to create vertex shader, hr %#x.\n", hr); + } + + if (!context->vb) + context->vb = create_buffer_(line, device, D3D11_BIND_VERTEX_BUFFER, sizeof(quad), quad); + + hr = ID3D11Device_CreatePixelShader(device, ID3D10Blob_GetBufferPointer(ps_code), + ID3D10Blob_GetBufferSize(ps_code), NULL, &ps); + ok_(__FILE__, line)(hr == S_OK, "Failed to create pixel shader, hr %#x.\n", hr); + + ID3D11DeviceContext_IASetInputLayout(context->immediate_context, context->input_layout); + ID3D11DeviceContext_IASetPrimitiveTopology(context->immediate_context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + stride = sizeof(*quad); + offset = 0; + ID3D11DeviceContext_IASetVertexBuffers(context->immediate_context, 0, 1, &context->vb, &stride, &offset); + ID3D11DeviceContext_VSSetShader(context->immediate_context, context->vs, NULL, 0); + ID3D11DeviceContext_PSSetShader(context->immediate_context, ps, NULL, 0); + + ID3D11DeviceContext_Draw(context->immediate_context, 4, 0); + + ID3D11PixelShader_Release(ps); +} + +#define get_readback_vec4_d3d11(context, x, y) get_readback_vec4_d3d11_(__LINE__, context, x, y) +static struct vec4 get_readback_vec4_d3d11_(unsigned int line, struct d3d11_test_context *context, + unsigned int x, unsigned int y) +{ + ID3D11Device *device = context->device; + D3D11_MAPPED_SUBRESOURCE map_desc; + D3D11_TEXTURE2D_DESC texture_desc; + ID3D11Resource *rb_texture; + struct vec4 ret; + HRESULT hr; + + ID3D11Texture2D_GetDesc(context->rt, &texture_desc); + texture_desc.Usage = D3D11_USAGE_STAGING; + texture_desc.BindFlags = 0; + texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + texture_desc.MiscFlags = 0; + hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, (ID3D11Texture2D **)&rb_texture); + ok_(__FILE__, line)(hr == S_OK, "Failed to create texture, hr %#x.\n", hr); + + ID3D11DeviceContext_CopyResource(context->immediate_context, rb_texture, (ID3D11Resource *)context->rt); + hr = ID3D11DeviceContext_Map(context->immediate_context, rb_texture, 0, D3D11_MAP_READ, 0, &map_desc); + ok_(__FILE__, line)(hr == S_OK, "Failed to map texture, hr %#x.\n", hr); + + ret = *((struct vec4 *)((BYTE *)map_desc.pData + y * map_desc.RowPitch) + x); + + ID3D11DeviceContext_Unmap(context->immediate_context, rb_texture, 0); + ID3D11Resource_Release(rb_texture); + + return ret; +} + +static void test_sm4_swizzle(void) +{ + static const struct vec4 uniform = {0.0303f, 0.0f, 0.0f, 0.0202f}; + struct d3d11_test_context test_context; + ID3D10Blob *ps_code; + ID3D11Buffer *cb; + struct vec4 v; + + static const char ps_source[] = + "uniform float4 color;\n" + "float4 main() : SV_TARGET\n" + "{\n" + " float4 ret = color;\n" + " ret.gb = ret.ra;\n" + " ret.ra = float2(0.0101, 0.0404);\n" + " return ret;\n" + "}"; + + if (!init_d3d11_test_context(&test_context)) + return; + + todo_wine ps_code = compile_shader(ps_source, "ps_4_0"); + if (ps_code) + { + cb = create_buffer(test_context.device, D3D11_BIND_CONSTANT_BUFFER, sizeof(uniform), &uniform); + ID3D11DeviceContext_PSSetConstantBuffers(test_context.immediate_context, 0, 1, &cb); + draw_quad_d3d11(&test_context, ps_code); + + v = get_readback_vec4_d3d11(&test_context, 0, 0); + ok(compare_vec4(&v, 0.0101f, 0.0303f, 0.0202f, 0.0404f, 0), + "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v.x, v.y, v.z, v.w); + + ID3D11Buffer_Release(cb); + ID3D10Blob_Release(ps_code); + } + release_d3d11_test_context(&test_context); +} + +static void test_sm4_math(void) +{ + static const float uniforms[8] = {2.5f, 0.3f, 0.2f, 0.7f, 0.1f, 1.5f}; + struct d3d11_test_context test_context; + ID3D10Blob *ps_code; + ID3D11Buffer *cb; + struct vec4 v; + + static const char ps_source[] = + "float4 main(uniform float u, uniform float v, uniform float w, uniform float x,\n" + " uniform float y, uniform float z) : SV_TARGET\n" + "{\n" + " return float4(x * y - z / w + --u / -v,\n" + " z * x / y + w / -v,\n" + " u + v - w,\n" + " x / y / w);\n" + "}"; + + if (!init_d3d11_test_context(&test_context)) + return; + + todo_wine ps_code = compile_shader(ps_source, "ps_4_0"); + if (ps_code) + { + cb = create_buffer(test_context.device, D3D11_BIND_CONSTANT_BUFFER, sizeof(uniforms), uniforms); + ID3D11DeviceContext_PSSetConstantBuffers(test_context.immediate_context, 0, 1, &cb); + draw_quad_d3d11(&test_context, ps_code); + + v = get_readback_vec4_d3d11(&test_context, 0, 0); + ok(compare_vec4(&v, -12.43f, 9.833333f, 1.6f, 35.0f, 1), + "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v.x, v.y, v.z, v.w); + + ID3D11Buffer_Release(cb); + ID3D10Blob_Release(ps_code); + } + release_d3d11_test_context(&test_context); +} + +static void test_sm4_conditionals(void) +{ + struct d3d11_test_context test_context; + ID3D10Blob *ps_code; + unsigned int i; + struct vec4 v; + + static const char ps_source[] = + "float4 main(float4 pos : SV_POSITION) : SV_TARGET\n" + "{\n" + " if(pos.x > 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" + "}"; + + if (!init_d3d11_test_context(&test_context)) + return; + + todo_wine ps_code = compile_shader(ps_source, "ps_4_0"); + if (ps_code) + { + draw_quad_d3d11(&test_context, ps_code); + + for (i = 0; i < 200; i += 40) + { + v = get_readback_vec4_d3d11(&test_context, 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_d3d11(&test_context, 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); + } + release_d3d11_test_context(&test_context); +} + +static void test_sm4_trig(void) +{ + struct d3d11_test_context test_context; + ID3D10Blob *ps_code; + unsigned int i; + struct vec4 v; + + static const char ps_source[] = + "float4 main(float4 pos : SV_POSITION) : SV_TARGET\n" + "{\n" + " return float4(sin(pos.x - 0.5), cos(pos.x - 0.5), 0, 0);\n" + "}"; + + if (!init_d3d11_test_context(&test_context)) + return; + + todo_wine ps_code = compile_shader(ps_source, "ps_4_0"); + if (ps_code) + { + draw_quad_d3d11(&test_context, ps_code); + + for (i = 0; i < 640; i += 20) + { + v = get_readback_vec4_d3d11(&test_context, i, 0); + ok(compare_vec4(&v, sinf(i), cosf(i), 0.0f, 0.0f, 4096), + "Test %u: Got {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n", + i, v.x, v.y, v.z, v.w, sinf(i), cos(i), 0.0f, 0.0f); + } + + ID3D10Blob_Release(ps_code); + } + release_d3d11_test_context(&test_context); +} + START_TEST(hlsl) { HMODULE mod; @@ -665,4 +1105,16 @@ START_TEST(hlsl) test_float_vectors(); test_trig(); test_fail(); + + if (!(mod = LoadLibraryA("d3d11.dll"))) + { + skip("Direct3D 11 is not available.\n"); + return; + } + pD3D11CreateDevice = (void *)GetProcAddress(mod, "D3D11CreateDevice"); + + test_sm4_swizzle(); + test_sm4_math(); + test_sm4_conditionals(); + test_sm4_trig(); }
On Tue, Feb 18, 2020 at 9:32 PM Zebediah Figura z.figura12@gmail.com wrote:
In particular, port those for which there is an interesting difference in code generation.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com
It might make more sense to put this in a separate file, à la ddraw, since almost no code is shared between d3d9 and d3d11 parts.
It might be a good idea. Another potential advantage is that then we'll have two separate entries on test.winehq.org. I'm okay either way though.
+#define init_d3d11_test_context(a) init_d3d11_test_context_(__LINE__, a) +static BOOL init_d3d11_test_context_(unsigned int line, struct d3d11_test_context *context) +{
- const D3D11_TEXTURE2D_DESC texture_desc =
- {
.Width = 640,
.Height = 480,
.MipLevels = 1,
.ArraySize = 1,
.Format = DXGI_FORMAT_R32G32B32A32_FLOAT,
.SampleDesc.Count = 1,
.Usage = D3D11_USAGE_DEFAULT,
.BindFlags = D3D11_BIND_RENDER_TARGET,
- };
- unsigned int rt_width, rt_height;
- D3D11_VIEWPORT vp;
- HRESULT hr;
- RECT rect;
- memset(context, 0, sizeof(*context));
- if (!(context->device = create_device()))
- {
skip_(__FILE__, line)("Failed to create device.\n");
return FALSE;
- }
- rt_width = 640;
- rt_height = 480;
- SetRect(&rect, 0, 0, rt_width, rt_height);
- AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
- context->window = CreateWindowA("static", "d3d11_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0, 0, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, NULL, NULL);
- context->swapchain = create_swapchain(context->device, context->window);
This reminds me that's probably better to do something similar WRT the window for d3d9 too, in the previous patch.
+#define get_readback_vec4_d3d11(context, x, y) get_readback_vec4_d3d11_(__LINE__, context, x, y) +static struct vec4 get_readback_vec4_d3d11_(unsigned int line, struct d3d11_test_context *context,
unsigned int x, unsigned int y)
+{
- ID3D11Device *device = context->device;
- D3D11_MAPPED_SUBRESOURCE map_desc;
- D3D11_TEXTURE2D_DESC texture_desc;
- ID3D11Resource *rb_texture;
- struct vec4 ret;
- HRESULT hr;
- ID3D11Texture2D_GetDesc(context->rt, &texture_desc);
- texture_desc.Usage = D3D11_USAGE_STAGING;
- texture_desc.BindFlags = 0;
- texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
- texture_desc.MiscFlags = 0;
- hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, (ID3D11Texture2D **)&rb_texture);
- ok_(__FILE__, line)(hr == S_OK, "Failed to create texture, hr %#x.\n", hr);
- ID3D11DeviceContext_CopyResource(context->immediate_context, rb_texture, (ID3D11Resource *)context->rt);
- hr = ID3D11DeviceContext_Map(context->immediate_context, rb_texture, 0, D3D11_MAP_READ, 0, &map_desc);
- ok_(__FILE__, line)(hr == S_OK, "Failed to map texture, hr %#x.\n", hr);
- ret = *((struct vec4 *)((BYTE *)map_desc.pData + y * map_desc.RowPitch) + x);
- ID3D11DeviceContext_Unmap(context->immediate_context, rb_texture, 0);
- ID3D11Resource_Release(rb_texture);
- return ret;
+}
Same point WRT texture readback as the previous patch.
+static void test_sm4_swizzle(void) +{
- static const struct vec4 uniform = {0.0303f, 0.0f, 0.0f, 0.0202f};
- struct d3d11_test_context test_context;
- ID3D10Blob *ps_code;
- ID3D11Buffer *cb;
- struct vec4 v;
- static const char ps_source[] =
"uniform float4 color;\n"
"float4 main() : SV_TARGET\n"
"{\n"
" float4 ret = color;\n"
" ret.gb = ret.ra;\n"
" ret.ra = float2(0.0101, 0.0404);\n"
" return ret;\n"
"}";
- if (!init_d3d11_test_context(&test_context))
return;
- todo_wine ps_code = compile_shader(ps_source, "ps_4_0");
- if (ps_code)
- {
cb = create_buffer(test_context.device, D3D11_BIND_CONSTANT_BUFFER, sizeof(uniform), &uniform);
ID3D11DeviceContext_PSSetConstantBuffers(test_context.immediate_context, 0, 1, &cb);
More of an open question than anything: is the "global" constant buffer always supposed to be at index 0?
On 2/25/20 11:32 AM, Matteo Bruni wrote:
On Tue, Feb 18, 2020 at 9:32 PM Zebediah Figura z.figura12@gmail.com wrote:
In particular, port those for which there is an interesting difference in code generation.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com
It might make more sense to put this in a separate file, à la ddraw, since almost no code is shared between d3d9 and d3d11 parts.
It might be a good idea. Another potential advantage is that then we'll have two separate entries on test.winehq.org. I'm okay either way though.
+#define init_d3d11_test_context(a) init_d3d11_test_context_(__LINE__, a) +static BOOL init_d3d11_test_context_(unsigned int line, struct d3d11_test_context *context) +{
- const D3D11_TEXTURE2D_DESC texture_desc =
- {
.Width = 640,
.Height = 480,
.MipLevels = 1,
.ArraySize = 1,
.Format = DXGI_FORMAT_R32G32B32A32_FLOAT,
.SampleDesc.Count = 1,
.Usage = D3D11_USAGE_DEFAULT,
.BindFlags = D3D11_BIND_RENDER_TARGET,
- };
- unsigned int rt_width, rt_height;
- D3D11_VIEWPORT vp;
- HRESULT hr;
- RECT rect;
- memset(context, 0, sizeof(*context));
- if (!(context->device = create_device()))
- {
skip_(__FILE__, line)("Failed to create device.\n");
return FALSE;
- }
- rt_width = 640;
- rt_height = 480;
- SetRect(&rect, 0, 0, rt_width, rt_height);
- AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
- context->window = CreateWindowA("static", "d3d11_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0, 0, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, NULL, NULL);
- context->swapchain = create_swapchain(context->device, context->window);
This reminds me that's probably better to do something similar WRT the window for d3d9 too, in the previous patch.
Sure. I mostly left it as is because it doesn't save much code.
+#define get_readback_vec4_d3d11(context, x, y) get_readback_vec4_d3d11_(__LINE__, context, x, y) +static struct vec4 get_readback_vec4_d3d11_(unsigned int line, struct d3d11_test_context *context,
unsigned int x, unsigned int y)
+{
- ID3D11Device *device = context->device;
- D3D11_MAPPED_SUBRESOURCE map_desc;
- D3D11_TEXTURE2D_DESC texture_desc;
- ID3D11Resource *rb_texture;
- struct vec4 ret;
- HRESULT hr;
- ID3D11Texture2D_GetDesc(context->rt, &texture_desc);
- texture_desc.Usage = D3D11_USAGE_STAGING;
- texture_desc.BindFlags = 0;
- texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
- texture_desc.MiscFlags = 0;
- hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, (ID3D11Texture2D **)&rb_texture);
- ok_(__FILE__, line)(hr == S_OK, "Failed to create texture, hr %#x.\n", hr);
- ID3D11DeviceContext_CopyResource(context->immediate_context, rb_texture, (ID3D11Resource *)context->rt);
- hr = ID3D11DeviceContext_Map(context->immediate_context, rb_texture, 0, D3D11_MAP_READ, 0, &map_desc);
- ok_(__FILE__, line)(hr == S_OK, "Failed to map texture, hr %#x.\n", hr);
- ret = *((struct vec4 *)((BYTE *)map_desc.pData + y * map_desc.RowPitch) + x);
- ID3D11DeviceContext_Unmap(context->immediate_context, rb_texture, 0);
- ID3D11Resource_Release(rb_texture);
- return ret;
+}
Same point WRT texture readback as the previous patch.
+static void test_sm4_swizzle(void) +{
- static const struct vec4 uniform = {0.0303f, 0.0f, 0.0f, 0.0202f};
- struct d3d11_test_context test_context;
- ID3D10Blob *ps_code;
- ID3D11Buffer *cb;
- struct vec4 v;
- static const char ps_source[] =
"uniform float4 color;\n"
"float4 main() : SV_TARGET\n"
"{\n"
" float4 ret = color;\n"
" ret.gb = ret.ra;\n"
" ret.ra = float2(0.0101, 0.0404);\n"
" return ret;\n"
"}";
- if (!init_d3d11_test_context(&test_context))
return;
- todo_wine ps_code = compile_shader(ps_source, "ps_4_0");
- if (ps_code)
- {
cb = create_buffer(test_context.device, D3D11_BIND_CONSTANT_BUFFER, sizeof(uniform), &uniform);
ID3D11DeviceContext_PSSetConstantBuffers(test_context.immediate_context, 0, 1, &cb);
More of an open question than anything: is the "global" constant buffer always supposed to be at index 0?
I don't think it's documented anywhere. In practice there seems to be a stable ordering—$Global, then $Param, then declared cbuffers in order.
For what it's worth, d2d1 (and I guess d3d11 tests in general?) kind of depend on this, though maybe the logic there is that we ship the bytecode and therefore already know what the buffer register is...
On Tue, Feb 25, 2020 at 6:59 PM Zebediah Figura zfigura@codeweavers.com wrote:
On 2/25/20 11:32 AM, Matteo Bruni wrote:
On Tue, Feb 18, 2020 at 9:32 PM Zebediah Figura z.figura12@gmail.com wrote:
In particular, port those for which there is an interesting difference in code generation.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com
It might make more sense to put this in a separate file, à la ddraw, since almost no code is shared between d3d9 and d3d11 parts.
It might be a good idea. Another potential advantage is that then we'll have two separate entries on test.winehq.org. I'm okay either way though.
+#define init_d3d11_test_context(a) init_d3d11_test_context_(__LINE__, a) +static BOOL init_d3d11_test_context_(unsigned int line, struct d3d11_test_context *context) +{
- const D3D11_TEXTURE2D_DESC texture_desc =
- {
.Width = 640,
.Height = 480,
.MipLevels = 1,
.ArraySize = 1,
.Format = DXGI_FORMAT_R32G32B32A32_FLOAT,
.SampleDesc.Count = 1,
.Usage = D3D11_USAGE_DEFAULT,
.BindFlags = D3D11_BIND_RENDER_TARGET,
- };
- unsigned int rt_width, rt_height;
- D3D11_VIEWPORT vp;
- HRESULT hr;
- RECT rect;
- memset(context, 0, sizeof(*context));
- if (!(context->device = create_device()))
- {
skip_(__FILE__, line)("Failed to create device.\n");
return FALSE;
- }
- rt_width = 640;
- rt_height = 480;
- SetRect(&rect, 0, 0, rt_width, rt_height);
- AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
- context->window = CreateWindowA("static", "d3d11_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0, 0, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, NULL, NULL);
- context->swapchain = create_swapchain(context->device, context->window);
This reminds me that's probably better to do something similar WRT the window for d3d9 too, in the previous patch.
Sure. I mostly left it as is because it doesn't save much code.
I understand it wasn't clear at all but I was referring to creating a sensible window and then using AdjustWindowRect() in the d3d9 tests.
+#define get_readback_vec4_d3d11(context, x, y) get_readback_vec4_d3d11_(__LINE__, context, x, y) +static struct vec4 get_readback_vec4_d3d11_(unsigned int line, struct d3d11_test_context *context,
unsigned int x, unsigned int y)
+{
- ID3D11Device *device = context->device;
- D3D11_MAPPED_SUBRESOURCE map_desc;
- D3D11_TEXTURE2D_DESC texture_desc;
- ID3D11Resource *rb_texture;
- struct vec4 ret;
- HRESULT hr;
- ID3D11Texture2D_GetDesc(context->rt, &texture_desc);
- texture_desc.Usage = D3D11_USAGE_STAGING;
- texture_desc.BindFlags = 0;
- texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
- texture_desc.MiscFlags = 0;
- hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, (ID3D11Texture2D **)&rb_texture);
- ok_(__FILE__, line)(hr == S_OK, "Failed to create texture, hr %#x.\n", hr);
- ID3D11DeviceContext_CopyResource(context->immediate_context, rb_texture, (ID3D11Resource *)context->rt);
- hr = ID3D11DeviceContext_Map(context->immediate_context, rb_texture, 0, D3D11_MAP_READ, 0, &map_desc);
- ok_(__FILE__, line)(hr == S_OK, "Failed to map texture, hr %#x.\n", hr);
- ret = *((struct vec4 *)((BYTE *)map_desc.pData + y * map_desc.RowPitch) + x);
- ID3D11DeviceContext_Unmap(context->immediate_context, rb_texture, 0);
- ID3D11Resource_Release(rb_texture);
- return ret;
+}
Same point WRT texture readback as the previous patch.
+static void test_sm4_swizzle(void) +{
- static const struct vec4 uniform = {0.0303f, 0.0f, 0.0f, 0.0202f};
- struct d3d11_test_context test_context;
- ID3D10Blob *ps_code;
- ID3D11Buffer *cb;
- struct vec4 v;
- static const char ps_source[] =
"uniform float4 color;\n"
"float4 main() : SV_TARGET\n"
"{\n"
" float4 ret = color;\n"
" ret.gb = ret.ra;\n"
" ret.ra = float2(0.0101, 0.0404);\n"
" return ret;\n"
"}";
- if (!init_d3d11_test_context(&test_context))
return;
- todo_wine ps_code = compile_shader(ps_source, "ps_4_0");
- if (ps_code)
- {
cb = create_buffer(test_context.device, D3D11_BIND_CONSTANT_BUFFER, sizeof(uniform), &uniform);
ID3D11DeviceContext_PSSetConstantBuffers(test_context.immediate_context, 0, 1, &cb);
More of an open question than anything: is the "global" constant buffer always supposed to be at index 0?
I don't think it's documented anywhere. In practice there seems to be a stable ordering—$Global, then $Param, then declared cbuffers in order.
For what it's worth, d2d1 (and I guess d3d11 tests in general?) kind of depend on this, though maybe the logic there is that we ship the bytecode and therefore already know what the buffer register is...
Yes, that's not really a dependency since everything is hardcoded. I guess, in theory, the test should use reflection to get the constant buffer index but a comment along the lines of what you wrote here should be also okay.
On 2/27/20 4:28 AM, Matteo Bruni wrote:
On Tue, Feb 25, 2020 at 6:59 PM Zebediah Figura zfigura@codeweavers.com wrote:
On 2/25/20 11:32 AM, Matteo Bruni wrote:
On Tue, Feb 18, 2020 at 9:32 PM Zebediah Figura z.figura12@gmail.com wrote:
In particular, port those for which there is an interesting difference in code generation.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com
It might make more sense to put this in a separate file, à la ddraw, since almost no code is shared between d3d9 and d3d11 parts.
It might be a good idea. Another potential advantage is that then we'll have two separate entries on test.winehq.org. I'm okay either way though.
+#define init_d3d11_test_context(a) init_d3d11_test_context_(__LINE__, a) +static BOOL init_d3d11_test_context_(unsigned int line, struct d3d11_test_context *context) +{
- const D3D11_TEXTURE2D_DESC texture_desc =
- {
.Width = 640,
.Height = 480,
.MipLevels = 1,
.ArraySize = 1,
.Format = DXGI_FORMAT_R32G32B32A32_FLOAT,
.SampleDesc.Count = 1,
.Usage = D3D11_USAGE_DEFAULT,
.BindFlags = D3D11_BIND_RENDER_TARGET,
- };
- unsigned int rt_width, rt_height;
- D3D11_VIEWPORT vp;
- HRESULT hr;
- RECT rect;
- memset(context, 0, sizeof(*context));
- if (!(context->device = create_device()))
- {
skip_(__FILE__, line)("Failed to create device.\n");
return FALSE;
- }
- rt_width = 640;
- rt_height = 480;
- SetRect(&rect, 0, 0, rt_width, rt_height);
- AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
- context->window = CreateWindowA("static", "d3d11_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0, 0, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, NULL, NULL);
- context->swapchain = create_swapchain(context->device, context->window);
This reminds me that's probably better to do something similar WRT the window for d3d9 too, in the previous patch.
Sure. I mostly left it as is because it doesn't save much code.
I understand it wasn't clear at all but I was referring to creating a sensible window and then using AdjustWindowRect() in the d3d9 tests.
Ah, I assumed you just meant using a test_context (which I did anyway, and I guess it's probably better.) I'll resend with AdjustWindowRect() too.
+#define get_readback_vec4_d3d11(context, x, y) get_readback_vec4_d3d11_(__LINE__, context, x, y) +static struct vec4 get_readback_vec4_d3d11_(unsigned int line, struct d3d11_test_context *context,
unsigned int x, unsigned int y)
+{
- ID3D11Device *device = context->device;
- D3D11_MAPPED_SUBRESOURCE map_desc;
- D3D11_TEXTURE2D_DESC texture_desc;
- ID3D11Resource *rb_texture;
- struct vec4 ret;
- HRESULT hr;
- ID3D11Texture2D_GetDesc(context->rt, &texture_desc);
- texture_desc.Usage = D3D11_USAGE_STAGING;
- texture_desc.BindFlags = 0;
- texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
- texture_desc.MiscFlags = 0;
- hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, (ID3D11Texture2D **)&rb_texture);
- ok_(__FILE__, line)(hr == S_OK, "Failed to create texture, hr %#x.\n", hr);
- ID3D11DeviceContext_CopyResource(context->immediate_context, rb_texture, (ID3D11Resource *)context->rt);
- hr = ID3D11DeviceContext_Map(context->immediate_context, rb_texture, 0, D3D11_MAP_READ, 0, &map_desc);
- ok_(__FILE__, line)(hr == S_OK, "Failed to map texture, hr %#x.\n", hr);
- ret = *((struct vec4 *)((BYTE *)map_desc.pData + y * map_desc.RowPitch) + x);
- ID3D11DeviceContext_Unmap(context->immediate_context, rb_texture, 0);
- ID3D11Resource_Release(rb_texture);
- return ret;
+}
Same point WRT texture readback as the previous patch.
+static void test_sm4_swizzle(void) +{
- static const struct vec4 uniform = {0.0303f, 0.0f, 0.0f, 0.0202f};
- struct d3d11_test_context test_context;
- ID3D10Blob *ps_code;
- ID3D11Buffer *cb;
- struct vec4 v;
- static const char ps_source[] =
"uniform float4 color;\n"
"float4 main() : SV_TARGET\n"
"{\n"
" float4 ret = color;\n"
" ret.gb = ret.ra;\n"
" ret.ra = float2(0.0101, 0.0404);\n"
" return ret;\n"
"}";
- if (!init_d3d11_test_context(&test_context))
return;
- todo_wine ps_code = compile_shader(ps_source, "ps_4_0");
- if (ps_code)
- {
cb = create_buffer(test_context.device, D3D11_BIND_CONSTANT_BUFFER, sizeof(uniform), &uniform);
ID3D11DeviceContext_PSSetConstantBuffers(test_context.immediate_context, 0, 1, &cb);
More of an open question than anything: is the "global" constant buffer always supposed to be at index 0?
I don't think it's documented anywhere. In practice there seems to be a stable ordering—$Global, then $Param, then declared cbuffers in order.
For what it's worth, d2d1 (and I guess d3d11 tests in general?) kind of depend on this, though maybe the logic there is that we ship the bytecode and therefore already know what the buffer register is...
Yes, that's not really a dependency since everything is hardcoded. I guess, in theory, the test should use reflection to get the constant buffer index but a comment along the lines of what you wrote here should be also okay.
I guess it's not too difficult to use reflection, at least if we write a helper for it. Fortunately the layout is documented, so we just need the index.
I do wonder if applications in the wild depend on the generated buffer order, though even if they do that doesn't mean we should too...
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/d3dcompiler_43/tests/hlsl.c | 39 ++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/dlls/d3dcompiler_43/tests/hlsl.c b/dlls/d3dcompiler_43/tests/hlsl.c index 5cb64253e88..97789d14297 100644 --- a/dlls/d3dcompiler_43/tests/hlsl.c +++ b/dlls/d3dcompiler_43/tests/hlsl.c @@ -569,6 +569,44 @@ static void test_trig(void) DestroyWindow(window); }
+static void test_comma(void) +{ + IDirect3DDevice9 *device; + ID3D10Blob *ps_code; + struct vec4 v; + HWND window; + + static const char ps_source[] = + "float4 main(float x: TEXCOORD0): COLOR\n" + "{\n" + " float4 ret;\n" + " return (ret = float4(0.1, 0.2, 0.3, 0.4)), ret + 0.5;\n" + "}"; + + window = create_window(); + ok(!!window, "Failed to create a window.\n"); + + if (!(device = create_d3d9_device(window))) + { + DestroyWindow(window); + return; + } + + todo_wine ps_code = compile_shader(ps_source, "ps_2_0"); + if (ps_code) + { + draw_quad(device, ps_code); + + v = get_readback_vec4_d3d9(device, 0, 0); + ok(compare_vec4(&v, 0.6f, 0.7f, 0.8f, 0.9f, 0), + "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v.x, v.y, v.z, v.w); + + ID3D10Blob_Release(ps_code); + } + IDirect3DDevice9_Release(device); + DestroyWindow(window); +} + static void test_fail(void) { static const char *tests[] = @@ -1104,6 +1142,7 @@ START_TEST(hlsl) test_conditionals(); test_float_vectors(); test_trig(); + test_comma(); test_fail();
if (!(mod = LoadLibraryA("d3d11.dll")))
On Tue, Feb 18, 2020 at 9:32 PM Zebediah Figura z.figura12@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@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.
On 2/25/20 11:30 AM, Matteo Bruni wrote:
On Tue, Feb 18, 2020 at 9:32 PM Zebediah Figura z.figura12@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@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).
Eh, I guess the helper isn't really doing much anyway. Maybe just a two-line helper to translate four floats into a D3DXVECTOR4 would be best.
+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.
I guess that strikes me as more of a d3d core test than a d3dcompiler test, but I don't feel strongly about it.
On Tue, Feb 25, 2020 at 6:59 PM Zebediah Figura zfigura@codeweavers.com wrote:
On 2/25/20 11:30 AM, Matteo Bruni wrote:
On Tue, Feb 18, 2020 at 9:32 PM Zebediah Figura z.figura12@gmail.com wrote:
@@ -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.
I guess that strikes me as more of a d3d core test than a d3dcompiler test, but I don't feel strongly about it.
Not necessarily, depending on whether the natively generated shader does or doesn't have explicit bounds checking. I guess it probably doesn't so this is no concern, but worth a look IMO.
On 2/27/20 4:25 AM, Matteo Bruni wrote:
On Tue, Feb 25, 2020 at 6:59 PM Zebediah Figura zfigura@codeweavers.com wrote:
On 2/25/20 11:30 AM, Matteo Bruni wrote:
On Tue, Feb 18, 2020 at 9:32 PM Zebediah Figura z.figura12@gmail.com wrote:
@@ -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.
I guess that strikes me as more of a d3d core test than a d3dcompiler test, but I don't feel strongly about it.
Not necessarily, depending on whether the natively generated shader does or doesn't have explicit bounds checking. I guess it probably doesn't so this is no concern, but worth a look IMO.
Ah, makes sense. I'll put it on my list, then.