X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fcompiler%2Fglsl%2Flinker.cpp;h=52646752c977c08426de190954204198467a521d;hb=5d2b2b59c451915c0b11184ae47c0673fdff3146;hp=977d91f5118b129f31d04ba8574b42de4190acf2;hpb=d4a3b09c4bfd955dab92dbb27ab8bc273d18e649;p=mesa.git diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp index 977d91f5118..52646752c97 100644 --- a/src/compiler/glsl/linker.cpp +++ b/src/compiler/glsl/linker.cpp @@ -86,7 +86,7 @@ #include "util/u_string.h" #include "util/u_math.h" -#include "main/imports.h" + #include "main/shaderobj.h" #include "main/enums.h" #include "main/mtypes.h" @@ -260,6 +260,8 @@ public: class array_resize_visitor : public deref_type_updater { public: + using deref_type_updater::visit; + unsigned num_vertices; gl_shader_program *prog; gl_shader_stage stage; @@ -330,7 +332,7 @@ public: invalid_stream_id(0), invalid_stream_id_from_emit_vertex(false), end_primitive_found(false), - uses_non_zero_stream(false) + used_streams(0) { /* empty */ } @@ -351,8 +353,7 @@ public: return visit_stop; } - if (stream_id != 0) - uses_non_zero_stream = true; + used_streams |= 1 << stream_id; return visit_continue; } @@ -375,8 +376,7 @@ public: return visit_stop; } - if (stream_id != 0) - uses_non_zero_stream = true; + used_streams |= 1 << stream_id; return visit_continue; } @@ -397,9 +397,9 @@ public: return invalid_stream_id; } - bool uses_streams() + unsigned active_stream_mask() { - return uses_non_zero_stream; + return used_streams; } bool uses_end_primitive() @@ -412,7 +412,7 @@ private: int invalid_stream_id; bool invalid_stream_id_from_emit_vertex; bool end_primitive_found; - bool uses_non_zero_stream; + unsigned used_streams; }; /* Class that finds array derefs and check if indexes are dynamic. */ @@ -809,7 +809,7 @@ validate_geometry_shader_emissions(struct gl_context *ctx, emit_vertex.error_stream(), ctx->Const.MaxVertexStreams - 1); } - prog->Geom.UsesStreams = emit_vertex.uses_streams(); + prog->Geom.ActiveStreamMask = emit_vertex.active_stream_mask(); prog->Geom.UsesEndPrimitive = emit_vertex.uses_end_primitive(); /* From the ARB_gpu_shader5 spec: @@ -832,11 +832,11 @@ validate_geometry_shader_emissions(struct gl_context *ctx, * Since we can call EmitVertex() and EndPrimitive() when we output * primitives other than points, calling EmitStreamVertex(0) or * EmitEndPrimitive(0) should not produce errors. This it also what Nvidia - * does. Currently we only set prog->Geom.UsesStreams to TRUE when - * EmitStreamVertex() or EmitEndPrimitive() are called with a non-zero + * does. We can use prog->Geom.ActiveStreamMask to check whether only the + * first (zero) stream is active. * stream. */ - if (prog->Geom.UsesStreams && + if (prog->Geom.ActiveStreamMask & ~(1 << 0) && sh->Program->info.gs.output_primitive != GL_POINTS) { linker_error(prog, "EmitStreamVertex(n) and EndStreamPrimitive(n) " "with n>0 requires point output\n"); @@ -1062,9 +1062,13 @@ cross_validate_globals(struct gl_context *ctx, struct gl_shader_program *prog, * no vendor actually implemented that behavior. The 4.20 * behavior matches the implemented behavior of at least one other * vendor, so we'll implement that for all GLSL versions. + * If (at least) one of these constant expressions is implicit, + * because it was added by glsl_zero_init, we skip the verification. */ if (var->constant_initializer != NULL) { - if (existing->constant_initializer != NULL) { + if (existing->constant_initializer != NULL && + !existing->data.is_implicit_initializer && + !var->data.is_implicit_initializer) { if (!var->constant_initializer->has_value(existing->constant_initializer)) { linker_error(prog, "initializers for %s " "`%s' have differing values\n", @@ -1076,7 +1080,8 @@ cross_validate_globals(struct gl_context *ctx, struct gl_shader_program *prog, * not have an initializer but a later instance does, * replace the former with the later. */ - variables->replace_variable(existing->name, var); + if (!var->data.is_implicit_initializer) + variables->replace_variable(existing->name, var); } } @@ -1506,6 +1511,8 @@ move_non_declarations(exec_list *instructions, exec_node *last, */ class array_sizing_visitor : public deref_type_updater { public: + using deref_type_updater::visit; + array_sizing_visitor() : mem_ctx(ralloc_context(NULL)), unnamed_interfaces(_mesa_pointer_hash_table_create(NULL)) @@ -1812,6 +1819,40 @@ link_bindless_layout_qualifiers(struct gl_shader_program *prog, } } +/** + * Check for conflicting viewport_relative settings across shaders, and sets + * the value for the linked shader. + */ +static void +link_layer_viewport_relative_qualifier(struct gl_shader_program *prog, + struct gl_program *gl_prog, + struct gl_shader **shader_list, + unsigned num_shaders) +{ + unsigned i; + + /* Find first shader with explicit layer declaration */ + for (i = 0; i < num_shaders; i++) { + if (shader_list[i]->redeclares_gl_layer) { + gl_prog->info.layer_viewport_relative = + shader_list[i]->layer_viewport_relative; + break; + } + } + + /* Now make sure that each subsequent shader's explicit layer declaration + * matches the first one's. + */ + for (; i < num_shaders; i++) { + if (shader_list[i]->redeclares_gl_layer && + shader_list[i]->layer_viewport_relative != + gl_prog->info.layer_viewport_relative) { + linker_error(prog, "all gl_Layer redeclarations must have identical " + "viewport_relative settings"); + } + } +} + /** * Performs the cross-validation of tessellation control shader vertices and * layout qualifiers for the attached tessellation control shaders, @@ -2429,9 +2470,7 @@ link_intrastage_shaders(void *mem_ctx, /* Create program and attach it to the linked shader */ struct gl_program *gl_prog = - ctx->Driver.NewProgram(ctx, - _mesa_shader_stage_to_program(shader_list[0]->Stage), - prog->Name, false); + ctx->Driver.NewProgram(ctx, shader_list[0]->Stage, prog->Name, false); if (!gl_prog) { prog->data->LinkStatus = LINKING_FAILURE; _mesa_delete_linked_shader(ctx, linked); @@ -2457,6 +2496,8 @@ link_intrastage_shaders(void *mem_ctx, link_bindless_layout_qualifiers(prog, shader_list, num_shaders); + link_layer_viewport_relative_qualifier(prog, gl_prog, shader_list, num_shaders); + populate_symbol_table(linked, shader_list[0]->symbols); /* The pointer to the main function in the final linked shader (i.e., the @@ -2530,6 +2571,7 @@ link_intrastage_shaders(void *mem_ctx, for (unsigned i = 0; i < num_ubo_blocks; i++) { linked->Program->sh.UniformBlocks[i] = &ubo_blocks[i]; } + linked->Program->sh.NumUniformBlocks = num_ubo_blocks; linked->Program->info.num_ubos = num_ubo_blocks; /* Copy ssbo blocks to linked shader list */ @@ -3321,135 +3363,6 @@ store_fragdepth_layout(struct gl_shader_program *prog) } } -/** - * Validate the resources used by a program versus the implementation limits - */ -static void -check_resources(struct gl_context *ctx, struct gl_shader_program *prog) -{ - unsigned total_uniform_blocks = 0; - unsigned total_shader_storage_blocks = 0; - - for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { - struct gl_linked_shader *sh = prog->_LinkedShaders[i]; - - if (sh == NULL) - continue; - - if (sh->num_uniform_components > - ctx->Const.Program[i].MaxUniformComponents) { - if (ctx->Const.GLSLSkipStrictMaxUniformLimitCheck) { - linker_warning(prog, "Too many %s shader default uniform block " - "components, but the driver will try to optimize " - "them out; this is non-portable out-of-spec " - "behavior\n", - _mesa_shader_stage_to_string(i)); - } else { - linker_error(prog, "Too many %s shader default uniform block " - "components\n", - _mesa_shader_stage_to_string(i)); - } - } - - if (sh->num_combined_uniform_components > - ctx->Const.Program[i].MaxCombinedUniformComponents) { - if (ctx->Const.GLSLSkipStrictMaxUniformLimitCheck) { - linker_warning(prog, "Too many %s shader uniform components, " - "but the driver will try to optimize them out; " - "this is non-portable out-of-spec behavior\n", - _mesa_shader_stage_to_string(i)); - } else { - linker_error(prog, "Too many %s shader uniform components\n", - _mesa_shader_stage_to_string(i)); - } - } - - total_shader_storage_blocks += sh->Program->info.num_ssbos; - total_uniform_blocks += sh->Program->info.num_ubos; - } - - if (total_uniform_blocks > ctx->Const.MaxCombinedUniformBlocks) { - linker_error(prog, "Too many combined uniform blocks (%d/%d)\n", - total_uniform_blocks, ctx->Const.MaxCombinedUniformBlocks); - } - - if (total_shader_storage_blocks > ctx->Const.MaxCombinedShaderStorageBlocks) { - linker_error(prog, "Too many combined shader storage blocks (%d/%d)\n", - total_shader_storage_blocks, - ctx->Const.MaxCombinedShaderStorageBlocks); - } - - for (unsigned i = 0; i < prog->data->NumUniformBlocks; i++) { - if (prog->data->UniformBlocks[i].UniformBufferSize > - ctx->Const.MaxUniformBlockSize) { - linker_error(prog, "Uniform block %s too big (%d/%d)\n", - prog->data->UniformBlocks[i].Name, - prog->data->UniformBlocks[i].UniformBufferSize, - ctx->Const.MaxUniformBlockSize); - } - } - - for (unsigned i = 0; i < prog->data->NumShaderStorageBlocks; i++) { - if (prog->data->ShaderStorageBlocks[i].UniformBufferSize > - ctx->Const.MaxShaderStorageBlockSize) { - linker_error(prog, "Shader storage block %s too big (%d/%d)\n", - prog->data->ShaderStorageBlocks[i].Name, - prog->data->ShaderStorageBlocks[i].UniformBufferSize, - ctx->Const.MaxShaderStorageBlockSize); - } - } -} - -static void -link_calculate_subroutine_compat(struct gl_shader_program *prog) -{ - unsigned mask = prog->data->linked_stages; - while (mask) { - const int i = u_bit_scan(&mask); - struct gl_program *p = prog->_LinkedShaders[i]->Program; - - for (unsigned j = 0; j < p->sh.NumSubroutineUniformRemapTable; j++) { - if (p->sh.SubroutineUniformRemapTable[j] == INACTIVE_UNIFORM_EXPLICIT_LOCATION) - continue; - - struct gl_uniform_storage *uni = p->sh.SubroutineUniformRemapTable[j]; - - if (!uni) - continue; - - int count = 0; - if (p->sh.NumSubroutineFunctions == 0) { - linker_error(prog, "subroutine uniform %s defined but no valid functions found\n", uni->type->name); - continue; - } - for (unsigned f = 0; f < p->sh.NumSubroutineFunctions; f++) { - struct gl_subroutine_function *fn = &p->sh.SubroutineFunctions[f]; - for (int k = 0; k < fn->num_compat_types; k++) { - if (fn->types[k] == uni->type) { - count++; - break; - } - } - } - uni->num_compatible_subroutines = count; - } - } -} - -static void -check_subroutine_resources(struct gl_shader_program *prog) -{ - unsigned mask = prog->data->linked_stages; - while (mask) { - const int i = u_bit_scan(&mask); - struct gl_program *p = prog->_LinkedShaders[i]->Program; - - if (p->sh.NumSubroutineUniformRemapTable > MAX_SUBROUTINE_UNIFORM_LOCATIONS) { - linker_error(prog, "Too many %s shader subroutine uniforms\n", - _mesa_shader_stage_to_string(i)); - } - } -} /** * Validate shader image resources. */ @@ -4118,226 +4031,14 @@ add_fragdata_arrays(const struct gl_context *ctx, return true; } -static char* -get_top_level_name(const char *name) -{ - const char *first_dot = strchr(name, '.'); - const char *first_square_bracket = strchr(name, '['); - int name_size = 0; - - /* The ARB_program_interface_query spec says: - * - * "For the property TOP_LEVEL_ARRAY_SIZE, a single integer identifying - * the number of active array elements of the top-level shader storage - * block member containing to the active variable is written to - * . If the top-level block member is not declared as an - * array, the value one is written to . If the top-level block - * member is an array with no declared size, the value zero is written - * to ." - */ - - /* The buffer variable is on top level.*/ - if (!first_square_bracket && !first_dot) - name_size = strlen(name); - else if ((!first_square_bracket || - (first_dot && first_dot < first_square_bracket))) - name_size = first_dot - name; - else - name_size = first_square_bracket - name; - - return strndup(name, name_size); -} - -static char* -get_var_name(const char *name) -{ - const char *first_dot = strchr(name, '.'); - - if (!first_dot) - return strdup(name); - - return strndup(first_dot+1, strlen(first_dot) - 1); -} - -static bool -is_top_level_shader_storage_block_member(const char* name, - const char* interface_name, - const char* field_name) -{ - bool result = false; - - /* If the given variable is already a top-level shader storage - * block member, then return array_size = 1. - * We could have two possibilities: if we have an instanced - * shader storage block or not instanced. - * - * For the first, we check create a name as it was in top level and - * compare it with the real name. If they are the same, then - * the variable is already at top-level. - * - * Full instanced name is: interface name + '.' + var name + - * NULL character - */ - int name_length = strlen(interface_name) + 1 + strlen(field_name) + 1; - char *full_instanced_name = (char *) calloc(name_length, sizeof(char)); - if (!full_instanced_name) { - fprintf(stderr, "%s: Cannot allocate space for name\n", __func__); - return false; - } - - snprintf(full_instanced_name, name_length, "%s.%s", - interface_name, field_name); - - /* Check if its top-level shader storage block member of an - * instanced interface block, or of a unnamed interface block. - */ - if (strcmp(name, full_instanced_name) == 0 || - strcmp(name, field_name) == 0) - result = true; - - free(full_instanced_name); - return result; -} - -static int -get_array_size(struct gl_uniform_storage *uni, const glsl_struct_field *field, - char *interface_name, char *var_name) -{ - /* The ARB_program_interface_query spec says: - * - * "For the property TOP_LEVEL_ARRAY_SIZE, a single integer identifying - * the number of active array elements of the top-level shader storage - * block member containing to the active variable is written to - * . If the top-level block member is not declared as an - * array, the value one is written to . If the top-level block - * member is an array with no declared size, the value zero is written - * to ." - */ - if (is_top_level_shader_storage_block_member(uni->name, - interface_name, - var_name)) - return 1; - else if (field->type->is_unsized_array()) - return 0; - else if (field->type->is_array()) - return field->type->length; - - return 1; -} - -static int -get_array_stride(struct gl_context *ctx, struct gl_uniform_storage *uni, - const glsl_type *iface, const glsl_struct_field *field, - char *interface_name, char *var_name) -{ - /* The ARB_program_interface_query spec says: - * - * "For the property TOP_LEVEL_ARRAY_STRIDE, a single integer - * identifying the stride between array elements of the top-level - * shader storage block member containing the active variable is - * written to . For top-level block members declared as - * arrays, the value written is the difference, in basic machine units, - * between the offsets of the active variable for consecutive elements - * in the top-level array. For top-level block members not declared as - * an array, zero is written to ." - */ - if (field->type->is_array()) { - const enum glsl_matrix_layout matrix_layout = - glsl_matrix_layout(field->matrix_layout); - bool row_major = matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR; - const glsl_type *array_type = field->type->fields.array; - - if (is_top_level_shader_storage_block_member(uni->name, - interface_name, - var_name)) - return 0; - - if (GLSL_INTERFACE_PACKING_STD140 == - iface-> - get_internal_ifc_packing(ctx->Const.UseSTD430AsDefaultPacking)) { - if (array_type->is_struct() || array_type->is_array()) - return glsl_align(array_type->std140_size(row_major), 16); - else - return MAX2(array_type->std140_base_alignment(row_major), 16); - } else { - return array_type->std430_array_stride(row_major); - } - } - return 0; -} - -static void -calculate_array_size_and_stride(struct gl_context *ctx, - struct gl_shader_program *shProg, - struct gl_uniform_storage *uni) -{ - int block_index = uni->block_index; - int array_size = -1; - int array_stride = -1; - char *var_name = get_top_level_name(uni->name); - char *interface_name = - get_top_level_name(uni->is_shader_storage ? - shProg->data->ShaderStorageBlocks[block_index].Name : - shProg->data->UniformBlocks[block_index].Name); - - if (strcmp(var_name, interface_name) == 0) { - /* Deal with instanced array of SSBOs */ - char *temp_name = get_var_name(uni->name); - if (!temp_name) { - linker_error(shProg, "Out of memory during linking.\n"); - goto write_top_level_array_size_and_stride; - } - free(var_name); - var_name = get_top_level_name(temp_name); - free(temp_name); - if (!var_name) { - linker_error(shProg, "Out of memory during linking.\n"); - goto write_top_level_array_size_and_stride; - } - } - - for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { - const gl_linked_shader *sh = shProg->_LinkedShaders[i]; - if (sh == NULL) - continue; - - foreach_in_list(ir_instruction, node, sh->ir) { - ir_variable *var = node->as_variable(); - if (!var || !var->get_interface_type() || - var->data.mode != ir_var_shader_storage) - continue; - - const glsl_type *iface = var->get_interface_type(); - - if (strcmp(interface_name, iface->name) != 0) - continue; - - for (unsigned i = 0; i < iface->length; i++) { - const glsl_struct_field *field = &iface->fields.structure[i]; - if (strcmp(field->name, var_name) != 0) - continue; - - array_stride = get_array_stride(ctx, uni, iface, field, - interface_name, var_name); - array_size = get_array_size(uni, field, interface_name, var_name); - goto write_top_level_array_size_and_stride; - } - } - } -write_top_level_array_size_and_stride: - free(interface_name); - free(var_name); - uni->top_level_array_stride = array_stride; - uni->top_level_array_size = array_size; -} - /** * Builds up a list of program resources that point to existing * resource data. */ void build_program_resource_list(struct gl_context *ctx, - struct gl_shader_program *shProg) + struct gl_shader_program *shProg, + bool add_packed_varyings_only) { /* Rebuild resource list. */ if (shProg->data->ProgramResourceList) { @@ -4377,6 +4078,11 @@ build_program_resource_list(struct gl_context *ctx, return; } + if (add_packed_varyings_only) { + _mesa_set_destroy(resource_set, NULL); + return; + } + if (!add_fragdata_arrays(ctx, shProg, resource_set)) return; @@ -4426,20 +4132,8 @@ build_program_resource_list(struct gl_context *ctx, if (shProg->data->UniformStorage[i].hidden) continue; - uint8_t stageref = - build_stageref(shProg, shProg->data->UniformStorage[i].name, - ir_var_uniform); - - /* Add stagereferences for uniforms in a uniform block. */ bool is_shader_storage = shProg->data->UniformStorage[i].is_shader_storage; - int block_index = shProg->data->UniformStorage[i].block_index; - if (block_index != -1) { - stageref |= is_shader_storage ? - shProg->data->ShaderStorageBlocks[block_index].stageref : - shProg->data->UniformBlocks[block_index].stageref; - } - GLenum type = is_shader_storage ? GL_BUFFER_VARIABLE : GL_UNIFORM; if (!link_util_should_add_buffer_variable(shProg, &shProg->data->UniformStorage[i], @@ -4450,9 +4144,6 @@ build_program_resource_list(struct gl_context *ctx, continue; if (is_shader_storage) { - calculate_array_size_and_stride(ctx, shProg, - &shProg->data->UniformStorage[i]); - /* From the OpenGL 4.6 specification, 7.3.1.1 Naming Active Resources: * * "For an active shader storage block member declared as an array @@ -4485,6 +4176,7 @@ build_program_resource_list(struct gl_context *ctx, buffer_block_index = shProg->data->UniformStorage[i].block_index; } + uint8_t stageref = shProg->data->UniformStorage[i].active_shader_mask; if (!link_util_add_program_resource(shProg, resource_set, type, &shProg->data->UniformStorage[i], stageref)) return; @@ -4750,17 +4442,19 @@ static void link_and_validate_uniforms(struct gl_context *ctx, struct gl_shader_program *prog) { + assert(!ctx->Const.UseNIRGLSLLinker); + update_array_sizes(prog); link_assign_uniform_locations(prog, ctx); if (prog->data->LinkStatus == LINKING_FAILURE) return; - link_assign_atomic_counter_resources(ctx, prog); - link_calculate_subroutine_compat(prog); - check_resources(ctx, prog); - check_subroutine_resources(prog); + link_util_calculate_subroutine_compat(prog); + link_util_check_uniform_resources(ctx, prog); + link_util_check_subroutine_resources(prog); check_image_resources(ctx, prog); + link_assign_atomic_counter_resources(ctx, prog); link_check_atomic_counter_resources(ctx, prog); } @@ -4808,7 +4502,8 @@ link_varyings_and_uniforms(unsigned first, unsigned last, if (!link_varyings(prog, first, last, ctx, mem_ctx)) return false; - link_and_validate_uniforms(ctx, prog); + if (!ctx->Const.UseNIRGLSLLinker) + link_and_validate_uniforms(ctx, prog); if (!prog->data->LinkStatus) return false; @@ -5196,8 +4891,10 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) /* Call opts after lowering const arrays to copy propagate things. */ if (ctx->Const.GLSLLowerConstArrays && - lower_const_arrays_to_uniforms(prog->_LinkedShaders[i]->ir, i)) + lower_const_arrays_to_uniforms(prog->_LinkedShaders[i]->ir, i, + ctx->Const.Program[i].MaxUniformComponents)) linker_optimisation_loop(ctx, prog->_LinkedShaders[i]->ir, i); + } /* Validation for special cases where we allow sampler array indexing