[PATCH 3/5] wined3d: Implement Fetch4 shader generation
Daniel Ansorregui
mailszeros at gmail.com
Wed Nov 21 19:28:21 CST 2018
- Implement shader generation of tex-ld/ldp/ldd/ldb/ldl
- Vertex texldl unimplemented yet, since it is not possible to access
ps_compile_args. Maybe move it to another place.
- Trigger PS re-generation at FETCH4 state change
Signed-off-by: Daniel Ansorregui <mailszeros at gmail.com>
---
dlls/wined3d/device.c | 4 ++
dlls/wined3d/glsl_shader.c | 126 ++++++++++++++++++++++++---------
dlls/wined3d/shader.c | 11 +++
dlls/wined3d/state.c | 14 ++++
dlls/wined3d/wined3d_private.h | 4 +-
5 files changed, 124 insertions(+), 35 deletions(-)
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index a89a33d676..0f7c433d1e 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -2088,7 +2088,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 e3aa5125fd..900190d728 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
{
@@ -3607,6 +3608,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 = flags & WINED3D_GLSL_SAMPLE_GATHER;
const char *base = "texture", *type_part = "", *suffix = "";
unsigned int coord_size, deriv_size;
@@ -3652,6 +3654,14 @@ static void shader_glsl_get_sample_function(const struct wined3d_shader_context
type_part = "";
}
+ if (gather)
+ {
+ 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);
@@ -5391,11 +5401,18 @@ 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 (priv->cur_ps_args->fetch4 & (1u << resource_idx)) swizzle = (3<<2)|(1<<4)|(2<<6); /* xwyz */
else swizzle = ins->src[1].swizzle;
/* 1.0-1.3: Use destination register as coordinate source.
@@ -5411,7 +5428,7 @@ static void shader_glsl_tex(const struct wined3d_shader_instruction *ins)
{
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);
@@ -5427,10 +5444,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])
@@ -5440,7 +5458,16 @@ 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 = (3<<2)|(1<<4)|(2<<6);
+ 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, 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);
@@ -5455,19 +5482,21 @@ static void shader_glsl_texldd(const struct wined3d_shader_instruction *ins)
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])
{
@@ -5476,6 +5505,18 @@ 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);
}
+
+ if (flags == WINED3D_GLSL_SAMPLE_GATHER){
+ swizzle = (3<<2)|(1<<4)|(2<<6);
+ shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, 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, NULL, NULL, lod_param.param_str, NULL,
"%s", coord_param.param_str);
shader_glsl_release_sample_function(ins->ctx, &sample_function);
@@ -6169,6 +6210,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;
@@ -6183,6 +6225,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);
@@ -6208,46 +6254,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 = (3<<2)|(1<<4)|(2<<6);
+ }
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,
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);
}
@@ -6293,6 +6350,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";
@@ -6304,8 +6364,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);
diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c
index e11a37cf07..909a59e2e5 100644
--- a/dlls/wined3d/shader.c
+++ b/dlls/wined3d/shader.c
@@ -4027,6 +4027,17 @@ 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'))
+ 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 42c109da57..ea56d704b5 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -3599,6 +3599,7 @@ static void sampler(struct wined3d_context *context, const struct wined3d_state
DWORD sampler_idx = state_id - STATE_SAMPLER(0);
DWORD mapped_stage = context->tex_unit_map[sampler_idx];
const struct wined3d_gl_info *gl_info = context->gl_info;
+ int i;
TRACE("Sampler %u.\n", sampler_idx);
@@ -3616,6 +3617,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 +3653,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 >> i) & 0x1) ^ fetch4)
+ {
+ if (fetch4)
+ context->last_was_fetch4 |= 1 << i;
+ else
+ context->last_was_fetch4 &= ~(1 << i);
+ 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 f75660f0ab..9dfdee898d 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1357,7 +1357,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
@@ -1892,6 +1893,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