[PATCH v4 3/4] wined3d: Implement Fetch4 GLSL shader generation

Daniel Ansorregui mailszeros at gmail.com
Mon Feb 4 18:19:22 CST 2019


- Implement shader generation of tex-ld/ldp/ldd/ldb/ldl
- FIXME: Vertex texldl unimplemented yet, since it is not possible to access
  ps_compile_args. Maybe move it to another place.
  Probably does not work on windows anyway
- Trigger PS re-generation at FETCH4 state change, by storing a context flag
- Add ps_compile_arg flag for fetch4

Signed-off-by: Daniel Ansorregui <mailszeros at gmail.com>
---
 dlls/wined3d/cs.c              |   5 +-
 dlls/wined3d/device.c          |   4 +
 dlls/wined3d/glsl_shader.c     | 214 ++++++++++++++++++++++-----------
 dlls/wined3d/shader.c          |  13 ++
 dlls/wined3d/state.c           |  13 ++
 dlls/wined3d/wined3d_private.h |   7 +-
 6 files changed, 186 insertions(+), 70 deletions(-)

diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index 7471d24e7e..890540c78d 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -1372,7 +1372,10 @@ static void wined3d_cs_exec_set_texture(struct wined3d_cs *cs, const void *data)
         if (!prev || wined3d_texture_gl(op->texture)->target != wined3d_texture_gl(prev)->target
                 || (!is_same_fixup(new_format->color_fixup, old_format->color_fixup)
                 && !(can_use_texture_swizzle(gl_info, new_format) && can_use_texture_swizzle(gl_info, old_format)))
-                || (new_fmt_flags & WINED3DFMT_FLAG_SHADOW) != (old_fmt_flags & WINED3DFMT_FLAG_SHADOW))
+                || (new_fmt_flags & WINED3DFMT_FLAG_SHADOW) != (old_fmt_flags & WINED3DFMT_FLAG_SHADOW)
+                || ((new_fmt_flags & WINED3DFMT_FLAG_ALLOW_FETCH4) != (old_fmt_flags & WINED3DFMT_FLAG_ALLOW_FETCH4)
+                    && cs->state.sampler_states[op->texture->sampler][WINED3D_SAMP_MIPMAP_LOD_BIAS]
+                    == MAKEFOURCC('G','E','T','4')))
             device_invalidate_state(cs->device, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL));
 
         if (!prev && op->stage < d3d_info->limits.ffp_blend_stages)
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index dee99dcde2..99248ffb1b 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -2082,7 +2082,11 @@ void CDECL wined3d_device_set_sampler_state(struct wined3d_device *device,
             device, sampler_idx, debug_d3dsamplerstate(state), value);
 
     if (sampler_idx >= WINED3DVERTEXTEXTURESAMPLER0 && sampler_idx <= WINED3DVERTEXTEXTURESAMPLER3)
+    {
         sampler_idx -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
+        if (state == WINED3D_SAMP_MIPMAP_LOD_BIAS && value == MAKEFOURCC('G','E','T','4'))
+            FIXME("Unsupported FETCH4 and Vertex Texture Sampler");
+    }
 
     if (sampler_idx >= ARRAY_SIZE(device->state.sampler_states))
     {
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 1950db06a9..e53306a6c2 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -49,6 +49,7 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag);
 #define WINED3D_GLSL_SAMPLE_GRAD        0x04
 #define WINED3D_GLSL_SAMPLE_LOAD        0x08
 #define WINED3D_GLSL_SAMPLE_OFFSET      0x10
+#define WINED3D_GLSL_SAMPLE_GATHER      0x20
 
 static const struct
 {
@@ -3613,6 +3614,7 @@ static void shader_glsl_get_sample_function(const struct wined3d_shader_context
     BOOL lod = flags & WINED3D_GLSL_SAMPLE_LOD;
     BOOL grad = flags & WINED3D_GLSL_SAMPLE_GRAD;
     BOOL offset = flags & WINED3D_GLSL_SAMPLE_OFFSET;
+    BOOL gather = !shadow && flags & WINED3D_GLSL_SAMPLE_GATHER;
     const char *base = "texture", *type_part = "", *suffix = "";
     unsigned int coord_size, deriv_size;
 
@@ -3658,6 +3660,19 @@ static void shader_glsl_get_sample_function(const struct wined3d_shader_context
         type_part = "";
     }
 
+    if (gather)
+    {
+        if (resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_3D)
+            FIXME("Unsupported Fetch4 and texture3D sampling");
+        else
+        {
+            base = "texture";
+            type_part = "Gather";
+            suffix = "";
+            projected = lod = grad = offset = FALSE;
+        }
+    }
+
     sample_function->name = string_buffer_get(priv->string_buffers);
     string_buffer_sprintf(sample_function->name, "%s%s%s%s%s%s", base, type_part, projected ? "Proj" : "",
             lod ? "Lod" : grad ? "Grad" : "", offset ? "Offset" : "", suffix);
@@ -3786,12 +3801,13 @@ static void shader_glsl_color_correction(const struct wined3d_shader_instruction
     string_buffer_release(priv->string_buffers, reg_name);
 }
 
-static void PRINTF_ATTR(9, 10) shader_glsl_gen_sample_code(const struct wined3d_shader_instruction *ins,
-        unsigned int sampler_bind_idx, const struct glsl_sample_function *sample_function, DWORD swizzle,
-        const char *dx, const char *dy, const char *bias, const struct wined3d_shader_texel_offset *offset,
-        const char *coord_reg_fmt, ...)
+static void PRINTF_ATTR(10, 11) shader_glsl_gen_sample_code(const struct wined3d_shader_instruction *ins,
+        unsigned int sampler_bind_idx, const struct glsl_sample_function *sample_function,
+        const DWORD swizzle, const DWORD sample_flags, const char *dx, const char *dy, const char *bias,
+        const struct wined3d_shader_texel_offset *offset, const char *coord_reg_fmt, ...)
 {
     const struct wined3d_shader_version *version = &ins->ctx->reg_maps->shader_version;
+    const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
     char dst_swizzle[6];
     struct color_fixup_desc fixup;
     BOOL np2_fixup = FALSE;
@@ -3833,10 +3849,8 @@ static void PRINTF_ATTR(9, 10) shader_glsl_gen_sample_code(const struct wined3d_
         if (!string_buffer_resize(ins->ctx->buffer, ret))
             break;
     }
-
     if (np2_fixup)
     {
-        const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
         const unsigned char idx = priv->cur_np2fixup_info->idx[sampler_bind_idx];
 
         switch (shader_glsl_get_write_mask_size(sample_function->coord_mask))
@@ -3859,6 +3873,20 @@ static void PRINTF_ATTR(9, 10) shader_glsl_gen_sample_code(const struct wined3d_
                 break;
         }
     }
+    if(sample_flags & WINED3D_GLSL_SAMPLE_GATHER)
+    {
+        if (sample_flags & WINED3D_GLSL_SAMPLE_PROJECTED)
+        {
+            struct wined3d_string_buffer *reg_name = string_buffer_get(priv->string_buffers);
+            shader_glsl_get_register_name(&ins->src[0].reg, ins->src[0].reg.data_type, reg_name, NULL, ins->ctx);
+            shader_addline(ins->ctx->buffer, " / %s.w", reg_name->buffer);
+            string_buffer_release(priv->string_buffers, reg_name);
+        }
+
+        /* Correct the fetch4 0.5 texel offset */
+        shader_addline(ins->ctx->buffer, " + (vec2(0.5) / textureSize(%s_sampler%u, 0).xy)",
+                shader_glsl_get_prefix(version->type), sampler_bind_idx);
+    }
     if (dx && dy)
         shader_addline(ins->ctx->buffer, ", %s, %s", dx, dy);
     else if (bias)
@@ -5397,11 +5425,19 @@ static void shader_glsl_tex(const struct wined3d_shader_instruction *ins)
         }
     }
 
+    /* Fetch4 overwrites the other texture flags */
+    if (priv->cur_ps_args->fetch4 & (1u << resource_idx))
+    {
+        sample_flags |= WINED3D_GLSL_SAMPLE_GATHER;
+        mask = 0;
+    }
+
     shader_glsl_get_sample_function(ins->ctx, resource_idx, resource_idx, sample_flags, &sample_function);
     mask |= sample_function.coord_mask;
     sample_function.coord_mask = mask;
 
     if (shader_version < WINED3D_SHADER_VERSION(2,0)) swizzle = WINED3DSP_NOSWIZZLE;
+    else if (sample_flags & WINED3D_GLSL_SAMPLE_GATHER) swizzle = WINED3DSP_FETCH4_SWIZZLE;
     else swizzle = ins->src[1].swizzle;
 
     /* 1.0-1.3: Use destination register as coordinate source.
@@ -5410,22 +5446,22 @@ static void shader_glsl_tex(const struct wined3d_shader_instruction *ins)
     {
         char coord_mask[6];
         shader_glsl_write_mask_to_str(mask, coord_mask);
-        shader_glsl_gen_sample_code(ins, resource_idx, &sample_function, swizzle, NULL, NULL, NULL, NULL,
-                "T%u%s", resource_idx, coord_mask);
+        shader_glsl_gen_sample_code(ins, resource_idx, &sample_function, swizzle, sample_flags, NULL, NULL,
+                NULL, NULL, "T%u%s", resource_idx, coord_mask);
     }
     else
     {
         struct glsl_src_param coord_param;
         shader_glsl_add_src_param(ins, &ins->src[0], mask, &coord_param);
-        if (ins->flags & WINED3DSI_TEXLD_BIAS)
+        if (ins->flags & WINED3DSI_TEXLD_BIAS && sample_flags != WINED3D_GLSL_SAMPLE_GATHER)
         {
             struct glsl_src_param bias;
             shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &bias);
-            shader_glsl_gen_sample_code(ins, resource_idx, &sample_function, swizzle, NULL, NULL, bias.param_str,
-                    NULL, "%s", coord_param.param_str);
+            shader_glsl_gen_sample_code(ins, resource_idx, &sample_function, swizzle, sample_flags,
+                    NULL, NULL, bias.param_str, NULL, "%s", coord_param.param_str);
         } else {
-            shader_glsl_gen_sample_code(ins, resource_idx, &sample_function, swizzle, NULL, NULL, NULL, NULL,
-                    "%s", coord_param.param_str);
+            shader_glsl_gen_sample_code(ins, resource_idx, &sample_function, swizzle, sample_flags,
+                    NULL, NULL, NULL, NULL, "%s", coord_param.param_str);
         }
     }
     shader_glsl_release_sample_function(ins->ctx, &sample_function);
@@ -5433,10 +5469,11 @@ static void shader_glsl_tex(const struct wined3d_shader_instruction *ins)
 
 static void shader_glsl_texldd(const struct wined3d_shader_instruction *ins)
 {
+    const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
     const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
     struct glsl_src_param coord_param, dx_param, dy_param;
     struct glsl_sample_function sample_function;
-    DWORD sampler_idx;
+    DWORD sampler_idx = ins->src[1].reg.idx[0].offset;
     DWORD swizzle = ins->src[1].swizzle;
 
     if (!shader_glsl_has_core_grad(gl_info) && !gl_info->supported[ARB_SHADER_TEXTURE_LOD])
@@ -5446,34 +5483,48 @@ static void shader_glsl_texldd(const struct wined3d_shader_instruction *ins)
         return;
     }
 
-    sampler_idx = ins->src[1].reg.idx[0].offset;
+    /* Fetch4 overwrites the other texture flags */
+    if (priv->cur_ps_args->fetch4 & (1u << sampler_idx))
+    {
+        shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, WINED3D_GLSL_SAMPLE_GATHER, &sample_function);
+        swizzle = WINED3DSP_FETCH4_SWIZZLE;
+        shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param);
+        shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, WINED3D_GLSL_SAMPLE_GATHER,
+                NULL, NULL, NULL, NULL, "%s", coord_param.param_str);
+        shader_glsl_release_sample_function(ins->ctx, &sample_function);
+        return;
+    }
 
     shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, WINED3D_GLSL_SAMPLE_GRAD, &sample_function);
     shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param);
     shader_glsl_add_src_param(ins, &ins->src[2], sample_function.deriv_mask, &dx_param);
     shader_glsl_add_src_param(ins, &ins->src[3], sample_function.deriv_mask, &dy_param);
 
-    shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, dx_param.param_str, dy_param.param_str,
-            NULL, NULL, "%s", coord_param.param_str);
+    shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, 0,
+            dx_param.param_str, dy_param.param_str, NULL, NULL, "%s", coord_param.param_str);
     shader_glsl_release_sample_function(ins->ctx, &sample_function);
 }
 
 static void shader_glsl_texldl(const struct wined3d_shader_instruction *ins)
 {
     const struct wined3d_shader_version *shader_version = &ins->ctx->reg_maps->shader_version;
+    const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
     const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
     struct glsl_src_param coord_param, lod_param;
     struct glsl_sample_function sample_function;
+    DWORD sampler_idx = ins->src[1].reg.idx[0].offset;
     DWORD swizzle = ins->src[1].swizzle;
-    DWORD sampler_idx;
+    DWORD flags = WINED3D_GLSL_SAMPLE_LOD;
 
-    sampler_idx = ins->src[1].reg.idx[0].offset;
+    /* This call can be used in vertex shader, without cur_ps_args */
+    if(priv->cur_ps_args && priv->cur_ps_args->fetch4 & (1u << sampler_idx))
+    {
+        flags = WINED3D_GLSL_SAMPLE_GATHER;
+    }
 
-    shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, WINED3D_GLSL_SAMPLE_LOD, &sample_function);
+    shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, flags, &sample_function);
     shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param);
 
-    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &lod_param);
-
     if (shader_version->type == WINED3D_SHADER_TYPE_PIXEL && !shader_glsl_has_core_grad(gl_info)
             && !gl_info->supported[ARB_SHADER_TEXTURE_LOD])
     {
@@ -5482,8 +5533,20 @@ static void shader_glsl_texldl(const struct wined3d_shader_instruction *ins)
          * even without the appropriate extension. */
         WARN("Using %s in fragment shader.\n", sample_function.name->buffer);
     }
-    shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, NULL, NULL, lod_param.param_str, NULL,
-            "%s", coord_param.param_str);
+
+    if (flags == WINED3D_GLSL_SAMPLE_GATHER){
+        swizzle = WINED3DSP_FETCH4_SWIZZLE;
+        shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, flags,
+                NULL, NULL, NULL, NULL, "%s", coord_param.param_str);
+        shader_glsl_release_sample_function(ins->ctx, &sample_function);
+        return;
+    }
+
+    shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, WINED3D_GLSL_SAMPLE_LOD, &sample_function);
+    shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &lod_param);
+    shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, flags, NULL, NULL,
+            lod_param.param_str, NULL, "%s", coord_param.param_str);
     shader_glsl_release_sample_function(ins->ctx, &sample_function);
 }
 
@@ -6175,6 +6238,7 @@ static void shader_glsl_ld(const struct wined3d_shader_instruction *ins)
     struct glsl_sample_function sample_function;
     DWORD flags = WINED3D_GLSL_SAMPLE_LOAD;
     BOOL has_lod_param;
+    const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
 
     if (wined3d_shader_instruction_has_texel_offset(ins))
         flags |= WINED3D_GLSL_SAMPLE_OFFSET;
@@ -6189,6 +6253,10 @@ static void shader_glsl_ld(const struct wined3d_shader_instruction *ins)
     }
     has_lod_param = is_mipmapped(reg_maps->resource_info[resource_idx].type);
 
+    if (priv->cur_ps_args && priv->cur_ps_args->fetch4 & (1u << resource_idx)){
+        FIXME("Unsupported FETCH4 and LD Sampling SM 5.0");
+    }
+
     shader_glsl_get_sample_function(ins->ctx, resource_idx, sampler_idx, flags, &sample_function);
     shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param);
     shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &lod_param);
@@ -6196,12 +6264,12 @@ static void shader_glsl_ld(const struct wined3d_shader_instruction *ins)
     if (is_multisampled(reg_maps->resource_info[resource_idx].type))
     {
         shader_glsl_add_src_param(ins, &ins->src[2], WINED3DSP_WRITEMASK_0, &sample_param);
-        shader_glsl_gen_sample_code(ins, sampler_bind_idx, &sample_function, ins->src[1].swizzle,
+        shader_glsl_gen_sample_code(ins, sampler_bind_idx, &sample_function, ins->src[1].swizzle, 0,
                 NULL, NULL, NULL, &ins->texel_offset, "%s, %s", coord_param.param_str, sample_param.param_str);
     }
     else
     {
-        shader_glsl_gen_sample_code(ins, sampler_bind_idx, &sample_function, ins->src[1].swizzle,
+        shader_glsl_gen_sample_code(ins, sampler_bind_idx, &sample_function, ins->src[1].swizzle, 0,
                 NULL, NULL, has_lod_param ? lod_param.param_str : NULL, &ins->texel_offset,
                 "%s", coord_param.param_str);
     }
@@ -6214,46 +6282,57 @@ static void shader_glsl_sample(const struct wined3d_shader_instruction *ins)
     struct glsl_src_param coord_param, lod_param, dx_param, dy_param;
     unsigned int resource_idx, sampler_idx, sampler_bind_idx;
     struct glsl_sample_function sample_function;
+    const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
+    DWORD swizzle = ins->src[1].swizzle;
     DWORD flags = 0;
 
+    resource_idx = ins->src[1].reg.idx[0].offset;
+    sampler_idx = ins->src[2].reg.idx[0].offset;
+
     if (ins->handler_idx == WINED3DSIH_SAMPLE_GRAD)
         flags |= WINED3D_GLSL_SAMPLE_GRAD;
     if (ins->handler_idx == WINED3DSIH_SAMPLE_LOD)
         flags |= WINED3D_GLSL_SAMPLE_LOD;
     if (wined3d_shader_instruction_has_texel_offset(ins))
         flags |= WINED3D_GLSL_SAMPLE_OFFSET;
-
-    resource_idx = ins->src[1].reg.idx[0].offset;
-    sampler_idx = ins->src[2].reg.idx[0].offset;
+    if (priv->cur_ps_args->fetch4 & (1u << sampler_idx))
+    {
+        flags = WINED3D_GLSL_SAMPLE_GATHER;
+        swizzle = WINED3DSP_FETCH4_SWIZZLE;
+    }
 
     shader_glsl_get_sample_function(ins->ctx, resource_idx, sampler_idx, flags, &sample_function);
     shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param);
 
-    switch (ins->handler_idx)
+    /* Fetch4 overwrites the other texture flags */
+    if (flags != WINED3D_GLSL_SAMPLE_GATHER)
     {
-        case WINED3DSIH_SAMPLE:
-            break;
-        case WINED3DSIH_SAMPLE_B:
-            shader_glsl_add_src_param(ins, &ins->src[3], WINED3DSP_WRITEMASK_0, &lod_param);
-            lod_param_str = lod_param.param_str;
-            break;
-        case WINED3DSIH_SAMPLE_GRAD:
-            shader_glsl_add_src_param(ins, &ins->src[3], sample_function.deriv_mask, &dx_param);
-            shader_glsl_add_src_param(ins, &ins->src[4], sample_function.deriv_mask, &dy_param);
-            dx_param_str = dx_param.param_str;
-            dy_param_str = dy_param.param_str;
-            break;
-        case WINED3DSIH_SAMPLE_LOD:
-            shader_glsl_add_src_param(ins, &ins->src[3], WINED3DSP_WRITEMASK_0, &lod_param);
-            lod_param_str = lod_param.param_str;
-            break;
-        default:
-            ERR("Unhandled opcode %s.\n", debug_d3dshaderinstructionhandler(ins->handler_idx));
-            break;
+        switch (ins->handler_idx)
+        {
+            case WINED3DSIH_SAMPLE:
+                break;
+            case WINED3DSIH_SAMPLE_B:
+                shader_glsl_add_src_param(ins, &ins->src[3], WINED3DSP_WRITEMASK_0, &lod_param);
+                lod_param_str = lod_param.param_str;
+                break;
+            case WINED3DSIH_SAMPLE_GRAD:
+                shader_glsl_add_src_param(ins, &ins->src[3], sample_function.deriv_mask, &dx_param);
+                shader_glsl_add_src_param(ins, &ins->src[4], sample_function.deriv_mask, &dy_param);
+                dx_param_str = dx_param.param_str;
+                dy_param_str = dy_param.param_str;
+                break;
+            case WINED3DSIH_SAMPLE_LOD:
+                shader_glsl_add_src_param(ins, &ins->src[3], WINED3DSP_WRITEMASK_0, &lod_param);
+                lod_param_str = lod_param.param_str;
+                break;
+            default:
+                ERR("Unhandled opcode %s.\n", debug_d3dshaderinstructionhandler(ins->handler_idx));
+                break;
+        }
     }
 
     sampler_bind_idx = shader_glsl_find_sampler(&ins->ctx->reg_maps->sampler_map, resource_idx, sampler_idx);
-    shader_glsl_gen_sample_code(ins, sampler_bind_idx, &sample_function, ins->src[1].swizzle,
+    shader_glsl_gen_sample_code(ins, sampler_bind_idx, &sample_function, swizzle, flags,
             dx_param_str, dy_param_str, lod_param_str, &ins->texel_offset, "%s", coord_param.param_str);
     shader_glsl_release_sample_function(ins->ctx, &sample_function);
 }
@@ -6299,6 +6378,9 @@ static void shader_glsl_sample_c(const struct wined3d_shader_instruction *ins)
     unsigned int coord_size;
     DWORD flags = 0;
 
+    resource_idx = ins->src[1].reg.idx[0].offset;
+    sampler_idx = ins->src[2].reg.idx[0].offset;
+
     if (ins->handler_idx == WINED3DSIH_SAMPLE_C_LZ)
     {
         lod_param = "0";
@@ -6310,8 +6392,6 @@ static void shader_glsl_sample_c(const struct wined3d_shader_instruction *ins)
 
     if (!(resource_info = shader_glsl_get_resource_info(ins, &ins->src[1].reg)))
         return;
-    resource_idx = ins->src[1].reg.idx[0].offset;
-    sampler_idx = ins->src[2].reg.idx[0].offset;
 
     shader_glsl_get_sample_function(ins->ctx, resource_idx, sampler_idx, flags, &sample_function);
     coord_size = shader_glsl_get_write_mask_size(sample_function.coord_mask);
@@ -6327,7 +6407,7 @@ static void shader_glsl_sample_c(const struct wined3d_shader_instruction *ins)
     }
     else
     {
-        shader_glsl_gen_sample_code(ins, sampler_bind_idx, &sample_function, WINED3DSP_NOSWIZZLE,
+        shader_glsl_gen_sample_code(ins, sampler_bind_idx, &sample_function, WINED3DSP_NOSWIZZLE, 0,
                 NULL, NULL, lod_param, &ins->texel_offset, "vec%u(%s, %s)",
                 coord_size, coord_param.param_str, compare_param.param_str);
     }
@@ -6469,18 +6549,18 @@ static void shader_glsl_texdp3tex(const struct wined3d_shader_instruction *ins)
     switch(mask_size)
     {
         case 1:
-            shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL,
-                    NULL, "dot(ffp_texcoord[%u].xyz, %s)", sampler_idx, src0_param.param_str);
+            shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, 0, NULL, NULL,
+                    NULL, NULL, "dot(ffp_texcoord[%u].xyz, %s)", sampler_idx, src0_param.param_str);
             break;
 
         case 2:
-            shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL,
-                    NULL, "vec2(dot(ffp_texcoord[%u].xyz, %s), 0.0)", sampler_idx, src0_param.param_str);
+            shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, 0, NULL, NULL,
+                    NULL, NULL, "vec2(dot(ffp_texcoord[%u].xyz, %s), 0.0)", sampler_idx, src0_param.param_str);
             break;
 
         case 3:
-            shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL,
-                    NULL, "vec3(dot(ffp_texcoord[%u].xyz, %s), 0.0, 0.0)", sampler_idx, src0_param.param_str);
+            shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, 0, NULL, NULL,
+                    NULL, NULL, "vec3(dot(ffp_texcoord[%u].xyz, %s), 0.0, 0.0)", sampler_idx, src0_param.param_str);
             break;
 
         default:
@@ -6588,7 +6668,7 @@ static void shader_glsl_texm3x2tex(const struct wined3d_shader_instruction *ins)
     shader_glsl_get_sample_function(ins->ctx, reg, reg, 0, &sample_function);
 
     /* Sample the texture using the calculated coordinates */
-    shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, NULL, "tmp0.xy");
+    shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, 0, NULL, NULL, NULL, NULL, "tmp0.xy");
     shader_glsl_release_sample_function(ins->ctx, &sample_function);
 }
 
@@ -6609,7 +6689,7 @@ static void shader_glsl_texm3x3tex(const struct wined3d_shader_instruction *ins)
     shader_glsl_get_sample_function(ins->ctx, reg, reg, 0, &sample_function);
 
     /* Sample the texture using the calculated coordinates */
-    shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, NULL, "tmp0.xyz");
+    shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, 0, NULL, NULL, NULL, NULL, "tmp0.xyz");
     shader_glsl_release_sample_function(ins->ctx, &sample_function);
 
     tex_mx->current_row = 0;
@@ -6660,7 +6740,7 @@ static void shader_glsl_texm3x3spec(const struct wined3d_shader_instruction *ins
     shader_glsl_write_mask_to_str(sample_function.coord_mask, coord_mask);
 
     /* Sample the texture */
-    shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE,
+    shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, 0,
             NULL, NULL, NULL, NULL, "tmp0%s", coord_mask);
     shader_glsl_release_sample_function(ins->ctx, &sample_function);
 
@@ -6694,7 +6774,7 @@ static void shader_glsl_texm3x3vspec(const struct wined3d_shader_instruction *in
     shader_glsl_write_mask_to_str(sample_function.coord_mask, coord_mask);
 
     /* Sample the texture using the calculated coordinates */
-    shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE,
+    shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, 0,
             NULL, NULL, NULL, NULL, "tmp0%s", coord_mask);
     shader_glsl_release_sample_function(ins->ctx, &sample_function);
 
@@ -6753,7 +6833,7 @@ static void shader_glsl_texbem(const struct wined3d_shader_instruction *ins)
 
     shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &coord_param);
 
-    shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, NULL,
+    shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, 0, NULL, NULL, NULL, NULL,
             "T%u%s + vec4(bumpenv_mat%u * %s, 0.0, 0.0)%s", sampler_idx, coord_mask, sampler_idx,
             coord_param.param_str, coord_mask);
 
@@ -6798,7 +6878,7 @@ static void shader_glsl_texreg2ar(const struct wined3d_shader_instruction *ins)
     shader_glsl_get_register_name(&ins->src[0].reg, ins->src[0].reg.data_type, reg_name, NULL, ins->ctx);
 
     shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, 0, &sample_function);
-    shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, NULL,
+    shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, 0, NULL, NULL, NULL, NULL,
             "%s.wx", reg_name->buffer);
     shader_glsl_release_sample_function(ins->ctx, &sample_function);
 
@@ -6818,7 +6898,7 @@ static void shader_glsl_texreg2gb(const struct wined3d_shader_instruction *ins)
     shader_glsl_get_register_name(&ins->src[0].reg, ins->src[0].reg.data_type, reg_name, NULL, ins->ctx);
 
     shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, 0, &sample_function);
-    shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, NULL,
+    shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, 0, NULL, NULL, NULL, NULL,
             "%s.yz", reg_name->buffer);
     shader_glsl_release_sample_function(ins->ctx, &sample_function);
 
@@ -6837,7 +6917,7 @@ static void shader_glsl_texreg2rgb(const struct wined3d_shader_instruction *ins)
     shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, 0, &sample_function);
     shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &src0_param);
 
-    shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, NULL,
+    shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, 0, NULL, NULL, NULL, NULL,
             "%s", src0_param.param_str);
     shader_glsl_release_sample_function(ins->ctx, &sample_function);
 }
diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c
index e11a37cf07..6e21444f8c 100644
--- a/dlls/wined3d/shader.c
+++ b/dlls/wined3d/shader.c
@@ -4027,6 +4027,19 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3
         }
     }
 
+    if (gl_info->supported[ARB_TEXTURE_GATHER])
+    {
+        for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i)
+        {
+            if (state->sampler_states[i][WINED3D_SAMP_MIPMAP_LOD_BIAS] == MAKEFOURCC('G','E','T','4')
+                    && state->textures[i]->resource.format_flags & WINED3DFMT_FLAG_ALLOW_FETCH4
+                    && shader->reg_maps.resource_info[i].type == WINED3D_SHADER_RESOURCE_TEXTURE_2D)
+                args->fetch4 |= 1 << i;
+            else
+                args->fetch4 &= ~(1 << i);
+        }
+    }
+
     if (context->d3d_info->limits.varying_count < wined3d_max_compat_varyings(context->gl_info))
     {
         const struct wined3d_shader *vs = state->shader[WINED3D_SHADER_TYPE_VERTEX];
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index 8708aa09b3..dc69e935c5 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -3616,6 +3616,8 @@ static void sampler(struct wined3d_context *context, const struct wined3d_state
     {
         struct wined3d_texture_gl *texture_gl = wined3d_texture_gl(state->textures[sampler_idx]);
         BOOL srgb = state->sampler_states[sampler_idx][WINED3D_SAMP_SRGB_TEXTURE];
+        BOOL fetch4 = state->sampler_states[sampler_idx][WINED3D_SAMP_MIPMAP_LOD_BIAS]
+                == MAKEFOURCC('G','E','T','4');
         const DWORD *sampler_states = state->sampler_states[sampler_idx];
         struct wined3d_device *device = context->device;
         struct wined3d_sampler_desc desc;
@@ -3650,6 +3652,17 @@ static void sampler(struct wined3d_context *context, const struct wined3d_state
         /* Trigger shader constant reloading (for NP2 texcoord fixup) */
         if (!(texture_gl->t.flags & WINED3D_TEXTURE_POW2_MAT_IDENT))
             context->constant_update_mask |= WINED3D_SHADER_CONST_PS_NP2_FIXUP;
+
+        /* Trigger pixel shader recompilation for FETCH4 changes */
+        if(gl_info->supported[ARB_TEXTURE_GATHER] &&
+                ((context->last_was_fetch4 >> sampler_idx) & 0x1) ^ fetch4)
+        {
+            if (fetch4)
+                context->last_was_fetch4 |= 1 << sampler_idx;
+            else
+                context->last_was_fetch4 &= ~(1 << sampler_idx);
+            context->shader_update_mask = (1u << WINED3D_SHADER_TYPE_PIXEL);
+        }
     }
     else
     {
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 4224461142..654e4ff610 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -521,7 +521,8 @@ enum wined3d_immconst_type
     WINED3D_IMMCONST_VEC4,
 };
 
-#define WINED3DSP_NOSWIZZLE (0u | (1u << 2) | (2u << 4) | (3u << 6))
+#define WINED3DSP_NOSWIZZLE      (0u | (1u << 2) | (2u << 4) | (3u << 6))
+#define WINED3DSP_FETCH4_SWIZZLE (2u | (0u << 2) | (1u << 4) | (3u << 6)) /* zxyw */
 
 enum wined3d_shader_src_modifier
 {
@@ -1358,7 +1359,8 @@ struct ps_compile_args
     DWORD alpha_test_func : 3;
     DWORD render_offscreen : 1;
     DWORD rt_alpha_swizzle : 8; /* MAX_RENDER_TARGET_VIEWS, 8 */
-    DWORD padding : 18;
+    WORD fetch4 : 16; /* MAX_FRAGMENT_SAMPLERS, 16 */
+    DWORD padding : 2;
 };
 
 enum fog_src_type
@@ -1893,6 +1895,7 @@ struct wined3d_context
     DWORD last_was_ffp_blit : 1;
     DWORD last_was_blit : 1;
     DWORD last_was_ckey : 1;
+    DWORD last_was_fetch4 : 16; /* MAX_FRAGMENT_SAMPLERS */
     DWORD fog_coord : 1;
     DWORD fog_enabled : 1;
     DWORD current : 1;
-- 
2.17.1




More information about the wine-devel mailing list