diff options
author | Kenneth Graunke <[email protected]> | 2014-05-30 23:52:22 -0700 |
---|---|---|
committer | Kenneth Graunke <[email protected]> | 2016-09-23 16:40:40 -0700 |
commit | b04ef3c08a288a5857349c9e582ee2718fa562f7 (patch) | |
tree | 5a0f938df2c14a190d14eee7efc25ed7a199eede /src | |
parent | 1617f59bc675d6e44d16ab56d95e910d2e2c8f4e (diff) |
glsl: Immediately inline built-ins rather than generating calls.
In the past, we imported the prototypes of built-in functions, generated
calls to those, and waited until link time to resolve the calls and
import the actual code for the built-in functions.
This severely limited our compile-time optimization opportunities: even
trivial functions like dot() were represented as function calls. We
also had no way of reasoning about those calls; they could have been
1,000 line functions with side-effects for all we knew.
Practically all built-in functions are trivial translations to
ir_expression opcodes, so it makes sense to just generate those inline.
Since we eventually inline all functions anyway, we may as well just do
it for all built-in functions.
There's only one snag: built-in functions that refer to built-in global
variables need those remapped to the variables in the shader being
compiled, rather than the ones in the built-in shader. Currently,
ftransform() is the only function matching those criteria, so it seemed
easier to just make it a special case.
On Skylake:
total instructions in shared programs: 12023491 -> 12024010 (0.00%)
instructions in affected programs: 77595 -> 78114 (0.67%)
helped: 97
HURT: 309
total cycles in shared programs: 137239044 -> 137295498 (0.04%)
cycles in affected programs: 16714026 -> 16770480 (0.34%)
helped: 4663
HURT: 4923
while these statistics are in the wrong direction, the number of
hurt programs is small (309 / 41282 = 0.75%), and I don't think
anything can be done about it. A change like this significantly
alters the order in which optimizations are performed.
Signed-off-by: Kenneth Graunke <[email protected]>
Reviewed-by; Ian Romanick <[email protected]>
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/glsl/ast_function.cpp | 46 |
1 files changed, 22 insertions, 24 deletions
diff --git a/src/compiler/glsl/ast_function.cpp b/src/compiler/glsl/ast_function.cpp index 7e62ab7d56d..ac3b52d24e5 100644 --- a/src/compiler/glsl/ast_function.cpp +++ b/src/compiler/glsl/ast_function.cpp @@ -430,7 +430,8 @@ generate_call(exec_list *instructions, ir_function_signature *sig, exec_list *actual_parameters, ir_variable *sub_var, ir_rvalue *array_idx, - struct _mesa_glsl_parse_state *state) + struct _mesa_glsl_parse_state *state, + bool inline_immediately) { void *ctx = state; exec_list post_call_conversions; @@ -542,6 +543,10 @@ generate_call(exec_list *instructions, ir_function_signature *sig, ir_call *call = new(ctx) ir_call(sig, deref, actual_parameters, sub_var, array_idx); instructions->push_tail(call); + if (inline_immediately) { + call->generate_inline(call); + call->remove(); + } /* Also emit any necessary out-parameter conversions. */ instructions->append_list(&post_call_conversions); @@ -557,19 +562,18 @@ match_function_by_name(const char *name, exec_list *actual_parameters, struct _mesa_glsl_parse_state *state) { - void *ctx = state; ir_function *f = state->symbols->get_function(name); ir_function_signature *local_sig = NULL; ir_function_signature *sig = NULL; /* Is the function hidden by a record type constructor? */ if (state->symbols->get_type(name)) - goto done; /* no match */ + return sig; /* no match */ /* Is the function hidden by a variable (impossible in 1.10)? */ if (!state->symbols->separate_function_namespace && state->symbols->get_variable(name)) - goto done; /* no match */ + return sig; /* no match */ if (f != NULL) { /* In desktop GL, the presence of a user-defined signature hides any @@ -583,31 +587,15 @@ match_function_by_name(const char *name, sig = local_sig = f->matching_signature(state, actual_parameters, allow_builtins, &is_exact); if (is_exact) - goto done; + return sig; if (!allow_builtins) - goto done; + return sig; } /* Local shader has no exact candidates; check the built-ins. */ _mesa_glsl_initialize_builtin_functions(); sig = _mesa_glsl_find_builtin_function(state, name, actual_parameters); - - done: - if (sig != NULL) { - /* If the match is from a linked built-in shader, import the - * prototype. - */ - if (sig != local_sig) { - if (f == NULL) { - f = new(ctx) ir_function(name); - state->symbols->add_global_function(f); - emit_function(state, f); - } - sig = sig->clone_prototype(f, NULL); - f->add_signature(sig); - } - } return sig; } @@ -2142,6 +2130,16 @@ ast_function_expression::hir(exec_list *instructions, this->expressions)) { /* an error has already been emitted */ value = ir_rvalue::error_value(ctx); + } else if (sig->is_builtin() && strcmp(func_name, "ftransform") == 0) { + /* ftransform refers to global variables, and we don't have any code + * for remapping the variable references in the built-in shader. + */ + ir_variable *mvp = + state->symbols->get_variable("gl_ModelViewProjectionMatrix"); + ir_variable *vtx = state->symbols->get_variable("gl_Vertex"); + value = new(ctx) ir_expression(ir_binop_mul, glsl_type::vec4_type, + new(ctx) ir_dereference_variable(mvp), + new(ctx) ir_dereference_variable(vtx)); } else { if (state->stage == MESA_SHADER_TESS_CTRL && sig->is_builtin() && strcmp(func_name, "barrier") == 0) { @@ -2162,8 +2160,8 @@ ast_function_expression::hir(exec_list *instructions, } } - value = generate_call(instructions, sig, - &actual_parameters, sub_var, array_idx, state); + value = generate_call(instructions, sig, &actual_parameters, sub_var, + array_idx, state, sig->is_builtin()); if (!value) { ir_variable *const tmp = new(ctx) ir_variable(glsl_type::void_type, "void_var", |