gallivm: add support for lowered IO in vertex shaders
authorMarek Olšák <marek.olsak@amd.com>
Fri, 11 Sep 2020 23:59:32 +0000 (19:59 -0400)
committerMarge Bot <eric+marge@anholt.net>
Fri, 25 Sep 2020 21:55:07 +0000 (21:55 +0000)
for Selection/Feedback/RasterPos in st/mesa.

Reviewed-by: Dave Airlie <airlied@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6698>

src/gallium/auxiliary/gallivm/lp_bld_nir.c
src/gallium/auxiliary/nir/nir_to_tgsi_info.c

index b5ee974..9387996 100644 (file)
@@ -978,6 +978,57 @@ out:
    *indir_out = offset;
 }
 
+static void
+visit_load_input(struct lp_build_nir_context *bld_base,
+                 nir_intrinsic_instr *instr,
+                 LLVMValueRef result[NIR_MAX_VEC_COMPONENTS])
+{
+   nir_variable var = {0};
+   var.data.location = nir_intrinsic_io_semantics(instr).location;
+   var.data.driver_location = nir_intrinsic_base(instr);
+   var.data.location_frac = nir_intrinsic_component(instr);
+
+   unsigned nc = nir_dest_num_components(instr->dest);
+   unsigned bit_size = nir_dest_bit_size(instr->dest);
+
+   nir_src offset = *nir_get_io_offset_src(instr);
+   bool indirect = !nir_src_is_const(offset);
+   if (!indirect)
+      assert(nir_src_as_uint(offset) == 0);
+   LLVMValueRef indir_index = indirect ? get_src(bld_base, offset) : NULL;
+
+   bld_base->load_var(bld_base, nir_var_shader_in, nc, bit_size, &var, 0, NULL, 0, indir_index, result);
+}
+
+static void
+visit_store_output(struct lp_build_nir_context *bld_base,
+                   nir_intrinsic_instr *instr)
+{
+   nir_variable var = {0};
+   var.data.location = nir_intrinsic_io_semantics(instr).location;
+   var.data.driver_location = nir_intrinsic_base(instr);
+   var.data.location_frac = nir_intrinsic_component(instr);
+
+   unsigned mask = nir_intrinsic_write_mask(instr);
+
+   unsigned bit_size = nir_src_bit_size(instr->src[0]);
+   LLVMValueRef src = get_src(bld_base, instr->src[0]);
+
+   nir_src offset = *nir_get_io_offset_src(instr);
+   bool indirect = !nir_src_is_const(offset);
+   if (!indirect)
+      assert(nir_src_as_uint(offset) == 0);
+   LLVMValueRef indir_index = indirect ? get_src(bld_base, offset) : NULL;
+
+   if (mask == 0x1 && LLVMGetTypeKind(LLVMTypeOf(src)) == LLVMArrayTypeKind) {
+      src = LLVMBuildExtractValue(bld_base->base.gallivm->builder,
+                                  src, 0, "");
+   }
+
+   bld_base->store_var(bld_base, nir_var_shader_out, util_last_bit(mask),
+                       bit_size, &var, mask, NULL, 0, indir_index, src);
+}
+
 static void visit_load_var(struct lp_build_nir_context *bld_base,
                            nir_intrinsic_instr *instr,
                            LLVMValueRef result[NIR_MAX_VEC_COMPONENTS])
@@ -1428,6 +1479,12 @@ static void visit_intrinsic(struct lp_build_nir_context *bld_base,
 {
    LLVMValueRef result[NIR_MAX_VEC_COMPONENTS] = {0};
    switch (instr->intrinsic) {
+   case nir_intrinsic_load_input:
+      visit_load_input(bld_base, instr, result);
+      break;
+   case nir_intrinsic_store_output:
+      visit_store_output(bld_base, instr);
+      break;
    case nir_intrinsic_load_deref:
       visit_load_var(bld_base, instr, result);
       break;
@@ -2020,6 +2077,22 @@ bool lp_build_nir_llvm(
    nir_foreach_shader_out_variable(variable, nir)
       handle_shader_output_decl(bld_base, nir, variable);
 
+   if (nir->info.io_lowered) {
+      uint64_t outputs_written = nir->info.outputs_written;
+
+      while (outputs_written) {
+         unsigned location = u_bit_scan64(&outputs_written);
+         nir_variable var = {0};
+
+         var.type = glsl_vec4_type();
+         var.data.mode = nir_var_shader_out;
+         var.data.location = location;
+         var.data.driver_location = util_bitcount64(nir->info.outputs_written &
+                                                    BITFIELD64_MASK(location));
+         bld_base->emit_var_decl(bld_base, &var);
+      }
+   }
+
    bld_base->regs = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
                                             _mesa_key_pointer_equal);
    bld_base->vars = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
index 299523f..20052ba 100644 (file)
@@ -573,7 +573,13 @@ void nir_tgsi_scan_shader(const struct nir_shader *nir,
    }
 
    info->num_inputs = nir->num_inputs;
-   info->file_max[TGSI_FILE_INPUT] = nir->num_inputs - 1;
+   if (nir->info.io_lowered) {
+      info->num_inputs = util_bitcount64(nir->info.inputs_read);
+      if (nir->info.inputs_read_indirectly)
+         info->indirect_files |= 1 << TGSI_FILE_INPUT;
+   }
+
+   info->file_max[TGSI_FILE_INPUT] = info->num_inputs - 1;
 
    i = 0;
    uint64_t processed_outputs = 0;
@@ -749,6 +755,27 @@ void nir_tgsi_scan_shader(const struct nir_shader *nir,
       }
    }
 
+   if (nir->info.io_lowered) {
+      uint64_t outputs_written = nir->info.outputs_written;
+
+      while (outputs_written) {
+         unsigned location = u_bit_scan64(&outputs_written);
+         unsigned i = util_bitcount64(nir->info.outputs_written &
+                                      BITFIELD64_MASK(location));
+         unsigned semantic_name, semantic_index;
+
+         tgsi_get_gl_varying_semantic(location, need_texcoord,
+                                      &semantic_name, &semantic_index);
+
+         info->output_semantic_name[i] = semantic_name;
+         info->output_semantic_index[i] = semantic_index;
+         info->output_usagemask[i] = 0xf;
+      }
+      num_outputs = util_bitcount64(nir->info.outputs_written);
+      if (nir->info.outputs_accessed_indirectly)
+         info->indirect_files |= 1 << TGSI_FILE_OUTPUT;
+   }
+
    uint32_t sampler_mask = 0, image_mask = 0;
    nir_foreach_uniform_variable(var, nir) {
       uint32_t sampler_count = glsl_type_get_sampler_count(var->type);