2 * Copyright (C) 2005 Henri Verbeet
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "wine/test.h"
23 static HMODULE d3d9_handle = 0;
25 static HWND create_window(void)
28 wc.lpfnWndProc = DefWindowProc;
29 wc.lpszClassName = "d3d9_test_wc";
32 return CreateWindow("d3d9_test_wc", "d3d9_test",
33 0, 0, 0, 0, 0, 0, 0, 0, 0);
36 static IDirect3DDevice9 *init_d3d9(void)
38 IDirect3D9 * (__stdcall * d3d9_create)(UINT SDKVersion) = 0;
39 IDirect3D9 *d3d9_ptr = 0;
40 IDirect3DDevice9 *device_ptr = 0;
41 D3DPRESENT_PARAMETERS present_parameters;
44 d3d9_create = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9");
45 ok(d3d9_create != NULL, "Failed to get address of Direct3DCreate9\n");
46 if (!d3d9_create) return NULL;
48 d3d9_ptr = d3d9_create(D3D_SDK_VERSION);
51 skip("could not create D3D9\n");
55 ZeroMemory(&present_parameters, sizeof(present_parameters));
56 present_parameters.Windowed = TRUE;
57 present_parameters.hDeviceWindow = create_window();
58 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
60 hres = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, NULL, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
64 skip("could not create device, IDirect3D9_CreateDevice returned %#x\n", hres);
71 static int get_refcount(IUnknown *object)
73 IUnknown_AddRef(object);
74 return IUnknown_Release(object);
77 static void test_get_set_vertex_shader(IDirect3DDevice9 *device_ptr)
80 static DWORD simple_vs[] = {0xFFFE0101, /* vs_1_1 */
81 0x0000001F, 0x80000000, 0x900F0000, /* dcl_position0 v0 */
82 0x00000009, 0xC0010000, 0x90E40000, 0xA0E40000, /* dp4 oPos.x, v0, c0 */
83 0x00000009, 0xC0020000, 0x90E40000, 0xA0E40001, /* dp4 oPos.y, v0, c1 */
84 0x00000009, 0xC0040000, 0x90E40000, 0xA0E40002, /* dp4 oPos.z, v0, c2 */
85 0x00000009, 0xC0080000, 0x90E40000, 0xA0E40003, /* dp4 oPos.w, v0, c3 */
86 0x0000FFFF}; /* END */
88 IDirect3DVertexShader9 *shader_ptr = 0;
89 IDirect3DVertexShader9 *current_shader_ptr = 0;
91 int shader_refcount = 0;
94 hret = IDirect3DDevice9_CreateVertexShader(device_ptr, simple_vs, &shader_ptr);
95 ok(hret == D3D_OK && shader_ptr != NULL, "CreateVertexShader returned: hret 0x%x, shader_ptr %p. "
96 "Expected hret 0x%x, shader_ptr != %p. Aborting.\n", hret, shader_ptr, D3D_OK, NULL);
97 if (hret != D3D_OK || shader_ptr == NULL) return;
99 /* SetVertexShader should not touch the shader's refcount. */
100 i = get_refcount((IUnknown *)shader_ptr);
101 hret = IDirect3DDevice9_SetVertexShader(device_ptr, shader_ptr);
102 shader_refcount = get_refcount((IUnknown *)shader_ptr);
103 ok(hret == D3D_OK && shader_refcount == i, "SetVertexShader returned: hret 0x%x, refcount %d. "
104 "Expected hret 0x%x, refcount %d.\n", hret, shader_refcount, D3D_OK, i);
106 /* GetVertexShader should increase the shader's refcount by one. */
107 i = shader_refcount+1;
108 hret = IDirect3DDevice9_GetVertexShader(device_ptr, ¤t_shader_ptr);
109 shader_refcount = get_refcount((IUnknown *)shader_ptr);
110 ok(hret == D3D_OK && shader_refcount == i && current_shader_ptr == shader_ptr,
111 "GetVertexShader returned: hret 0x%x, current_shader_ptr %p refcount %d. "
112 "Expected hret 0x%x, current_shader_ptr %p, refcount %d.\n", hret, current_shader_ptr, shader_refcount, D3D_OK, shader_ptr, i);
113 IDirect3DVertexShader9_Release(current_shader_ptr);
115 IDirect3DVertexShader9_Release(shader_ptr);
118 static void test_vertex_shader_constant(IDirect3DDevice9 *device_ptr, DWORD consts)
120 float c[4] = { 0.0, 0.0, 0.0, 0.0 };
121 float d[16] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
124 /* A simple check that the stuff works at all */
125 hr = IDirect3DDevice9_SetVertexShaderConstantF(device_ptr, 0, c, 1);
126 ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShaderConstantF returned 0x%08x\n", hr);
128 /* Test corner cases: Write to const MAX - 1, MAX, MAX + 1, and writing 4 consts from
131 hr = IDirect3DDevice9_SetVertexShaderConstantF(device_ptr, consts - 1, c, 1);
132 ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShaderConstantF returned 0x%08x\n", hr);
133 hr = IDirect3DDevice9_SetVertexShaderConstantF(device_ptr, consts + 0, c, 1);
134 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetVertexShaderConstantF returned 0x%08x\n", hr);
135 hr = IDirect3DDevice9_SetVertexShaderConstantF(device_ptr, consts + 1, c, 1);
136 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetVertexShaderConstantF returned 0x%08x\n", hr);
137 hr = IDirect3DDevice9_SetVertexShaderConstantF(device_ptr, consts - 1, d, 4);
138 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetVertexShaderConstantF returned 0x%08x\n", hr);
141 hr = IDirect3DDevice9_SetVertexShaderConstantF(device_ptr, -1, c, 1);
142 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetVertexShaderConstantF returned 0x%08x\n", hr);
145 static void test_get_set_pixel_shader(IDirect3DDevice9 *device_ptr)
147 static DWORD simple_ps[] = {0xFFFF0101, /* ps_1_1 */
148 0x00000051, 0xA00F0001, 0x3F800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0 */
149 0x00000042, 0xB00F0000, /* tex t0 */
150 0x00000008, 0x800F0000, 0xA0E40001, 0xA0E40000, /* dp3 r0, c1, c0 */
151 0x00000005, 0x800F0000, 0x90E40000, 0x80E40000, /* mul r0, v0, r0 */
152 0x00000005, 0x800F0000, 0xB0E40000, 0x80E40000, /* mul r0, t0, r0 */
153 0x0000FFFF}; /* END */
155 IDirect3DPixelShader9 *shader_ptr = 0;
156 IDirect3DPixelShader9 *current_shader_ptr = 0;
158 int shader_refcount = 0;
161 hret = IDirect3DDevice9_CreatePixelShader(device_ptr, simple_ps, &shader_ptr);
162 ok(hret == D3D_OK && shader_ptr != NULL, "CreatePixelShader returned: hret 0x%x, shader_ptr %p. "
163 "Expected hret 0x%x, shader_ptr != %p. Aborting.\n", hret, shader_ptr, D3D_OK, NULL);
164 if (hret != D3D_OK || shader_ptr == NULL) return;
166 /* SetPixelsShader should not touch the shader's refcount. */
167 i = get_refcount((IUnknown *)shader_ptr);
168 hret = IDirect3DDevice9_SetPixelShader(device_ptr, shader_ptr);
169 shader_refcount = get_refcount((IUnknown *)shader_ptr);
170 ok(hret == D3D_OK && shader_refcount == i, "SetPixelShader returned: hret 0x%x, refcount %d. "
171 "Expected hret 0x%x, refcount %d.\n", hret, shader_refcount, D3D_OK, i);
173 /* GetPixelShader should increase the shader's refcount by one. */
174 i = shader_refcount+1;
175 hret = IDirect3DDevice9_GetPixelShader(device_ptr, ¤t_shader_ptr);
176 shader_refcount = get_refcount((IUnknown *)shader_ptr);
177 ok(hret == D3D_OK && shader_refcount == i && current_shader_ptr == shader_ptr,
178 "GetPixelShader returned: hret 0x%x, current_shader_ptr %p refcount %d. "
179 "Expected hret 0x%x, current_shader_ptr %p, refcount %d.\n", hret, current_shader_ptr, shader_refcount, D3D_OK, shader_ptr, i);
180 IDirect3DPixelShader9_Release(current_shader_ptr);
182 IDirect3DPixelShader9_Release(shader_ptr);
185 static void test_pixel_shader_constant(IDirect3DDevice9 *device_ptr)
187 float c[4] = { 0.0, 0.0, 0.0, 0.0 };
188 float d[16] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
192 /* A simple check that the stuff works at all */
193 hr = IDirect3DDevice9_SetPixelShaderConstantF(device_ptr, 0, c, 1);
194 ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShaderConstantF returned 0x%08x\n", hr);
196 /* Is there really no max pixel shader constant value??? Test how far I can go */
197 while(SUCCEEDED(IDirect3DDevice9_SetPixelShaderConstantF(device_ptr, consts++, c, 1)));
199 trace("SetPixelShaderConstantF was able to set %d shader constants\n", consts);
201 /* Test corner cases: writing 4 consts from MAX - 1, everything else is pointless
202 * given the way the constant limit was found out
204 hr = IDirect3DDevice9_SetPixelShaderConstantF(device_ptr, consts - 1, d, 4);
205 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetPixelShaderConstantF returned 0x%08x\n", hr);
208 hr = IDirect3DDevice9_SetPixelShaderConstantF(device_ptr, -1, c, 1);
209 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetPixelShaderConstantF returned 0x%08x\n", hr);
212 static void test_wrong_shader(IDirect3DDevice9 *device_ptr)
214 static const DWORD simple_vs[] =
216 0xfffe0101, /* vs_1_1 */
217 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position0 v0 */
218 0x00000009, 0xc0010000, 0x90e40000, 0xa0e40000, /* dp4 oPos.x, v0, c0 */
219 0x00000009, 0xc0020000, 0x90e40000, 0xa0e40001, /* dp4 oPos.y, v0, c1 */
220 0x00000009, 0xc0040000, 0x90e40000, 0xa0e40002, /* dp4 oPos.z, v0, c2 */
221 0x00000009, 0xc0080000, 0x90e40000, 0xa0e40003, /* dp4 oPos.w, v0, c3 */
225 static const DWORD simple_ps[] =
227 0xffff0101, /* ps_1_1 */
228 0x00000051, 0xa00f0001, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0 */
229 0x00000042, 0xb00f0000, /* tex t0 */
230 0x00000008, 0x800f0000, 0xa0e40001, 0xa0e40000, /* dp3 r0, c1, c0 */
231 0x00000005, 0x800f0000, 0x90e40000, 0x80e40000, /* mul r0, v0, r0 */
232 0x00000005, 0x800f0000, 0xb0e40000, 0x80e40000, /* mul r0, t0, r0 */
236 const DWORD vs_3_0[] = {
237 0xfffe0300, /* vs_3_0 */
238 0x0200001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
239 0x0200001f, 0x80000000, 0xe00f0000, /* dcl_position o0 */
240 0x02000001, 0xe00f0000, 0x90e40000, /* mov o0, v0 */
245 float4 main(const float4 color : COLOR) : SV_TARGET
254 static const DWORD ps_4_0[] =
256 0x43425844, 0x4da9446f, 0xfbe1f259, 0x3fdb3009, 0x517521fa, 0x00000001, 0x000001ac,
257 0x00000005, 0x00000034, 0x0000008c, 0x000000bc, 0x000000f0, 0x00000130, 0x46454452,
258 0x00000050, 0x00000000, 0x00000000, 0x00000000, 0x0000001c, 0xffff0400, 0x00000100,
259 0x0000001c, 0x7263694d, 0x666f736f, 0x52282074, 0x4c482029, 0x53204c53, 0x65646168,
260 0x6f432072, 0x6c69706d, 0x39207265, 0x2e39322e, 0x2e323539, 0x31313133, 0xababab00,
261 0x4e475349, 0x00000028, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
262 0x00000003, 0x00000000, 0x00000f0f, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000002c,
263 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000,
264 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000038, 0x00000040,
265 0x0000000e, 0x03001062, 0x001010f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000000,
266 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, 0x54415453,
267 0x00000074, 0x00000002, 0x00000000, 0x00000000, 0x00000002, 0x00000000, 0x00000000,
268 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
269 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
270 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
271 0x00000000, 0x00000000,
274 IDirect3DVertexShader9 *vs = NULL;
275 IDirect3DPixelShader9 *ps = NULL;
279 hret = IDirect3DDevice9_CreateVertexShader(device_ptr, simple_ps, &vs);
280 ok(hret == D3DERR_INVALIDCALL, "CreateVertexShader returned: hret 0x%x, shader_ptr %p.\n", hret, vs);
281 hret = IDirect3DDevice9_CreatePixelShader(device_ptr, simple_vs, &ps);
282 ok(hret == D3DERR_INVALIDCALL, "CreatePixelShader returned: hret 0x%x, shader_ptr %p.\n", hret, ps);
284 hret = IDirect3DDevice9_CreatePixelShader(device_ptr, ps_4_0, &ps);
285 ok(hret == D3DERR_INVALIDCALL, "CreatePixelShader returned: hret 0x%x, shader_ptr %p.\n", hret, ps);
287 IDirect3DDevice9_GetDeviceCaps(device_ptr, &caps);
288 if (caps.VertexShaderVersion < D3DVS_VERSION(3, 0))
290 hret = IDirect3DDevice9_CreateVertexShader(device_ptr, vs_3_0, &vs);
291 ok(hret == D3DERR_INVALIDCALL, "CreateVertexShader returned: hret 0x%x, shader_ptr %p.\n", hret, vs);
294 skip("This GPU supports SM3, skipping unsupported shader test.\n");
300 IDirect3DDevice9 *device_ptr;
303 d3d9_handle = LoadLibraryA("d3d9.dll");
306 skip("Could not load d3d9.dll\n");
310 device_ptr = init_d3d9();
311 if (!device_ptr) return;
313 IDirect3DDevice9_GetDeviceCaps(device_ptr, &caps);
315 if (caps.VertexShaderVersion & 0xffff)
317 test_get_set_vertex_shader(device_ptr);
318 test_vertex_shader_constant(device_ptr, caps.MaxVertexShaderConst);
320 else skip("No vertex shader support\n");
322 if (caps.PixelShaderVersion & 0xffff)
324 test_get_set_pixel_shader(device_ptr);
325 /* No max pixel shader constant value??? */
326 test_pixel_shader_constant(device_ptr);
327 if (caps.VertexShaderVersion & 0xffff)
328 test_wrong_shader(device_ptr);
330 else skip("No pixel shader support\n");
332 refcount = IDirect3DDevice9_Release(device_ptr);
333 ok(!refcount, "Device has %u references left\n", refcount);