[2/3] wined3d: Implement check for shader creation if hardware supports requested version.

Pauli Nieminen suokkos at gmail.com
Wed Dec 17 08:37:46 CST 2008


This fixes civ 4 rendering problems if no pixelshader support is enabled.
Civ 4 doesn't check for caps so it doesn't know if shader is support if
creation doesn't fail.
---
 dlls/d3d9/tests/shader.c    |  264 +++++++++++++++++++++++++++++++++++++++++++
 dlls/wined3d/pixelshader.c  |   25 ++++
 dlls/wined3d/vertexshader.c |   24 ++++
 3 files changed, 313 insertions(+), 0 deletions(-)

diff --git a/dlls/d3d9/tests/shader.c b/dlls/d3d9/tests/shader.c
index 522f128..8ca68dd 100644
--- a/dlls/d3d9/tests/shader.c
+++ b/dlls/d3d9/tests/shader.c
@@ -74,6 +74,268 @@ static int get_refcount(IUnknown *object)
     return IUnknown_Release(object);
 }
 
+static inline void test_create_vshader_version_check(IDirect3DDevice9 *device_ptr, const D3DCAPS9 *caps,
+        const DWORD version, const DWORD *shader_code)
+{
+    IDirect3DVertexShader9 *vshader_ptr = 0;
+    HRESULT hret = 0;
+
+    hret = IDirect3DDevice9_CreateVertexShader(device_ptr, shader_code, &vshader_ptr);
+
+
+    if( version <= caps->VertexShaderVersion ) {
+        ok(hret == D3D_OK && vshader_ptr != NULL,
+            "Vertex shader (0x%x) creation failed but d3dcaps claim to support it. hret = 0x%x, vshader_ptr = %p\n",
+            version, hret, vshader_ptr);
+        IDirect3DVertexShader9_Release(vshader_ptr);
+    } else {
+        ok(hret == D3DERR_INVALIDCALL && vshader_ptr == NULL,
+            "Vertex shader (0x%x) creation succesed but d3dcaps claim not to support it. hret = 0x%x, vshader_ptr = %p\n",
+            version, hret, vshader_ptr);
+    }
+
+}
+
+static inline void test_create_pshader_version_check(IDirect3DDevice9 *device_ptr, const D3DCAPS9 *caps,
+        const DWORD version, const DWORD *shader_code)
+{
+    IDirect3DPixelShader9 *pshader_ptr = 0;
+    HRESULT hret = 0;
+
+    hret = IDirect3DDevice9_CreatePixelShader(device_ptr, shader_code, &pshader_ptr);
+
+
+    if( version <= caps->PixelShaderVersion ) {
+        ok(hret == D3D_OK && pshader_ptr != NULL,
+            "Pixel shader (0x%x) creation failed but d3dcaps claim to support it. hret = 0x%x, pshader_ptr = %p\n",
+            version, hret, pshader_ptr);
+        IDirect3DPixelShader9_Release(pshader_ptr);
+    } else {
+        ok(hret == D3DERR_INVALIDCALL && pshader_ptr == NULL,
+            "Pixel shader (0x%x) creation succesed but d3dcaps claim not to support it. hret = 0x%x, pshader_ptr = %p\n",
+            version, hret, pshader_ptr);
+    }
+
+}
+
+static void test_create_shader_version_check(IDirect3DDevice9 *device_ptr,D3DCAPS9 *caps)
+{
+    const DWORD ps10_test_version[] =
+    {
+        0xffff0100,
+        /*    ps_1_0 */
+        0x00000042, 0xb00f0000, 0x00000001,
+        /*    tex t0 */
+        0x800f0000, 0xb0e40000, 0x0000ffff
+        /*    mov r0, t0 */
+    };
+
+    const DWORD ps11_test_version[] =
+    {
+        0xffff0101,
+        /*    ps_1_1 */
+        0x00000042, 0xb00f0000, 0x00000001,
+        /*    tex t0 */
+        0x800f0000, 0xb0e40000, 0x0000ffff
+        /*    mov r0, t0 */
+    };
+
+    const DWORD ps12_test_version[] =
+    {
+        0xffff0102,
+        /*    ps_1_0 */
+        0x00000042, 0xb00f0000, 0x00000001,
+        /*    tex t0 */
+        0x800f0000, 0xb0e40000, 0x0000ffff
+        /*    mov r0, t0 */
+    };
+
+    const DWORD ps13_test_version[] =
+    {
+        0xffff0103,
+        /*    ps_1_0 */
+        0x00000042, 0xb00f0000, 0x00000001,
+        /*    tex t0 */
+        0x800f0000, 0xb0e40000, 0x0000ffff
+        /*    mov r0, t0 */
+    };
+
+    const DWORD ps14_test_version[] =
+    {
+        0xffff0104,
+        /*    ps_1_4 */
+        0x00000042, 0x800f0004, 0xb0e40000, 0x00000001,
+        /*    texld r4, t0 */
+        0x800f0000, 0x80e40004, 0x0000ffff
+        /*    mov r0, r4 */
+    };
+
+    const DWORD ps20_test_version[] =
+    {
+        0xffff0200,
+        /*    ps_2_0 */
+        0x0200001f, 0x90000000, 0xa00f0800,
+        /*    dcl_2d s0 */
+        0x0200001f, 0x80000000, 0xb0030000, 0x03000042,
+        /*    dcl t0.xy */
+        0x800f0001, 0xb0e40000, 0xa0e40800, 0x02000001,
+        /*    texld r1, t0, s0 */
+        0x800f0800, 0x80e40001, 0x0000ffff
+        /*    mov oC0, r1 */
+    };
+
+    const DWORD ps2sw_test_version[] =
+    {
+        0xffff02ff,
+        /*    ps_2_sw */
+        0x0200001f, 0x90000000, 0xa00f0800,
+        /*    dcl_2d s0 */
+        0x0200001f, 0x80000000, 0xb0030000, 0x03000042,
+        /*    dcl t0.xy */
+        0x800f0001, 0xb0e40000, 0xa0e40800, 0x02000001,
+        /*    texld r1, t0, s0 */
+        0x800f0800, 0x80e40001, 0x0000ffff
+        /*    mov oC0, r1 */
+    };
+
+    const DWORD ps2x_test_version[] =
+    {
+        0xffff0201,
+        /*    ps_2_x */
+        0x0200001f, 0x90000000, 0xa00f0800,
+        /*    dcl_2d s0 */
+        0x0200001f, 0x80000000, 0xb0030000, 0x03000042,
+        /*    dcl t0.xy */
+        0x800f0001, 0xb0e40000, 0xa0e40800, 0x02000001,
+        /*    texld r1, t0, s0 */
+        0x800f0800, 0x80e40001, 0x0000ffff
+        /*    mov oC0, r1 */
+    };
+
+    const DWORD ps30_test_version[] =
+    {
+        0xffff0300,
+        /*    ps_3_0 */
+        0x0200001f, 0x90000000, 0xa00f0800,
+        /*    dcl_2d s0 */
+        0x0200001f, 0x80000000, 0x90030000, 0x03000042,
+        /*    dcl v0.xy */
+        0x800f0001, 0x90e40000, 0xa0e40800, 0x02000001,
+        /*    texld r1, v0, s0 */
+        0x800f0800, 0x80e40001, 0x0000ffff
+        /*    mov oC0, r1 */
+    };
+
+    const DWORD ps3sw_test_version[] =
+    {
+        0xffff03ff,
+        /*    ps_3_0 */
+        0x0200001f, 0x90000000, 0xa00f0800,
+        /*    dcl_2d s0 */
+        0x0200001f, 0x80000000, 0x90030000, 0x03000042,
+        /*    dcl v0.xy */
+        0x800f0001, 0x90e40000, 0xa0e40800, 0x02000001,
+        /*    texld r1, v0, s0 */
+        0x800f0800, 0x80e40001, 0x0000ffff
+        /*    mov oC0, r1 */
+    };
+
+    const DWORD vs10_test_version[] =
+    {
+        0xfffe0100,
+        /*    vs_1_0 */
+        0x00000001, 0xc00f0000, 0x90e40000, 0x0000ffff
+        /*    mov oPos, v0 */
+    };
+
+    const DWORD vs11_test_version[] =
+    {
+        0xfffe0101,
+        /*    vs_1_1 */
+        0x00000001, 0xc00f0000, 0x90e40000, 0x0000ffff
+        /*    mov oPos, v0 */
+    };
+
+    const DWORD vs20_test_version[] =
+    {
+        0xfffe0200,
+        /*    vs_2_0 */
+        0x02000001, 0xc00f0000, 0x90e40000, 0x0000ffff
+        /*    mov oPos, v0 */
+    };
+
+    const DWORD vs2sw_test_version[] =
+    {
+        0xfffe02ff,
+        /*    vs_2_sw */
+        0x02000001, 0xc00f0000, 0x90e40000, 0x0000ffff
+        /*    mov oPos, v0 */
+    };
+
+    const DWORD vs2x_test_version[] =
+    {
+        0xfffe0201,
+        /*    vs_2_x */
+        0x02000001, 0xc00f0000, 0x90e40000, 0x0000ffff
+        /*    mov oPos, v0 */
+    };
+
+    const DWORD vs30_test_version[] =
+    {
+        0xfffe0300,
+        /*    vs_3_0 */
+        0x02000001, 0xe00f0000, 0x90e40000, 0x0000ffff
+        /*    mov o0, v0 */
+    };
+
+    const DWORD vs3sw_test_version[] =
+    {
+        0xfffe03ff,
+        /*    vs_3_sw */
+        0x02000001, 0xe00f0000, 0x90e40000, 0x0000ffff
+        /*    mov o0, v0 */
+    };
+
+    /* Vertex shaders */
+    DWORD version = D3DVS_VERSION(1,0);
+    test_create_vshader_version_check(device_ptr, caps, version, vs10_test_version);
+    version = D3DVS_VERSION(1,1);
+    test_create_vshader_version_check(device_ptr, caps, version, vs11_test_version);
+    version = D3DVS_VERSION(2,0);
+    test_create_vshader_version_check(device_ptr, caps, version, vs20_test_version);
+    version = D3DVS_VERSION(2,1);
+    test_create_vshader_version_check(device_ptr, caps, version, vs2x_test_version);
+    version = D3DVS_VERSION(2,0xff);
+    test_create_vshader_version_check(device_ptr, caps, version, vs2sw_test_version);
+    version = D3DVS_VERSION(3,0);
+    test_create_vshader_version_check(device_ptr, caps, version, vs30_test_version);
+    version = D3DVS_VERSION(3,0xff);
+    test_create_vshader_version_check(device_ptr, caps, version, vs3sw_test_version);
+
+    /* Pixel shaders */
+    version = D3DPS_VERSION(1,0);
+    test_create_pshader_version_check(device_ptr, caps, version, ps10_test_version);
+    version = D3DPS_VERSION(1,1);
+    test_create_pshader_version_check(device_ptr, caps, version, ps11_test_version);
+    version = D3DPS_VERSION(1,2);
+    test_create_pshader_version_check(device_ptr, caps, version, ps12_test_version);
+    version = D3DPS_VERSION(1,3);
+    test_create_pshader_version_check(device_ptr, caps, version, ps13_test_version);
+    version = D3DPS_VERSION(1,4);
+    test_create_pshader_version_check(device_ptr, caps, version, ps14_test_version);
+    version = D3DPS_VERSION(2,0);
+    test_create_pshader_version_check(device_ptr, caps, version, ps20_test_version);
+    version = D3DPS_VERSION(2,1);
+    test_create_pshader_version_check(device_ptr, caps, version, ps2x_test_version);
+    version = D3DPS_VERSION(2,0xff);
+    test_create_pshader_version_check(device_ptr, caps, version, ps2sw_test_version);
+    version = D3DPS_VERSION(3,0);
+    test_create_pshader_version_check(device_ptr, caps, version, ps30_test_version);
+    version = D3DPS_VERSION(3,0xff);
+    test_create_pshader_version_check(device_ptr, caps, version, ps3sw_test_version);
+
+}
+
 static void test_get_set_vertex_shader(IDirect3DDevice9 *device_ptr)
 {
 
@@ -228,6 +490,8 @@ START_TEST(shader)
 
     IDirect3DDevice9_GetDeviceCaps(device_ptr, &caps);
 
+    test_create_shader_version_check(device_ptr, &caps);
+
     if (caps.VertexShaderVersion & 0xffff)
     {
         test_get_set_vertex_shader(device_ptr);
diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c
index b6b84b0..14dba26 100644
--- a/dlls/wined3d/pixelshader.c
+++ b/dlls/wined3d/pixelshader.c
@@ -296,6 +296,25 @@ static void pshader_set_limits(
       }
 }
 
+/**
+ * checks if shader version supported that is required by new
+ * shader.
+ */
+static inline BOOL is_pshader_version_supported(IWineD3DDeviceImpl *deviceImpl, const DWORD shader_version) {
+    struct shader_caps shader_caps;
+    const WineD3D_GL_Info *gl_info = &deviceImpl->adapter->gl_info;
+
+    deviceImpl->shader_backend->shader_get_caps(deviceImpl->devType ,gl_info, &shader_caps);
+    /* Check which shader this is */
+    if(shader_is_pshader_version(shader_version)) {
+        /* Check if high enough shader version is supported */
+        return shader_caps.PixelShaderVersion >= shader_version;
+    }
+
+    return FALSE;
+}
+
+
 static HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *iface, CONST DWORD *pFunction) {
 
     IWineD3DPixelShaderImpl *This =(IWineD3DPixelShaderImpl *)iface;
@@ -319,6 +338,12 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *i
     hr = shader_get_registers_used((IWineD3DBaseShader *)This, reg_maps, This->semantics_in, NULL, pFunction);
     if (FAILED(hr)) return hr;
 
+    /* If no hardware support this function should fail */
+    if (!is_pshader_version_supported(deviceImpl, reg_maps->shader_version)) {
+        WARN("No hardware support for pixel shader version (0x%x).\n",reg_maps->shader_version);
+        return WINED3DERR_INVALIDCALL;
+    }
+
     pshader_set_limits(This);
 
     for (i = 0; i < MAX_REG_INPUT; ++i)
diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c
index 063f576..5d63241 100644
--- a/dlls/wined3d/vertexshader.c
+++ b/dlls/wined3d/vertexshader.c
@@ -419,6 +419,24 @@ static HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader*
     return WINED3D_OK;
 }
 
+/**
+ * checks if shader version supported that is required by new
+ * shader.
+ */
+static inline BOOL is_vshader_version_supported(IWineD3DDeviceImpl *deviceImpl, const DWORD shader_version) {
+    struct shader_caps shader_caps;
+    const WineD3D_GL_Info *gl_info = &deviceImpl->adapter->gl_info;
+
+    deviceImpl->shader_backend->shader_get_caps(deviceImpl->devType ,gl_info, &shader_caps);
+    /* Check which shader this is */
+    if(shader_is_vshader_version(shader_version)) {
+        /* Check if high enough shader version is supported */
+        return shader_caps.VertexShaderVersion >= shader_version;
+    }
+
+    return FALSE;
+}
+
 /* Note that for vertex shaders CompileShader isn't called until the
  * shader is first used. The reason for this is that we need the vertex
  * declaration the shader will be used with in order to determine if
@@ -448,6 +466,12 @@ static HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader
             This->semantics_in, This->semantics_out, pFunction);
     if (hr != WINED3D_OK) return hr;
 
+    /* If no hardware support this function should fail */
+    if (!is_vshader_version_supported(deviceImpl, reg_maps->shader_version)) {
+        WARN("No hardware support for vertex shader version (0x%x).\n",reg_maps->shader_version);
+        return WINED3DERR_INVALIDCALL;
+    }
+
     vshader_set_limits(This);
 
     This->baseShader.shader_mode = deviceImpl->vs_selected_mode;
-- 
1.5.6.3




More information about the wine-patches mailing list