From 72bfe131d1a1c4087dcc4b00405f7c612300378b Mon Sep 17 00:00:00 2001 From: Jason Green Date: Fri, 28 Jul 2006 04:14:14 -0400 Subject: [PATCH] wined3d: More shader fixes / new instructions. - Replace gl_FragColor with gl_FragData[0] for GLSL pixel shader output. - Subtract 1 more constant from total GLSL allowed float constants to accommodate the PROJECTION matrix row that we reference. --- dlls/wined3d/arb_program_shader.c | 1 - dlls/wined3d/directx.c | 4 +- dlls/wined3d/glsl_shader.c | 127 ++++++++++++++++++++++++++++-- dlls/wined3d/pixelshader.c | 18 ++--- dlls/wined3d/vertexshader.c | 8 +- dlls/wined3d/wined3d_private.h | 6 ++ 6 files changed, 140 insertions(+), 24 deletions(-) diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index a2b07dbe65d..6700de3ac42 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -171,7 +171,6 @@ void shader_generate_arb_declarations( /* Need to PARAM the environment parameters (constants) so we can use relative addressing */ shader_addline(buffer, "PARAM C[%d] = { program.env[0..%d] };\n", max_constantsF, max_constantsF - 1); - shader_addline(buffer, "PARAM PROJECTION = state.matrix.projection.row[1];\n"); } static const char* shift_tab[] = { diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 5b3549418a8..4454d98a3fd 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -243,8 +243,8 @@ void select_shader_max_constants(WineD3D_GL_Info *gl_info) { switch (wined3d_settings.vs_selected_mode) { case SHADER_GLSL: - /* Subtract the other potential uniforms from the max available (bools & ints) */ - gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - MAX_CONST_B - MAX_CONST_I; + /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */ + gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - MAX_CONST_B - MAX_CONST_I - 1; break; case SHADER_ARB: /* We have to subtract any other PARAMs that we might use in our shader programs. diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index b3ae5cbf25f..63af4f7e16d 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -638,12 +638,10 @@ static void shader_glsl_get_register_name( sprintf(tmpStr, "Vsampler%lu", reg); break; case D3DSPR_COLOROUT: - if (reg == 0) - sprintf(tmpStr, "gl_FragColor"); - else { + sprintf(tmpStr, "gl_FragData[%lu]", reg); + if (reg > 0) { /* TODO: See GL_ARB_draw_buffers */ FIXME("Unsupported write to render target %lu\n", reg); - sprintf(tmpStr, "unsupported_register"); } break; case D3DSPR_RASTOUT: @@ -914,7 +912,6 @@ void shader_glsl_map2gl(SHADER_OPCODE_ARG* arg) { case D3DSIO_NRM: strcat(tmpLine, "normalize"); break; case D3DSIO_LOGP: case D3DSIO_LOG: strcat(tmpLine, "log2"); break; - case D3DSIO_EXPP: case D3DSIO_EXP: strcat(tmpLine, "exp2"); break; case D3DSIO_SGE: strcat(tmpLine, "greaterThanEqual"); break; case D3DSIO_SLT: strcat(tmpLine, "lessThan"); break; @@ -942,6 +939,39 @@ void shader_glsl_map2gl(SHADER_OPCODE_ARG* arg) { } +/** Process the D3DSIO_EXPP instruction in GLSL: + * For shader model 1.x, do the following (and honor the writemask, so use a temporary variable): + * dst.x = 2^(floor(src)) + * dst.y = src - floor(src) + * dst.z = 2^src (partial precision is allowed, but optional) + * dst.w = 1.0; + * For 2.0 shaders, just do this (honoring writemask and swizzle): + * dst = 2^src; (partial precision is allowed, but optional) + */ +void shader_glsl_expp(SHADER_OPCODE_ARG* arg) { + + char tmpLine[256]; + char dst_str[100], src_str[100]; + char dst_reg[50], src_reg[50]; + char dst_mask[6], src_mask[6]; + IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader; + DWORD hex_version = This->baseShader.hex_version; + + shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str); + shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src_reg, src_mask, src_str); + shader_glsl_add_dst(arg->dst, dst_reg, dst_mask, tmpLine); + + if (hex_version < D3DPS_VERSION(2,0)) { + shader_addline(arg->buffer, "tmp0.x = vec4(exp2(floor(%s))).x;\n", src_str); + shader_addline(arg->buffer, "tmp0.y = vec4(%s - floor(%s)).y;\n", src_str, src_str); + shader_addline(arg->buffer, "tmp0.z = vec4(exp2(%s)).x;\n", src_str); + shader_addline(arg->buffer, "tmp0.w = 1.0;\n"); + shader_addline(arg->buffer, "%svec4(tmp0))%s;\n", tmpLine, dst_mask); + } else { + shader_addline(arg->buffer, "%svec4(exp2(%s)))%s;\n", tmpLine, src_str, dst_mask); + } +} + /** Process the RCP (reciprocal or inverse) opcode in GLSL (dst = 1 / src) */ void shader_glsl_rcp(SHADER_OPCODE_ARG* arg) { @@ -1354,6 +1384,73 @@ void pshader_glsl_texcoord(SHADER_OPCODE_ARG* arg) { } } +/** Process the D3DSIO_TEXDP3TEX instruction in GLSL: + * Take a 3-component dot product of the TexCoord[dstreg] and src, + * then perform a 1D texture lookup from stage dstregnum, place into dst. */ +void pshader_glsl_texdp3tex(SHADER_OPCODE_ARG* arg) { + + DWORD dstreg = arg->dst & D3DSP_REGNUM_MASK; + char src0_str[100], dst_str[100]; + char src0_name[50], dst_name[50]; + char src0_mask[6], dst_mask[6]; + + shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_name, dst_mask, dst_str); + shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_name, src0_mask, src0_str); + + shader_addline(arg->buffer, "tmp0.x = dot(vec3(gl_TexCoord[%lu]), vec3(%s));\n", dstreg, src0_str); + shader_addline(arg->buffer, "%s = vec4(texture1D(Psampler%lu, tmp0.x))%s;\n", dst_str, dstreg, dst_mask); +} + +/** Process the D3DSIO_TEXDP3 instruction in GLSL: + * Take a 3-component dot product of the TexCoord[dstreg] and src. */ +void pshader_glsl_texdp3(SHADER_OPCODE_ARG* arg) { + + DWORD dstreg = arg->dst & D3DSP_REGNUM_MASK; + char src0_str[100], dst_str[100]; + char src0_name[50], dst_name[50]; + char src0_mask[6], dst_mask[6]; + + shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_name, dst_mask, dst_str); + shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_name, src0_mask, src0_str); + + shader_addline(arg->buffer, "%s = vec4(dot(vec3(T%lu), vec3(%s)))%s;\n", + dst_str, dstreg, src0_str, dst_mask); +} + +/** Process the D3DSIO_TEXDEPTH instruction in GLSL: + * Calculate the depth as dst.x / dst.y */ +void pshader_glsl_texdepth(SHADER_OPCODE_ARG* arg) { + + char dst_str[100]; + char dst_reg[50]; + char dst_mask[6]; + + shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str); + + shader_addline(arg->buffer, "gl_FragDepth = %s.x / %s.y;\n", dst_reg, dst_reg); +} + +/** Process the D3DSIO_TEXM3X2DEPTH instruction in GLSL: + * Last row of a 3x2 matrix multiply, use the result to calculate the depth: + * Calculate tmp0.y = TexCoord[dstreg] . src.xyz; (tmp0.x has already been calculated) + * depth = (tmp0.y == 0.0) ? 1.0 : tmp0.x / tmp0.y + */ +void pshader_glsl_texm3x2depth(SHADER_OPCODE_ARG* arg) { + + DWORD dstreg = arg->dst & D3DSP_REGNUM_MASK; + char src0_str[100], dst_str[100]; + char src0_name[50], dst_name[50]; + char src0_mask[6], dst_mask[6]; + + shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_name, dst_mask, dst_str); + shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_name, src0_mask, src0_str); + + shader_addline(arg->buffer, "tmp0.y = dot(vec3(T%lu), vec3(%s));\n", dstreg, src0_str); + shader_addline(arg->buffer, "gl_FragDepth = vec4((tmp0.y == 0.0) ? 1.0 : tmp0.x / tmp0.y)%s;\n", dst_str, dst_name); +} + +/** Process the D3DSIO_TEXM3X2PAD instruction in GLSL + * Calculate the 1st of a 2-row matrix multiplication. */ void pshader_glsl_texm3x2pad(SHADER_OPCODE_ARG* arg) { DWORD reg = arg->dst & D3DSP_REGNUM_MASK; @@ -1363,7 +1460,7 @@ void pshader_glsl_texm3x2pad(SHADER_OPCODE_ARG* arg) { char src0_mask[6]; shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_name, src0_mask, src0_str); - shader_addline(buffer, "tmp0.x = dot(vec3(T%lu), vec3(%s));\n", reg, src0_name, src0_str); + shader_addline(buffer, "tmp0.x = dot(vec3(T%lu), vec3(%s));\n", reg, src0_str); } /** Process the D3DSIO_TEXM3X3PAD instruction in GLSL @@ -1429,6 +1526,24 @@ void pshader_glsl_texm3x3tex(SHADER_OPCODE_ARG* arg) { current_state->current_row = 0; } +/** Process the D3DSIO_TEXM3X3 instruction in GLSL + * Perform the 3rd row of a 3x3 matrix multiply */ +void pshader_glsl_texm3x3(SHADER_OPCODE_ARG* arg) { + + char src0_str[100]; + char src0_name[50]; + char src0_mask[6]; + DWORD reg = arg->dst & D3DSP_REGNUM_MASK; + IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader; + SHADER_PARSE_STATE* current_state = &This->baseShader.parse_state; + + shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_name, src0_mask, src0_str); + + shader_addline(arg->buffer, "tmp0.z = dot(vec3(T%lu), vec3(%s));\n", reg, src0_str); + shader_addline(arg->buffer, "T%lu = vec4(tmp0.x, tmp0.y, tmp0.z, 1.0);\n", reg); + current_state->current_row = 0; +} + /** Process the D3DSIO_TEXM3X3SPEC instruction in GLSL * Peform the final texture lookup based on the previous 2 3x3 matrix multiplies */ void pshader_glsl_texm3x3spec(SHADER_OPCODE_ARG* arg) { diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c index 7e11c471b83..9e7b8526859 100644 --- a/dlls/wined3d/pixelshader.c +++ b/dlls/wined3d/pixelshader.c @@ -618,9 +618,6 @@ static void pshader_texldl(WINED3DSHADERVECTOR* d) { FIXME(" : Stub\n"); } -/** - * log, exp, frc, m*x* seems to be macros ins ... to see - */ CONST SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[] = { /* Arithmethic */ @@ -641,7 +638,7 @@ CONST SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[] = { {D3DSIO_ABS, "abs", "ABS", 1, 2, pshader_abs, pshader_hw_map2gl, shader_glsl_map2gl, 0, 0}, {D3DSIO_EXP, "exp", "EX2", 1, 2, pshader_exp, pshader_hw_map2gl, shader_glsl_map2gl, 0, 0}, {D3DSIO_LOG, "log", "LG2", 1, 2, pshader_log, pshader_hw_map2gl, shader_glsl_map2gl, 0, 0}, - {D3DSIO_EXPP, "expp", "EXP", 1, 2, pshader_expp, pshader_hw_map2gl, shader_glsl_map2gl, 0, 0}, + {D3DSIO_EXPP, "expp", "EXP", 1, 2, pshader_expp, pshader_hw_map2gl, shader_glsl_expp, 0, 0}, {D3DSIO_LOGP, "logp", "LOG", 1, 2, pshader_logp, pshader_hw_map2gl, shader_glsl_map2gl, 0, 0}, {D3DSIO_DST, "dst", "DST", 1, 3, pshader_dst, pshader_hw_map2gl, shader_glsl_dst, 0, 0}, {D3DSIO_LRP, "lrp", "LRP", 1, 4, pshader_lrp, pshader_hw_map2gl, shader_glsl_lrp, 0, 0}, @@ -717,13 +714,12 @@ CONST SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[] = { {D3DSIO_TEXM3x3SPEC, "texm3x3spec", "undefined", 1, 3, pshader_texm3x3spec, pshader_hw_texm3x3spec, pshader_glsl_texm3x3spec, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)}, {D3DSIO_TEXM3x3VSPEC, "texm3x3vspec", "undefined", 1, 2, pshader_texm3x3vspec, pshader_hw_texm3x3vspec, pshader_glsl_texm3x3vspec, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)}, {D3DSIO_TEXM3x3TEX, "texm3x3tex", "undefined", 1, 2, pshader_texm3x3tex, pshader_hw_texm3x3tex, pshader_glsl_texm3x3tex, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)}, - {D3DSIO_TEXDP3TEX, "texdp3tex", GLNAME_REQUIRE_GLSL, 1, 2, pshader_texdp3tex, NULL, NULL, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)}, - {D3DSIO_TEXM3x2DEPTH, "texm3x2depth", GLNAME_REQUIRE_GLSL, 1, 2, pshader_texm3x2depth, NULL, NULL, D3DPS_VERSION(1,3), D3DPS_VERSION(1,3)}, - {D3DSIO_TEXDP3, "texdp3", GLNAME_REQUIRE_GLSL, 1, 2, pshader_texdp3, NULL, NULL, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)}, - {D3DSIO_TEXM3x3, "texm3x3", GLNAME_REQUIRE_GLSL, 1, 2, pshader_texm3x3, NULL, NULL, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)}, - {D3DSIO_TEXDEPTH, "texdepth", GLNAME_REQUIRE_GLSL, 1, 1, pshader_texdepth, NULL, NULL, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)}, + {D3DSIO_TEXDP3TEX, "texdp3tex", GLNAME_REQUIRE_GLSL, 1, 2, pshader_texdp3tex, NULL, pshader_glsl_texdp3tex, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)}, + {D3DSIO_TEXM3x2DEPTH, "texm3x2depth", GLNAME_REQUIRE_GLSL, 1, 2, pshader_texm3x2depth, NULL, pshader_glsl_texm3x2depth, D3DPS_VERSION(1,3), D3DPS_VERSION(1,3)}, + {D3DSIO_TEXDP3, "texdp3", GLNAME_REQUIRE_GLSL, 1, 2, pshader_texdp3, NULL, pshader_glsl_texdp3, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)}, + {D3DSIO_TEXM3x3, "texm3x3", GLNAME_REQUIRE_GLSL, 1, 2, pshader_texm3x3, NULL, pshader_glsl_texm3x3, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)}, + {D3DSIO_TEXDEPTH, "texdepth", GLNAME_REQUIRE_GLSL, 1, 1, pshader_texdepth, NULL, pshader_glsl_texdepth, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)}, {D3DSIO_BEM, "bem", GLNAME_REQUIRE_GLSL, 1, 3, pshader_bem, NULL, NULL, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)}, - /* TODO: dp2add can be made out of multiple instuctions */ {D3DSIO_DSX, "dsx", GLNAME_REQUIRE_GLSL, 1, 2, pshader_dsx, NULL, NULL, 0, 0}, {D3DSIO_DSY, "dsy", GLNAME_REQUIRE_GLSL, 1, 2, pshader_dsy, NULL, NULL, 0, 0}, {D3DSIO_TEXLDD, "texldd", GLNAME_REQUIRE_GLSL, 1, 5, pshader_texldd, NULL, NULL, D3DPS_VERSION(2,1), -1}, @@ -854,7 +850,7 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateShader( /* Pixel shaders < 2.0 place the resulting color in R0 implicitly */ if (This->baseShader.hex_version < D3DPS_VERSION(2,0)) - shader_addline(&buffer, "gl_FragColor = R0;\n"); + shader_addline(&buffer, "gl_FragData[0] = R0;\n"); shader_addline(&buffer, "}\n\0"); TRACE("Compiling shader object %u\n", shader_obj); diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c index 7e29e721b6b..0d4bac642c5 100644 --- a/dlls/wined3d/vertexshader.c +++ b/dlls/wined3d/vertexshader.c @@ -472,9 +472,6 @@ static void vshader_texldl(WINED3DSHADERVECTOR* d) { FIXME(" : Stub\n"); } -/** - * log, exp, frc, m*x* seems to be macros ins ... to see - */ CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = { /* Arithmetic */ @@ -495,7 +492,7 @@ CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = { {D3DSIO_ABS, "abs", "ABS", 1, 2, vshader_abs, vshader_hw_map2gl, shader_glsl_map2gl, 0, 0}, {D3DSIO_EXP, "exp", "EX2", 1, 2, vshader_exp, vshader_hw_map2gl, shader_glsl_map2gl, 0, 0}, {D3DSIO_LOG, "log", "LG2", 1, 2, vshader_log, vshader_hw_map2gl, shader_glsl_map2gl, 0, 0}, - {D3DSIO_EXPP, "expp", "EXP", 1, 2, vshader_expp, vshader_hw_map2gl, shader_glsl_map2gl, 0, 0}, + {D3DSIO_EXPP, "expp", "EXP", 1, 2, vshader_expp, vshader_hw_map2gl, shader_glsl_expp, 0, 0}, {D3DSIO_LOGP, "logp", "LOG", 1, 2, vshader_logp, vshader_hw_map2gl, shader_glsl_map2gl, 0, 0}, {D3DSIO_LIT, "lit", "LIT", 1, 2, vshader_lit, vshader_hw_map2gl, shader_glsl_lit, 0, 0}, {D3DSIO_DST, "dst", "DST", 1, 3, vshader_dst, vshader_hw_map2gl, shader_glsl_dst, 0, 0}, @@ -746,6 +743,9 @@ static VOID IWineD3DVertexShaderImpl_GenerateShader( /* Base Declarations */ shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, &buffer, &GLINFO_LOCATION); + + /* We need the projection matrix to correctly render upside-down objects (render to texture) */ + shader_addline(&buffer, "PARAM PROJECTION = state.matrix.projection.row[1];\n"); if (reg_maps->fog) { This->usesFog = 1; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 5329e42b0f6..05194a4d144 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1493,6 +1493,7 @@ extern void shader_glsl_compare(SHADER_OPCODE_ARG* arg); extern void shader_glsl_def(SHADER_OPCODE_ARG* arg); extern void shader_glsl_defi(SHADER_OPCODE_ARG* arg); extern void shader_glsl_defb(SHADER_OPCODE_ARG* arg); +extern void shader_glsl_expp(SHADER_OPCODE_ARG* arg); extern void shader_glsl_cmp(SHADER_OPCODE_ARG* arg); extern void shader_glsl_lit(SHADER_OPCODE_ARG* arg); extern void shader_glsl_dst(SHADER_OPCODE_ARG* arg); @@ -1512,8 +1513,13 @@ extern void shader_glsl_label(SHADER_OPCODE_ARG* arg); /** GLSL Pixel Shader Prototypes */ extern void pshader_glsl_tex(SHADER_OPCODE_ARG* arg); extern void pshader_glsl_texcoord(SHADER_OPCODE_ARG* arg); +extern void pshader_glsl_texdp3tex(SHADER_OPCODE_ARG* arg); +extern void pshader_glsl_texdp3(SHADER_OPCODE_ARG* arg); +extern void pshader_glsl_texdepth(SHADER_OPCODE_ARG* arg); +extern void pshader_glsl_texm3x2depth(SHADER_OPCODE_ARG* arg); extern void pshader_glsl_texm3x2pad(SHADER_OPCODE_ARG* arg); extern void pshader_glsl_texm3x2tex(SHADER_OPCODE_ARG* arg); +extern void pshader_glsl_texm3x3(SHADER_OPCODE_ARG* arg); extern void pshader_glsl_texm3x3pad(SHADER_OPCODE_ARG* arg); extern void pshader_glsl_texm3x3tex(SHADER_OPCODE_ARG* arg); extern void pshader_glsl_texm3x3spec(SHADER_OPCODE_ARG* arg);