<div dir="ltr">On 23 August 2013 17:45, Matt Turner <span dir="ltr"><<a href="mailto:mattst88@gmail.com" target="_blank">mattst88@gmail.com</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div class=""><div class="h5">On Fri, Aug 23, 2013 at 8:27 AM, Paul Berry <<a href="mailto:stereotype441@gmail.com">stereotype441@gmail.com</a>> wrote:<br>
> On 22 August 2013 16:08, Matt Turner <<a href="mailto:mattst88@gmail.com">mattst88@gmail.com</a>> wrote:<br>
>><br>
>> ---<br>
>>  src/mesa/drivers/dri/i965/brw_fs.cpp                     | 1 +<br>
>>  src/mesa/drivers/dri/i965/brw_fs.h                       | 1 +<br>
>>  src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp | 1 +<br>
>>  src/mesa/drivers/dri/i965/brw_fs_visitor.cpp             | 7 +++++++<br>
>>  4 files changed, 10 insertions(+)<br>
>><br>
>> diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp<br>
>> b/src/mesa/drivers/dri/i965/brw_fs.cpp<br>
>> index 52fa6f4..b770c0e 100644<br>
>> --- a/src/mesa/drivers/dri/i965/brw_fs.cpp<br>
>> +++ b/src/mesa/drivers/dri/i965/brw_fs.cpp<br>
>> @@ -179,6 +179,7 @@ ALU3(BFI2)<br>
>>  ALU1(FBH)<br>
>>  ALU1(FBL)<br>
>>  ALU1(CBIT)<br>
>> +ALU3(MAD)<br>
>><br>
>>  /** Gen4 predicated IF. */<br>
>>  fs_inst *<br>
>> diff --git a/src/mesa/drivers/dri/i965/brw_fs.h<br>
>> b/src/mesa/drivers/dri/i965/brw_fs.h<br>
>> index 9d240b5..cb4ac3b 100644<br>
>> --- a/src/mesa/drivers/dri/i965/brw_fs.h<br>
>> +++ b/src/mesa/drivers/dri/i965/brw_fs.h<br>
>> @@ -285,6 +285,7 @@ public:<br>
>>     fs_inst *FBH(fs_reg dst, fs_reg value);<br>
>>     fs_inst *FBL(fs_reg dst, fs_reg value);<br>
>>     fs_inst *CBIT(fs_reg dst, fs_reg value);<br>
>> +   fs_inst *MAD(fs_reg dst, fs_reg c, fs_reg b, fs_reg a);<br>
>><br>
>>     int type_size(const struct glsl_type *type);<br>
>>     fs_inst *get_instruction_generating_reg(fs_inst *start,<br>
>> diff --git a/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp<br>
>> b/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp<br>
>> index 4afae24..fa02d9b 100644<br>
>> --- a/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp<br>
>> +++ b/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp<br>
>> @@ -360,6 +360,7 @@<br>
>> ir_channel_expressions_visitor::visit_leave(ir_assignment *ir)<br>
>>        assert(!"not yet supported");<br>
>>        break;<br>
>><br>
>> +   case ir_triop_fma:<br>
>>     case ir_triop_lrp:<br>
>>     case ir_triop_bitfield_extract:<br>
>>        for (i = 0; i < vector_elements; i++) {<br>
>> diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp<br>
>> b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp<br>
>> index 964ad40..ac85d25 100644<br>
>> --- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp<br>
>> +++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp<br>
>> @@ -717,6 +717,13 @@ fs_visitor::visit(ir_expression *ir)<br>
>>        break;<br>
>>     }<br>
>><br>
>> +   case ir_triop_fma:<br>
>> +      /* Note that the instruction's argument order is reversed from GLSL<br>
>> +       * and the IR.<br>
>> +       */<br>
>> +      emit(MAD(this->result, op[2], op[1], op[0]));<br>
>> +      break;<br>
>> +<br>
><br>
><br>
> What happens if one of the ops is in a form that we can't encode in a 3-op<br>
> instruction (e.g. a constant)?  That's handled in patch 4/15 for the vs, and<br>
> it's handled inside emit_lrp, but I don't see it handled here.<br>
<br>
</div></div>I read your reply and thought "oh crap, I bet that doesn't work" but<br>
it actually does work. I honestly don't have any idea how or why.<br>
<br>
With fma(a, b, c) I get:<br>
<br>
mad(8) g14<1>F g3<4,1,1>F.x   g2.4<4,1,1>F.x g2<4,1,1>F.x<br>
mad(8) g13<1>F g3.1<4,1,1>F.x g2.5<4,1,1>F.x g2.1<4,1,1>F.x<br>
mad(8) g12<1>F g3.2<4,1,1>F.x g2.6<4,1,1>F.x g2.2<4,1,1>F.x<br>
mad(8) g11<1>F g3.3<4,1,1>F.x g2.7<4,1,1>F.x g2.3<4,1,1>F.x<br>
<br>
With fma(a, vec4(1.0, 1.0, 2.0, 2.0), c) I get:<br>
<br>
mov(8) g13<1>F 1F<br>
mov(8) g10<1>F 1F<br>
mov(8) g7<1>F  2F<br>
mov(8) g4<1>F  2F<br>
mad(8) g14<1>F g2.4<4,1,1>F.x g13<4,1,1>F g2<4,1,1>F.x<br>
mad(8) g11<1>F g2.5<4,1,1>F.x g10<4,1,1>F g2.1<4,1,1>F.x<br>
mad(8) g8<1>F  g2.6<4,1,1>F.x g7<4,1,1>F  g2.2<4,1,1>F.x<br>
mad(8) g5<1>F  g2.7<4,1,1>F.x g4<4,1,1>F  g2.3<4,1,1>F.x<br>
<br>
The IR just looks like it contains inline (constant float (...)) in<br>
the fma expression, so it doesn't seem to be something in the frontend<br>
doing it.<br>
<br>
Any guess what's going on?<br>
</blockquote></div><br></div><div class="gmail_extra">Aha!  I see what it is.  If you look at fs_visitor::visit(ir_constant *), you'll see that it emits MOVs.  Which means that in the code we were discussing, op[i] will never be a constant.<br>
<br></div><div class="gmail_extra">I double checked this with Eric, and both of us think that op[i] will only ever be of type GRF or UNIFORM, so probably this code is fine.<br><br></div><div class="gmail_extra">But it would be nice to have an assertion near the top of fs_visitor::visit(ir_expression *) to verify that this->result is 3-source compatible before we store it in op[operand].<br>
</div></div>