d3d8: Improve ValidateVertexShader().

Based largely on a patch by Sebastian Lackner.

Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Henri Verbeet 2019-02-08 02:09:37 +03:30 committed by Alexandre Julliard
parent 957a1f0216
commit 3ccbb762d2
2 changed files with 118 additions and 56 deletions

View File

@ -57,40 +57,50 @@ IDirect3D8 * WINAPI DECLSPEC_HOTPATCH Direct3DCreate8(UINT sdk_version)
return &object->IDirect3D8_iface; return &object->IDirect3D8_iface;
} }
/*********************************************************************** /* FIXME: We should probably use libvkd3d-shader for validation. */
* ValidateVertexShader (D3D8.@) HRESULT WINAPI ValidateVertexShader(const DWORD *vs_code, const DWORD *declaration,
* const D3DCAPS8 *caps, BOOL return_error, char **errors)
* 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)
{ {
HRESULT ret; const char *message = "";
static BOOL warned; SIZE_T message_size;
HRESULT hr = E_FAIL;
if (TRACE_ON(d3d8) || !warned) { TRACE("vs_code %p, declaration %p, caps %p, return_error %#x, errors %p.\n",
FIXME("(%p %p %p %d %p): stub\n", vertexshader, reserved1, reserved2, boolean, toto); vs_code, declaration, caps, return_error, errors);
warned = TRUE;
}
if (!vertexshader) if (!vs_code)
return E_FAIL; {
message = "Invalid code pointer.\n";
goto done;
}
if (reserved1 || reserved2) switch (*vs_code)
return E_FAIL; {
case D3DVS_VERSION(1, 1):
switch(*vertexshader) { case D3DVS_VERSION(1, 0):
case 0xFFFE0101:
case 0xFFFE0100:
ret=S_OK;
break; 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;
} }
/*********************************************************************** /***********************************************************************

View File

@ -27,6 +27,7 @@
#include <initguid.h> #include <initguid.h>
#include <d3d8.h> #include <d3d8.h>
#include "wine/test.h" #include "wine/test.h"
#include "wine/heap.h"
struct vec3 struct vec3
{ {
@ -51,7 +52,7 @@ struct device_desc
static DEVMODEW registry_mode; 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 HRESULT (WINAPI *ValidatePixelShader)(DWORD *, DWORD *, int, DWORD *);
static BOOL (WINAPI *pGetCursorInfo)(PCURSORINFO); static BOOL (WINAPI *pGetCursorInfo)(PCURSORINFO);
@ -4365,7 +4366,7 @@ static void test_set_rt_vp_scissor(void)
static void test_validate_vs(void) static void test_validate_vs(void)
{ {
static DWORD vs[] = static DWORD vs_code[] =
{ {
0xfffe0101, /* vs_1_1 */ 0xfffe0101, /* vs_1_1 */
0x00000009, 0xc0010000, 0x90e40000, 0xa0e40000, /* dp4 oPos.x, v0, c0 */ 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 */ 0x00000009, 0xc0080000, 0x90e40000, 0xa0e40003, /* dp4 oPos.w, v0, c3 */
0x0000ffff, /* end */ 0x0000ffff, /* end */
}; };
D3DCAPS8 caps;
char *errors;
HRESULT hr; HRESULT hr;
hr = ValidateVertexShader(0, 0, 0, 0, 0); static DWORD declaration_valid1[] =
ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr); {
hr = ValidateVertexShader(0, 0, 0, 1, 0); D3DVSD_STREAM(0),
ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr); D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT4),
hr = ValidateVertexShader(vs, 0, 0, 0, 0); D3DVSD_END()
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); };
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); hr = ValidateVertexShader(NULL, NULL, NULL, FALSE, NULL);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
/* Seems to do some version checking. */ hr = ValidateVertexShader(NULL, NULL, NULL, TRUE, NULL);
*vs = 0xfffe0100; /* vs_1_0 */ ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
hr = ValidateVertexShader(vs, 0, 0, 0, 0); hr = ValidateVertexShader(NULL, NULL, NULL, FALSE, &errors);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); 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_code, NULL, NULL, FALSE, NULL);
hr = ValidateVertexShader(vs, 0, 0, 1, 0); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr); hr = ValidateVertexShader(vs_code, NULL, NULL, TRUE, NULL);
/* I've seen that applications always pass the 2nd and 3rd parameter as 0. ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
* Simple test with non-zero parameters. */ hr = ValidateVertexShader(vs_code, NULL, NULL, TRUE, &errors);
*vs = 0xfffe0101; /* vs_1_1 */ ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
hr = ValidateVertexShader(vs, vs, 0, 1, 0); ok(!*errors, "Got unexpected string \"%s\".\n", errors);
ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr); 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); 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 caps.VertexShaderVersion = D3DVS_VERSION(1, 2);
* other values doesn't seem to hurt. */ hr = ValidateVertexShader(vs_code, NULL, &caps, FALSE, NULL);
hr = ValidateVertexShader(vs, 0, 0, 12345, 0);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
/* What is the 5th parameter? The following seems to work ok. */ caps.VertexShaderVersion = D3DVS_VERSION(8, 8);
hr = ValidateVertexShader(vs, 0, 0, 1, vs); hr = ValidateVertexShader(vs_code, NULL, &caps, FALSE, NULL);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); 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) static void test_validate_ps(void)