diff options
Diffstat (limited to 'mesalib/src')
-rw-r--r-- | mesalib/src/gallium/auxiliary/Makefile.sources | 1 | ||||
-rw-r--r-- | mesalib/src/gallium/auxiliary/util/u_vbuf.c | 8 | ||||
-rw-r--r-- | mesalib/src/glsl/Makefile.sources | 1 | ||||
-rw-r--r-- | mesalib/src/glsl/ir_optimization.h | 4 | ||||
-rw-r--r-- | mesalib/src/glsl/link_varyings.cpp | 67 | ||||
-rw-r--r-- | mesalib/src/glsl/link_varyings.h | 9 | ||||
-rw-r--r-- | mesalib/src/glsl/linker.cpp | 135 | ||||
-rw-r--r-- | mesalib/src/glsl/opt_dead_builtin_varyings.cpp | 477 | ||||
-rw-r--r-- | mesalib/src/mapi/glapi/gen/SConscript | 16 | ||||
-rw-r--r-- | mesalib/src/mesa/SConscript | 17 | ||||
-rw-r--r-- | mesalib/src/mesa/main/mtypes.h | 14 | ||||
-rw-r--r-- | mesalib/src/mesa/main/shaderobj.h | 4 | ||||
-rw-r--r-- | mesalib/src/mesa/program/ir_to_mesa.cpp | 10 | ||||
-rw-r--r-- | mesalib/src/mesa/program/program.h | 2 | ||||
-rw-r--r-- | mesalib/src/mesa/state_tracker/st_context.c | 5 | ||||
-rw-r--r-- | mesalib/src/mesa/state_tracker/st_extensions.c | 24 | ||||
-rw-r--r-- | mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 10 |
17 files changed, 653 insertions, 151 deletions
diff --git a/mesalib/src/gallium/auxiliary/Makefile.sources b/mesalib/src/gallium/auxiliary/Makefile.sources index 20ff5ba73..47517626d 100644 --- a/mesalib/src/gallium/auxiliary/Makefile.sources +++ b/mesalib/src/gallium/auxiliary/Makefile.sources @@ -163,6 +163,7 @@ GENERATED_SOURCES := \ GALLIVM_SOURCES := \ gallivm/lp_bld_arit.c \ + gallivm/lp_bld_arit_overflow.c \ gallivm/lp_bld_assert.c \ gallivm/lp_bld_bitarit.c \ gallivm/lp_bld_const.c \ diff --git a/mesalib/src/gallium/auxiliary/util/u_vbuf.c b/mesalib/src/gallium/auxiliary/util/u_vbuf.c index 5936f74a0..52b360ed7 100644 --- a/mesalib/src/gallium/auxiliary/util/u_vbuf.c +++ b/mesalib/src/gallium/auxiliary/util/u_vbuf.c @@ -403,13 +403,13 @@ u_vbuf_translate_buffers(struct u_vbuf *mgr, struct translate_key *key, switch (ib->index_size) { case 4: - tr->run_elts(tr, (unsigned*)map, num_indices, 0, out_map); + tr->run_elts(tr, (unsigned*)map, num_indices, 0, 0, out_map); break; case 2: - tr->run_elts16(tr, (uint16_t*)map, num_indices, 0, out_map); + tr->run_elts16(tr, (uint16_t*)map, num_indices, 0, 0, out_map); break; case 1: - tr->run_elts8(tr, map, num_indices, 0, out_map); + tr->run_elts8(tr, map, num_indices, 0, 0, out_map); break; } @@ -428,7 +428,7 @@ u_vbuf_translate_buffers(struct u_vbuf *mgr, struct translate_key *key, out_offset -= key->output_stride * start_vertex; - tr->run(tr, 0, num_vertices, 0, out_map); + tr->run(tr, 0, num_vertices, 0, 0, out_map); } /* Unmap all buffers. */ diff --git a/mesalib/src/glsl/Makefile.sources b/mesalib/src/glsl/Makefile.sources index acd19d1ff..979c4165f 100644 --- a/mesalib/src/glsl/Makefile.sources +++ b/mesalib/src/glsl/Makefile.sources @@ -82,6 +82,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/opt_constant_variable.cpp \ $(GLSL_SRCDIR)/opt_copy_propagation.cpp \ $(GLSL_SRCDIR)/opt_copy_propagation_elements.cpp \ + $(GLSL_SRCDIR)/opt_dead_builtin_varyings.cpp \ $(GLSL_SRCDIR)/opt_dead_code.cpp \ $(GLSL_SRCDIR)/opt_dead_code_local.cpp \ $(GLSL_SRCDIR)/opt_dead_functions.cpp \ diff --git a/mesalib/src/glsl/ir_optimization.h b/mesalib/src/glsl/ir_optimization.h index d38d5e303..fad6f1bfe 100644 --- a/mesalib/src/glsl/ir_optimization.h +++ b/mesalib/src/glsl/ir_optimization.h @@ -76,6 +76,10 @@ bool do_constant_variable_unlinked(exec_list *instructions); bool do_copy_propagation(exec_list *instructions); bool do_copy_propagation_elements(exec_list *instructions); bool do_constant_propagation(exec_list *instructions); +void do_dead_builtin_varyings(struct gl_context *ctx, + exec_list *producer, exec_list *consumer, + unsigned num_tfeedback_decls, + class tfeedback_decl *tfeedback_decls); bool do_dead_code(exec_list *instructions, bool uniform_locations_assigned); bool do_dead_code_local(exec_list *instructions); bool do_dead_code_unlinked(exec_list *instructions); diff --git a/mesalib/src/glsl/link_varyings.cpp b/mesalib/src/glsl/link_varyings.cpp index 4fdbdc199..51cbdaa0e 100644 --- a/mesalib/src/glsl/link_varyings.cpp +++ b/mesalib/src/glsl/link_varyings.cpp @@ -1113,16 +1113,12 @@ assign_varying_locations(struct gl_context *ctx, } } - unsigned varying_vectors = 0; - if (consumer) { foreach_list(node, consumer->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if ((var == NULL) || (var->mode != ir_var_shader_in)) - continue; - - if (var->is_unmatched_generic_inout) { + if (var && var->mode == ir_var_shader_in && + var->is_unmatched_generic_inout) { if (prog->Version <= 120) { /* On page 25 (page 31 of the PDF) of the GLSL 1.20 spec: * @@ -1148,45 +1144,46 @@ assign_varying_locations(struct gl_context *ctx, * value is written by the previous stage. */ var->mode = ir_var_auto; - } else if (is_varying_var(consumer->Type, var)) { - /* The packing rules are used for vertex shader inputs are also - * used for fragment shader inputs. - */ - varying_vectors += count_attribute_slots(var->type); } } } + return true; +} + +bool +check_against_varying_limit(struct gl_context *ctx, + struct gl_shader_program *prog, + gl_shader *consumer) +{ + unsigned varying_vectors = 0; + + foreach_list(node, consumer->ir) { + ir_variable *const var = ((ir_instruction *) node)->as_variable(); + + if (var && var->mode == ir_var_shader_in && + is_varying_var(consumer->Type, var)) { + /* The packing rules used for vertex shader inputs are also + * used for fragment shader inputs. + */ + varying_vectors += count_attribute_slots(var->type); + } + } + if (ctx->API == API_OPENGLES2 || prog->IsES) { if (varying_vectors > ctx->Const.MaxVarying) { - if (ctx->Const.GLSLSkipStrictMaxVaryingLimitCheck) { - linker_warning(prog, "shader uses too many varying vectors " - "(%u > %u), but the driver will try to optimize " - "them out; this is non-portable out-of-spec " - "behavior\n", - varying_vectors, ctx->Const.MaxVarying); - } else { - linker_error(prog, "shader uses too many varying vectors " - "(%u > %u)\n", - varying_vectors, ctx->Const.MaxVarying); - return false; - } + linker_error(prog, "shader uses too many varying vectors " + "(%u > %u)\n", + varying_vectors, ctx->Const.MaxVarying); + return false; } } else { const unsigned float_components = varying_vectors * 4; if (float_components > ctx->Const.MaxVarying * 4) { - if (ctx->Const.GLSLSkipStrictMaxVaryingLimitCheck) { - linker_warning(prog, "shader uses too many varying components " - "(%u > %u), but the driver will try to optimize " - "them out; this is non-portable out-of-spec " - "behavior\n", - float_components, ctx->Const.MaxVarying * 4); - } else { - linker_error(prog, "shader uses too many varying components " - "(%u > %u)\n", - float_components, ctx->Const.MaxVarying * 4); - return false; - } + linker_error(prog, "shader uses too many varying components " + "(%u > %u)\n", + float_components, ctx->Const.MaxVarying * 4); + return false; } } diff --git a/mesalib/src/glsl/link_varyings.h b/mesalib/src/glsl/link_varyings.h index ee1010a7b..7f7be353b 100644 --- a/mesalib/src/glsl/link_varyings.h +++ b/mesalib/src/glsl/link_varyings.h @@ -125,6 +125,10 @@ public: return this->vector_elements * this->matrix_columns * this->size; } + unsigned get_location() const { + return this->location; + } + private: /** * The name that was supplied to glTransformFeedbackVaryings. Used for @@ -232,4 +236,9 @@ assign_varying_locations(struct gl_context *ctx, unsigned num_tfeedback_decls, tfeedback_decl *tfeedback_decls); +bool +check_against_varying_limit(struct gl_context *ctx, + struct gl_shader_program *prog, + gl_shader *consumer); + #endif /* GLSL_LINK_VARYINGS_H */ diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index c168e47e0..ba97ade25 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -1514,31 +1514,31 @@ static bool check_resources(struct gl_context *ctx, struct gl_shader_program *prog) { static const char *const shader_names[MESA_SHADER_TYPES] = { - "vertex", "fragment", "geometry" + "vertex", "geometry", "fragment" }; const unsigned max_samplers[MESA_SHADER_TYPES] = { ctx->Const.VertexProgram.MaxTextureImageUnits, - ctx->Const.FragmentProgram.MaxTextureImageUnits, - ctx->Const.GeometryProgram.MaxTextureImageUnits + ctx->Const.GeometryProgram.MaxTextureImageUnits, + ctx->Const.FragmentProgram.MaxTextureImageUnits }; const unsigned max_default_uniform_components[MESA_SHADER_TYPES] = { ctx->Const.VertexProgram.MaxUniformComponents, - ctx->Const.FragmentProgram.MaxUniformComponents, - ctx->Const.GeometryProgram.MaxUniformComponents + ctx->Const.GeometryProgram.MaxUniformComponents, + ctx->Const.FragmentProgram.MaxUniformComponents }; const unsigned max_combined_uniform_components[MESA_SHADER_TYPES] = { ctx->Const.VertexProgram.MaxCombinedUniformComponents, - ctx->Const.FragmentProgram.MaxCombinedUniformComponents, - ctx->Const.GeometryProgram.MaxCombinedUniformComponents + ctx->Const.GeometryProgram.MaxCombinedUniformComponents, + ctx->Const.FragmentProgram.MaxCombinedUniformComponents }; const unsigned max_uniform_blocks[MESA_SHADER_TYPES] = { ctx->Const.VertexProgram.MaxUniformBlocks, - ctx->Const.FragmentProgram.MaxUniformBlocks, ctx->Const.GeometryProgram.MaxUniformBlocks, + ctx->Const.FragmentProgram.MaxUniformBlocks }; for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) { @@ -1836,9 +1836,9 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) goto done; } - unsigned prev; - for (prev = 0; prev < MESA_SHADER_TYPES; prev++) { - if (prog->_LinkedShaders[prev] != NULL) + unsigned first; + for (first = 0; first < MESA_SHADER_TYPES; first++) { + if (prog->_LinkedShaders[first] != NULL) break; } @@ -1850,7 +1850,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) * non-zero, but the program object has no vertex or geometry * shader; */ - if (prev >= MESA_SHADER_FRAGMENT) { + if (first >= MESA_SHADER_FRAGMENT) { linker_error(prog, "Transform feedback varyings specified, but " "no vertex or geometry shader is present."); goto done; @@ -1864,69 +1864,90 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) goto done; } - for (unsigned i = prev + 1; i < MESA_SHADER_TYPES; i++) { - if (prog->_LinkedShaders[i] == NULL) - continue; - - if (!assign_varying_locations( - ctx, mem_ctx, prog, prog->_LinkedShaders[prev], prog->_LinkedShaders[i], - i == MESA_SHADER_FRAGMENT ? num_tfeedback_decls : 0, - tfeedback_decls)) - goto done; - - prev = i; + /* Linking the stages in the opposite order (from fragment to vertex) + * ensures that inter-shader outputs written to in an earlier stage are + * eliminated if they are (transitively) not used in a later stage. + */ + int last, next; + for (last = MESA_SHADER_TYPES-1; last >= 0; last--) { + if (prog->_LinkedShaders[last] != NULL) + break; } - if (prev != MESA_SHADER_FRAGMENT && num_tfeedback_decls != 0) { - /* There was no fragment shader, but we still have to assign varying - * locations for use by transform feedback. - */ - if (!assign_varying_locations( - ctx, mem_ctx, prog, prog->_LinkedShaders[prev], NULL, num_tfeedback_decls, - tfeedback_decls)) - goto done; - } + if (last >= 0 && last < MESA_SHADER_FRAGMENT) { + gl_shader *const sh = prog->_LinkedShaders[last]; - if (!store_tfeedback_info(ctx, prog, num_tfeedback_decls, tfeedback_decls)) - goto done; + if (num_tfeedback_decls != 0) { + /* There was no fragment shader, but we still have to assign varying + * locations for use by transform feedback. + */ + if (!assign_varying_locations(ctx, mem_ctx, prog, + sh, NULL, + num_tfeedback_decls, tfeedback_decls)) + goto done; + } - if (prog->_LinkedShaders[MESA_SHADER_VERTEX] != NULL) { - demote_shader_inputs_and_outputs(prog->_LinkedShaders[MESA_SHADER_VERTEX], - ir_var_shader_out); + do_dead_builtin_varyings(ctx, sh->ir, NULL, + num_tfeedback_decls, tfeedback_decls); - /* Eliminate code that is now dead due to unused vertex outputs being - * demoted. + demote_shader_inputs_and_outputs(sh, ir_var_shader_out); + + /* Eliminate code that is now dead due to unused outputs being demoted. */ - while (do_dead_code(prog->_LinkedShaders[MESA_SHADER_VERTEX]->ir, false)) - ; + while (do_dead_code(sh->ir, false)) + ; } + else if (first == MESA_SHADER_FRAGMENT) { + /* If the program only contains a fragment shader... + */ + gl_shader *const sh = prog->_LinkedShaders[first]; - if (prog->_LinkedShaders[MESA_SHADER_GEOMETRY] != NULL) { - gl_shader *const sh = prog->_LinkedShaders[MESA_SHADER_GEOMETRY]; + do_dead_builtin_varyings(ctx, NULL, sh->ir, + num_tfeedback_decls, tfeedback_decls); demote_shader_inputs_and_outputs(sh, ir_var_shader_in); - demote_shader_inputs_and_outputs(sh, ir_var_shader_out); - /* Eliminate code that is now dead due to unused geometry outputs being - * demoted. - */ - while (do_dead_code(prog->_LinkedShaders[MESA_SHADER_GEOMETRY]->ir, false)) - ; + while (do_dead_code(sh->ir, false)) + ; } - if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] != NULL) { - gl_shader *const sh = prog->_LinkedShaders[MESA_SHADER_FRAGMENT]; + next = last; + for (int i = next - 1; i >= 0; i--) { + if (prog->_LinkedShaders[i] == NULL) + continue; - demote_shader_inputs_and_outputs(sh, ir_var_shader_in); + gl_shader *const sh_i = prog->_LinkedShaders[i]; + gl_shader *const sh_next = prog->_LinkedShaders[next]; + + if (!assign_varying_locations(ctx, mem_ctx, prog, sh_i, sh_next, + next == MESA_SHADER_FRAGMENT ? num_tfeedback_decls : 0, + tfeedback_decls)) + goto done; - /* Eliminate code that is now dead due to unused fragment inputs being - * demoted. This shouldn't actually do anything other than remove - * declarations of the (now unused) global variables. + do_dead_builtin_varyings(ctx, sh_i->ir, sh_next->ir, + next == MESA_SHADER_FRAGMENT ? num_tfeedback_decls : 0, + tfeedback_decls); + + demote_shader_inputs_and_outputs(sh_i, ir_var_shader_out); + demote_shader_inputs_and_outputs(sh_next, ir_var_shader_in); + + /* Eliminate code that is now dead due to unused outputs being demoted. */ - while (do_dead_code(prog->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir, false)) - ; + while (do_dead_code(sh_i->ir, false)) + ; + while (do_dead_code(sh_next->ir, false)) + ; + + /* This must be done after all dead varyings are eliminated. */ + if (!check_against_varying_limit(ctx, prog, sh_next)) + goto done; + + next = i; } + if (!store_tfeedback_info(ctx, prog, num_tfeedback_decls, tfeedback_decls)) + goto done; + update_array_sizes(prog); link_assign_uniform_locations(prog); store_fragdepth_layout(prog); diff --git a/mesalib/src/glsl/opt_dead_builtin_varyings.cpp b/mesalib/src/glsl/opt_dead_builtin_varyings.cpp new file mode 100644 index 000000000..2e813d24e --- /dev/null +++ b/mesalib/src/glsl/opt_dead_builtin_varyings.cpp @@ -0,0 +1,477 @@ +/* + * Copyright © 2013 Marek Olšák <maraeo@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file opt_dead_builtin_varyings.cpp + * + * This eliminates the built-in shader outputs which are either not written + * at all or not used by the next stage. It also eliminates unused elements + * of gl_TexCoord inputs, which reduces the overall varying usage. + * The varyings handled here are the primary and secondary color, the fog, + * and the texture coordinates (gl_TexCoord). + * + * This pass is necessary, because the Mesa GLSL linker cannot eliminate + * built-in varyings like it eliminates user-defined varyings, because + * the built-in varyings have pre-assigned locations. Also, the elimination + * of unused gl_TexCoord elements requires its own lowering pass anyway. + * + * It's implemented by replacing all occurences of dead varyings with + * temporary variables, which creates dead code. It is recommended to run + * a dead-code elimination pass after this. + * + * If any texture coordinate slots can be eliminated, the gl_TexCoord array is + * broken down into separate vec4 variables with locations equal to + * VARYING_SLOT_TEX0 + i. + */ + +#include "main/imports.h" /* for snprintf */ +#include "ir.h" +#include "ir_rvalue_visitor.h" +#include "ir_optimization.h" +#include "ir_print_visitor.h" +#include "glsl_types.h" +#include "link_varyings.h" + + +/** + * This obtains detailed information about built-in varyings from shader code. + */ +class varying_info_visitor : public ir_hierarchical_visitor { +public: + /* "mode" can be either ir_var_shader_in or ir_var_shader_out */ + varying_info_visitor(ir_variable_mode mode) + : lower_texcoord_array(true), + texcoord_array(NULL), + texcoord_usage(0), + color_usage(0), + tfeedback_color_usage(0), + fog(NULL), + has_fog(false), + tfeedback_has_fog(false), + mode(mode) + { + memset(color, 0, sizeof(color)); + memset(backcolor, 0, sizeof(backcolor)); + } + + virtual ir_visitor_status visit_enter(ir_dereference_array *ir) + { + ir_variable *var = ir->variable_referenced(); + + if (var && var->mode == this->mode && + var->location == VARYING_SLOT_TEX0) { + this->texcoord_array = var; + + ir_constant *index = ir->array_index->as_constant(); + if (index == NULL) { + /* There is variable indexing, we can't lower the texcoord array. + */ + this->texcoord_usage |= (1 << var->type->array_size()) - 1; + this->lower_texcoord_array = false; + } + else { + this->texcoord_usage |= 1 << index->get_uint_component(0); + } + + /* Don't visit the leaves of ir_dereference_array. */ + return visit_continue_with_parent; + } + + return visit_continue; + } + + virtual ir_visitor_status visit(ir_dereference_variable *ir) + { + ir_variable *var = ir->variable_referenced(); + + if (var->mode == this->mode && var->type->is_array() && + var->location == VARYING_SLOT_TEX0) { + /* This is a whole array dereference like "gl_TexCoord = x;", + * there's probably no point in lowering that. + */ + this->texcoord_usage |= (1 << var->type->array_size()) - 1; + this->lower_texcoord_array = false; + } + return visit_continue; + } + + virtual ir_visitor_status visit(ir_variable *var) + { + if (var->mode != this->mode) + return visit_continue; + + /* Handle colors and fog. */ + switch (var->location) { + case VARYING_SLOT_COL0: + this->color[0] = var; + this->color_usage |= 1; + break; + case VARYING_SLOT_COL1: + this->color[1] = var; + this->color_usage |= 2; + break; + case VARYING_SLOT_BFC0: + this->backcolor[0] = var; + this->color_usage |= 1; + break; + case VARYING_SLOT_BFC1: + this->backcolor[1] = var; + this->color_usage |= 2; + break; + case VARYING_SLOT_FOGC: + this->fog = var; + this->has_fog = true; + break; + } + + return visit_continue; + } + + void get(exec_list *ir, + unsigned num_tfeedback_decls, + tfeedback_decl *tfeedback_decls) + { + /* Handle the transform feedback varyings. */ + for (unsigned i = 0; i < num_tfeedback_decls; i++) { + if (!tfeedback_decls[i].is_varying()) + continue; + + unsigned location = tfeedback_decls[i].get_location(); + + switch (location) { + case VARYING_SLOT_COL0: + case VARYING_SLOT_BFC0: + this->tfeedback_color_usage |= 1; + break; + case VARYING_SLOT_COL1: + case VARYING_SLOT_BFC1: + this->tfeedback_color_usage |= 2; + break; + case VARYING_SLOT_FOGC: + this->tfeedback_has_fog = true; + break; + default: + if (location >= VARYING_SLOT_TEX0 && + location <= VARYING_SLOT_TEX7) { + this->lower_texcoord_array = false; + } + } + } + + /* Process the shader. */ + visit_list_elements(this, ir); + + if (!this->texcoord_array) { + this->lower_texcoord_array = false; + } + } + + bool lower_texcoord_array; + ir_variable *texcoord_array; + unsigned texcoord_usage; /* bitmask */ + + ir_variable *color[2]; + ir_variable *backcolor[2]; + unsigned color_usage; /* bitmask */ + unsigned tfeedback_color_usage; /* bitmask */ + + ir_variable *fog; + bool has_fog; + bool tfeedback_has_fog; + + ir_variable_mode mode; +}; + + +/** + * This replaces unused varyings with temporary variables. + * + * If "ir" is the producer, the "external" usage should come from + * the consumer. It also works the other way around. If either one is + * missing, set the "external" usage to a full mask. + */ +class replace_varyings_visitor : public ir_rvalue_visitor { +public: + replace_varyings_visitor(exec_list *ir, + const varying_info_visitor *info, + unsigned external_texcoord_usage, + unsigned external_color_usage, + bool external_has_fog) + : info(info), new_fog(NULL) + { + void *const ctx = ir; + + memset(this->new_texcoord, 0, sizeof(this->new_texcoord)); + memset(this->new_color, 0, sizeof(this->new_color)); + memset(this->new_backcolor, 0, sizeof(this->new_backcolor)); + + const char *mode_str = + info->mode == ir_var_shader_in ? "in" : "out"; + + /* Handle texcoord outputs. + * + * We're going to break down the gl_TexCoord array into separate + * variables. First, add declarations of the new variables all + * occurences of gl_TexCoord will be replaced with. + */ + if (info->lower_texcoord_array) { + for (int i = MAX_TEXTURE_COORD_UNITS-1; i >= 0; i--) { + if (info->texcoord_usage & (1 << i)) { + char name[32]; + + if (!(external_texcoord_usage & (1 << i))) { + /* This varying is unused in the next stage. Declare + * a temporary instead of an output. */ + snprintf(name, 32, "gl_%s_TexCoord%i_dummy", mode_str, i); + this->new_texcoord[i] = + new (ctx) ir_variable(glsl_type::vec4_type, name, + ir_var_temporary); + } + else { + snprintf(name, 32, "gl_%s_TexCoord%i", mode_str, i); + this->new_texcoord[i] = + new(ctx) ir_variable(glsl_type::vec4_type, name, + info->mode); + this->new_texcoord[i]->location = VARYING_SLOT_TEX0 + i; + this->new_texcoord[i]->explicit_location = true; + this->new_texcoord[i]->explicit_index = 0; + } + + ir->head->insert_before(new_texcoord[i]); + } + } + } + + /* Create dummy variables which will replace set-but-unused color and + * fog outputs. + */ + external_color_usage |= info->tfeedback_color_usage; + + for (int i = 0; i < 2; i++) { + char name[32]; + + if (!(external_color_usage & (1 << i))) { + if (info->color[i]) { + snprintf(name, 32, "gl_%s_FrontColor%i_dummy", mode_str, i); + this->new_color[i] = + new (ctx) ir_variable(glsl_type::vec4_type, name, + ir_var_temporary); + } + + if (info->backcolor[i]) { + snprintf(name, 32, "gl_%s_BackColor%i_dummy", mode_str, i); + this->new_backcolor[i] = + new (ctx) ir_variable(glsl_type::vec4_type, name, + ir_var_temporary); + } + } + } + + if (!external_has_fog && !info->tfeedback_has_fog && + info->fog) { + char name[32]; + + snprintf(name, 32, "gl_%s_FogFragCoord_dummy", mode_str); + this->new_fog = new (ctx) ir_variable(glsl_type::float_type, name, + ir_var_temporary); + } + + /* Now do the replacing. */ + visit_list_elements(this, ir); + } + + virtual ir_visitor_status visit(ir_variable *var) + { + /* Remove the gl_TexCoord array. */ + if (this->info->lower_texcoord_array && + var == this->info->texcoord_array) { + var->remove(); + } + + /* Replace set-but-unused color and fog outputs with dummy variables. */ + for (int i = 0; i < 2; i++) { + if (var == this->info->color[i] && this->new_color[i]) { + var->replace_with(this->new_color[i]); + } + if (var == this->info->backcolor[i] && + this->new_backcolor[i]) { + var->replace_with(this->new_backcolor[i]); + } + } + + if (var == this->info->fog && this->new_fog) { + var->replace_with(this->new_fog); + } + + return visit_continue; + } + + virtual void handle_rvalue(ir_rvalue **rvalue) + { + if (!*rvalue) + return; + + void *ctx = ralloc_parent(*rvalue); + + /* Replace an array dereference gl_TexCoord[i] with a single + * variable dereference representing gl_TexCoord[i]. + */ + if (this->info->lower_texcoord_array) { + /* gl_TexCoord[i] occurence */ + ir_dereference_array *const da = (*rvalue)->as_dereference_array(); + + if (da && da->variable_referenced() == + this->info->texcoord_array) { + unsigned i = da->array_index->as_constant()->get_uint_component(0); + + *rvalue = new(ctx) ir_dereference_variable(this->new_texcoord[i]); + return; + } + } + + /* Replace set-but-unused color and fog outputs with dummy variables. */ + ir_dereference_variable *const dv = (*rvalue)->as_dereference_variable(); + if (!dv) + return; + + ir_variable *var = dv->variable_referenced(); + + for (int i = 0; i < 2; i++) { + if (var == this->info->color[i] && this->new_color[i]) { + *rvalue = new(ctx) ir_dereference_variable(this->new_color[i]); + return; + } + if (var == this->info->backcolor[i] && + this->new_backcolor[i]) { + *rvalue = new(ctx) ir_dereference_variable(this->new_backcolor[i]); + return; + } + } + + if (var == this->info->fog && this->new_fog) { + *rvalue = new(ctx) ir_dereference_variable(this->new_fog); + } + } + + virtual ir_visitor_status visit_leave(ir_assignment *ir) + { + handle_rvalue(&ir->rhs); + handle_rvalue(&ir->condition); + + /* We have to use set_lhs when changing the LHS of an assignment. */ + ir_rvalue *lhs = ir->lhs; + + handle_rvalue(&lhs); + if (lhs != ir->lhs) { + ir->set_lhs(lhs); + } + + return visit_continue; + } + +private: + const varying_info_visitor *info; + struct ir_variable *new_texcoord[MAX_TEXTURE_COORD_UNITS]; + struct ir_variable *new_color[2]; + struct ir_variable *new_backcolor[2]; + struct ir_variable *new_fog; +}; + + +static void +lower_texcoord_array(exec_list *ir, const varying_info_visitor *info) +{ + replace_varyings_visitor(ir, info, + (1 << MAX_TEXTURE_COORD_UNITS) - 1, + 1 | 2, true); +} + + +void +do_dead_builtin_varyings(struct gl_context *ctx, + exec_list *producer, exec_list *consumer, + unsigned num_tfeedback_decls, + tfeedback_decl *tfeedback_decls) +{ + /* This optimization has no effect with the core context and GLES2, because + * the built-in varyings we're eliminating here are not available there. + * + * EXT_separate_shader_objects doesn't allow this optimization, + * because a program object can be bound partially (e.g. only one + * stage of a program object can be bound). + */ + if (ctx->API == API_OPENGL_CORE || + ctx->API == API_OPENGLES2 || + ctx->Extensions.EXT_separate_shader_objects) { + return; + } + + /* Information about built-in varyings. */ + varying_info_visitor producer_info(ir_var_shader_out); + varying_info_visitor consumer_info(ir_var_shader_in); + + if (producer) { + producer_info.get(producer, num_tfeedback_decls, tfeedback_decls); + + if (!consumer) { + /* At least eliminate unused gl_TexCoord elements. */ + if (producer_info.lower_texcoord_array) { + lower_texcoord_array(producer, &producer_info); + } + return; + } + } + + if (consumer) { + consumer_info.get(consumer, 0, NULL); + + if (!producer) { + /* At least eliminate unused gl_TexCoord elements. */ + if (consumer_info.lower_texcoord_array) { + lower_texcoord_array(consumer, &consumer_info); + } + return; + } + } + + /* Eliminate the varyings unused by the other shader. */ + if (producer_info.lower_texcoord_array || + producer_info.color_usage || + producer_info.has_fog) { + replace_varyings_visitor(producer, + &producer_info, + consumer_info.texcoord_usage, + consumer_info.color_usage, + consumer_info.has_fog); + } + + if (consumer_info.lower_texcoord_array || + consumer_info.color_usage || + consumer_info.has_fog) { + replace_varyings_visitor(consumer, + &consumer_info, + producer_info.texcoord_usage, + producer_info.color_usage, + producer_info.has_fog); + } +} diff --git a/mesalib/src/mapi/glapi/gen/SConscript b/mesalib/src/mapi/glapi/gen/SConscript index 18158ff8b..e4abe906a 100644 --- a/mesalib/src/mapi/glapi/gen/SConscript +++ b/mesalib/src/mapi/glapi/gen/SConscript @@ -44,6 +44,20 @@ env.CodeGenerate( env.CodeGenerate( target = '../../../mesa/main/remap_helper.h', script = 'remap_helper.py', - source = 'gl_and_es_API.xml', + source = sources, + command = python_cmd + ' $SCRIPT -f $SOURCE > $TARGET' + ) + +env.CodeGenerate( + target = '../../../mesa/main/enums.c', + script = 'gl_enums.py', + source = sources, + command = python_cmd + ' $SCRIPT -f $SOURCE > $TARGET' + ) + +env.CodeGenerate( + target = '../../../mesa/main/api_exec.c', + script = 'gl_genexec.py', + source = sources, command = python_cmd + ' $SCRIPT -f $SOURCE > $TARGET' ) diff --git a/mesalib/src/mesa/SConscript b/mesalib/src/mesa/SConscript index 0f1543802..d328fc13c 100644 --- a/mesalib/src/mesa/SConscript +++ b/mesalib/src/mesa/SConscript @@ -417,23 +417,6 @@ if (env['gcc'] or env['clang']) and \ env.Append(CPPPATH = [matypes[0].dir]) -# The enums.c file is generated from the GL/ES API.xml file -env.CodeGenerate( - target = 'main/enums.c', - script = GLAPI + 'gen/gl_enums.py', - source = GLAPI + 'gen/gl_and_es_API.xml', - command = python_cmd + ' $SCRIPT -f $SOURCE > $TARGET' - ) - -# The api_exec.c file is generated from the GL/ES API.xml file -env.CodeGenerate( - target = 'main/api_exec.c', - script = GLAPI + 'gen/gl_genexec.py', - source = GLAPI + 'gen/gl_and_es_API.xml', - command = python_cmd + ' $SCRIPT -f $SOURCE > $TARGET' - ) - - def write_git_sha1_h_file(filename): """Mesa looks for a git_sha1.h file at compile time in order to display the current git hash id in the GL_VERSION string. This function tries diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index 1f62e2c9c..2f7cce7ba 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -2173,13 +2173,16 @@ struct gl_shader /** * Shader stages. Note that these will become 5 with tessellation. - * These MUST have the same values as gallium's PIPE_SHADER_* + * + * The order must match how shaders are ordered in the pipeline. + * The GLSL linker assumes that if i<j, then the j-th shader is + * executed later than the i-th shader. */ typedef enum { MESA_SHADER_VERTEX = 0, - MESA_SHADER_FRAGMENT = 1, - MESA_SHADER_GEOMETRY = 2, + MESA_SHADER_GEOMETRY = 1, + MESA_SHADER_FRAGMENT = 2, MESA_SHADER_TYPES = 3 } gl_shader_type; @@ -2922,12 +2925,11 @@ struct gl_constants GLboolean StripTextureBorder; /** - * For drivers which can do a better job at eliminating unused varyings - * and uniforms than the GLSL compiler. + * For drivers which can do a better job at eliminating unused uniforms + * than the GLSL compiler. * * XXX Remove these as soon as a better solution is available. */ - GLboolean GLSLSkipStrictMaxVaryingLimitCheck; GLboolean GLSLSkipStrictMaxUniformLimitCheck; /** diff --git a/mesalib/src/mesa/main/shaderobj.h b/mesalib/src/mesa/main/shaderobj.h index 5ce85cfde..de1c9fcaf 100644 --- a/mesalib/src/mesa/main/shaderobj.h +++ b/mesalib/src/mesa/main/shaderobj.h @@ -123,8 +123,8 @@ _mesa_shader_index_to_type(GLuint i) { static const GLenum enums[MESA_SHADER_TYPES] = { GL_VERTEX_SHADER, - GL_FRAGMENT_SHADER, - GL_GEOMETRY_SHADER , + GL_GEOMETRY_SHADER, + GL_FRAGMENT_SHADER }; if (i >= MESA_SHADER_TYPES) return 0; diff --git a/mesalib/src/mesa/program/ir_to_mesa.cpp b/mesalib/src/mesa/program/ir_to_mesa.cpp index 35a9b8437..4af1c8241 100644 --- a/mesalib/src/mesa/program/ir_to_mesa.cpp +++ b/mesalib/src/mesa/program/ir_to_mesa.cpp @@ -3073,12 +3073,6 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) linked_prog = get_mesa_program(ctx, prog, prog->_LinkedShaders[i]); if (linked_prog) { - static const GLenum targets[] = { - GL_VERTEX_PROGRAM_ARB, - GL_FRAGMENT_PROGRAM_ARB, - GL_GEOMETRY_PROGRAM_NV - }; - if (i == MESA_SHADER_VERTEX) { ((struct gl_vertex_program *)linked_prog)->UsesClipDistance = prog->Vert.UsesClipDistance; @@ -3086,7 +3080,9 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) _mesa_reference_program(ctx, &prog->_LinkedShaders[i]->Program, linked_prog); - if (!ctx->Driver.ProgramStringNotify(ctx, targets[i], linked_prog)) { + if (!ctx->Driver.ProgramStringNotify(ctx, + _mesa_program_index_to_target(i), + linked_prog)) { return GL_FALSE; } } diff --git a/mesalib/src/mesa/program/program.h b/mesalib/src/mesa/program/program.h index ecda59b58..f28983894 100644 --- a/mesalib/src/mesa/program/program.h +++ b/mesalib/src/mesa/program/program.h @@ -205,8 +205,8 @@ _mesa_program_index_to_target(GLuint i) { static const GLenum enums[MESA_SHADER_TYPES] = { GL_VERTEX_PROGRAM_ARB, - GL_FRAGMENT_PROGRAM_ARB, GL_GEOMETRY_PROGRAM_NV, + GL_FRAGMENT_PROGRAM_ARB }; if(i >= MESA_SHADER_TYPES) return 0; diff --git a/mesalib/src/mesa/state_tracker/st_context.c b/mesalib/src/mesa/state_tracker/st_context.c index 7d18c2521..80393cff7 100644 --- a/mesalib/src/mesa/state_tracker/st_context.c +++ b/mesalib/src/mesa/state_tracker/st_context.c @@ -221,11 +221,6 @@ struct st_context *st_create_context(gl_api api, struct pipe_context *pipe, struct gl_context *shareCtx = share ? share->ctx : NULL; struct dd_function_table funcs; - /* Sanity checks */ - STATIC_ASSERT(MESA_SHADER_VERTEX == PIPE_SHADER_VERTEX); - STATIC_ASSERT(MESA_SHADER_FRAGMENT == PIPE_SHADER_FRAGMENT); - STATIC_ASSERT(MESA_SHADER_GEOMETRY == PIPE_SHADER_GEOMETRY); - memset(&funcs, 0, sizeof(funcs)); st_init_driver_functions(&funcs); diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index 83e8e2e96..32348ef73 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -68,7 +68,7 @@ void st_init_limits(struct st_context *st) { struct pipe_screen *screen = st->pipe->screen; struct gl_constants *c = &st->ctx->Const; - gl_shader_type sh; + unsigned sh; boolean can_ubo = TRUE; c->MaxTextureLevels @@ -149,23 +149,25 @@ void st_init_limits(struct st_context *st) can_ubo = FALSE; } - for (sh = 0; sh < MESA_SHADER_TYPES; ++sh) { - struct gl_shader_compiler_options *options = - &st->ctx->ShaderCompilerOptions[sh]; + for (sh = 0; sh < PIPE_SHADER_TYPES; ++sh) { + struct gl_shader_compiler_options *options; struct gl_program_constants *pc; switch (sh) { case PIPE_SHADER_FRAGMENT: pc = &c->FragmentProgram; + options = &st->ctx->ShaderCompilerOptions[MESA_SHADER_FRAGMENT]; break; case PIPE_SHADER_VERTEX: pc = &c->VertexProgram; + options = &st->ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX]; break; case PIPE_SHADER_GEOMETRY: pc = &c->GeometryProgram; + options = &st->ctx->ShaderCompilerOptions[MESA_SHADER_GEOMETRY]; break; default: - assert(0); + /* compute shader, etc. */ continue; } @@ -274,9 +276,6 @@ void st_init_limits(struct st_context *st) c->GLSLSkipStrictMaxUniformLimitCheck = screen->get_param(screen, PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS); - c->GLSLSkipStrictMaxVaryingLimitCheck = - screen->get_param(screen, PIPE_CAP_TGSI_CAN_COMPACT_VARYINGS); - if (can_ubo) { st->ctx->Extensions.ARB_uniform_buffer_object = GL_TRUE; c->UniformBufferOffsetAlignment = @@ -552,7 +551,14 @@ void st_init_extensions(struct st_context *st) ctx->Extensions.EXT_pixel_buffer_object = GL_TRUE; ctx->Extensions.EXT_point_parameters = GL_TRUE; ctx->Extensions.EXT_provoking_vertex = GL_TRUE; - ctx->Extensions.EXT_separate_shader_objects = GL_TRUE; + + /* IMPORTANT: + * Don't enable EXT_separate_shader_objects. It disallows a certain + * optimization in the GLSL compiler and therefore is considered + * harmful. + */ + ctx->Extensions.EXT_separate_shader_objects = GL_FALSE; + ctx->Extensions.EXT_texture_env_dot3 = GL_TRUE; ctx->Extensions.EXT_vertex_array_bgra = GL_TRUE; diff --git a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index 32bc2b37b..64e0a8a46 100644 --- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -5271,15 +5271,11 @@ st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) linked_prog = get_mesa_program(ctx, prog, prog->_LinkedShaders[i]); if (linked_prog) { - static const GLenum targets[] = { - GL_VERTEX_PROGRAM_ARB, - GL_FRAGMENT_PROGRAM_ARB, - GL_GEOMETRY_PROGRAM_NV - }; - _mesa_reference_program(ctx, &prog->_LinkedShaders[i]->Program, linked_prog); - if (!ctx->Driver.ProgramStringNotify(ctx, targets[i], linked_prog)) { + if (!ctx->Driver.ProgramStringNotify(ctx, + _mesa_program_index_to_target(i), + linked_prog)) { _mesa_reference_program(ctx, &prog->_LinkedShaders[i]->Program, NULL); _mesa_reference_program(ctx, &linked_prog, NULL); |