diff --git a/dlls/d3d8/tests/visual.c b/dlls/d3d8/tests/visual.c index e4178f25b70..a23c322b3fa 100644 --- a/dlls/d3d8/tests/visual.c +++ b/dlls/d3d8/tests/visual.c @@ -495,11 +495,127 @@ static void present_test(IDirect3DDevice8 *device) ok(color == 0x00ff0000, "Present failed: Got color 0x%08x, expected 0x00ff0000.\n", color); } +static void test_rcp_rsq(IDirect3DDevice8 *device) +{ + HRESULT hr; + DWORD shader; + DWORD color; + unsigned char c1, c2, c3; + float constant[4] = {1.0, 1.0, 1.0, 2.0}; + + static const float quad[][3] = { + {-1.0f, -1.0f, 0.0f}, + {-1.0f, 1.0f, 0.0f}, + { 1.0f, -1.0f, 0.0f}, + { 1.0f, 1.0f, 0.0f}, + }; + + const DWORD rcp_test[] = { + 0xfffe0101, /* vs.1.1 */ + + 0x0009fffe, 0x30303030, 0x30303030, /* Shaders have to have a minimal size. */ + 0x30303030, 0x30303030, 0x30303030, /* Add a filler comment. Usually D3DX8's*/ + 0x30303030, 0x30303030, 0x30303030, /* version comment makes the shader big */ + 0x00303030, /* enough to make windows happy */ + + 0x00000001, 0xc00f0000, 0x90e40000, /* mov oPos, v0 */ + 0x00000006, 0xd00f0000, 0xa0e40000, /* rcp oD0, c0 */ + 0x0000ffff /* END */ + }; + + const DWORD rsq_test[] = { + 0xfffe0101, /* vs.1.1 */ + + 0x0009fffe, 0x30303030, 0x30303030, /* Shaders have to have a minimal size. */ + 0x30303030, 0x30303030, 0x30303030, /* Add a filler comment. Usually D3DX8's*/ + 0x30303030, 0x30303030, 0x30303030, /* version comment makes the shader big */ + 0x00303030, /* enough to make windows happy */ + + 0x00000001, 0xc00f0000, 0x90e40000, /* mov oPos, v0 */ + 0x00000007, 0xd00f0000, 0xa0e40000, /* rsq oD0, c0 */ + 0x0000ffff /* END */ + }; + + DWORD decl[] = + { + D3DVSD_STREAM(0), + D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3), /* D3DVSDE_POSITION, Register v0 */ + D3DVSD_END() + }; + + hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff800080, 0.0, 0); + ok(hr == D3D_OK, "IDirect3DDevice8_Clear failed with %08x\n", hr); + + hr = IDirect3DDevice8_CreateVertexShader(device, decl, rcp_test, &shader, 0); + ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned with %08x\n", hr); + + IDirect3DDevice8_SetVertexShader(device, shader); + ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %08x\n", hr); + IDirect3DDevice8_SetVertexShaderConstant(device, 0, constant, 1); + + hr = IDirect3DDevice8_BeginScene(device); + ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene returned %08x\n", hr); + if(SUCCEEDED(hr)) + { + hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], 3 * sizeof(float)); + ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr); + hr = IDirect3DDevice8_EndScene(device); + ok(hr == D3D_OK, "IDirect3DDevice8_EndScene returned %08x\n", hr); + } + + hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL); + ok(SUCCEEDED(hr), "Present failed (%08x)\n", hr); + color = getPixelColor(device, 320, 240); + c1 = (color & 0x00ff0000 )>> 16; + c2 = (color & 0x0000ff00 )>> 8; + c3 = (color & 0x000000ff )>> 0; + ok(c1 == c2 && c2 == c3, "Color components differ: c1 = %02x, c2 = %02x, c3 = %02x\n", + c1, c2, c3); + ok(c1 >= 0x7c && c1 <= 0x84, "Color component value is %02x\n", c1); + + IDirect3DDevice8_SetVertexShader(device, 0); + IDirect3DDevice8_DeleteVertexShader(device, shader); + + hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff800080, 0.0, 0); + ok(hr == D3D_OK, "IDirect3DDevice8_Clear failed with %08x\n", hr); + + hr = IDirect3DDevice8_CreateVertexShader(device, decl, rsq_test, &shader, 0); + ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned with %08x\n", hr); + + IDirect3DDevice8_SetVertexShader(device, shader); + ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %08x\n", hr); + IDirect3DDevice8_SetVertexShaderConstant(device, 0, constant, 1); + + hr = IDirect3DDevice8_BeginScene(device); + ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene returned %08x\n", hr); + if(SUCCEEDED(hr)) + { + hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], 3 * sizeof(float)); + ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr); + hr = IDirect3DDevice8_EndScene(device); + ok(hr == D3D_OK, "IDirect3DDevice8_EndScene returned %08x\n", hr); + } + + hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL); + ok(SUCCEEDED(hr), "Present failed (%08x)\n", hr); + color = getPixelColor(device, 320, 240); + c1 = (color & 0x00ff0000 )>> 16; + c2 = (color & 0x0000ff00 )>> 8; + c3 = (color & 0x000000ff )>> 0; + ok(c1 == c2 && c2 == c3, "Color components differ: c1 = %02x, c2 = %02x, c3 = %02x\n", + c1, c2, c3); + ok(c1 >= 0xb0 && c1 <= 0xb8, "Color component value is %02x\n", c1); + + IDirect3DDevice8_SetVertexShader(device, 0); + IDirect3DDevice8_DeleteVertexShader(device, shader); +} + START_TEST(visual) { IDirect3DDevice8 *device_ptr; HRESULT hr; DWORD color; + D3DCAPS8 caps; d3d8_handle = LoadLibraryA("d3d8.dll"); if (!d3d8_handle) @@ -511,6 +627,8 @@ START_TEST(visual) device_ptr = init_d3d8(); if (!device_ptr) return; + IDirect3DDevice8_GetDeviceCaps(device_ptr, &caps); + /* Check for the reliability of the returned data */ hr = IDirect3DDevice8_Clear(device_ptr, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0); if(FAILED(hr)) @@ -548,6 +666,15 @@ START_TEST(visual) fog_test(device_ptr); present_test(device_ptr); + if (caps.VertexShaderVersion >= D3DVS_VERSION(1, 1)) + { + test_rcp_rsq(device_ptr); + } + else + { + skip("No vs.1.1 support\n"); + } + cleanup: if(device_ptr) IDirect3DDevice8_Release(device_ptr); } diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index e5ee5c649cb..d6f932a12a5 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -948,8 +948,10 @@ void vshader_hw_rsq_rcp(SHADER_OPCODE_ARG* arg) { strcat(tmpLine, ","); vshader_program_add_param(arg, src, TRUE, tmpLine); if ((WINED3DSP_NOSWIZZLE >> WINED3DSP_SWIZZLE_SHIFT) == swizzle) { - /* Dx sdk says .x is used if no swizzle is given */ - strcat(tmpLine, ".x"); + /* Dx sdk says .x is used if no swizzle is given, but our test shows that + * .w is used + */ + strcat(tmpLine, ".w"); } shader_addline(buffer, "%s;\n", tmpLine); diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 00536b5b1a5..b4e444e0925 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -1054,7 +1054,6 @@ void shader_glsl_map2gl(SHADER_OPCODE_ARG* arg) { switch (curOpcode->opcode) { case WINED3DSIO_MIN: instruction = "min"; break; case WINED3DSIO_MAX: instruction = "max"; break; - case WINED3DSIO_RSQ: instruction = "inversesqrt"; break; case WINED3DSIO_ABS: instruction = "abs"; break; case WINED3DSIO_FRC: instruction = "fract"; break; case WINED3DSIO_NRM: instruction = "normalize"; break; @@ -1132,7 +1131,7 @@ void shader_glsl_rcp(SHADER_OPCODE_ARG* arg) { write_mask = shader_glsl_append_dst(arg->buffer, arg); mask_size = shader_glsl_get_write_mask_size(write_mask); - shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0, &src_param); + shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_3, &src_param); if (mask_size > 1) { shader_addline(arg->buffer, "vec%d(1.0 / %s));\n", mask_size, src_param.param_str); @@ -1141,6 +1140,24 @@ void shader_glsl_rcp(SHADER_OPCODE_ARG* arg) { } } +void shader_glsl_rsq(SHADER_OPCODE_ARG* arg) { + SHADER_BUFFER* buffer = arg->buffer; + glsl_src_param_t src_param; + DWORD write_mask; + size_t mask_size; + + write_mask = shader_glsl_append_dst(buffer, arg); + mask_size = shader_glsl_get_write_mask_size(write_mask); + + shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_3, &src_param); + + if (mask_size > 1) { + shader_addline(buffer, "vec%d(inversesqrt(%s)));\n", mask_size, src_param.param_str); + } else { + shader_addline(buffer, "inversesqrt(%s));\n", src_param.param_str); + } +} + /** Process signed comparison opcodes in GLSL. */ void shader_glsl_compare(SHADER_OPCODE_ARG* arg) { glsl_src_param_t src0_param; diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c index eb41d1f9792..1202f154ce7 100644 --- a/dlls/wined3d/pixelshader.c +++ b/dlls/wined3d/pixelshader.c @@ -166,7 +166,7 @@ CONST SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[] = { {WINED3DSIO_MAD, "mad", "MAD", 1, 4, pshader_hw_map2gl, shader_glsl_mad, 0, 0}, {WINED3DSIO_MUL, "mul", "MUL", 1, 3, pshader_hw_map2gl, shader_glsl_arith, 0, 0}, {WINED3DSIO_RCP, "rcp", "RCP", 1, 2, pshader_hw_map2gl, shader_glsl_rcp, 0, 0}, - {WINED3DSIO_RSQ, "rsq", "RSQ", 1, 2, pshader_hw_map2gl, shader_glsl_map2gl, 0, 0}, + {WINED3DSIO_RSQ, "rsq", "RSQ", 1, 2, pshader_hw_map2gl, shader_glsl_rsq, 0, 0}, {WINED3DSIO_DP3, "dp3", "DP3", 1, 3, pshader_hw_map2gl, shader_glsl_dot, 0, 0}, {WINED3DSIO_DP4, "dp4", "DP4", 1, 3, pshader_hw_map2gl, shader_glsl_dot, 0, 0}, {WINED3DSIO_MIN, "min", "MIN", 1, 3, pshader_hw_map2gl, shader_glsl_map2gl, 0, 0}, diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c index cb3b8733aa5..1c95d65c155 100644 --- a/dlls/wined3d/vertexshader.c +++ b/dlls/wined3d/vertexshader.c @@ -92,7 +92,7 @@ CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = { {WINED3DSIO_MAD, "mad", "MAD", 1, 4, vshader_hw_map2gl, shader_glsl_mad, 0, 0}, {WINED3DSIO_MUL, "mul", "MUL", 1, 3, vshader_hw_map2gl, shader_glsl_arith, 0, 0}, {WINED3DSIO_RCP, "rcp", "RCP", 1, 2, vshader_hw_rsq_rcp, shader_glsl_rcp, 0, 0}, - {WINED3DSIO_RSQ, "rsq", "RSQ", 1, 2, vshader_hw_rsq_rcp, shader_glsl_map2gl, 0, 0}, + {WINED3DSIO_RSQ, "rsq", "RSQ", 1, 2, vshader_hw_rsq_rcp, shader_glsl_rsq, 0, 0}, {WINED3DSIO_DP3, "dp3", "DP3", 1, 3, vshader_hw_map2gl, shader_glsl_dot, 0, 0}, {WINED3DSIO_DP4, "dp4", "DP4", 1, 3, vshader_hw_map2gl, shader_glsl_dot, 0, 0}, {WINED3DSIO_MIN, "min", "MIN", 1, 3, vshader_hw_map2gl, shader_glsl_map2gl, 0, 0}, diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 77978a37b72..dbfe40c4226 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1714,6 +1714,7 @@ extern void shader_glsl_mnxn(SHADER_OPCODE_ARG* arg); extern void shader_glsl_lrp(SHADER_OPCODE_ARG* arg); extern void shader_glsl_dot(SHADER_OPCODE_ARG* arg); extern void shader_glsl_rcp(SHADER_OPCODE_ARG* arg); +extern void shader_glsl_rsq(SHADER_OPCODE_ARG* arg); extern void shader_glsl_cnd(SHADER_OPCODE_ARG* arg); extern void shader_glsl_compare(SHADER_OPCODE_ARG* arg); extern void shader_glsl_def(SHADER_OPCODE_ARG* arg);