[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, ¤t_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, ¤t_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