X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fprogram%2Fir_to_mesa.cpp;h=f875c00238f2f4c614686e61055e00cf8998193b;hb=8a8742d32799eeb52eb7dbd4fd134a028b099d4d;hp=653b8221deedec203ad92d54f00b5730f74182b8;hpb=fd249c803e3ae2acb83f5e3b7152728e73228b7b;p=mesa.git diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 653b8221dee..f875c00238f 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -30,12 +30,12 @@ */ #include -#include "main/compiler.h" #include "main/macros.h" #include "main/mtypes.h" #include "main/shaderapi.h" #include "main/shaderobj.h" #include "main/uniforms.h" +#include "main/glspirv.h" #include "compiler/glsl/ast.h" #include "compiler/glsl/ir.h" #include "compiler/glsl/ir_expression_flattening.h" @@ -46,12 +46,13 @@ #include "compiler/glsl_types.h" #include "compiler/glsl/linker.h" #include "compiler/glsl/program.h" +#include "compiler/glsl/shader_cache.h" +#include "compiler/glsl/string_to_uint_map.h" #include "program/prog_instruction.h" #include "program/prog_optimize.h" #include "program/prog_print.h" #include "program/program.h" #include "program/prog_parameter.h" -#include "util/string_to_uint_map.h" static int swizzle_for_size(int size); @@ -498,7 +499,7 @@ ir_to_mesa_visitor::src_reg_for_float(float val) } static int -type_size(const struct glsl_type *type) +storage_type_size(const struct glsl_type *type, bool bindless) { unsigned int i; int size; @@ -506,7 +507,12 @@ type_size(const struct glsl_type *type) switch (type->base_type) { case GLSL_TYPE_UINT: case GLSL_TYPE_INT: + case GLSL_TYPE_UINT8: + case GLSL_TYPE_INT8: + case GLSL_TYPE_UINT16: + case GLSL_TYPE_INT16: case GLSL_TYPE_FLOAT: + case GLSL_TYPE_FLOAT16: case GLSL_TYPE_BOOL: if (type->is_matrix()) { return type->matrix_columns; @@ -532,21 +538,27 @@ type_size(const struct glsl_type *type) return 1; } break; + case GLSL_TYPE_UINT64: + case GLSL_TYPE_INT64: + if (type->vector_elements > 2) + return 2; + else + return 1; case GLSL_TYPE_ARRAY: assert(type->length > 0); - return type_size(type->fields.array) * type->length; + return storage_type_size(type->fields.array, bindless) * type->length; case GLSL_TYPE_STRUCT: size = 0; for (i = 0; i < type->length; i++) { - size += type_size(type->fields.structure[i].type); + size += storage_type_size(type->fields.structure[i].type, bindless); } return size; case GLSL_TYPE_SAMPLER: case GLSL_TYPE_IMAGE: + if (!bindless) + return 0; + /* fall through */ case GLSL_TYPE_SUBROUTINE: - /* Samplers take up one slot in UNIFORMS[], but they're baked in - * at link time. - */ return 1; case GLSL_TYPE_ATOMIC_UINT: case GLSL_TYPE_VOID: @@ -560,6 +572,12 @@ type_size(const struct glsl_type *type) return 0; } +static int +type_size(const struct glsl_type *type) +{ + return storage_type_size(type, false); +} + /** * In the initial pass of codegen, we assign temporary numbers to * intermediate results. (not SSA -- variable assignments will reuse @@ -576,7 +594,7 @@ ir_to_mesa_visitor::get_temp(const glsl_type *type) src.reladdr = NULL; next_temp += type_size(type); - if (type->is_array() || type->is_record()) { + if (type->is_array() || type->is_struct()) { src.swizzle = SWIZZLE_NOOP; } else { src.swizzle = swizzle_for_size(type->vector_elements); @@ -600,11 +618,6 @@ ir_to_mesa_visitor::find_variable_storage(const ir_variable *var) void ir_to_mesa_visitor::visit(ir_variable *ir) { - if (strcmp(ir->name, "gl_FragCoord") == 0) { - this->prog->OriginUpperLeft = ir->data.origin_upper_left; - this->prog->PixelCenterInteger = ir->data.pixel_center_integer; - } - if (ir->data.mode == ir_var_uniform && strncmp(ir->name, "gl_", 3) == 0) { unsigned int i; const ir_state_slot *const slots = ir->get_state_slots(); @@ -648,7 +661,7 @@ ir_to_mesa_visitor::visit(ir_variable *ir) for (unsigned int i = 0; i < ir->get_num_state_slots(); i++) { int index = _mesa_add_state_reference(this->prog->Parameters, - (gl_state_index *)slots[i].tokens); + slots[i].tokens); if (storage->file == PROGRAM_STATE_VAR) { if (storage->index == -1) { @@ -997,7 +1010,7 @@ ir_to_mesa_visitor::visit(ir_expression *ir) return; } - for (operand = 0; operand < ir->get_num_operands(); operand++) { + for (operand = 0; operand < ir->num_operands; operand++) { this->result.file = PROGRAM_UNDEFINED; ir->operands[operand]->accept(this); if (this->result.file == PROGRAM_UNDEFINED) { @@ -1062,8 +1075,10 @@ ir_to_mesa_visitor::visit(ir_expression *ir) emit_scalar(ir, OPCODE_EX2, result_dst, op[0]); break; case ir_unop_exp: + assert(!"not reached: should be handled by exp_to_exp2"); + break; case ir_unop_log: - assert(!"not reached: should be handled by ir_explog_to_explog2"); + assert(!"not reached: should be handled by log_to_log2"); break; case ir_unop_log2: emit_scalar(ir, OPCODE_LG2, result_dst, op[0]); @@ -1120,22 +1135,6 @@ ir_to_mesa_visitor::visit(ir_expression *ir) case ir_binop_less: emit(ir, OPCODE_SLT, result_dst, op[0], op[1]); break; - case ir_binop_greater: - /* Negating the operands (as opposed to switching the order of the - * operands) produces the correct result when both are +/-Inf. - */ - op[0].negate = ~op[0].negate; - op[1].negate = ~op[1].negate; - emit(ir, OPCODE_SLT, result_dst, op[0], op[1]); - break; - case ir_binop_lequal: - /* Negating the operands (as opposed to switching the order of the - * operands) produces the correct result when both are +/-Inf. - */ - op[0].negate = ~op[0].negate; - op[1].negate = ~op[1].negate; - emit(ir, OPCODE_SGE, result_dst, op[0], op[1]); - break; case ir_binop_gequal: emit(ir, OPCODE_SGE, result_dst, op[0], op[1]); break; @@ -1354,13 +1353,20 @@ ir_to_mesa_visitor::visit(ir_expression *ir) emit(ir, OPCODE_LRP, result_dst, op[2], op[1], op[0]); break; + case ir_triop_csel: + /* We assume that boolean true and false are 1.0 and 0.0. OPCODE_CMP + * selects src1 if src0 is < 0, src2 otherwise. + */ + op[0].negate = ~op[0].negate; + emit(ir, OPCODE_CMP, result_dst, op[0], op[1], op[2]); + break; + case ir_binop_vector_extract: case ir_triop_fma: case ir_triop_bitfield_extract: case ir_triop_vector_insert: case ir_quadop_bitfield_insert: case ir_binop_ldexp: - case ir_triop_csel: case ir_binop_carry: case ir_binop_borrow: case ir_binop_imul_high: @@ -1373,9 +1379,38 @@ ir_to_mesa_visitor::visit(ir_expression *ir) case ir_unop_dFdy_fine: case ir_unop_subroutine_to_int: case ir_unop_get_buffer_size: - case ir_unop_vote_any: - case ir_unop_vote_all: - case ir_unop_vote_eq: + case ir_unop_bitcast_u642d: + case ir_unop_bitcast_i642d: + case ir_unop_bitcast_d2u64: + case ir_unop_bitcast_d2i64: + case ir_unop_i642i: + case ir_unop_u642i: + case ir_unop_i642u: + case ir_unop_u642u: + case ir_unop_i642b: + case ir_unop_i642f: + case ir_unop_u642f: + case ir_unop_i642d: + case ir_unop_u642d: + case ir_unop_i2i64: + case ir_unop_u2i64: + case ir_unop_b2i64: + case ir_unop_f2i64: + case ir_unop_d2i64: + case ir_unop_i2u64: + case ir_unop_u2u64: + case ir_unop_f2u64: + case ir_unop_d2u64: + case ir_unop_u642i64: + case ir_unop_i642u64: + case ir_unop_pack_int_2x32: + case ir_unop_unpack_int_2x32: + case ir_unop_pack_uint_2x32: + case ir_unop_unpack_uint_2x32: + case ir_unop_pack_sampler_2x32: + case ir_unop_unpack_sampler_2x32: + case ir_unop_pack_image_2x32: + case ir_unop_unpack_image_2x32: assert(!"not supported"); break; @@ -1498,7 +1533,7 @@ ir_to_mesa_visitor::visit(ir_dereference_array *ir) src_reg src; int element_size = type_size(ir->type); - index = ir->array_index->constant_expression_value(); + index = ir->array_index->constant_expression_value(ralloc_parent(ir)); ir->array->accept(this); src = this->result; @@ -1557,8 +1592,9 @@ ir_to_mesa_visitor::visit(ir_dereference_record *ir) ir->record->accept(this); + assert(ir->field_idx >= 0); for (i = 0; i < struct_type->length; i++) { - if (strcmp(struct_type->fields.structure[i].name, ir->field) == 0) + if (i == (unsigned) ir->field_idx) break; offset += type_size(struct_type->fields.structure[i].type); } @@ -1611,8 +1647,10 @@ calc_sampler_offsets(struct gl_shader_program *prog, ir_dereference *deref, switch (deref->ir_type) { case ir_type_dereference_array: { ir_dereference_array *deref_arr = deref->as_dereference_array(); + + void *mem_ctx = ralloc_parent(deref_arr); ir_constant *array_index = - deref_arr->array_index->constant_expression_value(); + deref_arr->array_index->constant_expression_value(mem_ctx); if (!array_index) { /* GLSL 1.10 and 1.20 allowed variable sampler array indices, @@ -1639,10 +1677,9 @@ calc_sampler_offsets(struct gl_shader_program *prog, ir_dereference *deref, case ir_type_dereference_record: { ir_dereference_record *deref_record = deref->as_dereference_record(); - unsigned field_index = - deref_record->record->type->field_index(deref_record->field); + unsigned field_index = deref_record->field_idx; *location += - deref_record->record->type->record_location_offset(field_index); + deref_record->record->type->struct_location_offset(field_index); calc_sampler_offsets(prog, deref_record->record->as_dereference(), offset, array_elements, location); break; @@ -1691,7 +1728,7 @@ ir_to_mesa_visitor::process_move_condition(ir_rvalue *ir) bool switch_order = false; ir_expression *const expr = ir->as_expression(); - if ((expr != NULL) && (expr->get_num_operands() == 2)) { + if ((expr != NULL) && (expr->num_operands == 2)) { bool zero_on_left = false; if (expr->operands[0]->is_zero()) { @@ -1705,10 +1742,6 @@ ir_to_mesa_visitor::process_move_condition(ir_rvalue *ir) /* a is - 0 + - 0 + * (a < 0) T F F ( a < 0) T F F * (0 < a) F F T (-a < 0) F F T - * (a <= 0) T T F (-a < 0) F F T (swap order of other operands) - * (0 <= a) F T T ( a < 0) T F F (swap order of other operands) - * (a > 0) F F T (-a < 0) F F T - * (0 > a) T F F ( a < 0) T F F * (a >= 0) F T T ( a < 0) T F F (swap order of other operands) * (0 >= a) T T F (-a < 0) F F T (swap order of other operands) * @@ -1722,16 +1755,6 @@ ir_to_mesa_visitor::process_move_condition(ir_rvalue *ir) negate = zero_on_left; break; - case ir_binop_greater: - switch_order = false; - negate = !zero_on_left; - break; - - case ir_binop_lequal: - switch_order = true; - negate = !zero_on_left; - break; - case ir_binop_gequal: switch_order = true; negate = zero_on_left; @@ -1856,11 +1879,12 @@ ir_to_mesa_visitor::visit(ir_constant *ir) * get lucky, copy propagation will eliminate the extra moves. */ - if (ir->type->base_type == GLSL_TYPE_STRUCT) { + if (ir->type->is_struct()) { src_reg temp_base = get_temp(ir->type); dst_reg temp = dst_reg(temp_base); - foreach_in_list(ir_constant, field_value, &ir->components) { + for (i = 0; i < ir->type->length; i++) { + ir_constant *const field_value = ir->get_record_field(i); int size = type_size(field_value->type); assert(size > 0); @@ -1868,7 +1892,7 @@ ir_to_mesa_visitor::visit(ir_constant *ir) field_value->accept(this); src = this->result; - for (i = 0; i < (unsigned int)size; i++) { + for (unsigned j = 0; j < (unsigned int)size; j++) { emit(ir, OPCODE_MOV, temp, src); src.index++; @@ -1887,7 +1911,7 @@ ir_to_mesa_visitor::visit(ir_constant *ir) assert(size > 0); for (i = 0; i < ir->type->length; i++) { - ir->array_elements[i]->accept(this); + ir->const_elements[i]->accept(this); src = this->result; for (int j = 0; j < size; j++) { emit(ir, OPCODE_MOV, temp, src); @@ -1905,7 +1929,7 @@ ir_to_mesa_visitor::visit(ir_constant *ir) dst_reg mat_column = dst_reg(mat); for (i = 0; i < ir->type->matrix_columns; i++) { - assert(ir->type->base_type == GLSL_TYPE_FLOAT); + assert(ir->type->is_float()); values = &ir->value.f[i * ir->type->vector_elements]; src = src_reg(PROGRAM_CONSTANT, -1, NULL); @@ -2363,11 +2387,10 @@ namespace { class add_uniform_to_shader : public program_resource_visitor { public: - add_uniform_to_shader(struct gl_shader_program *shader_program, - struct gl_program_parameter_list *params, - gl_shader_stage shader_type) - : shader_program(shader_program), params(params), idx(-1), - shader_type(shader_type) + add_uniform_to_shader(struct gl_context *ctx, + struct gl_shader_program *shader_program, + struct gl_program_parameter_list *params) + : ctx(ctx), params(params), idx(-1) { /* empty */ } @@ -2375,7 +2398,9 @@ public: void process(ir_variable *var) { this->idx = -1; - this->program_resource_visitor::process(var); + this->var = var; + this->program_resource_visitor::process(var, + ctx->Const.UseSTD430AsDefaultPacking); var->data.param_index = this->idx; } @@ -2385,10 +2410,10 @@ private: const enum glsl_interface_packing packing, bool last_field); - struct gl_shader_program *shader_program; + struct gl_context *ctx; struct gl_program_parameter_list *params; int idx; - gl_shader_stage shader_type; + ir_variable *var; }; } /* anonymous namespace */ @@ -2400,55 +2425,45 @@ add_uniform_to_shader::visit_field(const glsl_type *type, const char *name, const enum glsl_interface_packing, bool /* last_field */) { - unsigned int size; - - /* atomics don't get real storage */ - if (type->contains_atomic()) + /* opaque types don't use storage in the param list unless they are + * bindless samplers or images. + */ + if (type->contains_opaque() && !var->data.bindless) return; - if (type->is_vector() || type->is_scalar()) { - size = type->vector_elements; - if (type->is_64bit()) - size *= 2; - } else { - size = type_size(type) * 4; - } - - gl_register_file file; - if (type->without_array()->is_sampler()) { - file = PROGRAM_SAMPLER; - } else { - file = PROGRAM_UNIFORM; - } - + /* Add the uniform to the param list */ + assert(_mesa_lookup_parameter_index(params, name) < 0); int index = _mesa_lookup_parameter_index(params, name); - if (index < 0) { - index = _mesa_add_parameter(params, file, name, size, type->gl_type, - NULL, NULL); - /* Sampler uniform values are stored in prog->SamplerUnits, - * and the entry in that array is selected by this index we - * store in ParameterValues[]. - */ - if (file == PROGRAM_SAMPLER) { - unsigned location; - const bool found = - this->shader_program->UniformHash->get(location, - params->Parameters[index].Name); - assert(found); - - if (!found) - return; - - struct gl_uniform_storage *storage = - &this->shader_program->data->UniformStorage[location]; - - assert(storage->type->is_sampler() && - storage->opaque[shader_type].active); + unsigned num_params = type->arrays_of_arrays_size(); + num_params = MAX2(num_params, 1); + num_params *= type->without_array()->matrix_columns; + + bool is_dual_slot = type->without_array()->is_dual_slot(); + if (is_dual_slot) + num_params *= 2; + + _mesa_reserve_parameter_storage(params, num_params); + index = params->NumParameters; + + if (ctx->Const.PackedDriverUniformStorage) { + for (unsigned i = 0; i < num_params; i++) { + unsigned dmul = type->without_array()->is_64bit() ? 2 : 1; + unsigned comps = type->without_array()->vector_elements * dmul; + if (is_dual_slot) { + if (i & 0x1) + comps -= 4; + else + comps = 4; + } - for (unsigned int j = 0; j < size / 4; j++) - params->ParameterValues[index + j][0].f = - storage->opaque[shader_type].index + j; + _mesa_add_parameter(params, PROGRAM_UNIFORM, name, comps, + type->gl_type, NULL, NULL, false); + } + } else { + for (unsigned i = 0; i < num_params; i++) { + _mesa_add_parameter(params, PROGRAM_UNIFORM, name, 4, + type->gl_type, NULL, NULL, true); } } @@ -2468,13 +2483,14 @@ add_uniform_to_shader::visit_field(const glsl_type *type, const char *name, * \param params Parameter list to be filled in. */ void -_mesa_generate_parameters_list_for_uniforms(struct gl_shader_program +_mesa_generate_parameters_list_for_uniforms(struct gl_context *ctx, + struct gl_shader_program *shader_program, struct gl_linked_shader *sh, struct gl_program_parameter_list *params) { - add_uniform_to_shader add(shader_program, params, sh->Stage); + add_uniform_to_shader add(ctx, shader_program, params); foreach_in_list(ir_instruction, node, sh->ir) { ir_variable *var = node->as_variable(); @@ -2489,9 +2505,13 @@ _mesa_generate_parameters_list_for_uniforms(struct gl_shader_program void _mesa_associate_uniform_storage(struct gl_context *ctx, - struct gl_shader_program *shader_program, - struct gl_program_parameter_list *params) + struct gl_shader_program *shader_program, + struct gl_program *prog, + bool propagate_to_storage) { + struct gl_program_parameter_list *params = prog->Parameters; + gl_shader_stage shader_type = prog->info.stage; + /* After adding each uniform to the parameter list, connect the storage for * the parameter with the tracking structure used by the API for the * uniform. @@ -2499,15 +2519,15 @@ _mesa_associate_uniform_storage(struct gl_context *ctx, unsigned last_location = unsigned(~0); for (unsigned i = 0; i < params->NumParameters; i++) { if (params->Parameters[i].Type != PROGRAM_UNIFORM) - continue; + continue; unsigned location; const bool found = - shader_program->UniformHash->get(location, params->Parameters[i].Name); + shader_program->UniformHash->get(location, params->Parameters[i].Name); assert(found); if (!found) - continue; + continue; struct gl_uniform_storage *storage = &shader_program->data->UniformStorage[location]; @@ -2517,40 +2537,58 @@ _mesa_associate_uniform_storage(struct gl_context *ctx, continue; if (location != last_location) { - enum gl_uniform_driver_format format = uniform_native; - - unsigned columns = 0; - int dmul = 4 * sizeof(float); - switch (storage->type->base_type) { - case GLSL_TYPE_UINT: - assert(ctx->Const.NativeIntegers); - format = uniform_native; - columns = 1; - break; - case GLSL_TYPE_INT: - format = - (ctx->Const.NativeIntegers) ? uniform_native : uniform_int_float; - columns = 1; - break; + enum gl_uniform_driver_format format = uniform_native; + unsigned columns = 0; - case GLSL_TYPE_DOUBLE: - if (storage->type->vector_elements > 2) + int dmul; + if (ctx->Const.PackedDriverUniformStorage && !prog->is_arb_asm) { + dmul = storage->type->vector_elements * sizeof(float); + } else { + dmul = 4 * sizeof(float); + } + + switch (storage->type->base_type) { + case GLSL_TYPE_UINT64: + if (storage->type->vector_elements > 2) dmul *= 2; - /* fallthrough */ - case GLSL_TYPE_FLOAT: - format = uniform_native; - columns = storage->type->matrix_columns; - break; - case GLSL_TYPE_BOOL: - format = uniform_native; - columns = 1; - break; - case GLSL_TYPE_SAMPLER: - case GLSL_TYPE_IMAGE: + /* fallthrough */ + case GLSL_TYPE_UINT: + case GLSL_TYPE_UINT16: + case GLSL_TYPE_UINT8: + assert(ctx->Const.NativeIntegers); + format = uniform_native; + columns = 1; + break; + case GLSL_TYPE_INT64: + if (storage->type->vector_elements > 2) + dmul *= 2; + /* fallthrough */ + case GLSL_TYPE_INT: + case GLSL_TYPE_INT16: + case GLSL_TYPE_INT8: + format = + (ctx->Const.NativeIntegers) ? uniform_native : uniform_int_float; + columns = 1; + break; + case GLSL_TYPE_DOUBLE: + if (storage->type->vector_elements > 2) + dmul *= 2; + /* fallthrough */ + case GLSL_TYPE_FLOAT: + case GLSL_TYPE_FLOAT16: + format = uniform_native; + columns = storage->type->matrix_columns; + break; + case GLSL_TYPE_BOOL: + format = uniform_native; + columns = 1; + break; + case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_IMAGE: case GLSL_TYPE_SUBROUTINE: - format = uniform_native; - columns = 1; - break; + format = uniform_native; + columns = 1; + break; case GLSL_TYPE_ATOMIC_UINT: case GLSL_TYPE_ARRAY: case GLSL_TYPE_VOID: @@ -2558,25 +2596,66 @@ _mesa_associate_uniform_storage(struct gl_context *ctx, case GLSL_TYPE_ERROR: case GLSL_TYPE_INTERFACE: case GLSL_TYPE_FUNCTION: - assert(!"Should not get here."); - break; - } + assert(!"Should not get here."); + break; + } - _mesa_uniform_attach_driver_storage(storage, - dmul * columns, - dmul, - format, - ¶ms->ParameterValues[i]); + unsigned pvo = params->ParameterValueOffset[i]; + _mesa_uniform_attach_driver_storage(storage, dmul * columns, dmul, + format, + ¶ms->ParameterValues[pvo]); - /* After attaching the driver's storage to the uniform, propagate any - * data from the linker's backing store. This will cause values from - * initializers in the source code to be copied over. - */ - _mesa_propagate_uniforms_to_driver_storage(storage, - 0, - MAX2(1, storage->array_elements)); + /* When a bindless sampler/image is bound to a texture/image unit, we + * have to overwrite the constant value by the resident handle + * directly in the constant buffer before the next draw. One solution + * is to keep track a pointer to the base of the data. + */ + if (storage->is_bindless && (prog->sh.NumBindlessSamplers || + prog->sh.NumBindlessImages)) { + unsigned array_elements = MAX2(1, storage->array_elements); + + for (unsigned j = 0; j < array_elements; ++j) { + unsigned unit = storage->opaque[shader_type].index + j; + + if (storage->type->without_array()->is_sampler()) { + assert(unit >= 0 && unit < prog->sh.NumBindlessSamplers); + prog->sh.BindlessSamplers[unit].data = + ¶ms->ParameterValues[pvo] + 4 * j; + } else if (storage->type->without_array()->is_image()) { + assert(unit >= 0 && unit < prog->sh.NumBindlessImages); + prog->sh.BindlessImages[unit].data = + ¶ms->ParameterValues[pvo] + 4 * j; + } + } + } - last_location = location; + /* After attaching the driver's storage to the uniform, propagate any + * data from the linker's backing store. This will cause values from + * initializers in the source code to be copied over. + */ + if (propagate_to_storage) { + unsigned array_elements = MAX2(1, storage->array_elements); + if (ctx->Const.PackedDriverUniformStorage && !prog->is_arb_asm && + (storage->is_bindless || !storage->type->contains_opaque())) { + const int dmul = storage->type->is_64bit() ? 2 : 1; + const unsigned components = + storage->type->vector_elements * + storage->type->matrix_columns; + + for (unsigned s = 0; s < storage->num_driver_storage; s++) { + gl_constant_value *uni_storage = (gl_constant_value *) + storage->driver_storage[s].data; + memcpy(uni_storage, storage->storage, + sizeof(storage->storage[0]) * components * + array_elements * dmul); + } + } else { + _mesa_propagate_uniforms_to_driver_storage(storage, 0, + array_elements); + } + } + + last_location = location; } } } @@ -2801,7 +2880,7 @@ get_mesa_program(struct gl_context *ctx, v.shader_program = shader_program; v.options = options; - _mesa_generate_parameters_list_for_uniforms(shader_program, shader, + _mesa_generate_parameters_list_for_uniforms(ctx, shader_program, shader, prog->Parameters); /* Emit Mesa IR for main(). */ @@ -2917,9 +2996,8 @@ get_mesa_program(struct gl_context *ctx, do_set_program_inouts(shader->ir, prog, shader->Stage); - prog->SamplersUsed = shader->active_samplers; prog->ShadowSamplers = shader->shadow_samplers; - prog->ExternalSamplersUsed = gl_external_samplers(shader); + prog->ExternalSamplersUsed = gl_external_samplers(prog); _mesa_update_shader_textures_used(shader_program, prog); /* Set the gl_FragDepth layout. */ @@ -2927,15 +3005,13 @@ get_mesa_program(struct gl_context *ctx, prog->info.fs.depth_layout = shader_program->FragDepthLayout; } - if ((ctx->_Shader->Flags & GLSL_NO_OPT) == 0) { - _mesa_optimize_program(ctx, prog, prog); - } + _mesa_optimize_program(prog, prog); /* This has to be done last. Any operation that can cause * prog->ParameterValues to get reallocated (e.g., anything that adds a * program constant) has to happen before creating this linkage. */ - _mesa_associate_uniform_storage(ctx, shader_program, prog->Parameters); + _mesa_associate_uniform_storage(ctx, shader_program, prog, true); if (!shader_program->data->LinkStatus) { goto fail_exit; } @@ -2977,10 +3053,9 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) do_mat_op_to_vec(ir); lower_instructions(ir, (MOD_TO_FLOOR | DIV_TO_MUL_RCP | EXP_TO_EXP2 | LOG_TO_LOG2 | INT_DIV_TO_MUL_RCP + | MUL64_TO_MUL_AND_MUL_HIGH | ((options->EmitNoPow) ? POW_TO_EXP2 : 0))); - progress = do_lower_jumps(ir, true, true, options->EmitNoMainReturn, options->EmitNoCont, options->EmitNoLoops) || progress; - progress = do_common_optimization(ir, true, true, options, ctx->Const.NativeIntegers) || progress; @@ -3047,27 +3122,59 @@ void _mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) { unsigned int i; + bool spirv = false; _mesa_clear_shader_program_data(ctx, prog); - prog->data->LinkStatus = GL_TRUE; + prog->data = _mesa_create_shader_program_data(); + + prog->data->LinkStatus = LINKING_SUCCESS; for (i = 0; i < prog->NumShaders; i++) { if (!prog->Shaders[i]->CompileStatus) { - linker_error(prog, "linking with uncompiled shader"); + linker_error(prog, "linking with uncompiled/unspecialized shader"); + } + + if (!i) { + spirv = (prog->Shaders[i]->spirv_data != NULL); + } else if (spirv && !prog->Shaders[i]->spirv_data) { + /* The GL_ARB_gl_spirv spec adds a new bullet point to the list of + * reasons LinkProgram can fail: + * + * "All the shader objects attached to do not have the + * same value for the SPIR_V_BINARY_ARB state." + */ + linker_error(prog, + "not all attached shaders have the same " + "SPIR_V_BINARY_ARB state"); } } + prog->data->spirv = spirv; if (prog->data->LinkStatus) { - link_shaders(ctx, prog); + if (!spirv) + link_shaders(ctx, prog); + else + _mesa_spirv_link_shaders(ctx, prog); } - if (prog->data->LinkStatus) { - if (!ctx->Driver.LinkShader(ctx, prog)) { - prog->data->LinkStatus = GL_FALSE; - } + /* If LinkStatus is LINKING_SUCCESS, then reset sampler validated to true. + * Validation happens via the LinkShader call below. If LinkStatus is + * LINKING_SKIPPED, then SamplersValidated will have been restored from the + * shader cache. + */ + if (prog->data->LinkStatus == LINKING_SUCCESS) { + prog->SamplersValidated = GL_TRUE; } + if (prog->data->LinkStatus && !ctx->Driver.LinkShader(ctx, prog)) { + prog->data->LinkStatus = LINKING_FAILURE; + } + + /* Return early if we are loading the shader from on-disk cache */ + if (prog->data->LinkStatus == LINKING_SKIPPED) + return; + if (ctx->_Shader->Flags & GLSL_DUMP) { if (!prog->data->LinkStatus) { fprintf(stderr, "GLSL shader program %d failed to link\n", prog->Name); @@ -3078,6 +3185,11 @@ _mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) fprintf(stderr, "%s\n", prog->data->InfoLog); } } + +#ifdef ENABLE_SHADER_CACHE + if (prog->data->LinkStatus) + shader_cache_write_program_metadata(ctx, prog); +#endif } } /* extern "C" */