gl_shader_stage stage,
void *mem_ctx)
: ctx(_ctx), cs_input_local_size_specified(false), cs_input_local_size(),
- switch_state()
+ switch_state(), warnings_enabled(true)
{
assert(stage < MESA_SHADER_STAGES);
this->stage = stage;
/* Set default language version and extensions */
this->language_version = 110;
this->forced_language_version = ctx->Const.ForceGLSLVersion;
- this->zero_init = ctx->Const.GLSLZeroInit;
+ if (ctx->Const.GLSLZeroInit == 1) {
+ this->zero_init = (1u << ir_var_auto) | (1u << ir_var_temporary) | (1u << ir_var_shader_out);
+ } else if (ctx->Const.GLSLZeroInit == 2) {
+ this->zero_init = (1u << ir_var_auto) | (1u << ir_var_temporary) | (1u << ir_var_function_out);
+ } else {
+ this->zero_init = 0;
+ }
this->gl_version = 20;
this->compat_shader = true;
this->es_shader = false;
this->Const.MaxVertexOutputComponents = ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents;
this->Const.MaxGeometryInputComponents = ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxInputComponents;
this->Const.MaxGeometryOutputComponents = ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxOutputComponents;
+ this->Const.MaxGeometryShaderInvocations = ctx->Const.MaxGeometryShaderInvocations;
this->Const.MaxFragmentInputComponents = ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxInputComponents;
this->Const.MaxGeometryTextureImageUnits = ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits;
this->Const.MaxGeometryOutputVertices = ctx->Const.MaxGeometryOutputVertices;
this->current_function = NULL;
this->toplevel_ir = NULL;
this->found_return = false;
+ this->found_begin_interlock = false;
+ this->found_end_interlock = false;
this->all_invariant = false;
this->user_structures = NULL;
this->num_user_structures = 0;
sizeof(this->atomic_counter_offsets));
this->allow_extension_directive_midshader =
ctx->Const.AllowGLSLExtensionDirectiveMidShader;
+ this->allow_glsl_120_subset_in_110 =
+ ctx->Const.AllowGLSL120SubsetIn110;
this->allow_builtin_variable_redeclaration =
ctx->Const.AllowGLSLBuiltinVariableRedeclaration;
+ this->allow_layout_qualifier_on_function_parameter =
+ ctx->Const.AllowLayoutQualifiersOnFunctionParameters;
this->cs_input_local_size_variable_specified = false;
/* Get the offset that the new message will be written to. */
int msg_offset = strlen(state->info_log);
- ralloc_asprintf_append(&state->info_log, "%u:%u(%u): %s: ",
- locp->source,
- locp->first_line,
- locp->first_column,
- error ? "error" : "warning");
+ if (locp->path) {
+ ralloc_asprintf_append(&state->info_log, "\"%s\"", locp->path);
+ } else {
+ ralloc_asprintf_append(&state->info_log, "%u", locp->source);
+ }
+ ralloc_asprintf_append(&state->info_log, ":%u(%u): %s: ",
+ locp->first_line, locp->first_column,
+ error ? "error" : "warning");
+
ralloc_vasprintf_append(&state->info_log, fmt, ap);
const char *const msg = &state->info_log[msg_offset];
_mesa_glsl_warning(const YYLTYPE *locp, _mesa_glsl_parse_state *state,
const char *fmt, ...)
{
- va_list ap;
+ if (state->warnings_enabled) {
+ va_list ap;
- va_start(ap, fmt);
- _mesa_glsl_msg(locp, state, MESA_DEBUG_TYPE_OTHER, fmt, ap);
- va_end(ap);
+ va_start(ap, fmt);
+ _mesa_glsl_msg(locp, state, MESA_DEBUG_TYPE_OTHER, fmt, ap);
+ va_end(ap);
+ }
}
/** Checks if the context supports a user-facing extension */
#define EXT(name_str, driver_cap, ...) \
-static MAYBE_UNUSED bool \
+static UNUSED bool \
has_##name_str(const struct gl_context *ctx, gl_api api, uint8_t version) \
{ \
return ctx->Extensions.driver_cap && (version >= \
EXT(ARB_shader_texture_lod),
EXT(ARB_shader_viewport_layer_array),
EXT(ARB_shading_language_420pack),
+ EXT(ARB_shading_language_include),
EXT(ARB_shading_language_packing),
EXT(ARB_tessellation_shader),
EXT(ARB_texture_cube_map_array),
/* All other extensions go here, sorted alphabetically.
*/
EXT(AMD_conservative_depth),
+ EXT(AMD_gpu_shader_int64),
EXT(AMD_shader_stencil_export),
EXT(AMD_shader_trinary_minmax),
+ EXT(AMD_texture_texture4),
EXT(AMD_vertex_shader_layer),
EXT(AMD_vertex_shader_viewport_index),
EXT(ANDROID_extension_pack_es31a),
EXT(EXT_blend_func_extended),
+ EXT(EXT_demote_to_helper_invocation),
EXT(EXT_frag_depth),
EXT(EXT_draw_buffers),
+ EXT(EXT_draw_instanced),
EXT(EXT_clip_cull_distance),
EXT(EXT_geometry_point_size),
EXT_AEP(EXT_geometry_shader),
+ EXT(EXT_gpu_shader4),
EXT_AEP(EXT_gpu_shader5),
EXT_AEP(EXT_primitive_bounding_box),
EXT(EXT_separate_shader_objects),
EXT(EXT_shader_framebuffer_fetch),
EXT(EXT_shader_framebuffer_fetch_non_coherent),
+ EXT(EXT_shader_group_vote),
+ EXT(EXT_shader_image_load_formatted),
+ EXT(EXT_shader_image_load_store),
+ EXT(EXT_shader_implicit_conversions),
EXT(EXT_shader_integer_mix),
EXT_AEP(EXT_shader_io_blocks),
EXT(EXT_shader_samples_identical),
EXT(EXT_texture_array),
EXT_AEP(EXT_texture_buffer),
EXT_AEP(EXT_texture_cube_map_array),
+ EXT(EXT_texture_query_lod),
+ EXT(EXT_texture_shadow_lod),
EXT(INTEL_conservative_rasterization),
+ EXT(INTEL_shader_atomic_float_minmax),
+ EXT(INTEL_shader_integer_functions2),
EXT(MESA_shader_integer_functions),
+ EXT(NV_compute_shader_derivatives),
EXT(NV_fragment_shader_interlock),
EXT(NV_image_formats),
EXT(NV_shader_atomic_float),
+ EXT(NV_viewport_array2),
};
#undef EXT
}
/* If the aggregate is a struct, recursively set its fields' types. */
- } else if (type->is_record()) {
+ } else if (type->is_struct()) {
exec_node *expr_node = ai->expressions.get_head_raw();
/* Iterate through the struct's fields. */
}
+void
+ast_demote_statement::print(void) const
+{
+ printf("demote; ");
+}
+
+
void
ast_selection_statement::print(void) const
{
struct _mesa_glsl_parse_state *state)
{
/* Should have been prevented by the parser. */
- if (shader->Stage == MESA_SHADER_TESS_CTRL ||
- shader->Stage == MESA_SHADER_VERTEX) {
- assert(!state->in_qualifier->flags.i);
- } else if (shader->Stage != MESA_SHADER_GEOMETRY &&
- shader->Stage != MESA_SHADER_TESS_EVAL) {
+ if (shader->Stage != MESA_SHADER_GEOMETRY &&
+ shader->Stage != MESA_SHADER_TESS_EVAL &&
+ shader->Stage != MESA_SHADER_COMPUTE) {
assert(!state->in_qualifier->flags.i);
}
/* Should have been prevented by the parser. */
assert(!state->cs_input_local_size_specified);
assert(!state->cs_input_local_size_variable_specified);
+ assert(state->cs_derivative_group == DERIVATIVE_GROUP_NONE);
}
if (shader->Stage != MESA_SHADER_FRAGMENT) {
&invocations, false)) {
YYLTYPE loc = state->in_qualifier->invocations->get_location();
- if (invocations > MAX_GEOMETRY_SHADER_INVOCATIONS) {
+ if (invocations > state->Const.MaxGeometryShaderInvocations) {
_mesa_glsl_error(&loc, state,
"invocations (%d) exceeds "
"GL_MAX_GEOMETRY_SHADER_INVOCATIONS",
shader->info.Comp.LocalSizeVariable =
state->cs_input_local_size_variable_specified;
+
+ shader->info.Comp.DerivativeGroup = state->cs_derivative_group;
+
+ if (state->NV_compute_shader_derivatives_enable) {
+ /* We allow multiple cs_input_layout nodes, but do not store them in
+ * a convenient place, so for now live with an empty location error.
+ */
+ YYLTYPE loc = {0};
+ if (shader->info.Comp.DerivativeGroup == DERIVATIVE_GROUP_QUADS) {
+ if (shader->info.Comp.LocalSize[0] % 2 != 0) {
+ _mesa_glsl_error(&loc, state, "derivative_group_quadsNV must be used with a "
+ "local group size whose first dimension "
+ "is a multiple of 2\n");
+ }
+ if (shader->info.Comp.LocalSize[1] % 2 != 0) {
+ _mesa_glsl_error(&loc, state, "derivative_group_quadsNV must be used with a "
+ "local group size whose second dimension "
+ "is a multiple of 2\n");
+ }
+ } else if (shader->info.Comp.DerivativeGroup == DERIVATIVE_GROUP_LINEAR) {
+ if ((shader->info.Comp.LocalSize[0] *
+ shader->info.Comp.LocalSize[1] *
+ shader->info.Comp.LocalSize[2]) % 4 != 0) {
+ _mesa_glsl_error(&loc, state, "derivative_group_linearNV must be used with a "
+ "local group size whose total number of invocations "
+ "is a multiple of 4\n");
+ }
+ }
+ }
+
break;
case MESA_SHADER_FRAGMENT:
shader->bindless_image = state->bindless_image_specified;
shader->bound_sampler = state->bound_sampler_specified;
shader->bound_image = state->bound_image_specified;
+ shader->redeclares_gl_layer = state->redeclares_gl_layer;
+ shader->layer_viewport_relative = state->layer_viewport_relative;
}
/* src can be NULL if only the symbols found in the exec_list should be
shader->symbols);
}
-void
-_mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader,
- bool dump_ast, bool dump_hir, bool force_recompile)
+static bool
+can_skip_compile(struct gl_context *ctx, struct gl_shader *shader,
+ const char *source, bool force_recompile,
+ bool source_has_shader_include)
{
- const char *source = force_recompile && shader->FallbackSource ?
- shader->FallbackSource : shader->Source;
-
if (!force_recompile) {
if (ctx->Cache) {
char buf[41];
shader->CompileStatus = COMPILE_SKIPPED;
free((void *)shader->FallbackSource);
- shader->FallbackSource = NULL;
- return;
+
+ /* Copy pre-processed shader include to fallback source otherwise
+ * we have no guarantee the shader include source tree has not
+ * changed.
+ */
+ shader->FallbackSource = source_has_shader_include ?
+ strdup(source) : NULL;
+ return true;
}
}
} else {
/* We should only ever end up here if a re-compile has been forced by a
* shader cache miss. In which case we can skip the compile if its
- * already be done by a previous fallback or the initial compile call.
+ * already been done by a previous fallback or the initial compile call.
*/
if (shader->CompileStatus == COMPILE_SUCCESS)
- return;
-
- if (shader->CompileStatus == COMPILED_NO_OPTS) {
- opt_shader_and_create_symbol_table(ctx,
- NULL, /* source_symbols */
- shader);
- shader->CompileStatus = COMPILE_SUCCESS;
- return;
- }
+ return true;
}
- struct _mesa_glsl_parse_state *state =
+ return false;
+}
+
+void
+_mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader,
+ bool dump_ast, bool dump_hir, bool force_recompile)
+{
+ const char *source = force_recompile && shader->FallbackSource ?
+ shader->FallbackSource : shader->Source;
+
+ /* Note this will be true for shaders the have #include inside comments
+ * however that should be rare enough not to worry about.
+ */
+ bool source_has_shader_include =
+ strstr(source, "#include") == NULL ? false : true;
+
+ /* If there was no shader include we can check the shader cache and skip
+ * compilation before we run the preprocessor. We never skip compiling
+ * shaders that use ARB_shading_language_include because we would need to
+ * keep duplicate copies of the shader include source tree and paths.
+ */
+ if (!source_has_shader_include &&
+ can_skip_compile(ctx, shader, source, force_recompile, false))
+ return;
+
+ struct _mesa_glsl_parse_state *state =
new(shader) _mesa_glsl_parse_state(ctx, shader->Stage, shader);
if (ctx->Const.GenerateTemporaryNames)
(void) p_atomic_cmpxchg(&ir_variable::temporaries_allocate_names,
false, true);
- state->error = glcpp_preprocess(state, &source, &state->info_log,
- add_builtin_defines, state, ctx);
+ if (!source_has_shader_include || !force_recompile) {
+ state->error = glcpp_preprocess(state, &source, &state->info_log,
+ add_builtin_defines, state, ctx);
+ }
+
+ /* Now that we have run the preprocessor we can check the shader cache and
+ * skip compilation if possible for those shaders that contained a shader
+ * include.
+ */
+ if (source_has_shader_include &&
+ can_skip_compile(ctx, shader, source, force_recompile, true))
+ return;
if (!state->error) {
_mesa_glsl_lexer_ctor(state, source);
shader->Version = state->language_version;
shader->IsES = state->es_shader;
+ struct gl_shader_compiler_options *options =
+ &ctx->Const.ShaderCompilerOptions[shader->Stage];
+
if (!state->error && !shader->ir->is_empty()) {
+ if (options->LowerPrecisionFloat16 || options->LowerPrecisionInt16)
+ lower_precision(options, shader->ir);
+ lower_builtins(shader->ir);
assign_subroutine_indexes(state);
lower_subroutine(shader->ir, state);
-
- if (!ctx->Cache || force_recompile)
- opt_shader_and_create_symbol_table(ctx, state->symbols, shader);
- else {
- reparent_ir(shader->ir, shader->ir);
- shader->CompileStatus = COMPILED_NO_OPTS;
- }
+ opt_shader_and_create_symbol_table(ctx, state->symbols, shader);
}
if (!force_recompile) {
free((void *)shader->FallbackSource);
- shader->FallbackSource = NULL;
+
+ /* Copy pre-processed shader include to fallback source otherwise we
+ * have no guarantee the shader include source tree has not changed.
+ */
+ shader->FallbackSource = source_has_shader_include ?
+ strdup(source) : NULL;
}
delete state->symbols;
ralloc_free(state);
+
+ if (ctx->Cache && shader->CompileStatus == COMPILE_SUCCESS) {
+ char sha1_buf[41];
+ disk_cache_put_key(ctx->Cache, shader->sha1);
+ if (ctx->_Shader->Flags & GLSL_CACHE_INFO) {
+ _mesa_sha1_format(sha1_buf, shader->sha1);
+ fprintf(stderr, "marking shader: %s\n", sha1_buf);
+ }
+ }
}
} /* extern "C" */
bool native_integers)
{
const bool debug = false;
- GLboolean progress = GL_FALSE;
+ bool progress = false;
#define OPT(PASS, ...) do { \
if (debug) { \
OPT(lower_vector_insert, ir, false);
OPT(optimize_swizzles, ir);
- OPT(optimize_split_arrays, ir, linked);
+ /* Some drivers only call do_common_optimization() once rather than in a
+ * loop, and split arrays causes each element of a constant array to
+ * dereference is own copy of the entire array initilizer. This IR is not
+ * something that can be generated manually in a shader and is not
+ * accounted for by NIR optimisations, the result is an exponential slow
+ * down in compilation speed as a constant arrays element count grows. To
+ * avoid that here we make sure to always clean up the mess split arrays
+ * causes to constant arrays.
+ */
+ bool array_split = optimize_split_arrays(ir, linked);
+ if (array_split)
+ do_constant_propagation(ir);
+ progress |= array_split;
+
OPT(optimize_redundant_jumps, ir);
if (options->MaxUnrollIterations) {
return progress;
}
-
-extern "C" {
-
-/**
- * To be called at GL teardown time, this frees compiler datastructures.
- *
- * After calling this, any previously compiled shaders and shader
- * programs would be invalid. So this should happen at approximately
- * program exit.
- */
-void
-_mesa_destroy_shader_compiler(void)
-{
- _mesa_destroy_shader_compiler_caches();
-
- _mesa_glsl_release_types();
-}
-
-/**
- * Releases compiler caches to trade off performance for memory.
- *
- * Intended to be used with glReleaseShaderCompiler().
- */
-void
-_mesa_destroy_shader_compiler_caches(void)
-{
- _mesa_glsl_release_builtin_functions();
-}
-
-}