diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index 419d485de43..4d7dd583180 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -878,6 +878,33 @@ void pshader_hw_cmp(SHADER_OPCODE_ARG* arg) { pshader_gen_output_modifier_line(buffer, FALSE, dst_wmask, shift, dst_name); } +/** Process the WINED3DSIO_DP2ADD instruction in ARB. + * dst = dot2(src0, src1) + src2 */ +void pshader_hw_dp2add(SHADER_OPCODE_ARG* arg) { + SHADER_BUFFER* buffer = arg->buffer; + char dst_wmask[20]; + char dst_name[50]; + char src_name[3][50]; + DWORD shift = (arg->dst & WINED3DSP_DSTSHIFT_MASK) >> WINED3DSP_DSTSHIFT_SHIFT; + BOOL sat = (arg->dst & WINED3DSP_DSTMOD_MASK) & WINED3DSPDM_SATURATE; + + pshader_get_register_name(arg->dst, dst_name); + shader_arb_get_write_mask(arg, arg->dst, dst_wmask); + + pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src_name[0]); + pshader_gen_input_modifier_line(buffer, arg->src[1], 1, src_name[1]); + pshader_gen_input_modifier_line(buffer, arg->src[2], 2, src_name[2]); + + /* Emulate a DP2 with a DP3 and 0.0 */ + shader_addline(buffer, "MOV TMP, %s;\n", src_name[0]); + shader_addline(buffer, "MOV TMP.z, 0.0;\n"); + shader_addline(buffer, "DP3 TMP2, TMP, %s;\n", src_name[1]); + shader_addline(buffer, "ADD%s %s%s, TMP2, %s;\n", sat ? "_SAT" : "", dst_name, dst_wmask, src_name[2]); + + if (shift != 0) + pshader_gen_output_modifier_line(buffer, FALSE, dst_wmask, shift, dst_name); +} + /* Map the opcode 1-to-1 to the GL code */ void pshader_hw_map2gl(SHADER_OPCODE_ARG* arg) { diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c index 2d89bad0571..10fb732badb 100644 --- a/dlls/wined3d/pixelshader.c +++ b/dlls/wined3d/pixelshader.c @@ -189,8 +189,7 @@ CONST SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[] = { {WINED3DSIO_NRM, "nrm", NULL, 1, 2, NULL, shader_glsl_map2gl, 0, 0}, {WINED3DSIO_SINCOS, "sincos", NULL, 1, 4, NULL, shader_glsl_sincos, WINED3DPS_VERSION(2,0), WINED3DPS_VERSION(2,1)}, {WINED3DSIO_SINCOS, "sincos", NULL, 1, 2, NULL, shader_glsl_sincos, WINED3DPS_VERSION(3,0), -1}, - /* TODO: dp2add can be made out of multiple instuctions */ - {WINED3DSIO_DP2ADD, "dp2add", GLNAME_REQUIRE_GLSL, 1, 4, NULL, pshader_glsl_dp2add, WINED3DPS_VERSION(2,0), -1}, + {WINED3DSIO_DP2ADD, "dp2add", NULL, 1, 4, pshader_hw_dp2add, pshader_glsl_dp2add, WINED3DPS_VERSION(2,0), -1}, /* Matrix */ {WINED3DSIO_M4x4, "m4x4", "undefined", 1, 3, NULL, shader_glsl_mnxn, 0, 0}, {WINED3DSIO_M4x3, "m4x3", "undefined", 1, 3, NULL, shader_glsl_mnxn, 0, 0}, diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 8844ffa0b42..70d44e4140b 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1786,6 +1786,7 @@ extern void pshader_hw_texdp3tex(SHADER_OPCODE_ARG* arg); extern void pshader_hw_texdp3(SHADER_OPCODE_ARG* arg); extern void pshader_hw_texm3x3(SHADER_OPCODE_ARG* arg); extern void pshader_hw_texm3x2depth(SHADER_OPCODE_ARG* arg); +extern void pshader_hw_dp2add(SHADER_OPCODE_ARG* arg); /* ARB vertex shader prototypes */ extern void vshader_hw_map2gl(SHADER_OPCODE_ARG* arg);