Exemplo n.º 1
0
ir_visitor_status
ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir)
{
   /* Note: for geometry shader inputs, lower_named_interface_blocks may
    * create 2D arrays, so we need to be able to handle those.  2D arrays
    * shouldn't be able to crop up for any other reason.
    */
   if (ir_dereference_array * const inner_array =
       ir->array->as_dereference_array()) {
      /*          ir => foo[i][j]
       * inner_array => foo[i]
       */
      if (ir_dereference_variable * const deref_var =
          inner_array->array->as_dereference_variable()) {
         if (this->shader_type == GL_GEOMETRY_SHADER &&
             deref_var->var->mode == ir_var_shader_in) {
            /* foo is a geometry shader input, so i is the vertex, and j the
             * part of the input we're accessing.
             */
            if (try_mark_partial_variable(deref_var->var, ir->array_index))
            {
               /* We've now taken care of foo and j, but i might contain a
                * subexpression that accesses shader inputs.  So manually
                * visit i and then continue with the parent.
                */
               inner_array->array_index->accept(this);
               return visit_continue_with_parent;
            }
         }
      }
   } else if (ir_dereference_variable * const deref_var =
              ir->array->as_dereference_variable()) {
      /* ir => foo[i], where foo is a variable. */
      if (this->shader_type == GL_GEOMETRY_SHADER &&
          deref_var->var->mode == ir_var_shader_in) {
         /* foo is a geometry shader input, so i is the vertex, and we're
          * accessing the entire input.
          */
         mark_whole_variable(deref_var->var);
         /* We've now taken care of foo, but i might contain a subexpression
          * that accesses shader inputs.  So manually visit i and then
          * continue with the parent.
          */
         ir->array_index->accept(this);
         return visit_continue_with_parent;
      } else if (is_shader_inout(deref_var->var)) {
         /* foo is a shader input/output, but not a geometry shader input,
          * so i is the part of the input we're accessing.
          */
         if (try_mark_partial_variable(deref_var->var, ir->array_index))
            return visit_continue_with_parent;
      }
   }

   /* The expression is something we don't recognize.  Just visit its
    * subexpressions.
    */
   return visit_continue;
}
/* Default handler: Mark all the locations in the variable as used. */
ir_visitor_status
ir_set_program_inouts_visitor::visit(ir_dereference_variable *ir)
{
   if (!is_shader_inout(ir->var))
      return visit_continue;

   mark_whole_variable(ir->var);

   return visit_continue;
}
Exemplo n.º 3
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;
   }
}