diff --git a/src/compiler/glsl/ast_to_hir.cpp b/src/compiler/glsl/ast_to_hir.cpp index bee30a241c3..2ab21f2ffaa 100644 --- a/src/compiler/glsl/ast_to_hir.cpp +++ b/src/compiler/glsl/ast_to_hir.cpp @@ -941,6 +941,7 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state, if (lhs_var) lhs_var->data.assigned = true; + bool omit_assignment = false; if (!error_emitted) { if (non_lvalue_description != NULL) { _mesa_glsl_error(&lhs_loc, state, @@ -957,10 +958,15 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state, * no such distinction, that is why this check here is limited to * buffer variables alone. */ - _mesa_glsl_error(&lhs_loc, state, - "assignment to read-only variable '%s'", - lhs_var->name); - error_emitted = true; + + if (state->ignore_write_to_readonly_var) + omit_assignment = true; + else { + _mesa_glsl_error(&lhs_loc, state, + "assignment to read-only variable '%s'", + lhs_var->name); + error_emitted = true; + } } else if (lhs->type->is_array() && !state->check_version(state->allow_glsl_120_subset_in_110 ? 110 : 120, 300, &lhs_loc, @@ -1018,6 +1024,11 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state, error_emitted = true; } + if (omit_assignment) { + *out_rvalue = needs_rvalue ? ir_rvalue::error_value(ctx) : NULL; + return error_emitted; + } + /* Most callers of do_assignment (assign, add_assign, pre_inc/dec, * but not post_inc) need the converted assigned value as an rvalue * to handle things like: diff --git a/src/compiler/glsl/glsl_parser_extras.cpp b/src/compiler/glsl/glsl_parser_extras.cpp index a02e3d8be92..44c041633d2 100644 --- a/src/compiler/glsl/glsl_parser_extras.cpp +++ b/src/compiler/glsl/glsl_parser_extras.cpp @@ -321,6 +321,8 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, ctx->Const.AllowGLSL120SubsetIn110; this->allow_builtin_variable_redeclaration = ctx->Const.AllowGLSLBuiltinVariableRedeclaration; + this->ignore_write_to_readonly_var = + ctx->Const.GLSLIgnoreWriteToReadonlyVar; this->cs_input_local_size_variable_specified = false; diff --git a/src/compiler/glsl/glsl_parser_extras.h b/src/compiler/glsl/glsl_parser_extras.h index 18e3f86a64f..6a7bf1747bb 100644 --- a/src/compiler/glsl/glsl_parser_extras.h +++ b/src/compiler/glsl/glsl_parser_extras.h @@ -945,6 +945,7 @@ struct _mesa_glsl_parse_state { bool allow_extension_directive_midshader; bool allow_glsl_120_subset_in_110; bool allow_builtin_variable_redeclaration; + bool ignore_write_to_readonly_var; /** * Known subroutine type declarations. diff --git a/src/gallium/auxiliary/pipe-loader/driinfo_gallium.h b/src/gallium/auxiliary/pipe-loader/driinfo_gallium.h index 2fa2a37f6d9..95bd3a7c057 100644 --- a/src/gallium/auxiliary/pipe-loader/driinfo_gallium.h +++ b/src/gallium/auxiliary/pipe-loader/driinfo_gallium.h @@ -29,6 +29,7 @@ DRI_CONF_SECTION_DEBUG DRI_CONF_ALLOW_HIGHER_COMPAT_VERSION(false) DRI_CONF_FORCE_GLSL_ABS_SQRT(false) DRI_CONF_GLSL_CORRECT_DERIVATIVES_AFTER_DISCARD(false) + DRI_CONF_GLSL_IGNORE_WRITE_TO_READONLY_VAR(false) DRI_CONF_ALLOW_DRAW_OUT_OF_ORDER(false) DRI_CONF_ALLOW_INCORRECT_PRIMITIVE_ID(false) DRI_CONF_FORCE_COMPAT_PROFILE(false) diff --git a/src/gallium/frontends/dri/dri_screen.c b/src/gallium/frontends/dri/dri_screen.c index e8d95fcbe0b..b565a1fe8ec 100644 --- a/src/gallium/frontends/dri/dri_screen.c +++ b/src/gallium/frontends/dri/dri_screen.c @@ -86,6 +86,8 @@ dri_fill_st_options(struct dri_screen *screen) driQueryOptionb(optionCache, "allow_glsl_builtin_variable_redeclaration"); options->allow_higher_compat_version = driQueryOptionb(optionCache, "allow_higher_compat_version"); + options->glsl_ignore_write_to_readonly_var = + driQueryOptionb(optionCache, "glsl_ignore_write_to_readonly_var"); options->glsl_zero_init = driQueryOptionb(optionCache, "glsl_zero_init"); options->force_integer_tex_nearest = driQueryOptionb(optionCache, "force_integer_tex_nearest"); diff --git a/src/gallium/include/frontend/api.h b/src/gallium/include/frontend/api.h index 6141ffadea1..d0e13d40f4d 100644 --- a/src/gallium/include/frontend/api.h +++ b/src/gallium/include/frontend/api.h @@ -227,6 +227,7 @@ struct st_config_options bool allow_glsl_relaxed_es; bool allow_glsl_builtin_variable_redeclaration; bool allow_higher_compat_version; + bool glsl_ignore_write_to_readonly_var; bool glsl_zero_init; bool vs_position_always_invariant; bool force_glsl_abs_sqrt; diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 2a37f9d1ea5..2fa16354d40 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -3959,6 +3959,12 @@ struct gl_constants */ GLboolean ForceGLSLAbsSqrt; + /** + * Forces the GLSL compiler to ignore writes to readonly vars rather than + * throwing an error. + */ + GLboolean GLSLIgnoreWriteToReadonlyVar; + /** * Types of variable to default initialized to zero. Supported values are: * - 0: no zero initialization diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c index 075bb28e14d..cd18ac9a4e2 100644 --- a/src/mesa/state_tracker/st_extensions.c +++ b/src/mesa/state_tracker/st_extensions.c @@ -1194,6 +1194,8 @@ void st_init_extensions(struct pipe_screen *screen, consts->AllowGLSLCrossStageInterpolationMismatch = options->allow_glsl_cross_stage_interpolation_mismatch; + consts->GLSLIgnoreWriteToReadonlyVar = options->glsl_ignore_write_to_readonly_var; + consts->PrimitiveRestartFixedIndex = screen->get_param(screen, PIPE_CAP_PRIMITIVE_RESTART_FIXED_INDEX); diff --git a/src/util/driconf.h b/src/util/driconf.h index 248ab2d6ceb..1c2515e2964 100644 --- a/src/util/driconf.h +++ b/src/util/driconf.h @@ -204,6 +204,10 @@ DRI_CONF_OPT_B(glsl_correct_derivatives_after_discard, def, \ "Implicit and explicit derivatives after a discard behave as if the discard didn't happen") +#define DRI_CONF_GLSL_IGNORE_WRITE_TO_READONLY_VAR(def) \ + DRI_CONF_OPT_B(glsl_ignore_write_to_readonly_var, def, \ + "Forces the GLSL compiler to ignore writes to readonly vars rather than throwing an error") + #define DRI_CONF_ALLOW_GLSL_CROSS_STAGE_INTERPOLATION_MISMATCH(def) \ DRI_CONF_OPT_B(allow_glsl_cross_stage_interpolation_mismatch, def, \ "Allow interpolation qualifier mismatch across shader stages")