wined3d: Avoid reading uninitialized texcoord varyings in pixel shaders.

Signed-off-by: Matteo Bruni <mbruni@codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
This commit is contained in:
Matteo Bruni 2015-10-06 14:24:21 +02:00 committed by Alexandre Julliard
parent f511787423
commit 08b21528ed
4 changed files with 77 additions and 41 deletions

View File

@ -4538,7 +4538,7 @@ static void find_arb_ps_compile_args(const struct wined3d_state *state,
int i;
WORD int_skip;
find_ps_compile_args(state, shader, context->stream_info.position_transformed, &args->super, gl_info);
find_ps_compile_args(state, shader, context->stream_info.position_transformed, &args->super, context);
/* This forces all local boolean constants to 1 to make them stateblock independent */
args->bools = shader->reg_maps.local_bool_consts;

View File

@ -1806,12 +1806,6 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
if (map & 1) shader_addline(buffer, "ivec4 A%u;\n", i);
}
/* Declare texture coordinate temporaries and initialize them */
for (i = 0, map = reg_maps->texcoord; map; map >>= 1, ++i)
{
if (map & 1) shader_addline(buffer, "vec4 T%u = gl_TexCoord[%u];\n", i, i);
}
if (version->type == WINED3D_SHADER_TYPE_VERTEX)
{
for (i = 0; i < shader->input_signature.element_count; ++i)
@ -1858,10 +1852,12 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
if (gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
{
shader_addline(buffer, "vec4 ffp_texcoord[%u];\n", MAX_TEXTURES);
shader_addline(buffer, "float ffp_varying_fogcoord;\n");
}
else
{
shader_addline(buffer, "vec4 ffp_texcoord[%u];\n", MAX_TEXTURES);
declare_in_varying(gl_info, buffer, FALSE, "float ffp_varying_fogcoord;\n");
}
}
@ -4209,7 +4205,7 @@ static void shader_glsl_texcoord(const struct wined3d_shader_instruction *ins)
char dst_mask[6];
shader_glsl_get_write_mask(&ins->dst[0], dst_mask);
shader_addline(buffer, "clamp(gl_TexCoord[%u], 0.0, 1.0)%s);\n",
shader_addline(buffer, "clamp(ffp_texcoord[%u], 0.0, 1.0)%s);\n",
ins->dst[0].reg.idx[0].offset, dst_mask);
}
else
@ -4220,33 +4216,22 @@ static void shader_glsl_texcoord(const struct wined3d_shader_instruction *ins)
shader_glsl_get_swizzle(&ins->src[0], FALSE, write_mask, dst_swizzle);
if (src_mod == WINED3DSPSM_DZ)
if (src_mod == WINED3DSPSM_DZ || src_mod == WINED3DSPSM_DW)
{
unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask);
struct glsl_src_param div_param;
DWORD src_writemask = src_mod == WINED3DSPSM_DZ ? WINED3DSP_WRITEMASK_2 : WINED3DSP_WRITEMASK_3;
shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_2, &div_param);
shader_glsl_add_src_param(ins, &ins->src[0], src_writemask, &div_param);
if (mask_size > 1) {
shader_addline(buffer, "gl_TexCoord[%u]%s / vec%d(%s));\n", reg, dst_swizzle, mask_size, div_param.param_str);
} else {
shader_addline(buffer, "gl_TexCoord[%u]%s / %s);\n", reg, dst_swizzle, div_param.param_str);
}
if (mask_size > 1)
shader_addline(buffer, "ffp_texcoord[%u]%s / vec%d(%s));\n", reg, dst_swizzle, mask_size, div_param.param_str);
else
shader_addline(buffer, "ffp_texcoord[%u]%s / %s);\n", reg, dst_swizzle, div_param.param_str);
}
else if (src_mod == WINED3DSPSM_DW)
else
{
unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask);
struct glsl_src_param div_param;
shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &div_param);
if (mask_size > 1) {
shader_addline(buffer, "gl_TexCoord[%u]%s / vec%d(%s));\n", reg, dst_swizzle, mask_size, div_param.param_str);
} else {
shader_addline(buffer, "gl_TexCoord[%u]%s / %s);\n", reg, dst_swizzle, div_param.param_str);
}
} else {
shader_addline(buffer, "gl_TexCoord[%u]%s);\n", reg, dst_swizzle);
shader_addline(buffer, "ffp_texcoord[%u]%s);\n", reg, dst_swizzle);
}
}
}
@ -4276,17 +4261,17 @@ static void shader_glsl_texdp3tex(const struct wined3d_shader_instruction *ins)
{
case 1:
shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL,
"dot(gl_TexCoord[%u].xyz, %s)", sampler_idx, src0_param.param_str);
"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,
"vec2(dot(gl_TexCoord[%u].xyz, %s), 0.0)", sampler_idx, src0_param.param_str);
"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,
"vec3(dot(gl_TexCoord[%u].xyz, %s), 0.0, 0.0)", sampler_idx, src0_param.param_str);
"vec3(dot(ffp_texcoord[%u].xyz, %s), 0.0, 0.0)", sampler_idx, src0_param.param_str);
break;
default:
@ -4491,7 +4476,7 @@ static void shader_glsl_texm3x3vspec(const struct wined3d_shader_instruction *in
shader_addline(buffer, "tmp0.z = dot(vec3(T%u), vec3(%s));\n", reg, src0_param.param_str);
/* Construct the eye-ray vector from w coordinates */
shader_addline(buffer, "tmp1.xyz = normalize(vec3(gl_TexCoord[%u].w, gl_TexCoord[%u].w, gl_TexCoord[%u].w));\n",
shader_addline(buffer, "tmp1.xyz = normalize(vec3(ffp_texcoord[%u].w, ffp_texcoord[%u].w, ffp_texcoord[%u].w));\n",
tex_mx->texcoord_w[0], tex_mx->texcoord_w[1], reg);
shader_addline(buffer, "tmp0.xyz = -reflect(tmp1.xyz, normalize(tmp0.xyz));\n");
@ -4732,7 +4717,10 @@ static void shader_glsl_input_pack(const struct wined3d_shader *shader, struct w
}
else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_TEXCOORD))
{
if (semantic_idx < 8 && args->vp_mode == pretransformed)
if (args->pointsprite)
shader_addline(buffer, "ps_in[%u] = vec4(gl_PointCoord.xy, 0.0, 0.0);\n",
shader->u.ps.input_reg_map[input->register_idx]);
else if (args->vp_mode == pretransformed && args->texcoords_initialized & (1u << semantic_idx))
shader_addline(buffer, "ps_in[%u]%s = gl_TexCoord[%u]%s;\n",
shader->u.ps.input_reg_map[input->register_idx], reg_mask, semantic_idx, reg_mask);
else
@ -5137,6 +5125,23 @@ static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context
if (reg_maps->shader_version.major < 3 || args->vp_mode != vertexshader)
{
unsigned int i;
WORD map = reg_maps->texcoord;
for (i = 0; map; map >>= 1, ++i)
{
if (map & 1)
{
if (args->pointsprite)
shader_addline(buffer, "ffp_texcoord[%u] = vec4(gl_PointCoord.xy, 0.0, 0.0);\n", i);
else if (args->texcoords_initialized & (1u << i))
shader_addline(buffer, "ffp_texcoord[%u] = gl_TexCoord[%u];\n", i, i);
else
shader_addline(buffer, "ffp_texcoord[%u] = vec4(0.0);\n", i);
shader_addline(buffer, "vec4 T%u = ffp_texcoord[%u];\n", i, i);
}
}
if (legacy_context)
shader_addline(buffer, "ffp_varying_fogcoord = gl_FogFragCoord;\n");
}
@ -6816,7 +6821,7 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
{
struct ps_compile_args ps_compile_args;
pshader = state->shader[WINED3D_SHADER_TYPE_PIXEL];
find_ps_compile_args(state, pshader, context->stream_info.position_transformed, &ps_compile_args, gl_info);
find_ps_compile_args(state, pshader, context->stream_info.position_transformed, &ps_compile_args, context);
ps_id = find_glsl_pshader(context, &priv->shader_buffer, &priv->string_buffers,
pshader, &ps_compile_args, &np2fixup_info);
ps_list = &pshader->linked_programs;
@ -8406,8 +8411,8 @@ static void glsl_fragment_pipe_fog(struct wined3d_context *context,
static void glsl_fragment_pipe_vdecl(struct wined3d_context *context,
const struct wined3d_state *state, DWORD state_id)
{
/* Because of settings->texcoords_initialized. */
if (!use_ps(state) && context->gl_info->limits.glsl_varyings < wined3d_max_compat_varyings(context->gl_info))
/* Because of settings->texcoords_initialized and args->texcoords_initialized. */
if (context->gl_info->limits.glsl_varyings < wined3d_max_compat_varyings(context->gl_info))
context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_FOGENABLE)))
@ -8417,8 +8422,8 @@ static void glsl_fragment_pipe_vdecl(struct wined3d_context *context,
static void glsl_fragment_pipe_vs(struct wined3d_context *context,
const struct wined3d_state *state, DWORD state_id)
{
/* Because of settings->texcoords_initialized. */
if (!use_ps(state) && context->gl_info->limits.glsl_varyings < wined3d_max_compat_varyings(context->gl_info))
/* Because of settings->texcoords_initialized and args->texcoords_initialized. */
if (context->gl_info->limits.glsl_varyings < wined3d_max_compat_varyings(context->gl_info))
context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
}

View File

@ -2397,8 +2397,9 @@ static HRESULT geometryshader_init(struct wined3d_shader *shader, struct wined3d
}
void find_ps_compile_args(const struct wined3d_state *state, const struct wined3d_shader *shader,
BOOL position_transformed, struct ps_compile_args *args, const struct wined3d_gl_info *gl_info)
BOOL position_transformed, struct ps_compile_args *args, const struct wined3d_context *context)
{
const struct wined3d_gl_info *gl_info = context->gl_info;
const struct wined3d_texture *texture;
UINT i;
@ -2571,6 +2572,35 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3
}
}
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];
args->texcoords_initialized = 0;
for (i = 0; i < MAX_TEXTURES; ++i)
{
if (vs)
{
if (state->shader[WINED3D_SHADER_TYPE_VERTEX]->reg_maps.output_registers & (1u << i))
args->texcoords_initialized |= 1u << i;
}
else
{
const struct wined3d_stream_info *si = &context->stream_info;
unsigned int coord_idx = state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX];
if ((state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX] >> WINED3D_FFP_TCI_SHIFT)
& WINED3D_FFP_TCI_MASK
|| (coord_idx < MAX_TEXTURES && (si->use_map & (1u << (WINED3D_FFP_TEXCOORD0 + coord_idx)))))
args->texcoords_initialized |= 1u << i;
}
}
}
else
{
args->texcoords_initialized = (1u << MAX_TEXTURES) - 1;
}
args->pointsprite = state->render_states[WINED3D_RS_POINTSPRITEENABLE]
&& state->gl_primitive_type == GL_POINTS;
}

View File

@ -833,11 +833,12 @@ struct ps_compile_args {
WORD tex_transform; /* ps 1.0-1.3, 4 textures */
WORD tex_types; /* ps 1.0 - 1.4, 6 textures */
WORD srgb_correction;
WORD np2_fixup;
/* Bitmap for NP2 texcoord fixups (16 samplers max currently).
D3D9 has a limit of 16 samplers and the fixup is superfluous
in D3D10 (unconditional NP2 support mandatory). */
WORD np2_fixup;
WORD shadow; /* MAX_FRAGMENT_SAMPLERS, 16 */
WORD texcoords_initialized; /* MAX_TEXTURES, 8 */
BOOL pointsprite;
};
@ -3006,7 +3007,7 @@ struct wined3d_shader
void pixelshader_update_resource_types(struct wined3d_shader *shader, WORD tex_types) DECLSPEC_HIDDEN;
void find_ps_compile_args(const struct wined3d_state *state, const struct wined3d_shader *shader,
BOOL position_transformed, struct ps_compile_args *args,
const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
const struct wined3d_context *context) DECLSPEC_HIDDEN;
void find_vs_compile_args(const struct wined3d_state *state, const struct wined3d_shader *shader,
WORD swizzle_map, struct vs_compile_args *args) DECLSPEC_HIDDEN;