[PATCH] wined3d: Implement check for shader creation if hardware supports requested version.

Pauli Nieminen suokkos at gmail.com
Tue Dec 16 18:05:30 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  |  262 ++++++++++++++++++++++++++++++++++++++++++++-
 dlls/wined3d/baseshader.c |   50 +++++++++-
 2 files changed, 308 insertions(+), 4 deletions(-)

diff --git a/dlls/d3d9/tests/shader.c b/dlls/d3d9/tests/shader.c
index 522f128..193681b 100644
--- a/dlls/d3d9/tests/shader.c
+++ b/dlls/d3d9/tests/shader.c
@@ -44,7 +44,7 @@ static IDirect3DDevice9 *init_d3d9(void)
     d3d9_create = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9");
     ok(d3d9_create != NULL, "Failed to get address of Direct3DCreate9\n");
     if (!d3d9_create) return NULL;
-    
+
     d3d9_ptr = d3d9_create(D3D_SDK_VERSION);
     if (!d3d9_ptr)
     {
@@ -74,6 +74,260 @@ 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", version, hret, 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", 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", version, hret, 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", 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)
 {
 
@@ -111,7 +365,7 @@ static void test_get_set_vertex_shader(IDirect3DDevice9 *device_ptr)
     i = shader_refcount+1;
     hret = IDirect3DDevice9_GetVertexShader(device_ptr, &current_shader_ptr);
     shader_refcount = get_refcount((IUnknown *)shader_ptr);
-    ok(hret == D3D_OK && shader_refcount == i && current_shader_ptr == shader_ptr, 
+    ok(hret == D3D_OK && shader_refcount == i && current_shader_ptr == shader_ptr,
         "GetVertexShader returned: hret 0x%x, current_shader_ptr %p refcount %d. "
         "Expected hret 0x%x, current_shader_ptr %p, refcount %d.\n", hret, current_shader_ptr, shader_refcount, D3D_OK, shader_ptr, i);
 }
@@ -179,7 +433,7 @@ static void test_get_set_pixel_shader(IDirect3DDevice9 *device_ptr)
     i = shader_refcount+1;
     hret = IDirect3DDevice9_GetPixelShader(device_ptr, &current_shader_ptr);
     shader_refcount = get_refcount((IUnknown *)shader_ptr);
-    ok(hret == D3D_OK && shader_refcount == i && current_shader_ptr == shader_ptr, 
+    ok(hret == D3D_OK && shader_refcount == i && current_shader_ptr == shader_ptr,
         "GetPixelShader returned: hret 0x%x, current_shader_ptr %p refcount %d. "
         "Expected hret 0x%x, current_shader_ptr %p, refcount %d.\n", hret, current_shader_ptr, shader_refcount, D3D_OK, shader_ptr, i);
 }
@@ -228,6 +482,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/baseshader.c b/dlls/wined3d/baseshader.c
index 9cc0e2b..99eba6b 100644
--- a/dlls/wined3d/baseshader.c
+++ b/dlls/wined3d/baseshader.c
@@ -197,6 +197,34 @@ static void shader_delete_constant_list(struct list* clist) {
     }
     list_init(clist);
 }
+/**
+ * checks if shader version supported that is required by new
+ * shader.
+ */
+static inline BOOL is_shader_version_supported(IWineD3DDeviceImpl *deviceImpl, const DWORD *byte_code)
+{
+//	IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)shader;
+	struct shader_caps shader_caps;
+	const DWORD shader_version = *byte_code; /* First instruction should be shader version */
+    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;
+	} 
+	else if(shader_is_vshader_version(shader_version)) 
+	{
+		// Check if high enough shader version is supported
+		return shader_caps.VertexShaderVersion >= shader_version;
+	}
+	
+	ERR("First instruction in shader isn't correct shader version. (0x%x)\n", shader_version);
+
+	return FALSE;
+}
 
 /* Note that this does not count the loop register
  * as an address register. */
@@ -216,7 +244,27 @@ HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, struct shader_reg_m
     memset(reg_maps->bumpmat, 0, sizeof(reg_maps->bumpmat));
     memset(reg_maps->luminanceparams, 0, sizeof(reg_maps->luminanceparams));
 
-    /* get_registers_used is called on every compile on some 1.x shaders, which can result
+	/* If no hardware support this function should fail */
+	if (!is_shader_version_supported((IWineD3DDeviceImpl*)This->baseShader.device, pToken))
+	{
+		static BOOL warned = FALSE;
+		if (!warned)
+		{
+			warned = TRUE;
+			ERR("No hardware support for shader version.\n");
+		}
+		return WINED3DERR_INVALIDCALL;
+	}
+
+
+    if (!pToken)
+    {
+        WARN("Got a NULL pFunction, returning.\n");
+        This->baseShader.functionLength = 0;
+        return WINED3D_OK;
+    }
+
+	/* get_registers_used is called on every compile on some 1.x shaders, which can result
      * in stacking up a collection of local constants. Delete the old constants if existing
      */
     shader_delete_constant_list(&This->baseShader.constantsF);
-- 
1.5.6.3




More information about the wine-patches mailing list