wined3d: Pass a wined3d_device_context to wined3d_cs_emit_blt_sub_resource().
[wine/zf.git] / dlls / d3dcompiler_43 / tests / hlsl_d3d9.c
blob87f63023c582c88d7a9145d459d30beb48a414c6
1 /*
2 * Copyright (C) 2010 Travis Athougies
3 * Copyright (C) 2020 Zebediah Figura for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COBJMACROS
20 #include "wine/test.h"
21 #include "wine/heap.h"
22 #include "d3dx9.h"
23 #include "d3dcompiler.h"
25 #include <math.h>
27 static pD3DCompile ppD3DCompile;
29 static HRESULT (WINAPI *pD3DCompile2)(const void *data, SIZE_T data_size, const char *filename, const D3D_SHADER_MACRO *defines,
30 ID3DInclude *include, const char *entrypoint, const char *target, UINT sflags, UINT eflags, UINT secondary_flags,
31 const void *secondary_data, SIZE_T secondary_data_size, ID3DBlob **shader, ID3DBlob **error_messages);
32 static HRESULT (WINAPI *pD3DCompileFromFile)(const WCHAR *filename, const D3D_SHADER_MACRO *defines,
33 ID3DInclude *include, const char *entrypoint, const char *target, UINT flags1, UINT flags2,
34 ID3DBlob **code, ID3DBlob **errors);
35 static HRESULT (WINAPI *pD3DXGetShaderConstantTable)(const DWORD *byte_code, ID3DXConstantTable **constant_table);
37 struct vec2
39 float x, y;
42 struct vec4
44 float x, y, z, w;
47 static WCHAR temp_dir[MAX_PATH];
49 static BOOL create_file(const WCHAR *filename, const char *data, unsigned int size, WCHAR *out_path)
51 WCHAR path[MAX_PATH];
52 DWORD written;
53 HANDLE file;
55 if (!temp_dir[0])
56 GetTempPathW(ARRAY_SIZE(temp_dir), temp_dir);
57 lstrcpyW(path, temp_dir);
58 lstrcatW(path, filename);
60 file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
61 if (file == INVALID_HANDLE_VALUE)
62 return FALSE;
64 if (WriteFile(file, data, size, &written, NULL))
66 CloseHandle(file);
68 if (out_path)
69 lstrcpyW(out_path, path);
70 return TRUE;
73 CloseHandle(file);
74 return FALSE;
77 static void delete_file(const WCHAR *filename)
79 WCHAR path[MAX_PATH];
81 lstrcpyW(path, temp_dir);
82 lstrcatW(path, filename);
83 DeleteFileW(path);
86 static BOOL create_directory(const WCHAR *dir)
88 WCHAR path[MAX_PATH];
90 lstrcpyW(path, temp_dir);
91 lstrcatW(path, dir);
92 return CreateDirectoryW(path, NULL);
95 static void delete_directory(const WCHAR *dir)
97 WCHAR path[MAX_PATH];
99 lstrcpyW(path, temp_dir);
100 lstrcatW(path, dir);
101 RemoveDirectoryW(path);
104 #define compile_shader(a, b) compile_shader_(__LINE__, a, b)
105 static ID3D10Blob *compile_shader_(unsigned int line, const char *source, const char *target)
107 ID3D10Blob *blob = NULL, *errors = NULL;
108 HRESULT hr;
110 hr = ppD3DCompile(source, strlen(source), NULL, NULL, NULL, "main", target, 0, 0, &blob, &errors);
111 ok_(__FILE__, line)(hr == D3D_OK, "Failed to compile shader, hr %#x.\n", hr);
112 if (errors)
114 if (winetest_debug > 1)
115 trace_(__FILE__, line)("%s\n", (char *)ID3D10Blob_GetBufferPointer(errors));
116 ID3D10Blob_Release(errors);
118 return blob;
121 static IDirect3DDevice9 *create_device(HWND window)
123 D3DPRESENT_PARAMETERS present_parameters =
125 .Windowed = TRUE,
126 .hDeviceWindow = window,
127 .SwapEffect = D3DSWAPEFFECT_DISCARD,
128 .BackBufferWidth = 640,
129 .BackBufferHeight = 480,
130 .BackBufferFormat = D3DFMT_A8R8G8B8,
132 IDirect3DDevice9 *device;
133 IDirect3DSurface9 *rt;
134 IDirect3D9 *d3d;
135 D3DCAPS9 caps;
136 HRESULT hr;
138 d3d = Direct3DCreate9(D3D_SDK_VERSION);
139 ok(!!d3d, "Failed to create a D3D object.\n");
141 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
142 D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device);
143 IDirect3D9_Release(d3d);
144 if (FAILED(hr))
146 skip("Failed to create a 3D device, hr %#x.\n", hr);
147 return NULL;
150 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
151 ok(hr == D3D_OK, "Failed to get device caps, hr %#x.\n", hr);
152 if (caps.PixelShaderVersion < D3DPS_VERSION(2, 0) || caps.VertexShaderVersion < D3DVS_VERSION(2, 0))
154 skip("No shader model 2 support.\n");
155 IDirect3DDevice9_Release(device);
156 return NULL;
159 if (FAILED(hr = IDirect3DDevice9_CreateRenderTarget(device, 640, 480, D3DFMT_A32B32G32R32F,
160 D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL)))
162 skip("Failed to create an A32B32G32R32F surface, hr %#x.\n", hr);
163 IDirect3DDevice9_Release(device);
164 return NULL;
166 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
167 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
168 ok(hr == D3D_OK, "Failed to set render target, hr %#x.\n", hr);
169 IDirect3DSurface9_Release(rt);
171 return device;
174 struct test_context
176 IDirect3DDevice9 *device;
177 HWND window;
180 #define init_test_context(a) init_test_context_(__LINE__, a)
181 static BOOL init_test_context_(unsigned int line, struct test_context *context)
183 RECT rect = {0, 0, 640, 480};
185 AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
186 context->window = CreateWindowA("static", "d3dcompiler_test", WS_OVERLAPPEDWINDOW,
187 0, 0, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, NULL, NULL);
188 ok(!!context->window, "Failed to create a window.\n");
190 if (!(context->device = create_device(context->window)))
192 DestroyWindow(context->window);
193 return FALSE;
196 return TRUE;
199 #define release_test_context(context) release_test_context_(__LINE__, context)
200 static void release_test_context_(unsigned int line, struct test_context *context)
202 ULONG ref = IDirect3DDevice9_Release(context->device);
203 ok_(__FILE__, line)(!ref, "Device has %u references left.\n", ref);
204 DestroyWindow(context->window);
207 #define draw_quad(device, ps_code) draw_quad_(__LINE__, device, ps_code)
208 static void draw_quad_(unsigned int line, IDirect3DDevice9 *device, ID3D10Blob *ps_code)
210 IDirect3DVertexDeclaration9 *vertex_declaration;
211 IDirect3DVertexShader9 *vs;
212 IDirect3DPixelShader9 *ps;
213 ID3D10Blob *vs_code;
214 HRESULT hr;
216 static const D3DVERTEXELEMENT9 decl_elements[] =
218 {0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
219 {0, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
220 D3DDECL_END()
223 static const struct
225 struct vec2 position;
226 struct vec2 t0;
228 quad[] =
230 {{-1.0f, -1.0f}, {0.0f, 1.0f}},
231 {{-1.0f, 1.0f}, {0.0f, 0.0f}},
232 {{ 1.0f, -1.0f}, {1.0f, 1.0f}},
233 {{ 1.0f, 1.0f}, {1.0f, 0.0f}},
236 static const char vs_source[] =
237 "float4 main(float4 pos : POSITION, inout float2 texcoord : TEXCOORD0) : POSITION\n"
238 "{\n"
239 " return pos;\n"
240 "}";
242 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
243 ok_(__FILE__, line)(hr == D3D_OK, "Failed to create vertex declaration, hr %#x.\n", hr);
245 hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
246 ok_(__FILE__, line)(hr == D3D_OK, "Failed to set vertex declaration, hr %#x.\n", hr);
248 vs_code = compile_shader(vs_source, "vs_2_0");
250 hr = IDirect3DDevice9_CreateVertexShader(device, ID3D10Blob_GetBufferPointer(vs_code), &vs);
251 ok_(__FILE__, line)(hr == D3D_OK, "Failed to create vertex shader, hr %#x.\n", hr);
253 hr = IDirect3DDevice9_SetVertexShader(device, vs);
254 ok_(__FILE__, line)(hr == D3D_OK, "Failed to set vertex shader, hr %#x.\n", hr);
256 hr = IDirect3DDevice9_CreatePixelShader(device, ID3D10Blob_GetBufferPointer(ps_code), &ps);
257 ok_(__FILE__, line)(hr == D3D_OK, "Failed to create pixel shader, hr %#x.\n", hr);
259 hr = IDirect3DDevice9_SetPixelShader(device, ps);
260 ok_(__FILE__, line)(hr == D3D_OK, "Failed to set pixel shader, hr %#x.\n", hr);
262 hr = IDirect3DDevice9_BeginScene(device);
263 ok_(__FILE__, line)(hr == D3D_OK, "Failed to draw, hr %#x.\n", hr);
265 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
266 ok_(__FILE__, line)(hr == D3D_OK, "Failed to draw, hr %#x.\n", hr);
268 hr = IDirect3DDevice9_EndScene(device);
269 ok_(__FILE__, line)(hr == D3D_OK, "Failed to draw, hr %#x.\n", hr);
271 IDirect3DVertexDeclaration9_Release(vertex_declaration);
272 IDirect3DVertexShader9_Release(vs);
273 IDirect3DPixelShader9_Release(ps);
274 ID3D10Blob_Release(vs_code);
277 struct readback
279 IDirect3DSurface9 *surface;
280 D3DLOCKED_RECT rect;
283 static void init_readback(IDirect3DDevice9 *device, struct readback *rb)
285 IDirect3DSurface9 *rt;
286 D3DSURFACE_DESC desc;
287 HRESULT hr;
289 hr = IDirect3DDevice9Ex_GetRenderTarget(device, 0, &rt);
290 ok(hr == D3D_OK, "Failed to get render target, hr %#x.\n", hr);
292 hr = IDirect3DSurface9_GetDesc(rt, &desc);
293 ok(hr == D3D_OK, "Failed to get surface desc, hr %#x.\n", hr);
294 hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurface(device, desc.Width, desc.Height,
295 desc.Format, D3DPOOL_SYSTEMMEM, &rb->surface, NULL);
296 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
298 hr = IDirect3DDevice9Ex_GetRenderTargetData(device, rt, rb->surface);
299 ok(hr == D3D_OK, "Failed to get render target data, hr %#x.\n", hr);
301 hr = IDirect3DSurface9_LockRect(rb->surface, &rb->rect, NULL, D3DLOCK_READONLY);
302 ok(hr == D3D_OK, "Failed to lock surface, hr %#x.\n", hr);
304 IDirect3DSurface9_Release(rt);
307 static const struct vec4 *get_readback_vec4(const struct readback *rb, unsigned int x, unsigned int y)
309 return (struct vec4 *)((BYTE *)rb->rect.pBits + y * rb->rect.Pitch + x * sizeof(struct vec4));
312 static void release_readback(struct readback *rb)
314 IDirect3DSurface9_UnlockRect(rb->surface);
315 IDirect3DSurface9_Release(rb->surface);
318 static struct vec4 get_color_vec4(IDirect3DDevice9 *device, unsigned int x, unsigned int y)
320 struct readback rb;
321 struct vec4 ret;
323 init_readback(device, &rb);
324 ret = *get_readback_vec4(&rb, x, y);
325 release_readback(&rb);
327 return ret;
330 static BOOL compare_float(float f, float g, unsigned int ulps)
332 int x = *(int *)&f;
333 int y = *(int *)&g;
335 if (x < 0)
336 x = INT_MIN - x;
337 if (y < 0)
338 y = INT_MIN - y;
340 if (abs(x - y) > ulps)
341 return FALSE;
343 return TRUE;
346 static BOOL compare_vec4(const struct vec4 *vec, float x, float y, float z, float w, unsigned int ulps)
348 return compare_float(vec->x, x, ulps)
349 && compare_float(vec->y, y, ulps)
350 && compare_float(vec->z, z, ulps)
351 && compare_float(vec->w, w, ulps);
354 static void test_swizzle(void)
356 static const D3DXVECTOR4 color = {0.0303f, 0.0f, 0.0f, 0.0202f};
357 struct test_context test_context;
358 ID3DXConstantTable *constants;
359 ID3D10Blob *ps_code = NULL;
360 IDirect3DDevice9 *device;
361 unsigned int i;
362 struct vec4 v;
363 HRESULT hr;
365 static const struct
367 const char *source;
368 struct vec4 color;
370 tests[] =
373 "uniform float4 color;\n"
374 "float4 main() : COLOR\n"
375 "{\n"
376 " float4 ret = color;\n"
377 " ret.gb = ret.ra;\n"
378 " ret.ra = float2(0.0101, 0.0404);\n"
379 " return ret;\n"
380 "}",
381 {0.0101f, 0.0303f, 0.0202f, 0.0404f}
384 "float4 main() : COLOR\n"
385 "{\n"
386 " float4 ret = float4(0.1, 0.2, 0.3, 0.4);\n"
387 " ret.wyz.yx = float2(0.5, 0.6).yx;\n"
388 " return ret;\n"
389 "}",
390 {0.1f, 0.6f, 0.3f, 0.5f}
393 "float4 main() : COLOR\n"
394 "{\n"
395 " float4 ret;\n"
396 " ret.zwyx = float4(0.1, 0.2, 0.3, 0.4);\n"
397 " return ret;\n"
398 "}",
399 {0.4f, 0.3f, 0.1f, 0.2f}
402 "float4 main() : COLOR\n"
403 "{\n"
404 " float4 ret;\n"
405 " ret.yw.y = 0.1;\n"
406 " ret.xzy.yz.y.x = 0.2;\n"
407 " ret.yzwx.yzwx.wz.y = 0.3;\n"
408 " ret.zxy.xyz.zxy.xy.y = 0.4;\n"
409 " return ret;\n"
410 "}",
411 {0.3f, 0.2f, 0.4f, 0.1f}
414 "float4 main() : COLOR\n"
415 "{\n"
416 " float4 ret;\n"
417 " ret.yxz.yx = float2(0.1, 0.2);\n"
418 " ret.w.x = 0.3;\n"
419 " ret.wzyx.zyx.yx.x = 0.4;\n"
420 " return ret;\n"
421 "}",
422 {0.1f, 0.2f, 0.4f, 0.3f}
425 "float4 main() : COLOR\n"
426 "{\n"
427 " float4 ret = float4(0.1, 0.2, 0.3, 0.4).ywxz.zyyz;\n"
428 " return ret;\n"
429 "}",
430 {0.1f, 0.4f, 0.4f, 0.1f}
433 "float4 main() : COLOR\n"
434 "{\n"
435 " float4 ret = float4(0.1, 0.2, 0.3, 0.4);\n"
436 " ret.yxwz = ret;\n"
437 " ret = ret.wyzx;\n"
438 " return ret;\n"
439 "}",
440 {0.3f, 0.1f, 0.4f, 0.2f}
443 "float4 main() : COLOR\n"
444 "{\n"
445 " float4 ret;\n"
446 " ret.xyzw.xyzw = float4(0.1, 0.2, 0.3, 0.4);\n"
447 " return ret;\n"
448 "}",
449 {0.1f, 0.2f, 0.3f, 0.4f}
453 if (!init_test_context(&test_context))
454 return;
455 device = test_context.device;
457 for (i = 0; i < ARRAY_SIZE(tests); ++i)
459 todo_wine ps_code = compile_shader(tests[i].source, "ps_2_0");
460 if (ps_code)
462 if (i == 0)
464 hr = pD3DXGetShaderConstantTable(ID3D10Blob_GetBufferPointer(ps_code), &constants);
465 ok(hr == D3D_OK, "Failed to get constant table, hr %#x.\n", hr);
466 hr = ID3DXConstantTable_SetVector(constants, device, "color", &color);
467 ok(hr == D3D_OK, "Failed to set constant, hr %#x.\n", hr);
468 ID3DXConstantTable_Release(constants);
470 draw_quad(device, ps_code);
472 v = get_color_vec4(device, 0, 0);
473 ok(compare_vec4(&v, tests[i].color.x, tests[i].color.y, tests[i].color.z, tests[i].color.w, 0),
474 "Test %u: Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", i, v.x, v.y, v.z, v.w);
476 ID3D10Blob_Release(ps_code);
480 release_test_context(&test_context);
483 static void test_math(void)
485 struct test_context test_context;
486 ID3DXConstantTable *constants;
487 ID3D10Blob *ps_code = NULL;
488 IDirect3DDevice9 *device;
489 struct vec4 v;
490 HRESULT hr;
492 static const char ps_source[] =
493 "float4 main(uniform float u, uniform float v, uniform float w, uniform float x,\n"
494 " uniform float y, uniform float z): COLOR\n"
495 "{\n"
496 " return float4(x * y - z / w + --u / -v,\n"
497 " z * x / y + w / -v,\n"
498 " u + v - w,\n"
499 " x / y / w);\n"
500 "}";
502 if (!init_test_context(&test_context))
503 return;
504 device = test_context.device;
506 todo_wine ps_code = compile_shader(ps_source, "ps_2_0");
507 if (ps_code)
509 hr = pD3DXGetShaderConstantTable(ID3D10Blob_GetBufferPointer(ps_code), &constants);
510 ok(hr == D3D_OK, "Failed to get constant table, hr %#x.\n", hr);
511 hr = ID3DXConstantTable_SetFloat(constants, device, "$u", 2.5f);
512 ok(hr == D3D_OK, "Failed to set constant, hr %#x.\n", hr);
513 hr = ID3DXConstantTable_SetFloat(constants, device, "$v", 0.3f);
514 ok(hr == D3D_OK, "Failed to set constant, hr %#x.\n", hr);
515 hr = ID3DXConstantTable_SetFloat(constants, device, "$w", 0.2f);
516 ok(hr == D3D_OK, "Failed to set constant, hr %#x.\n", hr);
517 hr = ID3DXConstantTable_SetFloat(constants, device, "$x", 0.7f);
518 ok(hr == D3D_OK, "Failed to set constant, hr %#x.\n", hr);
519 hr = ID3DXConstantTable_SetFloat(constants, device, "$y", 0.1f);
520 ok(hr == D3D_OK, "Failed to set constant, hr %#x.\n", hr);
521 hr = ID3DXConstantTable_SetFloat(constants, device, "$z", 1.5f);
522 ok(hr == D3D_OK, "Failed to set constant, hr %#x.\n", hr);
523 ID3DXConstantTable_Release(constants);
525 draw_quad(device, ps_code);
527 v = get_color_vec4(device, 0, 0);
528 ok(compare_vec4(&v, -12.43f, 9.833333f, 1.6f, 35.0f, 1),
529 "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v.x, v.y, v.z, v.w);
531 ID3D10Blob_Release(ps_code);
533 release_test_context(&test_context);
536 static void test_conditionals(void)
538 struct test_context test_context;
539 ID3D10Blob *ps_code = NULL;
540 IDirect3DDevice9 *device;
541 const struct vec4 *v;
542 struct readback rb;
543 unsigned int i;
545 static const char ps_if_source[] =
546 "float4 main(float2 pos : TEXCOORD0) : COLOR\n"
547 "{\n"
548 " if((pos.x * 640.0) > 200.0)\n"
549 " return float4(0.1, 0.2, 0.3, 0.4);\n"
550 " else\n"
551 " return float4(0.9, 0.8, 0.7, 0.6);\n"
552 "}";
554 static const char ps_ternary_source[] =
555 "float4 main(float2 pos : TEXCOORD0) : COLOR\n"
556 "{\n"
557 " return (pos.x < 0.5 ? float4(0.5, 0.25, 0.5, 0.75) : float4(0.6, 0.8, 0.1, 0.2));\n"
558 "}";
560 if (!init_test_context(&test_context))
561 return;
562 device = test_context.device;
564 todo_wine ps_code = compile_shader(ps_if_source, "ps_2_0");
565 if (ps_code)
567 draw_quad(device, ps_code);
568 init_readback(device, &rb);
570 for (i = 0; i < 200; i += 40)
572 v = get_readback_vec4(&rb, i, 0);
573 ok(compare_vec4(v, 0.9f, 0.8f, 0.7f, 0.6f, 0),
574 "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v->x, v->y, v->z, v->w);
577 for (i = 240; i < 640; i += 40)
579 v = get_readback_vec4(&rb, i, 0);
580 ok(compare_vec4(v, 0.1f, 0.2f, 0.3f, 0.4f, 0),
581 "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v->x, v->y, v->z, v->w);
584 release_readback(&rb);
585 ID3D10Blob_Release(ps_code);
588 todo_wine ps_code = compile_shader(ps_ternary_source, "ps_2_0");
589 if (ps_code)
591 draw_quad(device, ps_code);
592 init_readback(device, &rb);
594 for (i = 0; i < 320; i += 40)
596 v = get_readback_vec4(&rb, i, 0);
597 ok(compare_vec4(v, 0.5f, 0.25f, 0.5f, 0.75f, 0),
598 "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v->x, v->y, v->z, v->w);
601 for (i = 360; i < 640; i += 40)
603 v = get_readback_vec4(&rb, i, 0);
604 ok(compare_vec4(v, 0.6f, 0.8f, 0.1f, 0.2f, 0),
605 "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v->x, v->y, v->z, v->w);
608 release_readback(&rb);
609 ID3D10Blob_Release(ps_code);
612 release_test_context(&test_context);
615 static void test_float_vectors(void)
617 struct test_context test_context;
618 ID3DXConstantTable *constants;
619 ID3D10Blob *ps_code = NULL;
620 IDirect3DDevice9 *device;
621 struct vec4 v;
622 HRESULT hr;
624 static const char ps_indexing_source[] =
625 "float4 main() : COLOR\n"
626 "{\n"
627 " float4 color;\n"
628 " color[0] = 0.020;\n"
629 " color[1] = 0.245;\n"
630 " color[2] = 0.351;\n"
631 " color[3] = 1.0;\n"
632 " return color;\n"
633 "}";
635 /* A uniform index is used so that the compiler can't optimize. */
636 static const char ps_uniform_indexing_source[] =
637 "uniform int i;\n"
638 "float4 main() : COLOR\n"
639 "{\n"
640 " float4 color = float4(0.5, 0.4, 0.3, 0.2);\n"
641 " color.g = color[i];\n"
642 " color.b = 0.8;\n"
643 " return color;\n"
644 "}";
646 if (!init_test_context(&test_context))
647 return;
648 device = test_context.device;
650 todo_wine ps_code = compile_shader(ps_indexing_source, "ps_2_0");
651 if (ps_code)
653 draw_quad(device, ps_code);
655 v = get_color_vec4(device, 0, 0);
656 ok(compare_vec4(&v, 0.02f, 0.245f, 0.351f, 1.0f, 0),
657 "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v.x, v.y, v.z, v.w);
659 ID3D10Blob_Release(ps_code);
662 todo_wine ps_code = compile_shader(ps_uniform_indexing_source, "ps_2_0");
663 if (ps_code)
665 hr = pD3DXGetShaderConstantTable(ID3D10Blob_GetBufferPointer(ps_code), &constants);
666 ok(hr == D3D_OK, "Failed to get constants, hr %#x.\n", hr);
667 hr = ID3DXConstantTable_SetInt(constants, device, "i", 2);
668 ok(hr == D3D_OK, "Failed to set constant, hr %#x.\n", hr);
669 ID3DXConstantTable_Release(constants);
670 draw_quad(device, ps_code);
672 v = get_color_vec4(device, 0, 0);
673 ok(compare_vec4(&v, 0.5f, 0.3f, 0.8f, 0.2f, 0),
674 "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v.x, v.y, v.z, v.w);
676 ID3D10Blob_Release(ps_code);
679 release_test_context(&test_context);
682 static void test_trig(void)
684 struct test_context test_context;
685 ID3D10Blob *ps_code = NULL;
686 IDirect3DDevice9 *device;
687 const struct vec4 *v;
688 struct readback rb;
689 unsigned int i;
691 static const char ps_source[] =
692 "float4 main(float x : TEXCOORD0) : COLOR\n"
693 "{\n"
694 " const float pi2 = 6.2831853;\n"
695 " float calcd_sin = (sin(x * pi2) + 1)/2;\n"
696 " float calcd_cos = (cos(x * pi2) + 1)/2;\n"
697 " return float4(calcd_sin, calcd_cos, 0, 0);\n"
698 "}";
700 if (!init_test_context(&test_context))
701 return;
702 device = test_context.device;
704 todo_wine ps_code = compile_shader(ps_source, "ps_2_0");
705 if (ps_code)
707 draw_quad(device, ps_code);
708 init_readback(device, &rb);
710 for (i = 0; i < 32; ++i)
712 float expect_x = (sinf(i * 2 * M_PI / 32) + 1.0f) / 2.0f;
713 float expect_y = (cosf(i * 2 * M_PI / 32) + 1.0f) / 2.0f;
714 v = get_readback_vec4(&rb, i * 640 / 32, 0);
715 ok(compare_vec4(v, expect_x, expect_y, 0.0f, 0.0f, 4096),
716 "Test %u: Got {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
717 i, v->x, v->y, v->z, v->w, expect_x, expect_y, 0.0f, 0.0f);
720 release_readback(&rb);
721 ID3D10Blob_Release(ps_code);
723 release_test_context(&test_context);
726 static void test_comma(void)
728 struct test_context test_context;
729 ID3D10Blob *ps_code = NULL;
730 struct vec4 v;
732 static const char ps_source[] =
733 "float4 main(float x: TEXCOORD0): COLOR\n"
734 "{\n"
735 " float4 ret;\n"
736 " return (ret = float4(0.1, 0.2, 0.3, 0.4)), ret + 0.5;\n"
737 "}";
739 if (!init_test_context(&test_context))
740 return;
742 todo_wine ps_code = compile_shader(ps_source, "ps_2_0");
743 if (ps_code)
745 draw_quad(test_context.device, ps_code);
747 v = get_color_vec4(test_context.device, 0, 0);
748 ok(compare_vec4(&v, 0.6f, 0.7f, 0.8f, 0.9f, 0),
749 "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v.x, v.y, v.z, v.w);
751 ID3D10Blob_Release(ps_code);
753 release_test_context(&test_context);
756 static void test_return(void)
758 struct test_context test_context;
759 ID3D10Blob *ps_code = NULL;
760 struct vec4 v;
762 static const char *void_source =
763 "void main(float x : TEXCOORD0, out float4 ret : COLOR)\n"
764 "{\n"
765 " ret = float4(0.1, 0.2, 0.3, 0.4);\n"
766 " return;\n"
767 " ret = float4(0.5, 0.6, 0.7, 0.8);\n"
768 "}";
770 static const char *implicit_conversion_source =
771 "float4 main(float x : TEXCOORD0) : COLOR\n"
772 "{\n"
773 " return float2x2(0.4, 0.3, 0.2, 0.1);\n"
774 "}";
776 if (!init_test_context(&test_context))
777 return;
779 todo_wine ps_code = compile_shader(void_source, "ps_2_0");
780 if (ps_code)
782 draw_quad(test_context.device, ps_code);
784 v = get_color_vec4(test_context.device, 0, 0);
785 ok(compare_vec4(&v, 0.1f, 0.2f, 0.3f, 0.4f, 0),
786 "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v.x, v.y, v.z, v.w);
788 ID3D10Blob_Release(ps_code);
791 todo_wine ps_code = compile_shader(implicit_conversion_source, "ps_2_0");
792 if (ps_code)
794 draw_quad(test_context.device, ps_code);
796 v = get_color_vec4(test_context.device, 0, 0);
797 ok(compare_vec4(&v, 0.4f, 0.3f, 0.2f, 0.1f, 0),
798 "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v.x, v.y, v.z, v.w);
800 ID3D10Blob_Release(ps_code);
803 release_test_context(&test_context);
806 static void test_array_dimensions(void)
808 struct test_context test_context;
809 ID3D10Blob *ps_code = NULL;
810 struct vec4 v;
812 static const char shader[] =
813 "float4 main(float x : TEXCOORD0) : COLOR\n"
814 "{\n"
815 " const int dim = 4;\n"
816 " float a[2 * 2] = {0.1, 0.2, 0.3, 0.4};\n"
817 " float b[4.1] = a;\n"
818 " float c[dim] = b;\n"
819 " float d[true] = {c[0]};\n"
820 " float e[65536];\n"
821 " return float4(d[0], c[0], c[1], c[3]);\n"
822 "}";
824 if (!init_test_context(&test_context))
825 return;
827 todo_wine ps_code = compile_shader(shader, "ps_2_0");
828 if (ps_code)
830 draw_quad(test_context.device, ps_code);
832 v = get_color_vec4(test_context.device, 0, 0);
833 ok(compare_vec4(&v, 0.1f, 0.1f, 0.2f, 0.4f, 0),
834 "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v.x, v.y, v.z, v.w);
836 ID3D10Blob_Release(ps_code);
839 release_test_context(&test_context);
842 static void test_majority(void)
844 static const D3DXMATRIX matrix = {{{0.1, 0.2, 0.0, 0.0, 0.3, 0.4}}};
845 struct test_context test_context;
846 ID3DXConstantTable *constants;
847 ID3D10Blob *ps_code = NULL;
848 IDirect3DDevice9 *device;
849 struct vec4 v;
850 HRESULT hr;
852 static const char ps_typedef_source[] =
853 "typedef float2x2 matrix_t;\n"
854 "typedef row_major matrix_t row_matrix_t;\n"
855 "typedef column_major matrix_t col_matrix_t;\n"
856 "uniform row_matrix_t r;\n"
857 "uniform col_matrix_t c;\n"
858 "float4 main() : COLOR\n"
859 "{\n"
860 " float4 ret;\n"
861 " ret.xy = mul(r, float2(0.5, 0.6));\n"
862 " ret.zw = mul(c, float2(0.5, 0.6));\n"
863 " return ret;\n"
864 "}";
866 static const char ps_default_source[] =
867 "#pragma pack_matrix(row_major)\n"
868 "uniform float2x2 r;\n"
869 "#pragma pack_matrix(column_major)\n"
870 "uniform float2x2 c;\n"
871 "float4 main() : COLOR\n"
872 "{\n"
873 " float4 ret;\n"
874 " ret.xy = mul(r, float2(0.5, 0.6));\n"
875 " ret.zw = mul(c, float2(0.5, 0.6));\n"
876 " return ret;\n"
877 "}";
879 if (!init_test_context(&test_context))
880 return;
881 device = test_context.device;
883 todo_wine ps_code = compile_shader(ps_typedef_source, "ps_2_0");
884 if (ps_code)
886 hr = pD3DXGetShaderConstantTable(ID3D10Blob_GetBufferPointer(ps_code), &constants);
887 ok(hr == D3D_OK, "Failed to get constant table, hr %#x.\n", hr);
888 hr = ID3DXConstantTable_SetMatrix(constants, device, "r", &matrix);
889 ok(hr == D3D_OK, "Failed to get constant table, hr %#x.\n", hr);
890 hr = ID3DXConstantTable_SetMatrix(constants, device, "c", &matrix);
891 ok(hr == D3D_OK, "Failed to get constant table, hr %#x.\n", hr);
892 ID3DXConstantTable_Release(constants);
894 draw_quad(test_context.device, ps_code);
896 v = get_color_vec4(test_context.device, 0, 0);
897 ok(compare_vec4(&v, 0.17f, 0.39f, 0.17f, 0.39f, 1),
898 "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v.x, v.y, v.z, v.w);
900 ID3D10Blob_Release(ps_code);
903 todo_wine ps_code = compile_shader(ps_default_source, "ps_2_0");
904 if (ps_code)
906 hr = pD3DXGetShaderConstantTable(ID3D10Blob_GetBufferPointer(ps_code), &constants);
907 ok(hr == D3D_OK, "Failed to get constant table, hr %#x.\n", hr);
908 hr = ID3DXConstantTable_SetMatrix(constants, device, "r", &matrix);
909 ok(hr == D3D_OK, "Failed to get constant table, hr %#x.\n", hr);
910 hr = ID3DXConstantTable_SetMatrix(constants, device, "c", &matrix);
911 ok(hr == D3D_OK, "Failed to get constant table, hr %#x.\n", hr);
912 ID3DXConstantTable_Release(constants);
914 draw_quad(test_context.device, ps_code);
916 v = get_color_vec4(test_context.device, 0, 0);
917 ok(compare_vec4(&v, 0.17f, 0.39f, 0.17f, 0.39f, 1),
918 "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v.x, v.y, v.z, v.w);
920 ID3D10Blob_Release(ps_code);
923 release_test_context(&test_context);
926 static void test_struct_assignment(void)
928 struct test_context test_context;
929 ID3D10Blob *ps_code = NULL;
930 struct vec4 v;
932 static const char ps_source[] =
933 "struct apple\n"
934 "{\n"
935 " struct\n"
936 " {\n"
937 " float4 a;\n"
938 " } m;\n"
939 " float4 b;\n"
940 "};\n"
941 "float4 main() : COLOR\n"
942 "{\n"
943 " struct apple q, r, s;\n"
944 " q.m.a = float4(0.1, 0.2, 0.3, 0.4);\n"
945 " q.b = float4(0.5, 0.1, 0.4, 0.5);\n"
946 " s = r = q;\n"
947 " return s.m.a + s.b;\n"
948 "}";
950 if (!init_test_context(&test_context))
951 return;
953 todo_wine ps_code = compile_shader(ps_source, "ps_2_0");
954 if (ps_code)
956 draw_quad(test_context.device, ps_code);
958 v = get_color_vec4(test_context.device, 0, 0);
959 ok(compare_vec4(&v, 0.6f, 0.3f, 0.7f, 0.9f, 1),
960 "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v.x, v.y, v.z, v.w);
962 ID3D10Blob_Release(ps_code);
964 release_test_context(&test_context);
967 static void test_struct_semantics(void)
969 struct test_context test_context;
970 ID3D10Blob *ps_code = NULL;
971 struct vec4 v;
973 static const char ps_source[] =
974 "struct input\n"
975 "{\n"
976 " struct\n"
977 " {\n"
978 " float4 texcoord : TEXCOORD0;\n"
979 " } m;\n"
980 "};\n"
981 "struct output\n"
982 "{\n"
983 " struct\n"
984 " {\n"
985 " float4 color : COLOR;\n"
986 " } m;\n"
987 "};\n"
988 "struct output main(struct input i)\n"
989 "{\n"
990 " struct output o;\n"
991 " o.m.color = i.m.texcoord;\n"
992 " return o;\n"
993 "}";
995 if (!init_test_context(&test_context))
996 return;
998 todo_wine ps_code = compile_shader(ps_source, "ps_2_0");
999 if (ps_code)
1001 draw_quad(test_context.device, ps_code);
1003 v = get_color_vec4(test_context.device, 64, 48);
1004 todo_wine ok(compare_vec4(&v, 0.1f, 0.1f, 0.0f, 0.0f, 4096),
1005 "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v.x, v.y, v.z, v.w);
1006 v = get_color_vec4(test_context.device, 320, 240);
1007 todo_wine ok(compare_vec4(&v, 0.5f, 0.5f, 0.0f, 0.0f, 4096),
1008 "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v.x, v.y, v.z, v.w);
1010 ID3D10Blob_Release(ps_code);
1012 release_test_context(&test_context);
1015 static void test_global_initializer(void)
1017 struct test_context test_context;
1018 ID3DXConstantTable *constants;
1019 ID3D10Blob *ps_code = NULL;
1020 struct vec4 v;
1021 HRESULT hr;
1023 static const char ps_source[] =
1024 "float myfunc()\n"
1025 "{\n"
1026 " return 0.6;\n"
1027 "}\n"
1028 "static float sf = myfunc() + 0.2;\n"
1029 "uniform float uf = 0.2;\n"
1030 "float4 main() : COLOR\n"
1031 "{\n"
1032 " return float4(sf, uf, 0, 0);\n"
1033 "}";
1035 if (!init_test_context(&test_context))
1036 return;
1038 todo_wine ps_code = compile_shader(ps_source, "ps_2_0");
1039 if (ps_code)
1041 hr = pD3DXGetShaderConstantTable(ID3D10Blob_GetBufferPointer(ps_code), &constants);
1042 ok(hr == D3D_OK, "Failed to get constant table, hr %#x.\n", hr);
1043 hr = ID3DXConstantTable_SetDefaults(constants, test_context.device);
1044 ok(hr == D3D_OK, "Failed to get constant table, hr %#x.\n", hr);
1045 ID3DXConstantTable_Release(constants);
1046 draw_quad(test_context.device, ps_code);
1048 v = get_color_vec4(test_context.device, 0, 0);
1049 todo_wine ok(compare_vec4(&v, 0.8f, 0.2f, 0.0f, 0.0f, 4096),
1050 "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v.x, v.y, v.z, v.w);
1052 ID3D10Blob_Release(ps_code);
1054 release_test_context(&test_context);
1057 static void test_samplers(void)
1059 struct test_context test_context;
1060 IDirect3DTexture9 *texture;
1061 ID3D10Blob *ps_code = NULL;
1062 D3DLOCKED_RECT map_desc;
1063 unsigned int i;
1064 struct vec4 v;
1065 HRESULT hr;
1067 static const char *tests[] =
1069 "sampler s;\n"
1070 "float4 main() : COLOR\n"
1071 "{\n"
1072 " return tex2D(s, float2(0.5, 0.5));\n"
1073 "}",
1075 "SamplerState s;\n"
1076 "float4 main() : COLOR\n"
1077 "{\n"
1078 " return tex2D(s, float2(0.5, 0.5));\n"
1079 "}",
1081 "sampler2D s;\n"
1082 "float4 main() : COLOR\n"
1083 "{\n"
1084 " return tex2D(s, float2(0.5, 0.5));\n"
1085 "}",
1087 "sampler s;\n"
1088 "Texture2D t;\n"
1089 "float4 main() : COLOR\n"
1090 "{\n"
1091 " return t.Sample(s, float2(0.5, 0.5));\n"
1092 "}",
1094 "SamplerState s;\n"
1095 "Texture2D t;\n"
1096 "float4 main() : COLOR\n"
1097 "{\n"
1098 " return t.Sample(s, float2(0.5, 0.5));\n"
1099 "}",
1102 if (!init_test_context(&test_context))
1103 return;
1105 hr = IDirect3DDevice9_CreateTexture(test_context.device, 2, 2, 1, D3DUSAGE_DYNAMIC,
1106 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
1107 ok(hr == D3D_OK, "Failed to create texture, hr %#x.\n", hr);
1109 hr = IDirect3DTexture9_LockRect(texture, 0, &map_desc, NULL, D3DLOCK_DISCARD);
1110 ok(hr == D3D_OK, "Failed to map texture, hr %#x.\n", hr);
1111 memset(map_desc.pBits, 0, 2 * map_desc.Pitch);
1112 ((DWORD *)map_desc.pBits)[1] = 0x00ff00ff;
1113 hr = IDirect3DTexture9_UnlockRect(texture, 0);
1114 ok(hr == D3D_OK, "Failed to unmap texture, hr %#x.\n", hr);
1116 hr = IDirect3DDevice9_SetTexture(test_context.device, 0, (IDirect3DBaseTexture9 *)texture);
1117 ok(hr == D3D_OK, "Failed to set texture, hr %#x.\n", hr);
1118 hr = IDirect3DDevice9_SetSamplerState(test_context.device, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
1119 ok(hr == D3D_OK, "Failed to set sampler state, hr %#x.\n", hr);
1121 for (i = 0; i < ARRAY_SIZE(tests); ++i)
1123 hr = IDirect3DDevice9_Clear(test_context.device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255, 0, 0), 1.0f, 0);
1124 ok(hr == D3D_OK, "Test %u: Failed to clear, hr %#x.\n", i, hr);
1125 todo_wine ps_code = compile_shader(tests[i], "ps_2_0");
1126 if (ps_code)
1128 draw_quad(test_context.device, ps_code);
1130 v = get_color_vec4(test_context.device, 0, 0);
1131 todo_wine ok(compare_vec4(&v, 0.25f, 0.0f, 0.25f, 0.0f, 128),
1132 "Test %u: Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", i, v.x, v.y, v.z, v.w);
1134 ID3D10Blob_Release(ps_code);
1138 IDirect3DTexture9_Release(texture);
1139 release_test_context(&test_context);
1142 static void check_constant_desc(const char *prefix, const D3DXCONSTANT_DESC *desc,
1143 const D3DXCONSTANT_DESC *expect, BOOL nonzero_defaultvalue)
1145 ok(!strcmp(desc->Name, expect->Name), "%s: got Name %s.\n", prefix, debugstr_a(desc->Name));
1146 ok(desc->RegisterSet == expect->RegisterSet, "%s: got RegisterSet %#x.\n", prefix, desc->RegisterSet);
1147 if (desc->RegisterSet == D3DXRS_SAMPLER)
1148 ok(desc->RegisterIndex == expect->RegisterIndex, "%s: got RegisterIndex %u.\n", prefix, desc->RegisterIndex);
1149 ok(desc->RegisterCount == expect->RegisterCount, "%s: got RegisterCount %u.\n", prefix, desc->RegisterCount);
1150 ok(desc->Class == expect->Class, "%s: got Class %#x.\n", prefix, desc->Class);
1151 ok(desc->Type == expect->Type, "%s: got Type %#x.\n", prefix, desc->Type);
1152 ok(desc->Rows == expect->Rows, "%s: got Rows %u.\n", prefix, desc->Rows);
1153 ok(desc->Columns == expect->Columns, "%s: got Columns %u.\n", prefix, desc->Columns);
1154 ok(desc->Elements == expect->Elements, "%s: got Elements %u.\n", prefix, desc->Elements);
1155 ok(desc->StructMembers == expect->StructMembers, "%s: got StructMembers %u.\n", prefix, desc->StructMembers);
1156 ok(desc->Bytes == expect->Bytes, "%s: got Bytes %u.\n", prefix, desc->Bytes);
1157 ok(!!desc->DefaultValue == nonzero_defaultvalue, "%s: got DefaultValue %p.\n", prefix, desc->DefaultValue);
1160 static void test_constant_table(void)
1162 static const char *source =
1163 "typedef float3x3 matrix_t;\n"
1164 "struct matrix_record { float3x3 a; } dummy;\n"
1165 "uniform float4 a;\n"
1166 "uniform float b;\n"
1167 "uniform float unused;\n"
1168 "uniform float3x1 c;\n"
1169 "uniform row_major float3x1 d;\n"
1170 "uniform uint e;\n"
1171 "uniform struct\n"
1172 "{\n"
1173 " float2x2 a;\n"
1174 " float b[2];\n"
1175 " float c;\n"
1176 "#pragma pack_matrix(row_major)\n"
1177 " float2x2 d;\n"
1178 "} f;\n"
1179 "uniform bool2 g[5];\n"
1180 "uniform matrix_t i;\n"
1181 "uniform struct matrix_record j;\n"
1182 "uniform matrix<float,3,1> k;\n"
1183 "sampler l : register(s5);\n"
1184 "sampler m {};\n"
1185 "texture dummy_texture;\n"
1186 "sampler n\n"
1187 "{\n"
1188 " Texture = dummy_texture;\n"
1189 " foo = bar + 2;\n"
1190 "};\n"
1191 "SamplerState o\n"
1192 "{\n"
1193 " Texture = dummy_texture;\n"
1194 " foo = bar + 2;\n"
1195 "};\n"
1196 "texture2D p;\n"
1197 "sampler q : register(s7);\n"
1198 "SamplerState r : register(s8);\n"
1199 "sampler2D s;\n"
1200 "float4 main(uniform float4 h, sampler t, uniform sampler u) : COLOR\n"
1201 "{\n"
1202 " return b + c._31 + d._31 + f.d._22 + tex2D(l, g[e]) + tex3D(m, h.xyz) + i._33 + j.a._33 + k._31\n"
1203 " + tex2D(n, a.xy) + tex2D(o, a.xy) + p.Sample(r, a.xy) + p.Sample(q, a.xy) + tex2D(s, a.xy)\n"
1204 " + tex2D(t, a.xy) + tex2D(u, a.xy);\n"
1205 "}";
1207 D3DXCONSTANTTABLE_DESC table_desc;
1208 ID3DXConstantTable *constants;
1209 ID3D10Blob *ps_code = NULL;
1210 D3DXHANDLE handle, field;
1211 D3DXCONSTANT_DESC desc;
1212 unsigned int i, j;
1213 HRESULT hr;
1214 UINT count;
1216 static const D3DXCONSTANT_DESC expect_constants[] =
1218 {"$h", D3DXRS_FLOAT4, 0, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 4, 1, 0, 16},
1219 {"$u", D3DXRS_SAMPLER, 10, 1, D3DXPC_OBJECT, D3DXPT_SAMPLER2D, 1, 1, 1, 0, 4},
1220 {"a", D3DXRS_FLOAT4, 0, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 4, 1, 0, 16},
1221 {"b", D3DXRS_FLOAT4, 0, 1, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 1, 0, 4},
1222 {"c", D3DXRS_FLOAT4, 0, 1, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 3, 1, 1, 0, 12},
1223 {"d", D3DXRS_FLOAT4, 0, 3, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 1, 1, 0, 12},
1224 {"e", D3DXRS_FLOAT4, 0, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4},
1225 {"f", D3DXRS_FLOAT4, 0, 7, D3DXPC_STRUCT, D3DXPT_VOID, 1, 11, 1, 4, 44},
1226 {"g", D3DXRS_FLOAT4, 0, 5, D3DXPC_VECTOR, D3DXPT_BOOL, 1, 2, 5, 0, 40},
1227 {"i", D3DXRS_FLOAT4, 0, 3, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 3, 1, 0, 36},
1228 {"j", D3DXRS_FLOAT4, 0, 3, D3DXPC_STRUCT, D3DXPT_VOID, 1, 9, 1, 1, 36},
1229 {"k", D3DXRS_FLOAT4, 0, 3, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 1, 1, 0, 12},
1230 {"l", D3DXRS_SAMPLER, 5, 1, D3DXPC_OBJECT, D3DXPT_SAMPLER2D, 1, 1, 1, 0, 4},
1231 {"m", D3DXRS_SAMPLER, 2, 1, D3DXPC_OBJECT, D3DXPT_SAMPLER3D, 1, 1, 1, 0, 4},
1232 {"n", D3DXRS_SAMPLER, 3, 1, D3DXPC_OBJECT, D3DXPT_SAMPLER2D, 1, 1, 1, 0, 4},
1233 {"o", D3DXRS_SAMPLER, 4, 1, D3DXPC_OBJECT, D3DXPT_SAMPLER2D, 1, 1, 1, 0, 4},
1234 {"q+p", D3DXRS_SAMPLER, 0, 1, D3DXPC_OBJECT, D3DXPT_TEXTURE2D, 1, 4, 1, 0, 16},
1235 {"r+p", D3DXRS_SAMPLER, 1, 1, D3DXPC_OBJECT, D3DXPT_TEXTURE2D, 1, 4, 1, 0, 16},
1236 {"s", D3DXRS_SAMPLER, 6, 1, D3DXPC_OBJECT, D3DXPT_SAMPLER2D, 1, 1, 1, 0, 4},
1237 {"t", D3DXRS_SAMPLER, 9, 1, D3DXPC_OBJECT, D3DXPT_SAMPLER2D, 1, 1, 1, 0, 4},
1240 static const D3DXCONSTANT_DESC expect_fields_f[] =
1242 {"a", D3DXRS_FLOAT4, 0, 2, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 2, 2, 1, 0, 16},
1243 {"b", D3DXRS_FLOAT4, 0, 2, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 2, 0, 8},
1244 {"c", D3DXRS_FLOAT4, 0, 1, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 1, 0, 4},
1245 {"d", D3DXRS_FLOAT4, 0, 2, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 2, 2, 1, 0, 16},
1248 static const D3DXCONSTANT_DESC expect_fields_j =
1249 {"a", D3DXRS_FLOAT4, 0, 3, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 3, 3, 1, 0, 36};
1251 todo_wine ps_code = compile_shader(source, "ps_2_0");
1252 if (!ps_code)
1253 return;
1255 hr = pD3DXGetShaderConstantTable(ID3D10Blob_GetBufferPointer(ps_code), &constants);
1256 ok(hr == D3D_OK, "Got hr %#x.\n", hr);
1258 hr = ID3DXConstantTable_GetDesc(constants, &table_desc);
1259 ok(hr == D3D_OK, "Got hr %#x.\n", hr);
1260 ok(table_desc.Version == D3DPS_VERSION(2, 0), "Got Version %#x.\n", table_desc.Version);
1261 ok(table_desc.Constants == ARRAY_SIZE(expect_constants), "Got %u constants.\n", table_desc.Constants);
1263 for (i = 0; i < table_desc.Constants; ++i)
1265 char prefix[30];
1267 handle = ID3DXConstantTable_GetConstant(constants, NULL, i);
1268 ok(!!handle, "Failed to get constant.\n");
1269 memset(&desc, 0xcc, sizeof(desc));
1270 count = 1;
1271 hr = ID3DXConstantTable_GetConstantDesc(constants, handle, &desc, &count);
1272 ok(hr == D3D_OK, "Got hr %#x.\n", hr);
1273 ok(count == 1, "Got count %u.\n", count);
1274 sprintf(prefix, "Test %u", i);
1275 check_constant_desc(prefix, &desc, &expect_constants[i], FALSE);
1277 if (!strcmp(desc.Name, "f"))
1279 for (j = 0; j < ARRAY_SIZE(expect_fields_f); ++j)
1281 field = ID3DXConstantTable_GetConstant(constants, handle, j);
1282 ok(!!field, "Failed to get constant.\n");
1283 memset(&desc, 0xcc, sizeof(desc));
1284 count = 1;
1285 hr = ID3DXConstantTable_GetConstantDesc(constants, field, &desc, &count);
1286 ok(hr == D3D_OK, "Got hr %#x.\n", hr);
1287 ok(count == 1, "Got count %u.\n", count);
1288 sprintf(prefix, "Test %u, %u", i, j);
1289 check_constant_desc(prefix, &desc, &expect_fields_f[j], !!j);
1292 else if (!strcmp(desc.Name, "j"))
1294 field = ID3DXConstantTable_GetConstant(constants, handle, 0);
1295 ok(!!field, "Failed to get constant.\n");
1296 memset(&desc, 0xcc, sizeof(desc));
1297 count = 1;
1298 hr = ID3DXConstantTable_GetConstantDesc(constants, field, &desc, &count);
1299 ok(hr == D3D_OK, "Got hr %#x.\n", hr);
1300 ok(count == 1, "Got count %u.\n", count);
1301 sprintf(prefix, "Test %u", i);
1302 check_constant_desc(prefix, &desc, &expect_fields_j, FALSE);
1306 ID3DXConstantTable_Release(constants);
1307 ID3D10Blob_Release(ps_code);
1310 static void test_fail(void)
1312 static const char *tests[] =
1314 /* 0 */
1315 "float4 test() : SV_TARGET\n"
1316 "{\n"
1317 " return y;\n"
1318 "}",
1320 "float4 test() : SV_TARGET\n"
1321 "{\n"
1322 " float4 x = float4(0, 0, 0, 0);\n"
1323 " x.xzzx = float4(1, 2, 3, 4);\n"
1324 " return x;\n"
1325 "}",
1327 "float4 test(float2 pos: TEXCOORD0) : SV_TARGET\n"
1328 "{\n"
1329 " float4 x = pos;\n"
1330 " return x;\n"
1331 "}",
1333 "float4 test(float2 pos, TEXCOORD0) ; SV_TARGET\n"
1334 "{\n"
1335 " pos = float4 x;\n"
1336 " mul(float4(5, 4, 3, 2), mvp) = x;\n"
1337 " return float4;\n"
1338 "}",
1340 "float4 563r(float2 45s: TEXCOORD0) : SV_TARGET\n"
1341 "{\n"
1342 " float2 x = 45s;\n"
1343 " return float4(x.x, x.y, 0, 0);\n"
1344 "}",
1346 /* 5 */
1347 "float4 test() : SV_TARGET\n"
1348 "{\n"
1349 " struct { int b,c; } x = {0};\n"
1350 " return y;\n"
1351 "}",
1353 "float4 test() : SV_TARGET\n"
1354 "{\n"
1355 " struct {} x = {};\n"
1356 " return y;\n"
1357 "}",
1359 "float4 test(float2 pos : TEXCOORD0) : SV_TARGET\n"
1360 "{\n"
1361 " return;\n"
1362 "}",
1364 "void test(float2 pos : TEXCOORD0)\n"
1365 "{\n"
1366 " return pos;\n"
1367 "}",
1369 "float4 test(float2 pos : TEXCOORD0) : SV_TARGET\n"
1370 "{\n"
1371 " return pos;\n"
1372 "}",
1374 /* 10 */
1375 "float4 test(float2 pos: TEXCOORD0) : SV_TARGET\n"
1376 "{\n"
1377 " float a[0];\n"
1378 " return float4(0, 0, 0, 0);\n"
1379 "}",
1381 "float4 test(float2 pos: TEXCOORD0) : SV_TARGET\n"
1382 "{\n"
1383 " float a[65537];\n"
1384 " return float4(0, 0, 0, 0);\n"
1385 "}",
1387 "float4 test(float2 pos: TEXCOORD0) : SV_TARGET\n"
1388 "{\n"
1389 " int x;\n"
1390 " float a[(x = 2)];\n"
1391 " return float4(0, 0, 0, 0);\n"
1392 "}",
1394 "uniform float4 test() : SV_TARGET\n"
1395 "{\n"
1396 " return float4(0, 0, 0, 0);\n"
1397 "}",
1399 "typedef row_major float4x4 matrix_t;\n"
1400 "typedef column_major matrix_t matrix2_t;\n"
1401 "float4 test() : SV_TARGET\n"
1402 "{\n"
1403 " return float4(0, 0, 0, 0);\n"
1404 "}",
1406 /* 15 */
1407 "float4 test()\n"
1408 "{\n"
1409 " return float4(0, 0, 0, 0);\n"
1410 "}",
1412 "float4 test(out float4 o : SV_TARGET)\n"
1413 "{\n"
1414 " o = float4(1, 1, 1, 1);\n"
1415 " return float4(0, 0, 0, 0);\n"
1416 "}",
1418 "struct {float4 a;};\n"
1419 "float4 test() : SV_TARGET\n"
1420 "{\n"
1421 " return float4(0, 0, 0, 0);\n"
1422 "}",
1425 static const char *targets[] = {"ps_2_0", "ps_3_0", "ps_4_0"};
1427 ID3D10Blob *compiled, *errors;
1428 unsigned int i, j;
1429 HRESULT hr;
1431 for (j = 0; j < ARRAY_SIZE(targets); ++j)
1433 for (i = 0; i < ARRAY_SIZE(tests); ++i)
1435 compiled = errors = NULL;
1436 hr = ppD3DCompile(tests[i], strlen(tests[i]), NULL, NULL, NULL, "test", targets[j], 0, 0, &compiled, &errors);
1437 ok(hr == E_FAIL, "Test %u, target %s, got unexpected hr %#x.\n", i, targets[j], hr);
1438 ok(!!errors, "Test %u, target %s, expected non-NULL error blob.\n", i, targets[j]);
1439 ok(!compiled, "Test %u, target %s, expected no compiled shader blob.\n", i, targets[j]);
1440 ID3D10Blob_Release(errors);
1445 static BOOL load_d3dcompiler(void)
1447 HMODULE module;
1449 #if D3D_COMPILER_VERSION == 47
1450 if (!(module = LoadLibraryA("d3dcompiler_47.dll"))) return FALSE;
1451 pD3DCompile2 = (void*)GetProcAddress(module, "D3DCompile2");
1452 pD3DCompileFromFile = (void*)GetProcAddress(module, "D3DCompileFromFile");
1453 #else
1454 if (!(module = LoadLibraryA("d3dcompiler_43.dll"))) return FALSE;
1455 #endif
1457 ppD3DCompile = (void*)GetProcAddress(module, "D3DCompile");
1458 return TRUE;
1461 static HRESULT WINAPI test_d3dinclude_open(ID3DInclude *iface, D3D_INCLUDE_TYPE include_type,
1462 const char *filename, const void *parent_data, const void **data, UINT *bytes)
1464 static const char include1[] =
1465 "#define LIGHT float4(0.0f, 0.2f, 0.5f, 1.0f)\n";
1466 static const char include2[] =
1467 "#include \"include1.h\"\n"
1468 "float4 light_color = LIGHT;\n";
1469 char *buffer;
1471 trace("filename %s.\n", filename);
1472 trace("parent_data %p: %s.\n", parent_data, parent_data ? (char *)parent_data : "(null)");
1474 if (!strcmp(filename, "include1.h"))
1476 buffer = heap_alloc(strlen(include1));
1477 CopyMemory(buffer, include1, strlen(include1));
1478 *bytes = strlen(include1);
1479 ok(include_type == D3D_INCLUDE_LOCAL, "Unexpected include type %d.\n", include_type);
1480 ok(!strncmp(include2, parent_data, strlen(include2)),
1481 "Unexpected parent_data value.\n");
1483 else if (!strcmp(filename, "include\\include2.h"))
1485 buffer = heap_alloc(strlen(include2));
1486 CopyMemory(buffer, include2, strlen(include2));
1487 *bytes = strlen(include2);
1488 ok(!parent_data, "Unexpected parent_data value.\n");
1489 ok(include_type == D3D_INCLUDE_LOCAL, "Unexpected include type %d.\n", include_type);
1491 else
1493 ok(0, "Unexpected #include for file %s.\n", filename);
1494 return D3DERR_INVALIDCALL;
1497 *data = buffer;
1498 return S_OK;
1501 static HRESULT WINAPI test_d3dinclude_close(ID3DInclude *iface, const void *data)
1503 heap_free((void *)data);
1504 return S_OK;
1507 static const struct ID3DIncludeVtbl test_d3dinclude_vtbl =
1509 test_d3dinclude_open,
1510 test_d3dinclude_close
1513 struct test_d3dinclude
1515 ID3DInclude ID3DInclude_iface;
1518 static void test_d3dcompile(void)
1520 struct test_d3dinclude include = {{&test_d3dinclude_vtbl}};
1521 WCHAR filename[MAX_PATH], directory[MAX_PATH];
1522 ID3D10Blob *blob = NULL, *errors = NULL;
1523 CHAR filename_a[MAX_PATH];
1524 HRESULT hr;
1525 DWORD len;
1526 static const char ps_code[] =
1527 "#include \"include\\include2.h\"\n"
1528 "\n"
1529 "float4 main() : COLOR\n"
1530 "{\n"
1531 " return light_color;\n"
1532 "}";
1533 static const char include1[] =
1534 "#define LIGHT float4(0.0f, 0.2f, 0.5f, 1.0f)\n";
1535 static const char include1_wrong[] =
1536 "#define LIGHT nope\n";
1537 static const char include2[] =
1538 "#include \"include1.h\"\n"
1539 "float4 light_color = LIGHT;\n";
1541 create_file(L"source.ps", ps_code, strlen(ps_code), filename);
1542 create_directory(L"include");
1543 create_file(L"include\\include1.h", include1_wrong, strlen(include1_wrong), NULL);
1544 create_file(L"include1.h", include1, strlen(include1), NULL);
1545 create_file(L"include\\include2.h", include2, strlen(include2), NULL);
1547 len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL);
1548 WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, len, NULL, NULL);
1550 hr = ppD3DCompile(ps_code, sizeof(ps_code), filename_a, NULL, &include.ID3DInclude_iface, "main", "ps_2_0", 0, 0, &blob, &errors);
1551 todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
1552 todo_wine ok(!!blob, "Got unexpected blob.\n");
1553 ok(!errors, "Got unexpected errors.\n");
1554 if (blob)
1556 ID3D10Blob_Release(blob);
1557 blob = NULL;
1560 /* Also skip D3DCompile() D3D_COMPILE_STANDARD_FILE_INCLUDE tests from
1561 * d3dcompiler_43 or earlier since they crash on Windows. */
1562 if (!pD3DCompile2)
1564 skip("D3DCompile2() isn't supported.\n");
1565 goto cleanup;
1568 hr = ppD3DCompile(ps_code, sizeof(ps_code), NULL, NULL, D3D_COMPILE_STANDARD_FILE_INCLUDE,
1569 "main", "ps_2_0", 0, 0, &blob, &errors);
1570 ok(hr == E_FAIL, "Got hr %#x.\n", hr);
1571 ok(!blob, "Got unexpected blob.\n");
1572 ok(!!errors, "Got unexpected errors.\n");
1573 ID3D10Blob_Release(errors);
1574 errors = NULL;
1576 /* Windows always seems to resolve includes from the initial file location
1577 * instead of using the immediate parent, as it would be the case for
1578 * standard C preprocessor includes. */
1579 hr = ppD3DCompile(ps_code, sizeof(ps_code), filename_a, NULL, D3D_COMPILE_STANDARD_FILE_INCLUDE,
1580 "main", "ps_2_0", 0, 0, &blob, &errors);
1581 todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
1582 todo_wine ok(!!blob, "Got unexpected blob.\n");
1583 ok(!errors, "Got unexpected errors.\n");
1584 if (blob)
1586 ID3D10Blob_Release(blob);
1587 blob = NULL;
1590 hr = pD3DCompile2(ps_code, sizeof(ps_code), filename_a, NULL, &include.ID3DInclude_iface,
1591 "main", "ps_2_0", 0, 0, 0, NULL, 0, &blob, &errors);
1592 todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
1593 todo_wine ok(!!blob, "Got unexpected blob.\n");
1594 ok(!errors, "Got unexpected errors.\n");
1595 if (blob)
1597 ID3D10Blob_Release(blob);
1598 blob = NULL;
1601 hr = pD3DCompile2(ps_code, sizeof(ps_code), filename_a, NULL, D3D_COMPILE_STANDARD_FILE_INCLUDE,
1602 "main", "ps_2_0", 0, 0, 0, NULL, 0, &blob, &errors);
1603 todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
1604 todo_wine ok(!!blob, "Got unexpected blob.\n");
1605 ok(!errors, "Got unexpected errors.\n");
1606 if (blob)
1608 ID3D10Blob_Release(blob);
1609 blob = NULL;
1612 hr = pD3DCompileFromFile(L"nonexistent", NULL, NULL, "main", "vs_2_0", 0, 0, &blob, &errors);
1613 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "Got hr %#x.\n", hr);
1614 ok(!blob, "Got unexpected blob.\n");
1615 ok(!errors, "Got unexpected errors.\n");
1617 hr = pD3DCompileFromFile(filename, NULL, NULL, "main", "ps_2_0", 0, 0, &blob, &errors);
1618 ok(hr == E_FAIL, "Got hr %#x.\n", hr);
1619 ok(!blob, "Got unexpected blob.\n");
1620 ok(!!errors, "Got unexpected errors.\n");
1621 trace("%s.\n", (char *)ID3D10Blob_GetBufferPointer(errors));
1622 ID3D10Blob_Release(errors);
1623 errors = NULL;
1625 hr = pD3DCompileFromFile(filename, NULL, &include.ID3DInclude_iface, "main", "ps_2_0", 0, 0, &blob, &errors);
1626 todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
1627 todo_wine ok(!!blob, "Got unexpected blob.\n");
1628 ok(!errors, "Got unexpected errors.\n");
1629 if (blob)
1631 ID3D10Blob_Release(blob);
1632 blob = NULL;
1635 /* Windows always seems to resolve includes from the initial file location
1636 * instead of using the immediate parent, as it would be the case for
1637 * standard C preprocessor includes. */
1638 hr = pD3DCompileFromFile(filename, NULL, D3D_COMPILE_STANDARD_FILE_INCLUDE, "main", "ps_2_0", 0, 0, &blob, &errors);
1639 todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
1640 todo_wine ok(!!blob, "Got unexpected blob.\n");
1641 ok(!errors, "Got unexpected errors.\n");
1642 if (blob)
1644 ID3D10Blob_Release(blob);
1645 blob = NULL;
1648 GetCurrentDirectoryW(MAX_PATH, directory);
1649 SetCurrentDirectoryW(temp_dir);
1651 hr = ppD3DCompile(ps_code, sizeof(ps_code), "source.ps", NULL, D3D_COMPILE_STANDARD_FILE_INCLUDE,
1652 "main", "ps_2_0", 0, 0, &blob, &errors);
1653 todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
1654 todo_wine ok(!!blob, "Got unexpected blob.\n");
1655 ok(!errors, "Got unexpected errors.\n");
1656 if (blob)
1658 ID3D10Blob_Release(blob);
1659 blob = NULL;
1662 hr = pD3DCompile2(ps_code, sizeof(ps_code), "source.ps", NULL, D3D_COMPILE_STANDARD_FILE_INCLUDE,
1663 "main", "ps_2_0", 0, 0, 0, NULL, 0, &blob, &errors);
1664 todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
1665 todo_wine ok(!!blob, "Got unexpected blob.\n");
1666 ok(!errors, "Got unexpected errors.\n");
1667 if (blob)
1669 ID3D10Blob_Release(blob);
1670 blob = NULL;
1673 hr = pD3DCompileFromFile(L"source.ps", NULL, D3D_COMPILE_STANDARD_FILE_INCLUDE, "main", "ps_2_0", 0, 0, &blob, &errors);
1674 todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
1675 todo_wine ok(!!blob, "Got unexpected blob.\n");
1676 ok(!errors, "Got unexpected errors.\n");
1677 if (blob)
1679 ID3D10Blob_Release(blob);
1680 blob = NULL;
1683 SetCurrentDirectoryW(directory);
1685 cleanup:
1686 delete_file(L"source.ps");
1687 delete_file(L"include\\include1.h");
1688 delete_file(L"include1.h");
1689 delete_file(L"include\\include2.h");
1690 delete_directory(L"include");
1693 START_TEST(hlsl_d3d9)
1695 HMODULE mod;
1697 if (!load_d3dcompiler())
1699 win_skip("Could not load DLL.\n");
1700 return;
1703 if (!(mod = LoadLibraryA("d3dx9_36.dll")))
1705 win_skip("Failed to load d3dx9_36.dll.\n");
1706 return;
1708 pD3DXGetShaderConstantTable = (void *)GetProcAddress(mod, "D3DXGetShaderConstantTable");
1710 test_swizzle();
1711 test_math();
1712 test_conditionals();
1713 test_float_vectors();
1714 test_trig();
1715 test_comma();
1716 test_return();
1717 test_array_dimensions();
1718 test_majority();
1719 test_struct_assignment();
1720 test_struct_semantics();
1721 test_global_initializer();
1722 test_samplers();
1724 test_constant_table();
1725 test_fail();
1726 test_d3dcompile();