diff --git a/dlls/d3d8/d3d8_main.c b/dlls/d3d8/d3d8_main.c index 5fbd1652857..17f35c90894 100644 --- a/dlls/d3d8/d3d8_main.c +++ b/dlls/d3d8/d3d8_main.c @@ -57,40 +57,50 @@ IDirect3D8 * WINAPI DECLSPEC_HOTPATCH Direct3DCreate8(UINT sdk_version) return &object->IDirect3D8_iface; } -/*********************************************************************** - * ValidateVertexShader (D3D8.@) - * - * I've seen reserved1 and reserved2 always passed as 0's - * boolean seems always passed as 0 or 1, but other values work as well... - * toto result? - */ -HRESULT WINAPI ValidateVertexShader(DWORD* vertexshader, DWORD* reserved1, DWORD* reserved2, BOOL boolean, DWORD* toto) +/* FIXME: We should probably use libvkd3d-shader for validation. */ +HRESULT WINAPI ValidateVertexShader(const DWORD *vs_code, const DWORD *declaration, + const D3DCAPS8 *caps, BOOL return_error, char **errors) { - HRESULT ret; - static BOOL warned; + const char *message = ""; + SIZE_T message_size; + HRESULT hr = E_FAIL; - if (TRACE_ON(d3d8) || !warned) { - FIXME("(%p %p %p %d %p): stub\n", vertexshader, reserved1, reserved2, boolean, toto); - warned = TRUE; - } + TRACE("vs_code %p, declaration %p, caps %p, return_error %#x, errors %p.\n", + vs_code, declaration, caps, return_error, errors); - if (!vertexshader) - return E_FAIL; + if (!vs_code) + { + message = "Invalid code pointer.\n"; + goto done; + } - if (reserved1 || reserved2) - return E_FAIL; - - switch(*vertexshader) { - case 0xFFFE0101: - case 0xFFFE0100: - ret=S_OK; + switch (*vs_code) + { + case D3DVS_VERSION(1, 1): + case D3DVS_VERSION(1, 0): break; - default: - WARN("Invalid shader version token %#x.\n", *vertexshader); - ret=E_FAIL; - } - return ret; + default: + message = "Unsupported shader version.\n"; + goto done; + } + + if (caps && *vs_code > caps->VertexShaderVersion) + { + message = "Shader version not supported by caps.\n"; + goto done; + } + + hr = S_OK; + +done: + if (!return_error) + message = ""; + message_size = strlen(message) + 1; + if (errors && (*errors = heap_alloc(message_size))) + memcpy(*errors, message, message_size); + + return hr; } /*********************************************************************** diff --git a/dlls/d3d8/tests/device.c b/dlls/d3d8/tests/device.c index b57be7ad127..315640d3b37 100644 --- a/dlls/d3d8/tests/device.c +++ b/dlls/d3d8/tests/device.c @@ -27,6 +27,7 @@ #include #include #include "wine/test.h" +#include "wine/heap.h" struct vec3 { @@ -51,7 +52,7 @@ struct device_desc static DEVMODEW registry_mode; -static HRESULT (WINAPI *ValidateVertexShader)(DWORD *, DWORD *, DWORD *, int, DWORD *); +static HRESULT (WINAPI *ValidateVertexShader)(const DWORD *, const DWORD *, const D3DCAPS8 *, BOOL, char **); static HRESULT (WINAPI *ValidatePixelShader)(DWORD *, DWORD *, int, DWORD *); static BOOL (WINAPI *pGetCursorInfo)(PCURSORINFO); @@ -4365,7 +4366,7 @@ static void test_set_rt_vp_scissor(void) static void test_validate_vs(void) { - static DWORD vs[] = + static DWORD vs_code[] = { 0xfffe0101, /* vs_1_1 */ 0x00000009, 0xc0010000, 0x90e40000, 0xa0e40000, /* dp4 oPos.x, v0, c0 */ @@ -4374,40 +4375,91 @@ static void test_validate_vs(void) 0x00000009, 0xc0080000, 0x90e40000, 0xa0e40003, /* dp4 oPos.w, v0, c3 */ 0x0000ffff, /* end */ }; + D3DCAPS8 caps; + char *errors; HRESULT hr; - hr = ValidateVertexShader(0, 0, 0, 0, 0); - ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr); - hr = ValidateVertexShader(0, 0, 0, 1, 0); - ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr); - hr = ValidateVertexShader(vs, 0, 0, 0, 0); - ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + static DWORD declaration_valid1[] = + { + D3DVSD_STREAM(0), + D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT4), + D3DVSD_END() + }; + static DWORD declaration_valid2[] = + { + D3DVSD_STREAM(0), + D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT2), + D3DVSD_END() + }; + static DWORD declaration_invalid[] = + { + D3DVSD_STREAM(0), + D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT4), + D3DVSD_END() + }; - hr = ValidateVertexShader(vs, 0, 0, 1, 0); - ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); - /* Seems to do some version checking. */ - *vs = 0xfffe0100; /* vs_1_0 */ - hr = ValidateVertexShader(vs, 0, 0, 0, 0); - ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + hr = ValidateVertexShader(NULL, NULL, NULL, FALSE, NULL); + ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr); + hr = ValidateVertexShader(NULL, NULL, NULL, TRUE, NULL); + ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr); + hr = ValidateVertexShader(NULL, NULL, NULL, FALSE, &errors); + ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr); + ok(!*errors, "Got unexpected string \"%s\".\n", errors); + heap_free(errors); + hr = ValidateVertexShader(NULL, NULL, NULL, TRUE, &errors); + ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr); + ok(!!*errors, "Got unexpected empty string.\n"); + heap_free(errors); - *vs = 0xfffe0102; /* bogus version */ - hr = ValidateVertexShader(vs, 0, 0, 1, 0); - ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr); - /* I've seen that applications always pass the 2nd and 3rd parameter as 0. - * Simple test with non-zero parameters. */ - *vs = 0xfffe0101; /* vs_1_1 */ - hr = ValidateVertexShader(vs, vs, 0, 1, 0); - ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr); + hr = ValidateVertexShader(vs_code, NULL, NULL, FALSE, NULL); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + hr = ValidateVertexShader(vs_code, NULL, NULL, TRUE, NULL); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + hr = ValidateVertexShader(vs_code, NULL, NULL, TRUE, &errors); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + ok(!*errors, "Got unexpected string \"%s\".\n", errors); + heap_free(errors); - hr = ValidateVertexShader(vs, 0, vs, 1, 0); + hr = ValidateVertexShader(vs_code, declaration_valid1, NULL, FALSE, NULL); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + hr = ValidateVertexShader(vs_code, declaration_valid2, NULL, FALSE, NULL); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + hr = ValidateVertexShader(vs_code, declaration_invalid, NULL, FALSE, NULL); + todo_wine ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr); + + memset(&caps, 0, sizeof(caps)); + caps.VertexShaderVersion = D3DVS_VERSION(1, 1); + caps.MaxVertexShaderConst = 4; + hr = ValidateVertexShader(vs_code, NULL, &caps, FALSE, NULL); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + caps.VertexShaderVersion = D3DVS_VERSION(1, 0); + hr = ValidateVertexShader(vs_code, NULL, &caps, FALSE, NULL); ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr); - /* I've seen the 4th parameter always passed as either 0 or 1, but passing - * other values doesn't seem to hurt. */ - hr = ValidateVertexShader(vs, 0, 0, 12345, 0); + caps.VertexShaderVersion = D3DVS_VERSION(1, 2); + hr = ValidateVertexShader(vs_code, NULL, &caps, FALSE, NULL); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); - /* What is the 5th parameter? The following seems to work ok. */ - hr = ValidateVertexShader(vs, 0, 0, 1, vs); + caps.VertexShaderVersion = D3DVS_VERSION(8, 8); + hr = ValidateVertexShader(vs_code, NULL, &caps, FALSE, NULL); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + caps.VertexShaderVersion = D3DVS_VERSION(1, 1); + caps.MaxVertexShaderConst = 3; + hr = ValidateVertexShader(vs_code, NULL, &caps, FALSE, NULL); + todo_wine ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr); + + *vs_code = D3DVS_VERSION(1, 0); + hr = ValidateVertexShader(vs_code, NULL, NULL, FALSE, NULL); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + *vs_code = D3DVS_VERSION(1, 2); + hr = ValidateVertexShader(vs_code, NULL, NULL, TRUE, NULL); + ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr); + hr = ValidateVertexShader(vs_code, NULL, NULL, FALSE, &errors); + ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr); + ok(!*errors, "Got unexpected string \"%s\".\n", errors); + heap_free(errors); + hr = ValidateVertexShader(vs_code, NULL, NULL, TRUE, &errors); + ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr); + ok(!!*errors, "Got unexpected empty string.\n"); + heap_free(errors); } static void test_validate_ps(void)