Exemple #1
0
/**
 * Mark an entire variable as used.  Caller must ensure that the variable
 * represents a shader input or output.
 */
static void
mark_whole_variable(nir_shader *shader, nir_variable *var, bool is_output_read)
{
   const struct glsl_type *type = var->type;

   if (nir_is_per_vertex_io(var, shader->info.stage)) {
      assert(glsl_type_is_array(type));
      type = glsl_get_array_element(type);
   }

   const unsigned slots =
      var->data.compact ? DIV_ROUND_UP(glsl_get_length(type), 4)
                        : glsl_count_attribute_slots(type, false);

   set_io_mask(shader, var, 0, slots, is_output_read);
}
Exemple #2
0
static unsigned
get_io_offset(nir_deref_instr *deref, bool is_vertex_input)
{
   unsigned offset = 0;

   for (nir_deref_instr *d = deref; d; d = nir_deref_instr_parent(d)) {
      if (d->deref_type == nir_deref_type_array) {
         if (!nir_src_is_const(d->arr.index))
            return -1;

         offset += glsl_count_attribute_slots(d->type, is_vertex_input) *
                   nir_src_as_uint(d->arr.index);
      }
      /* TODO: we can get the offset for structs here see nir_lower_io() */
   }

   return offset;
}
Exemple #3
0
int
ir3_glsl_type_size(const struct glsl_type *type)
{
	return glsl_count_attribute_slots(type, false);
}
Exemple #4
0
static void
gather_intrinsic_info(nir_intrinsic_instr *instr, nir_shader *shader,
                      void *dead_ctx)
{
   switch (instr->intrinsic) {
   case nir_intrinsic_discard:
   case nir_intrinsic_discard_if:
      assert(shader->info.stage == MESA_SHADER_FRAGMENT);
      shader->info.fs.uses_discard = true;
      break;

   case nir_intrinsic_interp_deref_at_centroid:
   case nir_intrinsic_interp_deref_at_sample:
   case nir_intrinsic_interp_deref_at_offset:
   case nir_intrinsic_load_deref:
   case nir_intrinsic_store_deref:{
      nir_deref_instr *deref = nir_src_as_deref(instr->src[0]);
      nir_variable *var = nir_deref_instr_get_variable(deref);

      if (var->data.mode == nir_var_shader_in ||
          var->data.mode == nir_var_shader_out) {
         bool is_output_read = false;
         if (var->data.mode == nir_var_shader_out &&
             instr->intrinsic == nir_intrinsic_load_deref)
            is_output_read = true;

         if (!try_mask_partial_io(shader, var, deref, is_output_read))
            mark_whole_variable(shader, var, is_output_read);

         /* We need to track which input_reads bits correspond to a
          * dvec3/dvec4 input attribute */
         if (shader->info.stage == MESA_SHADER_VERTEX &&
             var->data.mode == nir_var_shader_in &&
             glsl_type_is_dual_slot(glsl_without_array(var->type))) {
            for (unsigned i = 0; i < glsl_count_attribute_slots(var->type, false); i++) {
               int idx = var->data.location + i;
               shader->info.vs.double_inputs |= BITFIELD64_BIT(idx);
            }
         }
      }
      break;
   }

   case nir_intrinsic_load_draw_id:
   case nir_intrinsic_load_frag_coord:
   case nir_intrinsic_load_front_face:
   case nir_intrinsic_load_vertex_id:
   case nir_intrinsic_load_vertex_id_zero_base:
   case nir_intrinsic_load_base_vertex:
   case nir_intrinsic_load_first_vertex:
   case nir_intrinsic_load_is_indexed_draw:
   case nir_intrinsic_load_base_instance:
   case nir_intrinsic_load_instance_id:
   case nir_intrinsic_load_sample_id:
   case nir_intrinsic_load_sample_pos:
   case nir_intrinsic_load_sample_mask_in:
   case nir_intrinsic_load_primitive_id:
   case nir_intrinsic_load_invocation_id:
   case nir_intrinsic_load_local_invocation_id:
   case nir_intrinsic_load_local_invocation_index:
   case nir_intrinsic_load_work_group_id:
   case nir_intrinsic_load_num_work_groups:
   case nir_intrinsic_load_tess_coord:
   case nir_intrinsic_load_tess_level_outer:
   case nir_intrinsic_load_tess_level_inner:
   case nir_intrinsic_load_patch_vertices_in:
      shader->info.system_values_read |=
         (1ull << nir_system_value_from_intrinsic(instr->intrinsic));
      break;

   case nir_intrinsic_end_primitive:
   case nir_intrinsic_end_primitive_with_counter:
      assert(shader->info.stage == MESA_SHADER_GEOMETRY);
      shader->info.gs.uses_end_primitive = 1;
      /* fall through */

   case nir_intrinsic_emit_vertex:
      if (nir_intrinsic_stream_id(instr) > 0)
         shader->info.gs.uses_streams = true;

      break;

   default:
      break;
   }
}
Exemple #5
0
static void
var_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member,
                  const struct vtn_decoration *dec, void *void_var)
{
   struct vtn_variable *vtn_var = void_var;

   /* Handle decorations that apply to a vtn_variable as a whole */
   switch (dec->decoration) {
   case SpvDecorationNonWritable:
      /* Do nothing with this for now */
      return;
   case SpvDecorationBinding:
      vtn_var->binding = dec->literals[0];
      return;
   case SpvDecorationDescriptorSet:
      vtn_var->descriptor_set = dec->literals[0];
      return;

   case SpvDecorationLocation: {
      unsigned location = dec->literals[0];
      bool is_vertex_input;
      if (b->shader->stage == MESA_SHADER_FRAGMENT &&
          vtn_var->mode == vtn_variable_mode_output) {
         is_vertex_input = false;
         location += FRAG_RESULT_DATA0;
      } else if (b->shader->stage == MESA_SHADER_VERTEX &&
                 vtn_var->mode == vtn_variable_mode_input) {
         is_vertex_input = true;
         location += VERT_ATTRIB_GENERIC0;
      } else if (vtn_var->mode == vtn_variable_mode_input ||
                 vtn_var->mode == vtn_variable_mode_output) {
         is_vertex_input = false;
         location += VARYING_SLOT_VAR0;
      } else {
         assert(!"Location must be on input or output variable");
      }

      if (vtn_var->var) {
         vtn_var->var->data.location = location;
         vtn_var->var->data.explicit_location = true;
      } else {
         assert(vtn_var->members);
         unsigned length =
            glsl_get_length(glsl_without_array(vtn_var->type->type));
         for (unsigned i = 0; i < length; i++) {
            vtn_var->members[i]->data.location = location;
            vtn_var->members[i]->data.explicit_location = true;
            location +=
               glsl_count_attribute_slots(vtn_var->members[i]->interface_type,
                                          is_vertex_input);
         }
      }
      return;
   }

   default:
      break;
   }

   /* Now we handle decorations that apply to a particular nir_variable */
   nir_variable *nir_var = vtn_var->var;
   if (val->value_type == vtn_value_type_access_chain) {
      assert(val->access_chain->length == 0);
      assert(val->access_chain->var == void_var);
      assert(member == -1);
   } else {
      assert(val->value_type == vtn_value_type_type);
      if (member != -1)
         nir_var = vtn_var->members[member];
   }

   if (nir_var == NULL)
      return;

   switch (dec->decoration) {
   case SpvDecorationRelaxedPrecision:
      break; /* FIXME: Do nothing with this for now. */
   case SpvDecorationNoPerspective:
      nir_var->data.interpolation = INTERP_QUALIFIER_NOPERSPECTIVE;
      break;
   case SpvDecorationFlat:
      nir_var->data.interpolation = INTERP_QUALIFIER_FLAT;
      break;
   case SpvDecorationCentroid:
      nir_var->data.centroid = true;
      break;
   case SpvDecorationSample:
      nir_var->data.sample = true;
      break;
   case SpvDecorationInvariant:
      nir_var->data.invariant = true;
      break;
   case SpvDecorationConstant:
      assert(nir_var->constant_initializer != NULL);
      nir_var->data.read_only = true;
      break;
   case SpvDecorationNonWritable:
      nir_var->data.read_only = true;
      break;
   case SpvDecorationComponent:
      nir_var->data.location_frac = dec->literals[0];
      break;
   case SpvDecorationIndex:
      nir_var->data.explicit_index = true;
      nir_var->data.index = dec->literals[0];
      break;
   case SpvDecorationBuiltIn: {
      SpvBuiltIn builtin = dec->literals[0];

      if (builtin == SpvBuiltInWorkgroupSize) {
         /* This shouldn't be a builtin.  It's actually a constant. */
         nir_var->data.mode = nir_var_global;
         nir_var->data.read_only = true;

         nir_constant *c = rzalloc(nir_var, nir_constant);
         c->value.u[0] = b->shader->info.cs.local_size[0];
         c->value.u[1] = b->shader->info.cs.local_size[1];
         c->value.u[2] = b->shader->info.cs.local_size[2];
         nir_var->constant_initializer = c;
         break;
      }

      nir_variable_mode mode = nir_var->data.mode;
      vtn_get_builtin_location(b, builtin, &nir_var->data.location, &mode);
      nir_var->data.explicit_location = true;
      nir_var->data.mode = mode;

      if (builtin == SpvBuiltInFragCoord || builtin == SpvBuiltInSamplePosition)
         nir_var->data.origin_upper_left = b->origin_upper_left;
      break;
   }
   case SpvDecorationRowMajor:
   case SpvDecorationColMajor:
   case SpvDecorationGLSLShared:
   case SpvDecorationPatch:
   case SpvDecorationRestrict:
   case SpvDecorationAliased:
   case SpvDecorationVolatile:
   case SpvDecorationCoherent:
   case SpvDecorationNonReadable:
   case SpvDecorationUniform:
      /* This is really nice but we have no use for it right now. */
   case SpvDecorationCPacked:
   case SpvDecorationSaturatedConversion:
   case SpvDecorationStream:
   case SpvDecorationOffset:
   case SpvDecorationXfbBuffer:
   case SpvDecorationFuncParamAttr:
   case SpvDecorationFPRoundingMode:
   case SpvDecorationFPFastMathMode:
   case SpvDecorationLinkageAttributes:
   case SpvDecorationSpecId:
      break;
   default:
      unreachable("Unhandled variable decoration");
   }
}