diff options
| -rw-r--r-- | src/mesa/drivers/dri/i965/brw_eu.h | 1 | ||||
| -rw-r--r-- | src/mesa/drivers/dri/i965/brw_eu_emit.c | 92 | ||||
| -rw-r--r-- | src/mesa/drivers/dri/i965/brw_fs.cpp | 14 | ||||
| -rw-r--r-- | src/mesa/drivers/dri/i965/brw_structs.h | 15 | 
4 files changed, 112 insertions, 10 deletions
| diff --git a/src/mesa/drivers/dri/i965/brw_eu.h b/src/mesa/drivers/dri/i965/brw_eu.h index b4538e6e8a..df5ce56ba6 100644 --- a/src/mesa/drivers/dri/i965/brw_eu.h +++ b/src/mesa/drivers/dri/i965/brw_eu.h @@ -1009,6 +1009,7 @@ void brw_math_invert( struct brw_compile *p,  void brw_set_src1( struct brw_instruction *insn,                            struct brw_reg reg ); +void brw_set_uip_jip(struct brw_compile *p);  /* brw_optimize.c */  void brw_optimize(struct brw_compile *p); diff --git a/src/mesa/drivers/dri/i965/brw_eu_emit.c b/src/mesa/drivers/dri/i965/brw_eu_emit.c index 660f5b4845..7eb7bdfa1e 100644 --- a/src/mesa/drivers/dri/i965/brw_eu_emit.c +++ b/src/mesa/drivers/dri/i965/brw_eu_emit.c @@ -1029,16 +1029,24 @@ void brw_ENDIF(struct brw_compile *p,  struct brw_instruction *brw_BREAK(struct brw_compile *p, int pop_count)  { +   struct intel_context *intel = &p->brw->intel;     struct brw_instruction *insn; +     insn = next_insn(p, BRW_OPCODE_BREAK); -   brw_set_dest(insn, brw_ip_reg()); -   brw_set_src0(insn, brw_ip_reg()); -   brw_set_src1(insn, brw_imm_d(0x0)); +   if (intel->gen >= 6) { +      brw_set_dest(insn, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); +      brw_set_src0(insn, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); +      brw_set_src1(insn, brw_imm_d(0x0)); +   } else { +      brw_set_dest(insn, brw_ip_reg()); +      brw_set_src0(insn, brw_ip_reg()); +      brw_set_src1(insn, brw_imm_d(0x0)); +      insn->bits3.if_else.pad0 = 0; +      insn->bits3.if_else.pop_count = pop_count; +   }     insn->header.compression_control = BRW_COMPRESSION_NONE;     insn->header.execution_size = BRW_EXECUTE_8; -   /* insn->header.mask_control = BRW_MASK_DISABLE; */ -   insn->bits3.if_else.pad0 = 0; -   insn->bits3.if_else.pop_count = pop_count; +     return insn;  } @@ -2013,6 +2021,78 @@ void brw_urb_WRITE(struct brw_compile *p,  		       swizzle);  } +static int +brw_find_next_block_end(struct brw_compile *p, int start) +{ +   int ip; + +   for (ip = start + 1; ip < p->nr_insn; ip++) { +      struct brw_instruction *insn = &p->store[ip]; + +      switch (insn->header.opcode) { +      case BRW_OPCODE_ENDIF: +      case BRW_OPCODE_ELSE: +      case BRW_OPCODE_WHILE: +	 return ip; +      } +   } +   assert(!"not reached"); +   return start + 1; +} + +/* There is no DO instruction on gen6, so to find the end of the loop + * we have to see if the loop is jumping back before our start + * instruction. + */ +static int +brw_find_loop_end(struct brw_compile *p, int start) +{ +   int ip; +   int br = 2; + +   for (ip = start + 1; ip < p->nr_insn; ip++) { +      struct brw_instruction *insn = &p->store[ip]; + +      if (insn->header.opcode == BRW_OPCODE_WHILE) { +	 if (ip + insn->bits1.branch_gen6.jump_count / br < start) +	    return ip; +      } +   } +   assert(!"not reached"); +   return start + 1; +} + +/* After program generation, go back and update the UIP and JIP of + * BREAK and CONT instructions to their correct locations. + */ +void +brw_set_uip_jip(struct brw_compile *p) +{ +   struct intel_context *intel = &p->brw->intel; +   int ip; +   int br = 2; + +   if (intel->gen < 6) +      return; + +   for (ip = 0; ip < p->nr_insn; ip++) { +      struct brw_instruction *insn = &p->store[ip]; + +      switch (insn->header.opcode) { +      case BRW_OPCODE_BREAK: +	 insn->bits3.break_cont.jip = br * (brw_find_next_block_end(p, ip) - ip); +	 insn->bits3.break_cont.uip = br * (brw_find_loop_end(p, ip) - ip + 1); +	 break; +      case BRW_OPCODE_CONTINUE: +	 /* JIP is set at CONTINUE emit time, since that's when we +	  * know where the start of the loop is. +	  */ +	 insn->bits3.break_cont.uip = br * (brw_find_next_block_end(p, ip) - ip); +	 break; +      } +   } +} +  void brw_ff_sync(struct brw_compile *p,  		   struct brw_reg dest,  		   GLuint msg_reg_nr, diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp index cf45fcaa06..46061c77ed 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs.cpp @@ -933,6 +933,10 @@ fs_visitor::visit(ir_expression *ir)        assert(!"not reached: should be handled by lower_noise");        break; +   case ir_quadop_vector: +      assert(!"not reached: should be handled by lower_quadop_vector"); +      break; +     case ir_unop_sqrt:        emit_math(FS_OPCODE_SQRT, this->result, op[0]);        break; @@ -3375,10 +3379,6 @@ fs_visitor::generate_code()  	 break;        case BRW_OPCODE_DO: -	 /* FINISHME: We need to write the loop instruction support still. */ -	 if (intel->gen >= 6) -	    this->fail = true; -  	 loop_stack[loop_stack_depth++] = brw_DO(p, BRW_EXECUTE_8);  	 if_depth_in_loop[loop_stack_depth] = 0;  	 break; @@ -3388,6 +3388,10 @@ fs_visitor::generate_code()  	 brw_set_predicate_control(p, BRW_PREDICATE_NONE);  	 break;        case BRW_OPCODE_CONTINUE: +	 /* FINISHME: We need to write the loop instruction support still. */ +	 if (intel->gen >= 6) +	    this->fail = true; +  	 brw_CONT(p, if_depth_in_loop[loop_stack_depth]);  	 brw_set_predicate_control(p, BRW_PREDICATE_NONE);  	 break; @@ -3491,6 +3495,8 @@ fs_visitor::generate_code()        last_native_inst = p->nr_insn;     } +   brw_set_uip_jip(p); +     /* OK, while the INTEL_DEBUG=wm above is very nice for debugging FS      * emit issues, it doesn't get the jump distances into the output,      * which is often something we want to debug.  So this is here in diff --git a/src/mesa/drivers/dri/i965/brw_structs.h b/src/mesa/drivers/dri/i965/brw_structs.h index 8ce9af9c4f..8f97bd136f 100644 --- a/src/mesa/drivers/dri/i965/brw_structs.h +++ b/src/mesa/drivers/dri/i965/brw_structs.h @@ -1539,6 +1539,21 @@ struct brw_instruction  	 GLuint  pad0:12;        } if_else; +      struct +      { +	 /* Signed jump distance to the ip to jump to if all channels +	  * are disabled after the break or continue.  It should point +	  * to the end of the innermost control flow block, as that's +	  * where some channel could get re-enabled. +	  */ +	 int jip:16; + +	 /* Signed jump distance to the location to resume execution +	  * of this channel if it's enabled for the break or continue. +	  */ +	 int uip:16; +      } break_cont; +        struct {  	 GLuint function:4;  	 GLuint int_type:1; | 
