i965: Add support for FB writes on Sandybridge.
authorZhenyu Wang <zhenyuw@linux.intel.com>
Fri, 20 Aug 2010 22:02:19 +0000 (15:02 -0700)
committerEric Anholt <eric@anholt.net>
Fri, 20 Aug 2010 23:17:40 +0000 (16:17 -0700)
src/mesa/drivers/dri/i965/brw_eu_emit.c
src/mesa/drivers/dri/i965/brw_wm_emit.c

index 523f119f435cca6f9650361702313badcc41f607..c9b4770fd9aeec09709b302fce499decd772482b 100644 (file)
@@ -372,9 +372,23 @@ static void brw_set_dp_write_message( struct brw_context *brw,
                                      GLuint send_commit_msg)
 {
    struct intel_context *intel = &brw->intel;
-   brw_set_src1(insn, brw_imm_d(0));
+   brw_set_src1(insn, brw_imm_ud(0));
 
-   if (intel->gen == 5) {
+   if (intel->gen >= 6) {
+       insn->bits3.dp_render_cache.binding_table_index = binding_table_index;
+       insn->bits3.dp_render_cache.msg_control = msg_control;
+       insn->bits3.dp_render_cache.pixel_scoreboard_clear = pixel_scoreboard_clear;
+       insn->bits3.dp_render_cache.msg_type = msg_type;
+       insn->bits3.dp_render_cache.send_commit_msg = send_commit_msg;
+       insn->bits3.dp_render_cache.header_present = 0; /* XXX */
+       insn->bits3.dp_render_cache.response_length = response_length;
+       insn->bits3.dp_render_cache.msg_length = msg_length;
+       insn->bits3.dp_render_cache.end_of_thread = end_of_thread;
+       insn->header.destreg__conditionalmod = BRW_MESSAGE_TARGET_DATAPORT_WRITE;
+       /* XXX really need below? */
+       insn->bits2.send_gen5.sfid = BRW_MESSAGE_TARGET_DATAPORT_WRITE;
+       insn->bits2.send_gen5.end_of_thread = end_of_thread;
+   } else if (intel->gen == 5) {
        insn->bits3.dp_write_gen5.binding_table_index = binding_table_index;
        insn->bits3.dp_write_gen5.msg_control = msg_control;
        insn->bits3.dp_write_gen5.pixel_scoreboard_clear = pixel_scoreboard_clear;
@@ -1344,22 +1358,40 @@ void brw_fb_WRITE(struct brw_compile *p,
                   GLuint response_length,
                   GLboolean eot)
 {
-   struct brw_instruction *insn = next_insn(p, BRW_OPCODE_SEND);
-   
+   struct intel_context *intel = &p->brw->intel;
+   struct brw_instruction *insn;
+   GLuint msg_control, msg_type;
+
+   insn = next_insn(p, BRW_OPCODE_SEND);
    insn->header.predicate_control = 0; /* XXX */
-   insn->header.compression_control = BRW_COMPRESSION_NONE; 
-   insn->header.destreg__conditionalmod = msg_reg_nr;
-  
+   insn->header.compression_control = BRW_COMPRESSION_NONE;
+
+   if (intel->gen >= 6) {
+       /* headerless version, just submit color payload */
+       src0 = brw_message_reg(msg_reg_nr);
+
+       if (msg_length >= 8)
+         msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE;
+       else
+         msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_SINGLE_SOURCE_SUBSPAN01;
+       msg_type = BRW_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE_GEN6;
+   } else {
+      insn->header.destreg__conditionalmod = msg_reg_nr;
+
+      msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE;
+       msg_type = BRW_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE;
+   }
+
    brw_set_dest(insn, dest);
    brw_set_src0(insn, src0);
    brw_set_dp_write_message(p->brw,
                            insn,
                            binding_table_index,
-                           BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE, /* msg_control */
-                           BRW_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE, /* msg_type */
+                           msg_control,
+                           msg_type,
                            msg_length,
                            1,  /* pixel scoreboard */
-                           response_length, 
+                           response_length,
                            eot,
                            0 /* send_commit_msg */);
 }
index f2ace7d13d69442aa6d5dc1a77fa75a4b0bc8c96..78de2ceda951607e233d6001f6d7dce0677044c7 100644 (file)
@@ -1230,6 +1230,7 @@ static void fire_fb_write( struct brw_wm_compile *c,
                           GLuint eot )
 {
    struct brw_compile *p = &c->func;
+   struct intel_context *intel = &p->brw->intel;
    struct brw_reg dst;
 
    if (c->dispatch_width == 16)
@@ -1240,6 +1241,7 @@ static void fire_fb_write( struct brw_wm_compile *c,
    /* Pass through control information:
     */
 /*  mov (8) m1.0<1>:ud   r1.0<8;8,1>:ud   { Align1 NoMask } */
+   if (intel->gen < 6) /* gen6, use headerless for fb write */
    {
       brw_push_insn_state(p);
       brw_set_mask_control(p, BRW_MASK_DISABLE); /* ? */
@@ -1297,6 +1299,8 @@ void emit_fb_write(struct brw_wm_compile *c,
    struct intel_context *intel = &brw->intel;
    GLuint nr = 2;
    GLuint channel;
+   int step = 0;
+   int base_reg; /* For gen6 fb write with no header, starting from color payload directly!. */
 
    /* Reserve a space for AA - may not be needed:
     */
@@ -1308,6 +1312,11 @@ void emit_fb_write(struct brw_wm_compile *c,
     */
    brw_push_insn_state(p);
 
+   if (intel->gen >= 6)
+       base_reg = nr;
+   else
+       base_reg = 0;
+
    for (channel = 0; channel < 4; channel++) {
       if (intel->gen >= 6) {
         /* gen6 SIMD16 single source DP write looks like:
@@ -1339,6 +1348,16 @@ void emit_fb_write(struct brw_wm_compile *c,
         brw_MOV(p,
                 brw_message_reg(nr + channel + BRW_MRF_COMPR4),
                 arg0[channel]);
+      } else if (intel->gen >= 6) {
+         brw_set_compression_control(p, BRW_COMPRESSION_NONE);
+         brw_MOV(p, brw_message_reg(nr + channel + step), arg0[channel]); 
+         if (c->dispatch_width == 16) {
+             brw_set_compression_control(p, BRW_COMPRESSION_NONE);
+             brw_MOV(p,
+                     brw_message_reg(nr + channel + step + 1),
+                     sechalf(arg0[channel]));
+             ++step;
+         }
       } else {
         /*  mov (8) m2.0<1>:ud   r28.0<8;8,1>:ud  { Align1 } */
         /*  mov (8) m6.0<1>:ud   r29.0<8;8,1>:ud  { Align1 SecHalf } */
@@ -1357,7 +1376,18 @@ void emit_fb_write(struct brw_wm_compile *c,
    }
    /* skip over the regs populated above:
     */
-   nr += 8;
+   if (intel->gen < 6) {
+      nr += 8; /* XXX: always uses SIMD16 write currently. */
+   } else {
+      if (c->dispatch_width == 16)
+        nr += 8;
+      else
+        nr += 4;
+
+      /* Subtract off the message header, since we send headerless. */
+      nr -= 2;
+   }
+
    brw_pop_insn_state(p);
 
    if (c->key.source_depth_to_render_target)
@@ -1394,7 +1424,7 @@ void emit_fb_write(struct brw_wm_compile *c,
       if (c->key.aa_dest_stencil_reg)
         emit_aa(c, arg1, 2);
 
-      fire_fb_write(c, 0, nr, target, eot);
+      fire_fb_write(c, base_reg, nr, target, eot);
    }
    else {
       struct brw_reg v1_null_ud = vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_UD));