[PATCH 1/5] wined3d: Explicitly check the shader type in shader_generate_glsl_declarations().

Henri Verbeet hverbeet at codeweavers.com
Tue Oct 23 04:23:41 CDT 2012


---
 dlls/wined3d/glsl_shader.c |  107 ++++++++++++++++++++++++--------------------
 1 files changed, 59 insertions(+), 48 deletions(-)

diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 7b51dcd..26a9a81 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -896,6 +896,7 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
         struct wined3d_shader_buffer *buffer, const struct wined3d_shader *shader,
         const struct wined3d_shader_reg_maps *reg_maps, const struct shader_glsl_ctx_priv *ctx_priv)
 {
+    const struct wined3d_shader_version *version = &reg_maps->shader_version;
     const struct wined3d_state *state = &shader->device->stateBlock->state;
     const struct ps_compile_args *ps_args = ctx_priv->cur_ps_args;
     const struct wined3d_gl_info *gl_info = context->gl_info;
@@ -905,9 +906,7 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
     const char *prefix;
     DWORD map;
 
-    /* There are some minor differences between pixel and vertex shaders */
-    char pshader = shader_is_pshader_version(reg_maps->shader_version.type);
-    prefix = shader_glsl_get_prefix(reg_maps->shader_version.type);
+    prefix = shader_glsl_get_prefix(version->type);
 
     /* Prototype the subroutines */
     for (i = 0, map = reg_maps->labels; map; map >>= 1, ++i)
@@ -919,20 +918,25 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
     if (shader->limits.constant_float > 0)
     {
         unsigned max_constantsF;
-        /* Unless the shader uses indirect addressing, always declare the maximum array size and ignore that we need some
-         * uniforms privately. E.g. if GL supports 256 uniforms, and we need 2 for the pos fixup and immediate values, still
-         * declare VC[256]. If the shader needs more uniforms than we have it won't work in any case. If it uses less, the
-         * compiler will figure out which uniforms are really used and strip them out. This allows a shader to use c255 on
-         * a dx9 card, as long as it doesn't also use all the other constants.
+
+        /* Unless the shader uses indirect addressing, always declare the
+         * maximum array size and ignore that we need some uniforms privately.
+         * E.g. if GL supports 256 uniforms, and we need 2 for the pos fixup
+         * and immediate values, still declare VC[256]. If the shader needs
+         * more uniforms than we have it won't work in any case. If it uses
+         * less, the compiler will figure out which uniforms are really used
+         * and strip them out. This allows a shader to use c255 on a dx9 card,
+         * as long as it doesn't also use all the other constants.
          *
-         * If the shader uses indirect addressing the compiler must assume that all declared uniforms are used. In this case,
-         * declare only the amount that we're assured to have.
+         * If the shader uses indirect addressing the compiler must assume
+         * that all declared uniforms are used. In this case, declare only the
+         * amount that we're assured to have.
          *
          * Thus we run into problems in these two cases:
-         * 1) The shader really uses more uniforms than supported
-         * 2) The shader uses indirect addressing, less constants than supported, but uses a constant index > #supported consts
-         */
-        if (pshader)
+         * 1) The shader really uses more uniforms than supported.
+         * 2) The shader uses indirect addressing, less constants than
+         *    supported, but uses a constant index > #supported consts. */
+        if (version->type == WINED3D_SHADER_TYPE_PIXEL)
         {
             /* No indirect addressing here. */
             max_constantsF = gl_info->limits.glsl_ps_float_constants;
@@ -1005,19 +1009,20 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
     {
         if (reg_maps->sampler_type[i])
         {
+            BOOL shadow_sampler = version->type == WINED3D_SHADER_TYPE_PIXEL && (ps_args->shadow & (1 << i));
             const struct wined3d_texture *texture;
 
             switch (reg_maps->sampler_type[i])
             {
                 case WINED3DSTT_1D:
-                    if (pshader && ps_args->shadow & (1 << i))
+                    if (shadow_sampler)
                         shader_addline(buffer, "uniform sampler1DShadow %s_sampler%u;\n", prefix, i);
                     else
                         shader_addline(buffer, "uniform sampler1D %s_sampler%u;\n", prefix, i);
                     break;
                 case WINED3DSTT_2D:
                     texture = state->textures[i];
-                    if (pshader && ps_args->shadow & (1 << i))
+                    if (shadow_sampler)
                     {
                         if (texture && texture->target == GL_TEXTURE_RECTANGLE_ARB)
                             shader_addline(buffer, "uniform sampler2DRectShadow %s_sampler%u;\n", prefix, i);
@@ -1033,11 +1038,13 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
                     }
                     break;
                 case WINED3DSTT_CUBE:
-                    if (pshader && ps_args->shadow & (1 << i)) FIXME("Unsupported Cube shadow sampler.\n");
+                    if (shadow_sampler)
+                        FIXME("Unsupported Cube shadow sampler.\n");
                     shader_addline(buffer, "uniform samplerCube %s_sampler%u;\n", prefix, i);
                     break;
                 case WINED3DSTT_VOLUME:
-                    if (pshader && ps_args->shadow & (1 << i)) FIXME("Unsupported 3D shadow sampler.\n");
+                    if (shadow_sampler)
+                        FIXME("Unsupported 3D shadow sampler.\n");
                     shader_addline(buffer, "uniform sampler3D %s_sampler%u;\n", prefix, i);
                     break;
                 default:
@@ -1049,12 +1056,13 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
     }
 
     /* Declare uniforms for NP2 texcoord fixup:
-     * This is NOT done inside the loop that declares the texture samplers since the NP2 fixup code
-     * is currently only used for the GeforceFX series and when forcing the ARB_npot extension off.
-     * Modern cards just skip the code anyway, so put it inside a separate loop. */
-    if (pshader && ps_args->np2_fixup) {
-
-        struct ps_np2fixup_info* const fixup = ctx_priv->cur_np2fixup_info;
+     * This is NOT done inside the loop that declares the texture samplers
+     * since the NP2 fixup code is currently only used for the GeforceFX
+     * series and when forcing the ARB_npot extension off. Modern cards just
+     * skip the code anyway, so put it inside a separate loop. */
+    if (version->type == WINED3D_SHADER_TYPE_PIXEL && ps_args->np2_fixup)
+    {
+        struct ps_np2fixup_info *fixup = ctx_priv->cur_np2fixup_info;
         UINT cur = 0;
 
         /* NP2/RECT textures in OpenGL use texcoords in the range [0,width]x[0,height]
@@ -1093,7 +1101,7 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
         if (map & 1) shader_addline(buffer, "vec4 T%u = gl_TexCoord[%u];\n", i, i);
     }
 
-    if (!pshader)
+    if (version->type == WINED3D_SHADER_TYPE_VERTEX)
     {
         /* Declare attributes. */
         for (i = 0, map = reg_maps->input_registers; map; map >>= 1, ++i)
@@ -1105,11 +1113,11 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
         shader_addline(buffer, "uniform vec4 posFixup;\n");
         shader_addline(buffer, "void order_ps_input(in vec4[%u]);\n", shader->limits.packed_output);
     }
-    else
+    else if (version->type == WINED3D_SHADER_TYPE_PIXEL)
     {
-        if (reg_maps->shader_version.major >= 3)
+        if (version->major >= 3)
         {
-            UINT in_count = min(vec4_varyings(reg_maps->shader_version.major, gl_info), shader->limits.packed_input);
+            UINT in_count = min(vec4_varyings(version->major, gl_info), shader->limits.packed_input);
 
             if (use_vs(state))
                 shader_addline(buffer, "varying vec4 %s_in[%u];\n", prefix, in_count);
@@ -1179,7 +1187,7 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
     }
 
     /* Declare loop registers aLx */
-    if (reg_maps->shader_version.major < 4)
+    if (version->major < 4)
     {
         for (i = 0; i < reg_maps->loop_depth; ++i)
         {
@@ -1204,25 +1212,28 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
         }
     }
 
-    /* Start the main program */
-    shader_addline(buffer, "void main() {\n");
-    if(pshader && reg_maps->vpos) {
-        /* DirectX apps expect integer values, while OpenGL drivers add approximately 0.5. This causes
-         * off-by-one problems as spotted by the vPos d3d9 visual test. Unfortunately the ATI cards do
-         * not add exactly 0.5, but rather something like 0.49999999 or 0.50000001, which still causes
-         * precision troubles when we just subtract 0.5.
-         *
-         * To deal with that just floor() the position. This will eliminate the fraction on all cards.
-         *
-         * TODO: Test how that behaves with multisampling once we can enable multisampling in winex11.
-         *
-         * An advantage of floor is that it works even if the driver doesn't add 1/2. It is somewhat
-         * questionable if 1.5, 2.5, ... are the proper values to return in gl_FragCoord, even though
-         * coordinates specify the pixel centers instead of the pixel corners. This code will behave
-         * correctly on drivers that returns integer values.
-         */
-        shader_addline(buffer, "vpos = floor(vec4(0, ycorrection[0], 0, 0) + gl_FragCoord * vec4(1, ycorrection[1], 1, 1));\n");
-    }
+    /* Start the main program. */
+    shader_addline(buffer, "void main()\n{\n");
+
+    /* Direct3D applications expect integer vPos values, while OpenGL drivers
+     * add approximately 0.5. This causes off-by-one problems as spotted by
+     * the vPos d3d9 visual test. Unfortunately ATI cards do not add exactly
+     * 0.5, but rather something like 0.49999999 or 0.50000001, which still
+     * causes precision troubles when we just subtract 0.5.
+     *
+     * To deal with that, just floor() the position. This will eliminate the
+     * fraction on all cards.
+     *
+     * TODO: Test how this behaves with multisampling.
+     *
+     * An advantage of floor is that it works even if the driver doesn't add
+     * 0.5. It is somewhat questionable if 1.5, 2.5, ... are the proper values
+     * to return in gl_FragCoord, even though coordinates specify the pixel
+     * centers instead of the pixel corners. This code will behave correctly
+     * on drivers that returns integer values. */
+    if (version->type == WINED3D_SHADER_TYPE_PIXEL && reg_maps->vpos)
+        shader_addline(buffer,
+                "vpos = floor(vec4(0, ycorrection[0], 0, 0) + gl_FragCoord * vec4(1, ycorrection[1], 1, 1));\n");
 }
 
 /*****************************************************************************
-- 
1.7.8.6




More information about the wine-patches mailing list