2 * Copyright (C) 2008 Stefan Dösinger
3 * Copyright (C) 2009 Matteo Bruni
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
21 #include "wine/test.h"
25 #include "resources.h"
27 static HRESULT
create_file(const char *filename
, const char *data
, const unsigned int size
)
32 hfile
= CreateFileA(filename
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, 0);
33 if(hfile
== INVALID_HANDLE_VALUE
) return HRESULT_FROM_WIN32(GetLastError());
35 if(WriteFile(hfile
, data
, size
, &received
, NULL
))
42 return D3DERR_INVALIDCALL
;
45 static HRESULT WINAPI
testD3DXInclude_open(ID3DXInclude
*iface
, D3DXINCLUDE_TYPE include_type
,
46 const char *filename
, const void *parent_data
, const void **data
, UINT
*bytes
)
49 static const char shader
[] =
50 "#include \"incl.vsh\"\n"
52 static const char include
[] = "#define REGISTER r0\nvs.1.1\n";
53 static const char include2
[] = "#include \"incl3.vsh\"\n";
54 static const char include3
[] = "vs.1.1\n";
56 trace("filename %s.\n", filename
);
57 trace("parent_data %p: %s.\n", parent_data
, parent_data
? (char *)parent_data
: "(null)");
59 if (!strcmp(filename
, "shader.vsh"))
61 buffer
= HeapAlloc(GetProcessHeap(), 0, sizeof(shader
));
62 memcpy(buffer
, shader
, sizeof(shader
));
63 *bytes
= sizeof(shader
);
65 else if (!strcmp(filename
, "incl.vsh"))
67 buffer
= HeapAlloc(GetProcessHeap(), 0, sizeof(include
));
68 memcpy(buffer
, include
, sizeof(include
));
69 *bytes
= sizeof(include
);
70 /* This is included from the first D3DXAssembleShader with non-null ID3DXInclude test
71 * (parent_data == NULL) and from shader.vsh / shader[] (with matching parent_data).
72 * Allow both cases. */
73 ok(parent_data
== NULL
|| !strncmp(shader
, parent_data
, strlen(shader
)), "wrong parent_data value\n");
75 else if (!strcmp(filename
, "incl2.vsh"))
77 buffer
= HeapAlloc(GetProcessHeap(), 0, sizeof(include2
));
78 memcpy(buffer
, include2
, sizeof(include2
));
79 *bytes
= sizeof(include2
);
81 else if (!strcmp(filename
, "incl3.vsh"))
83 buffer
= HeapAlloc(GetProcessHeap(), 0, sizeof(include3
));
84 memcpy(buffer
, include3
, sizeof(include3
));
85 *bytes
= sizeof(include3
);
86 /* Also check for the correct parent_data content */
87 ok(parent_data
!= NULL
&& !strncmp(include2
, parent_data
, strlen(include2
)), "wrong parent_data value\n");
89 else if (!strcmp(filename
, "include/incl3.vsh"))
91 buffer
= HeapAlloc(GetProcessHeap(), 0, sizeof(include
));
92 memcpy(buffer
, include
, sizeof(include
));
93 *bytes
= sizeof(include
);
94 ok(!parent_data
, "wrong parent_data value\n");
98 ok(0, "Unexpected #include for file %s.\n", filename
);
99 return D3DERR_INVALIDCALL
;
105 static HRESULT WINAPI
testD3DXInclude_close(ID3DXInclude
*iface
, const void *data
)
107 HeapFree(GetProcessHeap(), 0, (void *)data
);
111 static const struct ID3DXIncludeVtbl D3DXInclude_Vtbl
= {
112 testD3DXInclude_open
,
113 testD3DXInclude_close
116 struct D3DXIncludeImpl
{
117 ID3DXInclude ID3DXInclude_iface
;
120 static void assembleshader_test(void)
122 static const char test1
[] =
125 static const char testincl
[] =
126 "#define REGISTER r0\n"
128 static const char testshader
[] =
129 "#include \"incl.vsh\"\n"
130 "mov REGISTER, v0\n";
131 static const char testshader2
[] =
132 "#include \"incl2.vsh\"\n"
133 "mov REGISTER, v0\n";
134 static const char testshader3
[] =
135 "#include \"include/incl3.vsh\"\n"
136 "mov REGISTER, v0\n";
137 static const char testincl3
[] =
138 "#include \"incl4.vsh\"\n";
139 static const char testincl4_ok
[] =
140 "#define REGISTER r0\n"
142 static const char testincl4_wrong
[] =
143 "#error \"wrong include\"\n";
145 ID3DXBuffer
*shader
, *messages
;
146 static const D3DXMACRO defines
[] = {
157 struct D3DXIncludeImpl include
;
158 HRESULT shader_vsh_res
;
159 static const WCHAR shader_filename_w
[] = {'s','h','a','d','e','r','.','v','s','h',0};
164 hr
= D3DXAssembleShader(test1
, strlen(test1
),
165 defines
, NULL
, D3DXSHADER_SKIPVALIDATION
,
167 ok(hr
== D3D_OK
, "pDefines test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
169 trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
170 ID3DXBuffer_Release(messages
);
172 if(shader
) ID3DXBuffer_Release(shader
);
174 /* NULL messages test */
176 hr
= D3DXAssembleShader(test1
, strlen(test1
),
177 defines
, NULL
, D3DXSHADER_SKIPVALIDATION
,
179 ok(hr
== D3D_OK
, "NULL messages test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
180 if(shader
) ID3DXBuffer_Release(shader
);
182 /* NULL shader test */
184 hr
= D3DXAssembleShader(test1
, strlen(test1
),
185 defines
, NULL
, D3DXSHADER_SKIPVALIDATION
,
187 ok(hr
== D3D_OK
, "NULL shader test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
189 trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
190 ID3DXBuffer_Release(messages
);
196 include
.ID3DXInclude_iface
.lpVtbl
= &D3DXInclude_Vtbl
;
197 hr
= D3DXAssembleShader(testshader
, strlen(testshader
), NULL
, &include
.ID3DXInclude_iface
,
198 D3DXSHADER_SKIPVALIDATION
, &shader
, &messages
);
199 ok(hr
== D3D_OK
, "pInclude test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
201 trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
202 ID3DXBuffer_Release(messages
);
204 if(shader
) ID3DXBuffer_Release(shader
);
206 /* "unexpected #include file from memory" test */
209 hr
= D3DXAssembleShader(testshader
, strlen(testshader
),
210 NULL
, NULL
, D3DXSHADER_SKIPVALIDATION
,
212 ok(hr
== D3DXERR_INVALIDDATA
, "D3DXAssembleShader test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
214 trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
215 ID3DXBuffer_Release(messages
);
217 if(shader
) ID3DXBuffer_Release(shader
);
219 /* recursive #include test */
222 hr
= D3DXAssembleShader(testshader2
, strlen(testshader2
), NULL
, &include
.ID3DXInclude_iface
,
223 D3DXSHADER_SKIPVALIDATION
, &shader
, &messages
);
224 ok(hr
== D3D_OK
, "D3DXAssembleShader test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
226 trace("recursive D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
227 ID3DXBuffer_Release(messages
);
229 if(shader
) ID3DXBuffer_Release(shader
);
231 /* #include with a path. */
234 hr
= D3DXAssembleShader(testshader3
, strlen(testshader3
), NULL
, &include
.ID3DXInclude_iface
,
235 D3DXSHADER_SKIPVALIDATION
, &shader
, &messages
);
236 ok(hr
== D3D_OK
, "D3DXAssembleShader test failed with error 0x%x - %d\n", hr
, hr
& 0x0000ffff);
239 trace("Path search D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
240 ID3DXBuffer_Release(messages
);
243 ID3DXBuffer_Release(shader
);
245 shader_vsh_res
= create_file("shader.vsh", testshader
, sizeof(testshader
) - 1);
246 if(SUCCEEDED(shader_vsh_res
)) {
247 create_file("incl.vsh", testincl
, sizeof(testincl
) - 1);
249 /* D3DXAssembleShaderFromFile + #include test */
252 hr
= D3DXAssembleShaderFromFileA("shader.vsh",
253 NULL
, NULL
, D3DXSHADER_SKIPVALIDATION
,
255 ok(hr
== D3D_OK
, "D3DXAssembleShaderFromFile test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
257 trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
258 ID3DXBuffer_Release(messages
);
260 if(shader
) ID3DXBuffer_Release(shader
);
262 /* D3DXAssembleShaderFromFile + pInclude test */
265 hr
= D3DXAssembleShaderFromFileA("shader.vsh", NULL
, &include
.ID3DXInclude_iface
,
266 D3DXSHADER_SKIPVALIDATION
, &shader
, &messages
);
267 ok(hr
== D3D_OK
, "D3DXAssembleShaderFromFile + pInclude test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
269 trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
270 ID3DXBuffer_Release(messages
);
272 if(shader
) ID3DXBuffer_Release(shader
);
274 create_file("shader3.vsh", testshader3
, sizeof(testshader3
) - 1);
275 create_file("incl4.vsh", testincl4_wrong
, sizeof(testincl4_wrong
) - 1);
276 if(CreateDirectoryA("include", NULL
)) {
277 create_file("include/incl3.vsh", testincl3
, sizeof(testincl3
) - 1);
278 create_file("include/incl4.vsh", testincl4_ok
, sizeof(testincl4_ok
) - 1);
280 /* path search #include test */
283 hr
= D3DXAssembleShaderFromFileA("shader3.vsh", NULL
, NULL
,
284 D3DXSHADER_SKIPVALIDATION
,
286 ok(hr
== D3D_OK
, "D3DXAssembleShaderFromFile path search test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
288 trace("D3DXAssembleShaderFromFile path search messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
289 ID3DXBuffer_Release(messages
);
291 if(shader
) ID3DXBuffer_Release(shader
);
292 } else skip("Couldn't create \"include\" directory\n");
294 DeleteFileA("shader.vsh");
295 DeleteFileA("incl.vsh");
296 DeleteFileA("shader3.vsh");
297 DeleteFileA("incl4.vsh");
298 DeleteFileA("include/incl3.vsh");
299 DeleteFileA("include/incl4.vsh");
300 RemoveDirectoryA("include");
302 /* The main shader is also to be loaded through the ID3DXInclude object. */
305 hr
= D3DXAssembleShaderFromFileA("shader.vsh", NULL
, &include
.ID3DXInclude_iface
,
306 D3DXSHADER_SKIPVALIDATION
, &shader
, &messages
);
307 ok(hr
== D3D_OK
, "D3DXAssembleShaderFromFile + pInclude main shader test failed with error 0x%x - %d\n",
308 hr
, hr
& 0x0000ffff);
311 trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
312 ID3DXBuffer_Release(messages
);
315 ID3DXBuffer_Release(shader
);
319 hr
= D3DXAssembleShaderFromFileW(shader_filename_w
, NULL
, &include
.ID3DXInclude_iface
,
320 D3DXSHADER_SKIPVALIDATION
, &shader
, &messages
);
321 ok(hr
== D3D_OK
, "D3DXAssembleShaderFromFile + pInclude main shader test failed with error 0x%x - %d\n",
322 hr
, hr
& 0x0000ffff);
325 trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
326 ID3DXBuffer_Release(messages
);
329 ID3DXBuffer_Release(shader
);
330 } else skip("Couldn't create \"shader.vsh\"\n");
332 /* NULL shader tests */
335 hr
= D3DXAssembleShader(NULL
, 0,
336 NULL
, NULL
, D3DXSHADER_SKIPVALIDATION
,
338 ok(hr
== D3DXERR_INVALIDDATA
, "NULL shader test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
340 trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
341 ID3DXBuffer_Release(messages
);
343 if(shader
) ID3DXBuffer_Release(shader
);
347 hr
= D3DXAssembleShaderFromFileA("nonexistent.vsh",
348 NULL
, NULL
, D3DXSHADER_SKIPVALIDATION
,
350 ok(hr
== D3DXERR_INVALIDDATA
|| hr
== E_FAIL
, /* I get this on WinXP */
351 "D3DXAssembleShaderFromFile nonexistent file test failed with error 0x%x - %d\n",
352 hr
, hr
& 0x0000FFFF);
354 trace("D3DXAssembleShaderFromFile messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
355 ID3DXBuffer_Release(messages
);
357 if(shader
) ID3DXBuffer_Release(shader
);
359 /* D3DXAssembleShaderFromResource test */
362 hr
= D3DXAssembleShaderFromResourceA(NULL
, MAKEINTRESOURCEA(IDB_ASMSHADER
),
363 NULL
, NULL
, D3DXSHADER_SKIPVALIDATION
,
365 ok(hr
== D3D_OK
, "D3DXAssembleShaderFromResource test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
367 trace("D3DXAssembleShaderFromResource messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
368 ID3DXBuffer_Release(messages
);
370 if(shader
) ID3DXBuffer_Release(shader
);
372 /* D3DXAssembleShaderFromResource with missing shader resource test */
375 hr
= D3DXAssembleShaderFromResourceA(NULL
, "notexisting",
376 NULL
, NULL
, D3DXSHADER_SKIPVALIDATION
,
378 ok(hr
== D3DXERR_INVALIDDATA
, "D3DXAssembleShaderFromResource NULL shader test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
380 trace("D3DXAssembleShaderFromResource messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
381 ID3DXBuffer_Release(messages
);
383 if(shader
) ID3DXBuffer_Release(shader
);
386 static void d3dxpreprocess_test(void)
388 static const char testincl
[] =
389 "#define REGISTER r0\n"
391 static const char testshader
[] =
392 "#include \"incl.vsh\"\n"
393 "mov REGISTER, v0\n";
394 static const char testshader3
[] =
395 "#include \"include/incl3.vsh\"\n"
396 "mov REGISTER, v0\n";
397 static const char testincl3
[] =
398 "#include \"incl4.vsh\"\n";
399 static const char testincl4_ok
[] =
400 "#define REGISTER r0\n"
402 static const char testincl4_wrong
[] =
403 "#error \"wrong include\"\n";
405 ID3DXBuffer
*shader
, *messages
;
406 HRESULT shader_vsh_res
;
407 static struct D3DXIncludeImpl include
= {{&D3DXInclude_Vtbl
}};
408 static const WCHAR shader_filename_w
[] = {'s','h','a','d','e','r','.','v','s','h',0};
410 shader_vsh_res
= create_file("shader.vsh", testshader
, sizeof(testshader
) - 1);
411 if(SUCCEEDED(shader_vsh_res
)) {
412 create_file("incl.vsh", testincl
, sizeof(testincl
) - 1);
413 create_file("shader3.vsh", testshader3
, sizeof(testshader3
) - 1);
414 create_file("incl4.vsh", testincl4_wrong
, sizeof(testincl4_wrong
) - 1);
415 if(CreateDirectoryA("include", NULL
)) {
416 create_file("include/incl3.vsh", testincl3
, sizeof(testincl3
) - 1);
417 create_file("include/incl4.vsh", testincl4_ok
, sizeof(testincl4_ok
) - 1);
419 /* path search #include test */
422 hr
= D3DXPreprocessShaderFromFileA("shader3.vsh", NULL
, NULL
,
424 ok(hr
== D3D_OK
, "D3DXPreprocessShaderFromFile path search test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
426 trace("D3DXPreprocessShaderFromFile path search messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
427 ID3DXBuffer_Release(messages
);
429 if(shader
) ID3DXBuffer_Release(shader
);
430 } else skip("Couldn't create \"include\" directory\n");
432 /* D3DXPreprocessShaderFromFile + #include test */
435 hr
= D3DXPreprocessShaderFromFileA("shader.vsh",
438 ok(hr
== D3D_OK
, "D3DXPreprocessShaderFromFile test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
440 trace("D3DXPreprocessShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
441 ID3DXBuffer_Release(messages
);
443 if(shader
) ID3DXBuffer_Release(shader
);
445 /* D3DXPreprocessShaderFromFile + pInclude test */
448 hr
= D3DXPreprocessShaderFromFileA("shader.vsh", NULL
, &include
.ID3DXInclude_iface
,
450 ok(hr
== D3D_OK
, "D3DXPreprocessShaderFromFile + pInclude test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
452 trace("D3DXPreprocessShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
453 ID3DXBuffer_Release(messages
);
455 if(shader
) ID3DXBuffer_Release(shader
);
457 DeleteFileA("shader.vsh");
458 DeleteFileA("incl.vsh");
459 DeleteFileA("shader3.vsh");
460 DeleteFileA("incl4.vsh");
461 DeleteFileA("include/incl3.vsh");
462 DeleteFileA("include/incl4.vsh");
463 RemoveDirectoryA("include");
465 /* The main shader is also to be loaded through the ID3DXInclude object. */
468 hr
= D3DXPreprocessShaderFromFileA("shader.vsh", NULL
, &include
.ID3DXInclude_iface
,
470 ok(hr
== D3D_OK
, "D3DXPreprocessShaderFromFile + pInclude main shader test failed with error 0x%x - %d\n",
471 hr
, hr
& 0x0000ffff);
474 trace("D3DXPreprocessShaderFromFile messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
475 ID3DXBuffer_Release(messages
);
478 ID3DXBuffer_Release(shader
);
482 hr
= D3DXPreprocessShaderFromFileW(shader_filename_w
, NULL
, &include
.ID3DXInclude_iface
,
484 ok(hr
== D3D_OK
, "D3DXPreprocessShaderFromFile + pInclude main shader test failed with error 0x%x - %d\n",
485 hr
, hr
& 0x0000ffff);
488 trace("D3DXPreprocessShaderFromFile messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
489 ID3DXBuffer_Release(messages
);
492 ID3DXBuffer_Release(shader
);
493 } else skip("Couldn't create \"shader.vsh\"\n");
495 /* NULL shader tests */
498 hr
= D3DXPreprocessShaderFromFileA("nonexistent.vsh",
501 ok(hr
== D3DXERR_INVALIDDATA
|| hr
== E_FAIL
, /* I get this on WinXP */
502 "D3DXPreprocessShaderFromFile nonexistent file test failed with error 0x%x - %d\n",
503 hr
, hr
& 0x0000FFFF);
505 trace("D3DXPreprocessShaderFromFile messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
506 ID3DXBuffer_Release(messages
);
508 if(shader
) ID3DXBuffer_Release(shader
);
510 /* D3DXPreprocessShaderFromResource test */
513 hr
= D3DXPreprocessShaderFromResourceA(NULL
, MAKEINTRESOURCEA(IDB_ASMSHADER
),
516 ok(hr
== D3D_OK
, "D3DXPreprocessShaderFromResource test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
518 trace("D3DXPreprocessShaderFromResource messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
519 ID3DXBuffer_Release(messages
);
521 if(shader
) ID3DXBuffer_Release(shader
);
523 /* D3DXPreprocessShaderFromResource with missing shader resource test */
526 hr
= D3DXPreprocessShaderFromResourceA(NULL
, "notexisting",
529 ok(hr
== D3DXERR_INVALIDDATA
, "D3DXPreprocessShaderFromResource NULL shader test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
531 trace("D3DXPreprocessShaderFromResource messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
532 ID3DXBuffer_Release(messages
);
534 if(shader
) ID3DXBuffer_Release(shader
);
539 assembleshader_test();
541 d3dxpreprocess_test();