st/nir: Rework fixup_varying_slots
[mesa.git] / src / mesa / program / ir_to_mesa.cpp
index 0dad6f9c71272fa6e78119ef6fbbc19a2e93f63c..3ee8490ddc0b8d052a6c9b985903d74f8a52842f 100644 (file)
@@ -35,6 +35,7 @@
 #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"
@@ -251,6 +252,7 @@ public:
    virtual void visit(ir_call *);
    virtual void visit(ir_return *);
    virtual void visit(ir_discard *);
+   virtual void visit(ir_demote *);
    virtual void visit(ir_texture *);
    virtual void visit(ir_if *);
    virtual void visit(ir_emit_vertex *);
@@ -497,84 +499,10 @@ ir_to_mesa_visitor::src_reg_for_float(float val)
    return src;
 }
 
-static int
-storage_type_size(const struct glsl_type *type, bool bindless)
-{
-   unsigned int i;
-   int size;
-
-   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;
-      } else {
-        /* Regardless of size of vector, it gets a vec4. This is bad
-         * packing for things like floats, but otherwise arrays become a
-         * mess.  Hopefully a later pass over the code can pack scalars
-         * down if appropriate.
-         */
-        return 1;
-      }
-      break;
-   case GLSL_TYPE_DOUBLE:
-      if (type->is_matrix()) {
-         if (type->vector_elements > 2)
-            return type->matrix_columns * 2;
-         else
-            return type->matrix_columns;
-      } else {
-         if (type->vector_elements > 2)
-            return 2;
-         else
-            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 storage_type_size(type->fields.array, bindless) * type->length;
-   case GLSL_TYPE_STRUCT:
-      size = 0;
-      for (i = 0; i < type->length; i++) {
-        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:
-      return 1;
-   case GLSL_TYPE_ATOMIC_UINT:
-   case GLSL_TYPE_VOID:
-   case GLSL_TYPE_ERROR:
-   case GLSL_TYPE_INTERFACE:
-   case GLSL_TYPE_FUNCTION:
-      assert(!"Invalid type in type_size");
-      break;
-   }
-
-   return 0;
-}
-
 static int
 type_size(const struct glsl_type *type)
 {
-   return storage_type_size(type, false);
+   return type->count_vec4_slots(false, false);
 }
 
 /**
@@ -593,7 +521,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);
@@ -617,11 +545,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();
@@ -1107,15 +1030,6 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
       inst->saturate = true;
       break;
    }
-   case ir_unop_noise: {
-      const enum prog_opcode opcode =
-        prog_opcode(OPCODE_NOISE1
-                    + (ir->operands[0]->type->vector_elements) - 1);
-      assert((opcode >= OPCODE_NOISE1) && (opcode <= OPCODE_NOISE4));
-
-      emit(ir, opcode, result_dst, op[0]);
-      break;
-   }
 
    case ir_binop_add:
       emit(ir, OPCODE_ADD, result_dst, op[0], op[1]);
@@ -1132,7 +1046,7 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
       break;
    case ir_binop_mod:
       /* Floating point should be lowered by MOD_TO_FLOOR in the compiler. */
-      assert(ir->type->is_integer());
+      assert(ir->type->is_integer_32());
       emit(ir, OPCODE_MUL, result_dst, op[0], op[1]);
       break;
 
@@ -1373,6 +1287,12 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
    case ir_binop_ldexp:
    case ir_binop_carry:
    case ir_binop_borrow:
+   case ir_binop_abs_sub:
+   case ir_binop_add_sat:
+   case ir_binop_sub_sat:
+   case ir_binop_avg:
+   case ir_binop_avg_round:
+   case ir_binop_mul_32x16:
    case ir_binop_imul_high:
    case ir_unop_interpolate_at_centroid:
    case ir_binop_interpolate_at_offset:
@@ -1415,6 +1335,18 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
    case ir_unop_unpack_sampler_2x32:
    case ir_unop_pack_image_2x32:
    case ir_unop_unpack_image_2x32:
+   case ir_unop_atan:
+   case ir_binop_atan2:
+   case ir_unop_clz:
+   case ir_unop_f162f:
+   case ir_unop_f2f16:
+   case ir_unop_f2fmp:
+   case ir_unop_f162b:
+   case ir_unop_b2f16:
+   case ir_unop_i2i:
+   case ir_unop_i2imp:
+   case ir_unop_u2u:
+   case ir_unop_u2ump:
       assert(!"not supported");
       break;
 
@@ -1435,7 +1367,7 @@ ir_to_mesa_visitor::visit(ir_swizzle *ir)
 {
    src_reg src;
    int i;
-   int swizzle[4];
+   int swizzle[4] = {0};
 
    /* Note that this is only swizzles in expressions, not those on the left
     * hand side of an assignment, which do write masking.  See ir_assignment
@@ -1683,7 +1615,7 @@ calc_sampler_offsets(struct gl_shader_program *prog, ir_dereference *deref,
       ir_dereference_record *deref_record = deref->as_dereference_record();
       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;
@@ -1883,7 +1815,7 @@ ir_to_mesa_visitor::visit(ir_constant *ir)
     * get lucky, copy propagation will eliminate the extra moves.
     */
 
-   if (ir->type->is_record()) {
+   if (ir->type->is_struct()) {
       src_reg temp_base = get_temp(ir->type);
       dst_reg temp = dst_reg(temp_base);
 
@@ -2205,6 +2137,12 @@ ir_to_mesa_visitor::visit(ir_discard *ir)
    emit(ir, OPCODE_KIL, undef_dst, this->result);
 }
 
+void
+ir_to_mesa_visitor::visit(ir_demote *ir)
+{
+   assert(!"demote statement unsupported");
+}
+
 void
 ir_to_mesa_visitor::visit(ir_if *ir)
 {
@@ -2394,7 +2332,7 @@ public:
    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)
+      : ctx(ctx), shader_program(shader_program), params(params), idx(-1)
    {
       /* empty */
    }
@@ -2415,6 +2353,7 @@ private:
                             bool last_field);
 
    struct gl_context *ctx;
+   struct gl_shader_program *shader_program;
    struct gl_program_parameter_list *params;
    int idx;
    ir_variable *var;
@@ -2476,6 +2415,21 @@ add_uniform_to_shader::visit_field(const glsl_type *type, const char *name,
     */
    if (this->idx < 0)
       this->idx = index;
+
+   /* Each Parameter will hold the index to the backing uniform storage.
+    * This avoids relying on names to match parameters and uniform
+    * storages later when associating uniform storage.
+    */
+   unsigned location = -1;
+   ASSERTED const bool found =
+      shader_program->UniformHash->get(location, params->Parameters[index].Name);
+   assert(found);
+
+   for (unsigned i = 0; i < num_params; i++) {
+      struct gl_program_parameter *param = &params->Parameters[index + i];
+      param->UniformStorageIndex = location;
+      param->MainUniformStorageIndex = params->Parameters[this->idx].UniformStorageIndex;
+   }
 }
 
 /**
@@ -2510,8 +2464,7 @@ _mesa_generate_parameters_list_for_uniforms(struct gl_context *ctx,
 void
 _mesa_associate_uniform_storage(struct gl_context *ctx,
                                 struct gl_shader_program *shader_program,
-                                struct gl_program *prog,
-                                bool propagate_to_storage)
+                                struct gl_program *prog)
 {
    struct gl_program_parameter_list *params = prog->Parameters;
    gl_shader_stage shader_type = prog->info.stage;
@@ -2525,13 +2478,7 @@ _mesa_associate_uniform_storage(struct gl_context *ctx,
       if (params->Parameters[i].Type != PROGRAM_UNIFORM)
          continue;
 
-      unsigned location;
-      const bool found =
-         shader_program->UniformHash->get(location, params->Parameters[i].Name);
-      assert(found);
-
-      if (!found)
-         continue;
+      unsigned location = params->Parameters[i].UniformStorageIndex;
 
       struct gl_uniform_storage *storage =
          &shader_program->data->UniformStorage[location];
@@ -2637,8 +2584,22 @@ _mesa_associate_uniform_storage(struct gl_context *ctx,
           * 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);
+         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);
          }
@@ -2999,7 +2960,7 @@ get_mesa_program(struct gl_context *ctx,
     * 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, true);
+   _mesa_associate_uniform_storage(ctx, shader_program, prog);
    if (!shader_program->data->LinkStatus) {
       goto fail_exit;
    }
@@ -3041,6 +3002,7 @@ _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_common_optimization(ir, true, true,
@@ -3055,8 +3017,6 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
         progress = lower_if_to_cond_assign((gl_shader_stage)i, ir,
                                             options->MaxIfDepth) || progress;
 
-         progress = lower_noise(ir) || progress;
-
         /* If there are forms of indirect addressing that the driver
          * cannot handle, perform the lowering pass.
          */
@@ -3098,7 +3058,7 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
       }
    }
 
-   build_program_resource_list(ctx, prog);
+   build_program_resource_list(ctx, prog, false);
    return prog->data->LinkStatus;
 }
 
@@ -3109,7 +3069,7 @@ void
 _mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
 {
    unsigned int i;
-   bool spirv;
+   bool spirv = false;
 
    _mesa_clear_shader_program_data(ctx, prog);
 
@@ -3136,9 +3096,13 @@ _mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
                       "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 LinkStatus is LINKING_SUCCESS, then reset sampler validated to true.
@@ -3154,6 +3118,9 @@ _mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
       prog->data->LinkStatus = LINKING_FAILURE;
    }
 
+   if (prog->data->LinkStatus != LINKING_FAILURE)
+      _mesa_create_program_resource_hash(prog);
+
    /* Return early if we are loading the shader from on-disk cache */
    if (prog->data->LinkStatus == LINKING_SKIPPED)
       return;