[Mesa-dev] [PATCH v4 (part2) 32/59] nir: Implement __intrinsic_store_load

Connor Abbott cwabbott0 at gmail.com
Wed Aug 5 12:21:05 PDT 2015


Title should say "__intrinsic_load_ssbo".

On Wed, Aug 5, 2015 at 1:30 AM, Iago Toral Quiroga <itoral at igalia.com> wrote:
> ---
>  src/glsl/nir/glsl_to_nir.cpp            | 67 ++++++++++++++++++++++++++++++++-
>  src/glsl/nir/nir_intrinsics.h           |  2 +-
>  src/glsl/nir/nir_lower_phis_to_scalar.c |  2 +
>  3 files changed, 69 insertions(+), 2 deletions(-)
>
> diff --git a/src/glsl/nir/glsl_to_nir.cpp b/src/glsl/nir/glsl_to_nir.cpp
> index cbec2df..be4cd66 100644
> --- a/src/glsl/nir/glsl_to_nir.cpp
> +++ b/src/glsl/nir/glsl_to_nir.cpp
> @@ -643,6 +643,8 @@ nir_visitor::visit(ir_call *ir)
>           op = nir_intrinsic_memory_barrier;
>        } else if (strcmp(ir->callee_name(), "__intrinsic_store_ssbo") == 0) {
>           op = nir_intrinsic_store_ssbo;
> +      } else if (strcmp(ir->callee_name(), "__intrinsic_load_ssbo") == 0) {
> +         op = nir_intrinsic_load_ssbo;
>        } else {
>           unreachable("not reached");
>        }
> @@ -766,11 +768,74 @@ nir_visitor::visit(ir_call *ir)
>           instr->src[1] = evaluate_rvalue(block);
>           break;
>        }
> +      case nir_intrinsic_load_ssbo: {
> +         exec_node *param = ir->actual_parameters.get_head();
> +         ir_rvalue *block = ((ir_instruction *)param)->as_rvalue();
> +
> +         param = param->get_next();
> +         ir_rvalue *offset = ((ir_instruction *)param)->as_rvalue();
> +
> +         /* Check if we need the indirect version */
> +         ir_constant *const_offset = offset->as_constant();
> +         if (!const_offset) {
> +            op = nir_intrinsic_load_ssbo_indirect;
> +            ralloc_free(instr);
> +            instr = nir_intrinsic_instr_create(shader, op);
> +            instr->src[1] = evaluate_rvalue(offset);
> +            instr->const_index[0] = 0;
> +         } else {
> +            instr->const_index[0] = const_offset->value.u[0];
> +         }
> +
> +         instr->src[0] = evaluate_rvalue(block);
> +
> +         instr->const_index[1] = 1; /* number of vec4's */
> +
> +         const glsl_type *type = ir->return_deref->var->type;
> +         instr->num_components = type->vector_elements;
> +
> +         /* Setup destination register */
> +         nir_ssa_dest_init(&instr->instr, &instr->dest,
> +                           type->vector_elements, NULL);
> +
> +         /* Insert the created nir instruction now since in the case of boolean
> +          * result we will need to emit another instruction after it
> +          */
> +         nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr);
> +
> +         /*
> +          * In SSBO/UBO's, a true boolean value is any non-zero value, but we
> +          * consider a true boolean to be ~0. Fix this up with a != 0
> +          * comparison.
> +          */
> +         if (type->base_type == GLSL_TYPE_BOOL) {
> +            nir_load_const_instr *const_zero =
> +               nir_load_const_instr_create(shader, 1);
> +            const_zero->value.u[0] = 0;
> +            nir_instr_insert_after_cf_list(this->cf_node_list,
> +                                           &const_zero->instr);
> +
> +            nir_alu_instr *compare = nir_alu_instr_create(shader, nir_op_ine);
> +            compare->src[0].src.is_ssa = true;
> +            compare->src[0].src.ssa = &instr->dest.ssa;
> +            compare->src[1].src.is_ssa = true;
> +            compare->src[1].src.ssa = &const_zero->def;
> +            for (unsigned i = 0; i < type->vector_elements; i++)
> +               compare->src[1].swizzle[i] = 0;
> +            compare->dest.write_mask = (1 << type->vector_elements) - 1;
> +
> +            nir_instr_insert_after_cf_list(this->cf_node_list, &compare->instr);
> +         }
> +
> +         break;
> +      }
>        default:
>           unreachable("not reached");
>        }
>
> -      nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr);
> +      /* nir_intrinsic_load_ssbo{_indirect} were already emitted */
> +      if (op != nir_intrinsic_load_ssbo && op != nir_intrinsic_load_ssbo_indirect)
> +         nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr);
>
>        if (ir->return_deref) {
>           nir_intrinsic_instr *store_instr =
> diff --git a/src/glsl/nir/nir_intrinsics.h b/src/glsl/nir/nir_intrinsics.h
> index 83eeecd..9877ea4 100644
> --- a/src/glsl/nir/nir_intrinsics.h
> +++ b/src/glsl/nir/nir_intrinsics.h
> @@ -168,7 +168,7 @@ SYSTEM_VALUE(invocation_id, 1)
>  LOAD(uniform, 0, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
>  LOAD(ubo, 1, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
>  LOAD(input, 0, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
> -/* LOAD(ssbo, 1, 0) */
> +LOAD(ssbo, 1, 0)

I realize you just uncommented this, but I made a mistake here. We
should be setting the CAN_ELIMINATE flag here, so that we can
eliminate dead loads through the normal mechanism. With those fixed,

Reviewed-by: Connor Abbott <connor.w.abbott at intel.com>

>
>  /*
>   * Stores work the same way as loads, except now the first register input is
> diff --git a/src/glsl/nir/nir_lower_phis_to_scalar.c b/src/glsl/nir/nir_lower_phis_to_scalar.c
> index 739170d..bdb7e6a 100644
> --- a/src/glsl/nir/nir_lower_phis_to_scalar.c
> +++ b/src/glsl/nir/nir_lower_phis_to_scalar.c
> @@ -94,6 +94,8 @@ is_phi_src_scalarizable(nir_phi_src *src,
>        case nir_intrinsic_load_uniform_indirect:
>        case nir_intrinsic_load_ubo:
>        case nir_intrinsic_load_ubo_indirect:
> +      case nir_intrinsic_load_ssbo:
> +      case nir_intrinsic_load_ssbo_indirect:
>        case nir_intrinsic_load_input:
>        case nir_intrinsic_load_input_indirect:
>           return true;
> --
> 1.9.1
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list