[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