[Mesa-dev] [PATCH 4/5] nir: Translate image load, store and atomic intrinsics from GLSL IR.

Connor Abbott cwabbott0 at gmail.com
Fri May 8 09:21:54 PDT 2015


On Fri, May 8, 2015 at 10:30 AM, Francisco Jerez <currojerez at riseup.net> wrote:
> Connor Abbott <cwabbott0 at gmail.com> writes:
>
>> On Tue, May 5, 2015 at 4:29 PM, Francisco Jerez <currojerez at riseup.net> wrote:
>>> ---
>>>  src/glsl/nir/glsl_to_nir.cpp | 125 +++++++++++++++++++++++++++++++++++++++----
>>>  1 file changed, 114 insertions(+), 11 deletions(-)
>>>
>>> diff --git a/src/glsl/nir/glsl_to_nir.cpp b/src/glsl/nir/glsl_to_nir.cpp
>>> index f6b8331..a01ab3b 100644
>>> --- a/src/glsl/nir/glsl_to_nir.cpp
>>> +++ b/src/glsl/nir/glsl_to_nir.cpp
>>> @@ -614,27 +614,130 @@ nir_visitor::visit(ir_call *ir)
>>>           op = nir_intrinsic_atomic_counter_inc_var;
>>>        } else if (strcmp(ir->callee_name(), "__intrinsic_atomic_predecrement") == 0) {
>>>           op = nir_intrinsic_atomic_counter_dec_var;
>>> +      } else if (strcmp(ir->callee_name(), "__intrinsic_image_load") == 0) {
>>> +         op = nir_intrinsic_image_load;
>>> +      } else if (strcmp(ir->callee_name(), "__intrinsic_image_store") == 0) {
>>> +         op = nir_intrinsic_image_store;
>>> +      } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_add") == 0) {
>>> +         op = nir_intrinsic_image_atomic_add;
>>> +      } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_min") == 0) {
>>> +         op = nir_intrinsic_image_atomic_min;
>>> +      } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_max") == 0) {
>>> +         op = nir_intrinsic_image_atomic_max;
>>> +      } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_and") == 0) {
>>> +         op = nir_intrinsic_image_atomic_and;
>>> +      } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_or") == 0) {
>>> +         op = nir_intrinsic_image_atomic_or;
>>> +      } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_xor") == 0) {
>>> +         op = nir_intrinsic_image_atomic_xor;
>>> +      } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_exchange") == 0) {
>>> +         op = nir_intrinsic_image_atomic_exchange;
>>> +      } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_comp_swap") == 0) {
>>> +         op = nir_intrinsic_image_atomic_comp_swap;
>>>        } else {
>>>           unreachable("not reached");
>>>        }
>>>
>>>        nir_intrinsic_instr *instr = nir_intrinsic_instr_create(shader, op);
>>> -      ir_dereference *param =
>>> -         (ir_dereference *) ir->actual_parameters.get_head();
>>> -      instr->variables[0] = evaluate_deref(&instr->instr, param);
>>> -      nir_ssa_dest_init(&instr->instr, &instr->dest, 1, NULL);
>>> +
>>> +      switch (op) {
>>> +      case nir_intrinsic_atomic_counter_read_var:
>>> +      case nir_intrinsic_atomic_counter_inc_var:
>>> +      case nir_intrinsic_atomic_counter_dec_var: {
>>> +         ir_dereference *param =
>>> +            (ir_dereference *) ir->actual_parameters.get_head();
>>> +         instr->variables[0] = evaluate_deref(&instr->instr, param);
>>> +         nir_ssa_dest_init(&instr->instr, &instr->dest, 1, NULL);
>>> +         break;
>>> +      }
>>> +      case nir_intrinsic_image_load:
>>> +      case nir_intrinsic_image_store:
>>> +      case nir_intrinsic_image_atomic_add:
>>> +      case nir_intrinsic_image_atomic_min:
>>> +      case nir_intrinsic_image_atomic_max:
>>> +      case nir_intrinsic_image_atomic_and:
>>> +      case nir_intrinsic_image_atomic_or:
>>> +      case nir_intrinsic_image_atomic_xor:
>>> +      case nir_intrinsic_image_atomic_exchange:
>>> +      case nir_intrinsic_image_atomic_comp_swap: {
>>> +         nir_load_const_instr *instr_zero = nir_load_const_instr_create(shader, 1);
>>> +         instr_zero->value.u[0] = 0;
>>> +         nir_instr_insert_after_cf_list(this->cf_node_list, &instr_zero->instr);
>>> +
>>> +         /* Set the image variable dereference. */
>>> +         exec_node *param = ir->actual_parameters.get_head();
>>> +         ir_dereference *image = (ir_dereference *)param;
>>> +         const glsl_type *type =
>>> +            image->variable_referenced()->type->without_array();
>>> +
>>> +         instr->variables[0] = evaluate_deref(&instr->instr, image);
>>> +         param = param->get_next();
>>> +
>>> +         /* Set the address argument, extending the coordinate vector to four
>>> +          * components.
>>> +          */
>>> +         const nir_src src_addr = evaluate_rvalue((ir_dereference *)param);
>>> +         nir_alu_instr *instr_addr = nir_alu_instr_create(shader, nir_op_vec4);
>>> +         nir_ssa_dest_init(&instr_addr->instr, &instr_addr->dest.dest, 4, NULL);
>>> +
>>> +         for (int i = 0; i < 4; i++) {
>>> +            if (i < type->coordinate_components()) {
>>> +               instr_addr->src[i].src = src_addr;
>>> +               instr_addr->src[i].swizzle[0] = i;
>>> +            } else {
>>> +               instr_addr->src[i].src = nir_src_for_ssa(&instr_zero->def);
>>
>> I think it would better convey the intent to create an ssa_undef_instr
>> and use that here instead of zero. Unless something else relies on the
>> extra coordinates being zeroed?
>>
> Yeah, that would work too.  Zero makes some sense because an
> n-dimensional image is largely equivalent to an n+1-dimensional image
> with the last dimension equal to one.  Some implementation
> *cough*i965*cough* actually requires you to send a whole vec4 of
> coordinates (in SIMD4x2 mode) no matter what dimensionality the surface
> has, and the last component must be zero.  That said, it doesn't really
> matter for the back-end what we do here because the implementation
> doesn't actually make use of this guarantee, and setting it to undefined
> might be slightly beneficial for other reasons, so I don't personally
> care.
>
> If you want it to be undefined I'll also go update the intrinsic
> documentation in PATCH 1.

Right... I guess it really doesn't matter too much. I don't think
optimizations will do any better if you set it to undefined. I think I
have a slight preference for undefined over zero since, as you said,
backends shouldn't really be using the rest of the coordinates, and
*maybe* it might generate better code for vec4 architectures in some
cases since the out-of-SSA pass won't have to stuff the zero's and the
coordinates into the same vector, but I'm fine with either one.

>
>>> +            }
>>> +         }
>>> +
>>> +         nir_instr_insert_after_cf_list(cf_node_list, &instr_addr->instr);
>>> +         instr->src[0] = nir_src_for_ssa(&instr_addr->dest.dest.ssa);
>>> +         param = param->get_next();
>>> +
>>> +         /* Set the sample argument, which should be zero for single-sample
>>> +          * images.
>>> +          */
>>> +         if (type->sampler_dimensionality == GLSL_SAMPLER_DIM_MS) {
>>> +            instr->src[1] = evaluate_rvalue((ir_dereference *)param);
>>> +            param = param->get_next();
>>> +         } else {
>>> +            instr->src[1] = nir_src_for_ssa(&instr_zero->def);
>>> +         }
>>> +
>>> +         /* Set the intrinsic parameters. */
>>> +         if (!param->is_tail_sentinel()) {
>>> +            instr->src[2] = evaluate_rvalue((ir_dereference *)param);
>>> +            param = param->get_next();
>>> +         }
>>> +
>>> +         if (!param->is_tail_sentinel()) {
>>> +            instr->src[3] = evaluate_rvalue((ir_dereference *)param);
>>> +            param = param->get_next();
>>> +         }
>>> +
>>> +         /* Set the intrinsic destination. */
>>> +         if (ir->return_deref)
>>> +            nir_ssa_dest_init(&instr->instr, &instr->dest,
>>> +                              ir->return_deref->type->vector_elements, NULL);
>>> +         break;
>>> +      }
>>> +      default:
>>> +         unreachable("not reached");
>>> +      }
>>>
>>>        nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr);
>>>
>>> -      nir_intrinsic_instr *store_instr =
>>> -         nir_intrinsic_instr_create(shader, nir_intrinsic_store_var);
>>> -      store_instr->num_components = 1;
>>> +      if (ir->return_deref) {
>>> +         nir_intrinsic_instr *store_instr =
>>> +            nir_intrinsic_instr_create(shader, nir_intrinsic_store_var);
>>> +         store_instr->num_components = ir->return_deref->type->vector_elements;
>>>
>>> -      store_instr->variables[0] = evaluate_deref(&store_instr->instr, ir->return_deref);
>>> -      store_instr->src[0].is_ssa = true;
>>> -      store_instr->src[0].ssa = &instr->dest.ssa;
>>> +         store_instr->variables[0] =
>>> +            evaluate_deref(&store_instr->instr, ir->return_deref);
>>> +         store_instr->src[0] = nir_src_for_ssa(&instr->dest.ssa);
>>>
>>> -      nir_instr_insert_after_cf_list(this->cf_node_list, &store_instr->instr);
>>> +         nir_instr_insert_after_cf_list(this->cf_node_list,
>>> +                                        &store_instr->instr);
>>> +      }
>>>
>>>        return;
>>>     }
>>> --
>>> 2.3.5
>>>
>>> _______________________________________________
>>> 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