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
20 #include "wine/test.h"
21 #include "wine/heap.h"
23 #include "d3dcompiler.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
);
47 static WCHAR temp_dir
[MAX_PATH
];
49 static BOOL
create_file(const WCHAR
*filename
, const char *data
, unsigned int size
, WCHAR
*out_path
)
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
)
64 if (WriteFile(file
, data
, size
, &written
, NULL
))
69 lstrcpyW(out_path
, path
);
77 static void delete_file(const WCHAR
*filename
)
81 lstrcpyW(path
, temp_dir
);
82 lstrcatW(path
, filename
);
86 static BOOL
create_directory(const WCHAR
*dir
)
90 lstrcpyW(path
, temp_dir
);
92 return CreateDirectoryW(path
, NULL
);
95 static void delete_directory(const WCHAR
*dir
)
99 lstrcpyW(path
, temp_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
;
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
);
114 if (winetest_debug
> 1)
115 trace_(__FILE__
, line
)("%s\n", (char *)ID3D10Blob_GetBufferPointer(errors
));
116 ID3D10Blob_Release(errors
);
121 static IDirect3DDevice9
*create_device(HWND window
)
123 D3DPRESENT_PARAMETERS present_parameters
=
126 .hDeviceWindow
= window
,
127 .SwapEffect
= D3DSWAPEFFECT_DISCARD
,
128 .BackBufferWidth
= 640,
129 .BackBufferHeight
= 480,
130 .BackBufferFormat
= D3DFMT_A8R8G8B8
,
132 IDirect3DDevice9
*device
;
133 IDirect3DSurface9
*rt
;
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
);
146 skip("Failed to create a 3D device, hr %#x.\n", hr
);
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
);
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
);
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
);
176 IDirect3DDevice9
*device
;
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
);
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
;
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},
225 struct vec2 position
;
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"
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
);
279 IDirect3DSurface9
*surface
;
283 static void init_readback(IDirect3DDevice9
*device
, struct readback
*rb
)
285 IDirect3DSurface9
*rt
;
286 D3DSURFACE_DESC desc
;
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
)
323 init_readback(device
, &rb
);
324 ret
= *get_readback_vec4(&rb
, x
, y
);
325 release_readback(&rb
);
330 static BOOL
compare_float(float f
, float g
, unsigned int ulps
)
340 if (abs(x
- y
) > ulps
)
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
;
373 "uniform float4 color;\n"
374 "float4 main() : COLOR\n"
376 " float4 ret = color;\n"
377 " ret.gb = ret.ra;\n"
378 " ret.ra = float2(0.0101, 0.0404);\n"
381 {0.0101f
, 0.0303f
, 0.0202f
, 0.0404f
}
384 "float4 main() : COLOR\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"
390 {0.1f
, 0.6f
, 0.3f
, 0.5f
}
393 "float4 main() : COLOR\n"
396 " ret.zwyx = float4(0.1, 0.2, 0.3, 0.4);\n"
399 {0.4f
, 0.3f
, 0.1f
, 0.2f
}
402 "float4 main() : COLOR\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"
411 {0.3f
, 0.2f
, 0.4f
, 0.1f
}
414 "float4 main() : COLOR\n"
417 " ret.yxz.yx = float2(0.1, 0.2);\n"
419 " ret.wzyx.zyx.yx.x = 0.4;\n"
422 {0.1f
, 0.2f
, 0.4f
, 0.3f
}
425 "float4 main() : COLOR\n"
427 " float4 ret = float4(0.1, 0.2, 0.3, 0.4).ywxz.zyyz;\n"
430 {0.1f
, 0.4f
, 0.4f
, 0.1f
}
433 "float4 main() : COLOR\n"
435 " float4 ret = float4(0.1, 0.2, 0.3, 0.4);\n"
440 {0.3f
, 0.1f
, 0.4f
, 0.2f
}
443 "float4 main() : COLOR\n"
446 " ret.xyzw.xyzw = float4(0.1, 0.2, 0.3, 0.4);\n"
449 {0.1f
, 0.2f
, 0.3f
, 0.4f
}
453 if (!init_test_context(&test_context
))
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");
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
;
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"
496 " return float4(x * y - z / w + --u / -v,\n"
497 " z * x / y + w / -v,\n"
502 if (!init_test_context(&test_context
))
504 device
= test_context
.device
;
506 todo_wine ps_code
= compile_shader(ps_source
, "ps_2_0");
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
;
545 static const char ps_if_source
[] =
546 "float4 main(float2 pos : TEXCOORD0) : COLOR\n"
548 " if((pos.x * 640.0) > 200.0)\n"
549 " return float4(0.1, 0.2, 0.3, 0.4);\n"
551 " return float4(0.9, 0.8, 0.7, 0.6);\n"
554 static const char ps_ternary_source
[] =
555 "float4 main(float2 pos : TEXCOORD0) : COLOR\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"
560 if (!init_test_context(&test_context
))
562 device
= test_context
.device
;
564 todo_wine ps_code
= compile_shader(ps_if_source
, "ps_2_0");
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");
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
;
624 static const char ps_indexing_source
[] =
625 "float4 main() : COLOR\n"
628 " color[0] = 0.020;\n"
629 " color[1] = 0.245;\n"
630 " color[2] = 0.351;\n"
635 /* A uniform index is used so that the compiler can't optimize. */
636 static const char ps_uniform_indexing_source
[] =
638 "float4 main() : COLOR\n"
640 " float4 color = float4(0.5, 0.4, 0.3, 0.2);\n"
641 " color.g = color[i];\n"
646 if (!init_test_context(&test_context
))
648 device
= test_context
.device
;
650 todo_wine ps_code
= compile_shader(ps_indexing_source
, "ps_2_0");
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");
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
;
691 static const char ps_source
[] =
692 "float4 main(float x : TEXCOORD0) : COLOR\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"
700 if (!init_test_context(&test_context
))
702 device
= test_context
.device
;
704 todo_wine ps_code
= compile_shader(ps_source
, "ps_2_0");
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
;
732 static const char ps_source
[] =
733 "float4 main(float x: TEXCOORD0): COLOR\n"
736 " return (ret = float4(0.1, 0.2, 0.3, 0.4)), ret + 0.5;\n"
739 if (!init_test_context(&test_context
))
742 todo_wine ps_code
= compile_shader(ps_source
, "ps_2_0");
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
;
762 static const char *void_source
=
763 "void main(float x : TEXCOORD0, out float4 ret : COLOR)\n"
765 " ret = float4(0.1, 0.2, 0.3, 0.4);\n"
767 " ret = float4(0.5, 0.6, 0.7, 0.8);\n"
770 static const char *implicit_conversion_source
=
771 "float4 main(float x : TEXCOORD0) : COLOR\n"
773 " return float2x2(0.4, 0.3, 0.2, 0.1);\n"
776 if (!init_test_context(&test_context
))
779 todo_wine ps_code
= compile_shader(void_source
, "ps_2_0");
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");
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
;
812 static const char shader
[] =
813 "float4 main(float x : TEXCOORD0) : COLOR\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"
821 " return float4(d[0], c[0], c[1], c[3]);\n"
824 if (!init_test_context(&test_context
))
827 todo_wine ps_code
= compile_shader(shader
, "ps_2_0");
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
;
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"
861 " ret.xy = mul(r, float2(0.5, 0.6));\n"
862 " ret.zw = mul(c, float2(0.5, 0.6));\n"
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"
874 " ret.xy = mul(r, float2(0.5, 0.6));\n"
875 " ret.zw = mul(c, float2(0.5, 0.6));\n"
879 if (!init_test_context(&test_context
))
881 device
= test_context
.device
;
883 todo_wine ps_code
= compile_shader(ps_typedef_source
, "ps_2_0");
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");
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
;
932 static const char ps_source
[] =
941 "float4 main() : COLOR\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"
947 " return s.m.a + s.b;\n"
950 if (!init_test_context(&test_context
))
953 todo_wine ps_code
= compile_shader(ps_source
, "ps_2_0");
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
;
973 static const char ps_source
[] =
978 " float4 texcoord : TEXCOORD0;\n"
985 " float4 color : COLOR;\n"
988 "struct output main(struct input i)\n"
990 " struct output o;\n"
991 " o.m.color = i.m.texcoord;\n"
995 if (!init_test_context(&test_context
))
998 todo_wine ps_code
= compile_shader(ps_source
, "ps_2_0");
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
;
1023 static const char ps_source
[] =
1028 "static float sf = myfunc() + 0.2;\n"
1029 "uniform float uf = 0.2;\n"
1030 "float4 main() : COLOR\n"
1032 " return float4(sf, uf, 0, 0);\n"
1035 if (!init_test_context(&test_context
))
1038 todo_wine ps_code
= compile_shader(ps_source
, "ps_2_0");
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
;
1067 static const char *tests
[] =
1070 "float4 main() : COLOR\n"
1072 " return tex2D(s, float2(0.5, 0.5));\n"
1076 "float4 main() : COLOR\n"
1078 " return tex2D(s, float2(0.5, 0.5));\n"
1082 "float4 main() : COLOR\n"
1084 " return tex2D(s, float2(0.5, 0.5));\n"
1089 "float4 main() : COLOR\n"
1091 " return t.Sample(s, float2(0.5, 0.5));\n"
1096 "float4 main() : COLOR\n"
1098 " return t.Sample(s, float2(0.5, 0.5));\n"
1102 if (!init_test_context(&test_context
))
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");
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"
1176 "#pragma pack_matrix(row_major)\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"
1185 "texture dummy_texture;\n"
1188 " Texture = dummy_texture;\n"
1193 " Texture = dummy_texture;\n"
1197 "sampler q : register(s7);\n"
1198 "SamplerState r : register(s8);\n"
1200 "float4 main(uniform float4 h, sampler t, uniform sampler u) : COLOR\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"
1207 D3DXCONSTANTTABLE_DESC table_desc
;
1208 ID3DXConstantTable
*constants
;
1209 ID3D10Blob
*ps_code
= NULL
;
1210 D3DXHANDLE handle
, field
;
1211 D3DXCONSTANT_DESC desc
;
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");
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
)
1267 handle
= ID3DXConstantTable_GetConstant(constants
, NULL
, i
);
1268 ok(!!handle
, "Failed to get constant.\n");
1269 memset(&desc
, 0xcc, sizeof(desc
));
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
));
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
));
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
[] =
1315 "float4 test() : SV_TARGET\n"
1320 "float4 test() : SV_TARGET\n"
1322 " float4 x = float4(0, 0, 0, 0);\n"
1323 " x.xzzx = float4(1, 2, 3, 4);\n"
1327 "float4 test(float2 pos: TEXCOORD0) : SV_TARGET\n"
1329 " float4 x = pos;\n"
1333 "float4 test(float2 pos, TEXCOORD0) ; SV_TARGET\n"
1335 " pos = float4 x;\n"
1336 " mul(float4(5, 4, 3, 2), mvp) = x;\n"
1340 "float4 563r(float2 45s: TEXCOORD0) : SV_TARGET\n"
1342 " float2 x = 45s;\n"
1343 " return float4(x.x, x.y, 0, 0);\n"
1347 "float4 test() : SV_TARGET\n"
1349 " struct { int b,c; } x = {0};\n"
1353 "float4 test() : SV_TARGET\n"
1355 " struct {} x = {};\n"
1359 "float4 test(float2 pos : TEXCOORD0) : SV_TARGET\n"
1364 "void test(float2 pos : TEXCOORD0)\n"
1369 "float4 test(float2 pos : TEXCOORD0) : SV_TARGET\n"
1375 "float4 test(float2 pos: TEXCOORD0) : SV_TARGET\n"
1378 " return float4(0, 0, 0, 0);\n"
1381 "float4 test(float2 pos: TEXCOORD0) : SV_TARGET\n"
1383 " float a[65537];\n"
1384 " return float4(0, 0, 0, 0);\n"
1387 "float4 test(float2 pos: TEXCOORD0) : SV_TARGET\n"
1390 " float a[(x = 2)];\n"
1391 " return float4(0, 0, 0, 0);\n"
1394 "uniform float4 test() : SV_TARGET\n"
1396 " return float4(0, 0, 0, 0);\n"
1399 "typedef row_major float4x4 matrix_t;\n"
1400 "typedef column_major matrix_t matrix2_t;\n"
1401 "float4 test() : SV_TARGET\n"
1403 " return float4(0, 0, 0, 0);\n"
1409 " return float4(0, 0, 0, 0);\n"
1412 "float4 test(out float4 o : SV_TARGET)\n"
1414 " o = float4(1, 1, 1, 1);\n"
1415 " return float4(0, 0, 0, 0);\n"
1418 "struct {float4 a;};\n"
1419 "float4 test() : SV_TARGET\n"
1421 " return float4(0, 0, 0, 0);\n"
1425 static const char *targets
[] = {"ps_2_0", "ps_3_0", "ps_4_0"};
1427 ID3D10Blob
*compiled
, *errors
;
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)
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");
1454 if (!(module
= LoadLibraryA("d3dcompiler_43.dll"))) return FALSE
;
1457 ppD3DCompile
= (void*)GetProcAddress(module
, "D3DCompile");
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";
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
);
1493 ok(0, "Unexpected #include for file %s.\n", filename
);
1494 return D3DERR_INVALIDCALL
;
1501 static HRESULT WINAPI
test_d3dinclude_close(ID3DInclude
*iface
, const void *data
)
1503 heap_free((void *)data
);
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
];
1526 static const char ps_code
[] =
1527 "#include \"include\\include2.h\"\n"
1529 "float4 main() : COLOR\n"
1531 " return light_color;\n"
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");
1556 ID3D10Blob_Release(blob
);
1560 /* Also skip D3DCompile() D3D_COMPILE_STANDARD_FILE_INCLUDE tests from
1561 * d3dcompiler_43 or earlier since they crash on Windows. */
1564 skip("D3DCompile2() isn't supported.\n");
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
);
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");
1586 ID3D10Blob_Release(blob
);
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");
1597 ID3D10Blob_Release(blob
);
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");
1608 ID3D10Blob_Release(blob
);
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
);
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");
1631 ID3D10Blob_Release(blob
);
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");
1644 ID3D10Blob_Release(blob
);
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");
1658 ID3D10Blob_Release(blob
);
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");
1669 ID3D10Blob_Release(blob
);
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");
1679 ID3D10Blob_Release(blob
);
1683 SetCurrentDirectoryW(directory
);
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
)
1697 if (!load_d3dcompiler())
1699 win_skip("Could not load DLL.\n");
1703 if (!(mod
= LoadLibraryA("d3dx9_36.dll")))
1705 win_skip("Failed to load d3dx9_36.dll.\n");
1708 pD3DXGetShaderConstantTable
= (void *)GetProcAddress(mod
, "D3DXGetShaderConstantTable");
1712 test_conditionals();
1713 test_float_vectors();
1717 test_array_dimensions();
1719 test_struct_assignment();
1720 test_struct_semantics();
1721 test_global_initializer();
1724 test_constant_table();