|
|
@@ -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); |
|
|
|
|
|
|
|
/* 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 (!state->error && !shader->ir->is_empty()) { |
|
|
|
assign_subroutine_indexes(shader, state); |
|
|
|
lower_subroutine(shader->ir, state); |
|
|
|
|
|
|
|
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; |