glsl: delay optimisations on individual shaders when cache is available
Due to a max limit of 65,536 entries on the index table that we use to decide if we can skip compiling individual shaders, it is very likely we will have collisions. To avoid doing too much work when the linked program may be in the cache this patch delays calling the optimisations until link time. Improves cold cache start-up times on Deus Ex by ~20 seconds. When deleting the cache index to simulate a worst case scenario of collisions in the index, warm cache start-up time improves by ~45 seconds. V2: fix indentation, make sure to call optimisations on cache fallback, make sure optimisations get called for XFB. Tested-by: Grazvydas Ignotas <notasas@gmail.com> Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de> Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
This commit is contained in:
parent
d2d6cf6c83
commit
c2bc0aa7b1
|
@ -1922,6 +1922,85 @@ do_late_parsing_checks(struct _mesa_glsl_parse_state *state)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
opt_shader_and_create_symbol_table(struct gl_context *ctx,
|
||||
struct gl_shader *shader)
|
||||
{
|
||||
assert(shader->CompileStatus != compile_failure &&
|
||||
!shader->ir->is_empty());
|
||||
|
||||
struct gl_shader_compiler_options *options =
|
||||
&ctx->Const.ShaderCompilerOptions[shader->Stage];
|
||||
|
||||
/* Do some optimization at compile time to reduce shader IR size
|
||||
* and reduce later work if the same shader is linked multiple times
|
||||
*/
|
||||
if (ctx->Const.GLSLOptimizeConservatively) {
|
||||
/* Run it just once. */
|
||||
do_common_optimization(shader->ir, false, false, options,
|
||||
ctx->Const.NativeIntegers);
|
||||
} else {
|
||||
/* Repeat it until it stops making changes. */
|
||||
while (do_common_optimization(shader->ir, false, false, options,
|
||||
ctx->Const.NativeIntegers))
|
||||
;
|
||||
}
|
||||
|
||||
validate_ir_tree(shader->ir);
|
||||
|
||||
enum ir_variable_mode other;
|
||||
switch (shader->Stage) {
|
||||
case MESA_SHADER_VERTEX:
|
||||
other = ir_var_shader_in;
|
||||
break;
|
||||
case MESA_SHADER_FRAGMENT:
|
||||
other = ir_var_shader_out;
|
||||
break;
|
||||
default:
|
||||
/* Something invalid to ensure optimize_dead_builtin_uniforms
|
||||
* doesn't remove anything other than uniforms or constants.
|
||||
*/
|
||||
other = ir_var_mode_count;
|
||||
break;
|
||||
}
|
||||
|
||||
optimize_dead_builtin_variables(shader->ir, other);
|
||||
|
||||
validate_ir_tree(shader->ir);
|
||||
|
||||
/* Retain any live IR, but trash the rest. */
|
||||
reparent_ir(shader->ir, shader->ir);
|
||||
|
||||
/* Destroy the symbol table. Create a new symbol table that contains only
|
||||
* the variables and functions that still exist in the IR. The symbol
|
||||
* table will be used later during linking.
|
||||
*
|
||||
* There must NOT be any freed objects still referenced by the symbol
|
||||
* table. That could cause the linker to dereference freed memory.
|
||||
*
|
||||
* We don't have to worry about types or interface-types here because those
|
||||
* are fly-weights that are looked up by glsl_type.
|
||||
*/
|
||||
foreach_in_list (ir_instruction, ir, shader->ir) {
|
||||
switch (ir->ir_type) {
|
||||
case ir_type_function:
|
||||
shader->symbols->add_function((ir_function *) ir);
|
||||
break;
|
||||
case ir_type_variable: {
|
||||
ir_variable *const var = (ir_variable *) ir;
|
||||
|
||||
if (var->data.mode != ir_var_temporary)
|
||||
shader->symbols->add_variable(var);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_mesa_glsl_initialize_derived_variables(ctx, shader);
|
||||
}
|
||||
|
||||
void
|
||||
_mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader,
|
||||
bool dump_ast, bool dump_hir, bool force_recompile)
|
||||
|
@ -1963,6 +2042,12 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader,
|
|||
*/
|
||||
if (shader->CompileStatus == compile_success)
|
||||
return;
|
||||
|
||||
if (shader->CompileStatus == compiled_no_opts) {
|
||||
opt_shader_and_create_symbol_table(ctx, shader);
|
||||
shader->CompileStatus = compile_success;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!state->error) {
|
||||
|
@ -1993,51 +2078,6 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if (!state->error && !shader->ir->is_empty()) {
|
||||
struct gl_shader_compiler_options *options =
|
||||
&ctx->Const.ShaderCompilerOptions[shader->Stage];
|
||||
|
||||
assign_subroutine_indexes(shader, state);
|
||||
lower_subroutine(shader->ir, state);
|
||||
|
||||
/* Do some optimization at compile time to reduce shader IR size
|
||||
* and reduce later work if the same shader is linked multiple times
|
||||
*/
|
||||
if (ctx->Const.GLSLOptimizeConservatively) {
|
||||
/* Run it just once. */
|
||||
do_common_optimization(shader->ir, false, false, options,
|
||||
ctx->Const.NativeIntegers);
|
||||
} else {
|
||||
/* Repeat it until it stops making changes. */
|
||||
while (do_common_optimization(shader->ir, false, false, options,
|
||||
ctx->Const.NativeIntegers))
|
||||
;
|
||||
}
|
||||
|
||||
validate_ir_tree(shader->ir);
|
||||
|
||||
enum ir_variable_mode other;
|
||||
switch (shader->Stage) {
|
||||
case MESA_SHADER_VERTEX:
|
||||
other = ir_var_shader_in;
|
||||
break;
|
||||
case MESA_SHADER_FRAGMENT:
|
||||
other = ir_var_shader_out;
|
||||
break;
|
||||
default:
|
||||
/* Something invalid to ensure optimize_dead_builtin_uniforms
|
||||
* doesn't remove anything other than uniforms or constants.
|
||||
*/
|
||||
other = ir_var_mode_count;
|
||||
break;
|
||||
}
|
||||
|
||||
optimize_dead_builtin_variables(shader->ir, other);
|
||||
|
||||
validate_ir_tree(shader->ir);
|
||||
}
|
||||
|
||||
if (shader->InfoLog)
|
||||
ralloc_free(shader->InfoLog);
|
||||
|
||||
|
@ -2050,38 +2090,18 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader,
|
|||
shader->Version = state->language_version;
|
||||
shader->IsES = state->es_shader;
|
||||
|
||||
/* Retain any live IR, but trash the rest. */
|
||||
reparent_ir(shader->ir, shader->ir);
|
||||
if (!state->error && !shader->ir->is_empty()) {
|
||||
assign_subroutine_indexes(shader, state);
|
||||
lower_subroutine(shader->ir, state);
|
||||
|
||||
/* Destroy the symbol table. Create a new symbol table that contains only
|
||||
* the variables and functions that still exist in the IR. The symbol
|
||||
* table will be used later during linking.
|
||||
*
|
||||
* There must NOT be any freed objects still referenced by the symbol
|
||||
* table. That could cause the linker to dereference freed memory.
|
||||
*
|
||||
* We don't have to worry about types or interface-types here because those
|
||||
* are fly-weights that are looked up by glsl_type.
|
||||
*/
|
||||
foreach_in_list (ir_instruction, ir, shader->ir) {
|
||||
switch (ir->ir_type) {
|
||||
case ir_type_function:
|
||||
shader->symbols->add_function((ir_function *) ir);
|
||||
break;
|
||||
case ir_type_variable: {
|
||||
ir_variable *const var = (ir_variable *) ir;
|
||||
|
||||
if (var->data.mode != ir_var_temporary)
|
||||
shader->symbols->add_variable(var);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
if (!ctx->Cache || force_recompile)
|
||||
opt_shader_and_create_symbol_table(ctx, shader);
|
||||
else {
|
||||
reparent_ir(shader->ir, shader->ir);
|
||||
shader->CompileStatus = compiled_no_opts;
|
||||
}
|
||||
}
|
||||
|
||||
_mesa_glsl_initialize_derived_variables(ctx, shader);
|
||||
|
||||
if (!force_recompile) {
|
||||
free((void *)shader->FallbackSource);
|
||||
shader->FallbackSource = NULL;
|
||||
|
|
|
@ -4641,9 +4641,6 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
|
|||
bool skip_cache = false;
|
||||
if (prog->TransformFeedback.NumVarying > 0) {
|
||||
for (unsigned i = 0; i < prog->NumShaders; i++) {
|
||||
if (prog->Shaders[i]->ir) {
|
||||
continue;
|
||||
}
|
||||
_mesa_glsl_compile_shader(ctx, prog->Shaders[i], false, false, true);
|
||||
}
|
||||
skip_cache = true;
|
||||
|
|
|
@ -1418,7 +1418,7 @@ shader_cache_read_program_metadata(struct gl_context *ctx,
|
|||
*/
|
||||
char sha1_buf[41];
|
||||
for (unsigned i = 0; i < prog->NumShaders; i++) {
|
||||
if (prog->Shaders[i]->CompileStatus == compile_success) {
|
||||
if (prog->Shaders[i]->CompileStatus == compiled_no_opts) {
|
||||
disk_cache_put_key(cache, prog->Shaders[i]->sha1);
|
||||
if (ctx->_Shader->Flags & GLSL_CACHE_INFO) {
|
||||
_mesa_sha1_format(sha1_buf, prog->Shaders[i]->sha1);
|
||||
|
|
|
@ -2504,7 +2504,8 @@ enum gl_compile_status
|
|||
{
|
||||
compile_failure = 0,
|
||||
compile_success,
|
||||
compile_skipped
|
||||
compile_skipped,
|
||||
compiled_no_opts
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue