From d4312ebb16578d7d8ae193edd3d293d3748c7df4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Thu, 25 Jun 2009 19:52:17 +0200 Subject: [PATCH] wined3d: Add the vertex shader footer in the main function. --- dlls/wined3d/arb_program_shader.c | 182 ++++++++++++++++-------------- 1 file changed, 98 insertions(+), 84 deletions(-) diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index a9862ad9712..e4383661981 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -201,6 +201,8 @@ struct shader_arb_ctx_priv int aL; unsigned int vs_clipplanes; + BOOL footer_written; + BOOL in_main_func; /* For 3.0 vertex shaders */ const char *vs_output[MAX_REG_OUTPUT]; @@ -2804,6 +2806,7 @@ static void shader_hw_label(const struct wined3d_shader_instruction *ins) SHADER_BUFFER *buffer = ins->ctx->buffer; struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; + priv->in_main_func = FALSE; /* Call instructions activate the NV extensions, not labels and rets. If there is an uncalled * subroutine, don't generate a label that will make GL complain */ @@ -2812,13 +2815,105 @@ static void shader_hw_label(const struct wined3d_shader_instruction *ins) shader_addline(buffer, "l%u:\n", ins->src[0].reg.idx); } +static void vshader_add_footer(IWineD3DVertexShaderImpl *This, SHADER_BUFFER *buffer, const struct arb_vs_compile_args *args, + struct shader_arb_ctx_priv *priv_ctx) +{ + const shader_reg_maps *reg_maps = &This->baseShader.reg_maps; + IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)This->baseShader.device; + const WineD3D_GL_Info *gl_info = &device->adapter->gl_info; + unsigned int i; + + /* The D3DRS_FOGTABLEMODE render state defines if the shader-generated fog coord is used + * or if the fragment depth is used. If the fragment depth is used(FOGTABLEMODE != NONE), + * the fog frag coord is thrown away. If the fog frag coord is used, but not written by + * the shader, it is set to 0.0(fully fogged, since start = 1.0, end = 0.0) + */ + if(args->super.fog_src == VS_FOG_Z) { + shader_addline(buffer, "MOV result.fogcoord, TMP_OUT.z;\n"); + } else if (!reg_maps->fog) { + /* posFixup.x is always 1.0, so we can savely use it */ + shader_addline(buffer, "ADD result.fogcoord, posFixup.x, -posFixup.x;\n"); + } + + /* Write the final position. + * + * OpenGL coordinates specify the center of the pixel while d3d coords specify + * the corner. The offsets are stored in z and w in posFixup. posFixup.y contains + * 1.0 or -1.0 to turn the rendering upside down for offscreen rendering. PosFixup.x + * contains 1.0 to allow a mad, but arb vs swizzles are too restricted for that. + */ + shader_addline(buffer, "MUL TA, posFixup, TMP_OUT.w;\n"); + shader_addline(buffer, "ADD TMP_OUT.x, TMP_OUT.x, TA.z;\n"); + shader_addline(buffer, "MAD TMP_OUT.y, TMP_OUT.y, posFixup.y, TA.w;\n"); + + if(use_nv_clip(gl_info) && priv_ctx->target_version >= NV2) + { + for(i = 0; i < priv_ctx->vs_clipplanes; i++) + { + shader_addline(buffer, "DP4 result.clip[%u].x, TMP_OUT, state.clip[%u].plane;\n", i, i); + } + } + else if(args->boolclip.clip_control[0]) + { + unsigned int cur_clip = 0; + char component[4] = {'x', 'y', 'z', 'w'}; + + for(i = 0; i < GL_LIMITS(clipplanes); i++) + { + if(args->boolclip.clip_control[1] & (1 << i)) + { + shader_addline(buffer, "DP4 TA.%c, TMP_OUT, state.clip[%u].plane;\n", + component[cur_clip++], i); + } + } + switch(cur_clip) + { + case 0: + shader_addline(buffer, "MOV TA, -helper_const.w;\n"); + break; + case 1: + shader_addline(buffer, "MOV TA.yzw, -helper_const.w;\n"); + break; + case 2: + shader_addline(buffer, "MOV TA.zw, -helper_const.w;\n"); + break; + case 3: + shader_addline(buffer, "MOV TA.w, -helper_const.w;\n"); + break; + } + shader_addline(buffer, "MOV result.texcoord[%u], TA;\n", + args->boolclip.clip_control[0] - 1); + } + + /* Z coord [0;1]->[-1;1] mapping, see comment in transform_projection in state.c + * and the glsl equivalent + */ + if(need_helper_const(gl_info)) { + shader_addline(buffer, "MAD TMP_OUT.z, TMP_OUT.z, helper_const.x, -TMP_OUT.w;\n"); + } else { + shader_addline(buffer, "ADD TMP_OUT.z, TMP_OUT.z, TMP_OUT.z;\n"); + shader_addline(buffer, "ADD TMP_OUT.z, TMP_OUT.z, -TMP_OUT.w;\n"); + } + + shader_addline(buffer, "MOV result.position, TMP_OUT;\n"); + + priv_ctx->footer_written = TRUE; +} + static void shader_hw_ret(const struct wined3d_shader_instruction *ins) { SHADER_BUFFER *buffer = ins->ctx->buffer; struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; + IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *) ins->ctx->shader; + BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type); if(priv->target_version == ARB) return; + if(vshader) + { + if(priv->in_main_func) vshader_add_footer((IWineD3DVertexShaderImpl *) shader, buffer, priv->cur_vs_args, priv); + } + shader_addline(buffer, "RET;\n"); } @@ -3565,89 +3660,6 @@ static void init_output_registers(IWineD3DVertexShaderImpl *shader, DWORD sig_nu } } -static void vshader_add_footer(IWineD3DVertexShaderImpl *This, SHADER_BUFFER *buffer, const struct arb_vs_compile_args *args, - struct shader_arb_ctx_priv *priv_ctx) -{ - const shader_reg_maps *reg_maps = &This->baseShader.reg_maps; - IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)This->baseShader.device; - const WineD3D_GL_Info *gl_info = &device->adapter->gl_info; - unsigned int i; - - /* The D3DRS_FOGTABLEMODE render state defines if the shader-generated fog coord is used - * or if the fragment depth is used. If the fragment depth is used(FOGTABLEMODE != NONE), - * the fog frag coord is thrown away. If the fog frag coord is used, but not written by - * the shader, it is set to 0.0(fully fogged, since start = 1.0, end = 0.0) - */ - if(args->super.fog_src == VS_FOG_Z) { - shader_addline(buffer, "MOV result.fogcoord, TMP_OUT.z;\n"); - } else if (!reg_maps->fog) { - /* posFixup.x is always 1.0, so we can savely use it */ - shader_addline(buffer, "ADD result.fogcoord, posFixup.x, -posFixup.x;\n"); - } - - /* Write the final position. - * - * OpenGL coordinates specify the center of the pixel while d3d coords specify - * the corner. The offsets are stored in z and w in posFixup. posFixup.y contains - * 1.0 or -1.0 to turn the rendering upside down for offscreen rendering. PosFixup.x - * contains 1.0 to allow a mad, but arb vs swizzles are too restricted for that. - */ - shader_addline(buffer, "MUL TA, posFixup, TMP_OUT.w;\n"); - shader_addline(buffer, "ADD TMP_OUT.x, TMP_OUT.x, TA.z;\n"); - shader_addline(buffer, "MAD TMP_OUT.y, TMP_OUT.y, posFixup.y, TA.w;\n"); - - if(use_nv_clip(gl_info) && priv_ctx->target_version >= NV2) - { - for(i = 0; i < priv_ctx->vs_clipplanes; i++) - { - shader_addline(buffer, "DP4 result.clip[%u].x, TMP_OUT, state.clip[%u].plane;\n", i, i); - } - } - else if(args->boolclip.clip_control[0]) - { - unsigned int cur_clip = 0; - char component[4] = {'x', 'y', 'z', 'w'}; - - for(i = 0; i < GL_LIMITS(clipplanes); i++) - { - if(args->boolclip.clip_control[1] & (1 << i)) - { - shader_addline(buffer, "DP4 TA.%c, TMP_OUT, state.clip[%u].plane;\n", - component[cur_clip++], i); - } - } - switch(cur_clip) - { - case 0: - shader_addline(buffer, "MOV TA, -helper_const.w;\n"); - break; - case 1: - shader_addline(buffer, "MOV TA.yzw, -helper_const.w;\n"); - break; - case 2: - shader_addline(buffer, "MOV TA.zw, -helper_const.w;\n"); - break; - case 3: - shader_addline(buffer, "MOV TA.w, -helper_const.w;\n"); - break; - } - shader_addline(buffer, "MOV result.texcoord[%u], TA;\n", - args->boolclip.clip_control[0] - 1); - } - - /* Z coord [0;1]->[-1;1] mapping, see comment in transform_projection in state.c - * and the glsl equivalent - */ - if(need_helper_const(gl_info)) { - shader_addline(buffer, "MAD TMP_OUT.z, TMP_OUT.z, helper_const.x, -TMP_OUT.w;\n"); - } else { - shader_addline(buffer, "ADD TMP_OUT.z, TMP_OUT.z, TMP_OUT.z;\n"); - shader_addline(buffer, "ADD TMP_OUT.z, TMP_OUT.z, -TMP_OUT.w;\n"); - } - - shader_addline(buffer, "MOV result.position, TMP_OUT;\n"); -} - /* GL locking is done by the caller */ static GLuint shader_arb_generate_vshader(IWineD3DVertexShaderImpl *This, SHADER_BUFFER *buffer, const struct arb_vs_compile_args *args, struct arb_vs_compiled_shader *compiled) @@ -3750,10 +3762,12 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShaderImpl *This, } } + /* The shader starts with the main function */ + priv_ctx.in_main_func = TRUE; /* Base Shader Body */ shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function, &priv_ctx); - vshader_add_footer(This, buffer, args, &priv_ctx); + if(!priv_ctx.footer_written) vshader_add_footer(This, buffer, args, &priv_ctx); shader_addline(buffer, "END\n");