<p dir="ltr"><br>
On Jan 28, 2016 09:22, "Matt Turner" <<a href="mailto:mattst88@gmail.com">mattst88@gmail.com</a>> wrote:<br>
><br>
> On Thu, Jan 28, 2016 at 12:32 AM, Iago Toral <<a href="mailto:itoral@igalia.com">itoral@igalia.com</a>> wrote:<br>
> > On Mon, 2016-01-25 at 15:18 -0800, Matt Turner wrote:<br>
> >> ---<br>
> >>  src/glsl/nir/nir.h                     |  4 ++++<br>
> >>  src/glsl/nir/nir_lower_alu_to_scalar.c | 32 ++++++++++++++++++++++++++++++++<br>
> >>  src/glsl/nir/nir_opcodes.py            | 10 ++++++++++<br>
> >>  src/glsl/nir/nir_opt_algebraic.py      | 20 ++++++++++++++++++++<br>
> >>  4 files changed, 66 insertions(+)<br>
> >><br>
> >> diff --git a/src/glsl/nir/nir.h b/src/glsl/nir/nir.h<br>
> >> index 7b39cbb..bbd5b1a 100644<br>
> >> --- a/src/glsl/nir/nir.h<br>
> >> +++ b/src/glsl/nir/nir.h<br>
> >> @@ -1469,6 +1469,10 @@ typedef struct nir_shader_compiler_options {<br>
> >>     bool lower_ffract;<br>
> >><br>
> >>     bool lower_pack_half_2x16;<br>
> >> +   bool lower_pack_unorm_2x16;<br>
> >> +   bool lower_pack_snorm_2x16;<br>
> >> +   bool lower_pack_unorm_4x8;<br>
> >> +   bool lower_pack_snorm_4x8;<br>
> >>     bool lower_unpack_half_2x16;<br>
> >><br>
> >>     bool lower_extract_byte;<br>
> >> diff --git a/src/glsl/nir/nir_lower_alu_to_scalar.c b/src/glsl/nir/nir_lower_alu_to_scalar.c<br>
> >> index 5372fbe..37cb022 100644<br>
> >> --- a/src/glsl/nir/nir_lower_alu_to_scalar.c<br>
> >> +++ b/src/glsl/nir/nir_lower_alu_to_scalar.c<br>
> >> @@ -134,6 +134,38 @@ lower_alu_instr_scalar(nir_alu_instr *instr, nir_builder *b)<br>
> >>        return;<br>
> >>     }<br>
> >><br>
> >> +   case nir_op_pack_uvec2_to_uint: {<br>
> >> +      assert(b->shader->options->lower_pack_snorm_2x16 ||<br>
> >> +             b->shader->options->lower_pack_unorm_2x16);<br>
> ><br>
> > So we only want opt_algebraic to generate these opcodes? Why? I see that<br>
> > this would be the case now, and it is true that there is probably no<br>
> > reason for other IR -> NIR translators to inject these opcodes directly<br>
> > without going through opt_algebraic, but do we need to prevent that with<br>
> > an assert?<br>
><br>
> Not really necessary to assert, but I certainly don't expect there to<br>
> be other uses of these opcodes.<br>
><br>
> > I am not against anyway, just curious.<br>
> ><br>
> >> +      nir_ssa_def *word =<br>
> >> +         nir_extract_uword(b, instr->src[0].src.ssa, nir_imm_int(b, 0));<br>
> >> +      nir_ssa_def *val =<br>
> >> +         nir_ior(b, nir_ishl(b, nir_channel(b, word, 1), nir_imm_int(b, 16)),<br>
> >> +                                nir_channel(b, word, 0));<br>
> >> +<br>
> >> +      nir_ssa_def_rewrite_uses(&instr->dest.dest.ssa, nir_src_for_ssa(val));<br>
> >> +      nir_instr_remove(&instr->instr);<br>
> >> +      break;<br>
> >> +   }<br>
> >> +<br>
> >> +   case nir_op_pack_uvec4_to_uint: {<br>
> >> +      assert(b->shader->options->lower_pack_snorm_4x8 ||<br>
> >> +             b->shader->options->lower_pack_unorm_4x8);<br>
> >> +<br>
> >> +      nir_ssa_def *byte =<br>
> >> +         nir_extract_ubyte(b, instr->src[0].src.ssa, nir_imm_int(b, 0));<br>
> >> +      nir_ssa_def *val =<br>
> >> +         nir_ior(b, nir_ior(b, nir_ishl(b, nir_channel(b, byte, 3), nir_imm_int(b, 24)),<br>
> >> +                               nir_ishl(b, nir_channel(b, byte, 2), nir_imm_int(b, 16))),<br>
> >> +                    nir_ior(b, nir_ishl(b, nir_channel(b, byte, 1), nir_imm_int(b, 8)),<br>
> >> +                               nir_channel(b, byte, 0)));<br>
> >> +<br>
> >> +      nir_ssa_def_rewrite_uses(&instr->dest.dest.ssa, nir_src_for_ssa(val));<br>
> >> +      nir_instr_remove(&instr->instr);<br>
> >> +      break;<br>
> >> +   }<br>
> >> +<br>
> >>     case nir_op_fdph: {<br>
> >>        nir_ssa_def *sum[4];<br>
> >>        for (unsigned i = 0; i < 3; i++) {<br>
> >> diff --git a/src/glsl/nir/nir_opcodes.py b/src/glsl/nir/nir_opcodes.py<br>
> >> index be3cd17..3b82c3c 100644<br>
> >> --- a/src/glsl/nir/nir_opcodes.py<br>
> >> +++ b/src/glsl/nir/nir_opcodes.py<br>
> >> @@ -237,6 +237,16 @@ unpack_2x16("unorm")<br>
> >>  unpack_4x8("unorm")<br>
> >>  unpack_2x16("half")<br>
> >><br>
> >> +unop_horiz("pack_uvec2_to_uint", 0, tuint, 2, tuint, """<br>
> >> +dst = (src0.x & 0xffff) | (src0.y >> 16);<br>
> >> +""")<br>
> ><br>
> > This should've 1 as the output size instead of 0.<br>
><br>
> I think there's a subtle (and perhaps meaningless) distinction between<br>
> 0 and 1. I think that 0 gives a scalar (uint) while 1 gives a<br>
> 1-component vector. The only difference I've seen is the use of dst vs<br>
> dst.x in the constant evaluation code.<br>
><br>
> Do you know of any other differences or a reason to prefer 1 over 0?</p>
<p dir="ltr">That's not quite correct. 1 means exactly one component while a destination size of 0 means that it's a vectorizable operation.  All 0-sized sources automatically take on the size of the destination.  This is how most standard ALU opcodes work.</p>
<p dir="ltr">> >> +unop_horiz("pack_uvec4_to_uint", 0, tuint, 4, tuint, """<br>
> >> +dst = (src0.x <<  0) |<br>
> >> +      (src0.y <<  8) |<br>
> >> +      (src0.z << 16) |<br>
> >> +      (src0.w << 24);<br>
> >> +""")<br>
> ><br>
> > Same here.<br>
> ><br>
> ><br>
> >>  # Lowered floating point unpacking operations.<br>
> >><br>
> >> diff --git a/src/glsl/nir/nir_opt_algebraic.py b/src/glsl/nir/nir_opt_algebraic.py<br>
> >> index b761b54..56b0f5e 100644<br>
> >> --- a/src/glsl/nir/nir_opt_algebraic.py<br>
> >> +++ b/src/glsl/nir/nir_opt_algebraic.py<br>
> >> @@ -258,6 +258,26 @@ optimizations = [<br>
> >>     (('extract_uword', a, b),<br>
> >>      ('iand', ('ushr', a, ('imul', b, 16)), 0xffff),<br>
> >>      'options->lower_extract_word'),<br>
> >> +<br>
> >> +    (('pack_unorm_2x16', 'v'),<br>
> >> +     ('pack_uvec2_to_uint',<br>
> >> +        ('f2u', ('fround_even', ('fmul', ('fsat', 'v'), 65535.0)))),<br>
> >> +     'options->lower_pack_unorm_2x16'),<br>
> >> +<br>
> >> +    (('pack_unorm_4x8', 'v'),<br>
> >> +     ('pack_uvec4_to_uint',<br>
> >> +        ('f2u', ('fround_even', ('fmul', ('fsat', 'v'), 255.0)))),<br>
> >> +     'options->lower_pack_unorm_4x8'),<br>
> >> +<br>
> >> +    (('pack_snorm_2x16', 'v'),<br>
> >> +     ('pack_uvec2_to_uint',<br>
> >> +        ('f2i', ('fround_even', ('fmul', ('fmin', 1.0, ('fmax', -1.0, 'v')), 32767.0)))),<br>
> >> +     'options->lower_pack_snorm_2x16'),<br>
> >> +<br>
> >> +    (('pack_snorm_4x8', 'v'),<br>
> >> +     ('pack_uvec4_to_uint',<br>
> >> +        ('f2i', ('fround_even', ('fmul', ('fmin', 1.0, ('fmax', -1.0, 'v')), 127.0)))),<br>
> >> +     'options->lower_pack_snorm_4x8'),<br>
> ><br>
> > I think the pack_snorm_* opcodes need a i2u conversion at the end.<br>
> > That's what the GLSL IR lowering is doing and also what the spec [1]<br>
> > seems to indicate:<br>
><br>
> Right, but since NIR operands are typeless, there's nothing to do (NIR<br>
> doesn't even have i2u/u2i).<br>
> _______________________________________________<br>
> mesa-dev mailing list<br>
> <a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
> <a href="http://lists.freedesktop.org/mailman/listinfo/mesa-dev">http://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
</p>