Henri Verbeet : d3d8: Improve ValidateVertexShader().

Alexandre Julliard julliard at winehq.org
Fri Feb 8 16:16:27 CST 2019


Module: wine
Branch: master
Commit: 3ccbb762d2982ca3cf3117b3cc4dd0cd92855593
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=3ccbb762d2982ca3cf3117b3cc4dd0cd92855593

Author: Henri Verbeet <hverbeet at codeweavers.com>
Date:   Fri Feb  8 02:27:37 2019 +0330

d3d8: Improve ValidateVertexShader().

Based largely on a patch by Sebastian Lackner.

Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/d3d8/d3d8_main.c    |  64 +++++++++++++++++-------------
 dlls/d3d8/tests/device.c | 100 +++++++++++++++++++++++++++++++++++------------
 2 files changed, 113 insertions(+), 51 deletions(-)

diff --git a/dlls/d3d8/d3d8_main.c b/dlls/d3d8/d3d8_main.c
index 5fbd165..17f35c9 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;
-  }
-
-  if (!vertexshader)
-      return E_FAIL;
+    TRACE("vs_code %p, declaration %p, caps %p, return_error %#x, errors %p.\n",
+            vs_code, declaration, caps, return_error, errors);
 
-  if (reserved1 || reserved2)
-      return E_FAIL;
+    if (!vs_code)
+    {
+        message = "Invalid code pointer.\n";
+        goto done;
+    }
 
-  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;
-        }
+            message = "Unsupported shader version.\n";
+            goto done;
+    }
 
-  return ret;
+    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 b57be7a..315640d 100644
--- a/dlls/d3d8/tests/device.c
+++ b/dlls/d3d8/tests/device.c
@@ -27,6 +27,7 @@
 #include <initguid.h>
 #include <d3d8.h>
 #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);
+    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(NULL, NULL, NULL, FALSE, NULL);
     ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
-    hr = ValidateVertexShader(0, 0, 0, 1, 0);
+    hr = ValidateVertexShader(NULL, NULL, NULL, TRUE, NULL);
     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);
+    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);
 
-    hr = ValidateVertexShader(vs, 0, 0, 1, 0);
+    hr = ValidateVertexShader(vs_code, NULL, NULL, FALSE, NULL);
     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);
+    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);
 
-    *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, 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);
 
-    hr = ValidateVertexShader(vs, 0, vs, 1, 0);
+    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)




More information about the wine-cvs mailing list