From d6c814663353d4449e67b6392dce203ffd32b8f4 Mon Sep 17 00:00:00 2001 From: Matteo Bruni Date: Thu, 12 Nov 2015 23:06:42 +0100 Subject: [PATCH] wined3d: Enforce a stable texture units mapping. The GLSL shader backend hardcodes the sampler uniforms at program link time, it can't handle a change in the mapping between draws with the same shader program. Signed-off-by: Matteo Bruni Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/wined3d/context.c | 37 +++++++++++++++++-------------------- dlls/wined3d/glsl_shader.c | 9 ++------- 2 files changed, 19 insertions(+), 27 deletions(-) diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index 92039059c35..80a9ba7ad2f 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -2542,6 +2542,7 @@ static void context_map_stage(struct wined3d_context *context, DWORD stage, DWOR DWORD i = context->rev_tex_unit_map[unit]; DWORD j = context->tex_unit_map[stage]; + TRACE("Mapping stage %u to unit %u.\n", stage, unit); context->tex_unit_map[stage] = unit; if (i != WINED3D_UNMAPPED_STAGE && i != stage) context->tex_unit_map[i] = WINED3D_UNMAPPED_STAGE; @@ -2688,8 +2689,7 @@ static void context_map_psamplers(struct wined3d_context *context, const struct } static BOOL context_unit_free_for_vs(const struct wined3d_context *context, - const struct wined3d_shader_resource_info *ps_resource_info, - const struct wined3d_shader_resource_info *vs_resource_info, DWORD unit) + const struct wined3d_shader_resource_info *ps_resource_info, DWORD unit) { DWORD current_mapping = context->rev_tex_unit_map[unit]; @@ -2711,8 +2711,7 @@ static BOOL context_unit_free_for_vs(const struct wined3d_context *context, return !ps_resource_info[current_mapping].type; } - /* Used by a vertex sampler */ - return !vs_resource_info[current_mapping - MAX_FRAGMENT_SAMPLERS].type; + return TRUE; } static void context_map_vsamplers(struct wined3d_context *context, BOOL ps, const struct wined3d_state *state) @@ -2738,18 +2737,15 @@ static void context_map_vsamplers(struct wined3d_context *context, BOOL ps, cons DWORD vsampler_idx = i + MAX_FRAGMENT_SAMPLERS; if (vs_resource_info[i].type) { - if (context->tex_unit_map[vsampler_idx] != WINED3D_UNMAPPED_STAGE) - { - /* Already mapped somewhere */ - continue; - } - while (start >= 0) { - if (context_unit_free_for_vs(context, ps_resource_info, vs_resource_info, start)) + if (context_unit_free_for_vs(context, ps_resource_info, start)) { - context_map_stage(context, vsampler_idx, start); - context_invalidate_state(context, STATE_SAMPLER(vsampler_idx)); + if (context->tex_unit_map[vsampler_idx] != start) + { + context_map_stage(context, vsampler_idx, start); + context_invalidate_state(context, STATE_SAMPLER(vsampler_idx)); + } --start; break; @@ -2757,6 +2753,8 @@ static void context_map_vsamplers(struct wined3d_context *context, BOOL ps, cons --start; } + if (context->tex_unit_map[vsampler_idx] == WINED3D_UNMAPPED_STAGE) + WARN("Couldn't find a free texture unit for vertex sampler %u.\n", i); } } } @@ -2765,13 +2763,12 @@ static void context_update_tex_unit_map(struct wined3d_context *context, const s { BOOL vs = use_vs(state); BOOL ps = use_ps(state); - /* - * Rules are: - * -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but - * that would be really messy and require shader recompilation - * -> When the mapping of a stage is changed, sampler and ALL texture stage states have - * to be reset. Because of that try to work with a 1:1 mapping as much as possible - */ + + /* Try to go for a 1:1 mapping of the samplers when possible. Pixel shaders + * need a 1:1 map at the moment. + * When the mapping of a stage is changed, sampler and ALL texture stage + * states have to be reset. */ + if (ps) context_map_psamplers(context, state); else diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 44e70901528..abfaef8742a 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -7095,13 +7095,8 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const GL_EXTCALL(glUseProgram(program_id)); checkGLcall("glUseProgram"); - /* Load the vertex and pixel samplers now. The function that finds the mappings makes sure - * that it stays the same for each vertexshader-pixelshader pair(=linked glsl program). If - * a pshader with fixed function pipeline is used there are no vertex samplers, and if a - * vertex shader with fixed function pixel processing is used we make sure that the card - * supports enough samplers to allow the max number of vertex samplers with all possible - * fixed function fragment processing setups. So once the program is linked these samplers - * won't change. */ + /* Texture unit mapping is set up to be the same each time the shader + * program is used so we can hardcode the sampler uniform values. */ shader_glsl_load_samplers(gl_info, priv, context->tex_unit_map, program_id); entry->constant_update_mask = 0;