#include "brw_wm.h"
/* Only guess, need a flag in gl_fragment_program later */
-GLboolean brw_wm_is_glsl(struct gl_fragment_program *fp)
+GLboolean brw_wm_is_glsl(const struct gl_fragment_program *fp)
{
int i;
for (i = 0; i < fp->Base.NumInstructions; i++) {
struct prog_instruction *inst = &fp->Base.Instructions[i];
switch (inst->Opcode) {
case OPCODE_IF:
+ case OPCODE_INT:
case OPCODE_ENDIF:
case OPCODE_CAL:
case OPCODE_BRK:
case OPCODE_RET:
+ case OPCODE_DDX:
+ case OPCODE_DDY:
case OPCODE_BGNLOOP:
return GL_TRUE;
default:
int i, j;
struct brw_reg reg;
int nr_interp_regs = 0;
- GLuint inputs = FRAG_BIT_WPOS | c->fp_interp_emitted;
+ GLuint inputs = FRAG_BIT_WPOS | c->fp_interp_emitted | c->fp_deriv_emitted;
for (i = 0; i < 4; i++) {
reg = (i < c->key.nr_depth_regs)
c->prog_data.first_curbe_grf = c->key.nr_depth_regs * 2;
c->prog_data.urb_read_length = nr_interp_regs * 2;
c->prog_data.curb_read_length = c->nr_creg;
- c->ret_reg = brw_uw1_reg(BRW_GENERAL_REGISTER_FILE, c->reg_index, 0);
- c->emit_mask_reg = brw_uw1_reg(BRW_GENERAL_REGISTER_FILE, c->reg_index, 1);
+ c->emit_mask_reg = brw_uw1_reg(BRW_GENERAL_REGISTER_FILE, c->reg_index, 0);
c->reg_index++;
+ c->stack = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, c->reg_index, 0);
+ c->reg_index += 2;
}
static struct brw_reg get_dst_reg(struct brw_wm_compile *c,
brw_set_saturate(p, 0);
}
+static void emit_int( struct brw_wm_compile *c,
+ struct prog_instruction *inst)
+{
+ int i;
+ struct brw_compile *p = &c->func;
+ GLuint mask = inst->DstReg.WriteMask;
+ brw_set_saturate(p, inst->SaturateMode != SATURATE_OFF);
+ for (i = 0; i < 4; i++) {
+ if (mask & (1<<i)) {
+ struct brw_reg src, dst;
+ dst = get_dst_reg(c, inst, i, 1) ;
+ src = get_src_reg(c, &inst->SrcReg[0], i, 1);
+ brw_RNDD(p, dst, src);
+ }
+ }
+ brw_set_saturate(p, 0);
+}
+
static void emit_mov( struct brw_wm_compile *c,
struct prog_instruction *inst)
{
static void fire_fb_write( struct brw_wm_compile *c,
GLuint base_reg,
- GLuint nr )
+ GLuint nr,
+ GLuint target,
+ GLuint eot)
{
struct brw_compile *p = &c->func;
-
/* Pass through control information:
*/
/* mov (8) m1.0<1>:ud r1.0<8;8,1>:ud { Align1 NoMask } */
retype(vec8(brw_null_reg()), BRW_REGISTER_TYPE_UW),
base_reg,
retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW),
- 0, /* render surface always 0 */
+ target,
nr,
0,
- 1);
+ eot);
}
static void emit_fb_write(struct brw_wm_compile *c,
struct brw_compile *p = &c->func;
int nr = 2;
int channel;
- struct brw_reg src0;//, src1, src2, dst;
+ GLuint target, eot;
+ struct brw_reg src0;
/* Reserve a space for AA - may not be needed:
*/
nr += 8;
brw_pop_insn_state(p);
}
- fire_fb_write(c, 0, nr);
+
+ if (c->key.source_depth_to_render_target)
+ {
+ if (c->key.computes_depth) {
+ src0 = get_src_reg(c, &inst->SrcReg[2], 2, 1);
+ brw_MOV(p, brw_message_reg(nr), src0);
+ } else {
+ src0 = get_src_reg(c, &inst->SrcReg[1], 1, 1);
+ brw_MOV(p, brw_message_reg(nr), src0);
+ }
+
+ nr += 2;
+ }
+ target = inst->Sampler >> 1;
+ eot = inst->Sampler & 1;
+ fire_fb_write(c, 0, nr, target, eot);
}
static void emit_pixel_w( struct brw_wm_compile *c,
{
emit_sop(c, inst, BRW_CONDITIONAL_NEQ);
}
+
+static void emit_ddx(struct brw_wm_compile *c,
+ struct prog_instruction *inst)
+{
+ struct brw_compile *p = &c->func;
+ GLuint mask = inst->DstReg.WriteMask;
+ struct brw_reg interp[4];
+ struct brw_reg dst;
+ struct brw_reg src0, w;
+ GLuint nr, i;
+ src0 = get_src_reg(c, &inst->SrcReg[0], 0, 1);
+ w = get_src_reg(c, &inst->SrcReg[1], 3, 1);
+ nr = src0.nr;
+ interp[0] = brw_vec1_grf(nr, 0);
+ interp[1] = brw_vec1_grf(nr, 4);
+ interp[2] = brw_vec1_grf(nr+1, 0);
+ interp[3] = brw_vec1_grf(nr+1, 4);
+ brw_set_saturate(p, inst->SaturateMode != SATURATE_OFF);
+ for(i = 0; i < 4; i++ ) {
+ if (mask & (1<<i)) {
+ dst = get_dst_reg(c, inst, i, 1);
+ brw_MOV(p, dst, interp[i]);
+ brw_MUL(p, dst, dst, w);
+ }
+ }
+ brw_set_saturate(p, 0);
+}
+
+static void emit_ddy(struct brw_wm_compile *c,
+ struct prog_instruction *inst)
+{
+ struct brw_compile *p = &c->func;
+ GLuint mask = inst->DstReg.WriteMask;
+ struct brw_reg interp[4];
+ struct brw_reg dst;
+ struct brw_reg src0, w;
+ GLuint nr, i;
+
+ src0 = get_src_reg(c, &inst->SrcReg[0], 0, 1);
+ nr = src0.nr;
+ w = get_src_reg(c, &inst->SrcReg[1], 3, 1);
+ interp[0] = brw_vec1_grf(nr, 0);
+ interp[1] = brw_vec1_grf(nr, 4);
+ interp[2] = brw_vec1_grf(nr+1, 0);
+ interp[3] = brw_vec1_grf(nr+1, 4);
+ brw_set_saturate(p, inst->SaturateMode != SATURATE_OFF);
+ for(i = 0; i < 4; i++ ) {
+ if (mask & (1<<i)) {
+ dst = get_dst_reg(c, inst, i, 1);
+ brw_MOV(p, dst, suboffset(interp[i], 1));
+ brw_MUL(p, dst, dst, w);
+ }
+ }
+ brw_set_saturate(p, 0);
+}
+
+static void emit_wpos_xy(struct brw_wm_compile *c,
+ struct prog_instruction *inst)
+{
+ struct brw_compile *p = &c->func;
+ GLuint mask = inst->DstReg.WriteMask;
+ struct brw_reg src0[2], dst[2];
+
+ dst[0] = get_dst_reg(c, inst, 0, 1);
+ dst[1] = get_dst_reg(c, inst, 1, 1);
+
+ src0[0] = get_src_reg(c, &inst->SrcReg[0], 0, 1);
+ src0[1] = get_src_reg(c, &inst->SrcReg[0], 1, 1);
+
+ /* Calculate the pixel offset from window bottom left into destination
+ * X and Y channels.
+ */
+ if (mask & WRITEMASK_X) {
+ /* X' = X - origin_x */
+ brw_ADD(p,
+ dst[0],
+ retype(src0[0], BRW_REGISTER_TYPE_W),
+ brw_imm_d(0 - c->key.origin_x));
+ }
+
+ if (mask & WRITEMASK_Y) {
+ /* Y' = height - (Y - origin_y) = height + origin_y - Y */
+ brw_ADD(p,
+ dst[1],
+ negate(retype(src0[1], BRW_REGISTER_TYPE_W)),
+ brw_imm_d(c->key.origin_y + c->key.drawable_height - 1));
+ }
+}
+
/* TODO
BIAS on SIMD8 not workind yet...
*/
{
struct brw_compile *p = &c->func;
struct brw_reg dst[4], src[4], payload_reg;
+ GLuint unit = c->fp->program.Base.SamplerUnits[inst->TexSrcUnit];
+
GLuint i;
payload_reg = get_reg(c, PROGRAM_PAYLOAD, PAYLOAD_DEPTH, 0, 1, 0, 0);
for (i = 0; i < 4; i++)
retype(vec8(dst[0]), BRW_REGISTER_TYPE_UW),
1,
retype(payload_reg, BRW_REGISTER_TYPE_UW),
- inst->TexSrcUnit + 1, /* surface */
- inst->TexSrcUnit, /* sampler */
+ unit + MAX_DRAW_BUFFERS, /* surface */
+ unit, /* sampler */
inst->DstReg.WriteMask,
BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS,
4,
{
struct brw_compile *p = &c->func;
struct brw_reg dst[4], src[4], payload_reg;
+ GLuint unit = c->fp->program.Base.SamplerUnits[inst->TexSrcUnit];
+
GLuint msg_len;
GLuint i, nr;
GLuint emit;
+ GLboolean shadow = (c->key.shadowtex_mask & (1<<unit)) ? 1 : 0;
payload_reg = get_reg(c, PROGRAM_PAYLOAD, PAYLOAD_DEPTH, 0, 1, 0, 0);
+
for (i = 0; i < 4; i++)
dst[i] = get_dst_reg(c, inst, i, 1);
for (i = 0; i < 4; i++)
msg_len += 1;
}
+ if (shadow) {
+ brw_MOV(p, brw_message_reg(5), brw_imm_f(0));
+ brw_MOV(p, brw_message_reg(6), src[2]);
+ }
+
brw_SAMPLE(p,
retype(vec8(dst[0]), BRW_REGISTER_TYPE_UW),
1,
retype(payload_reg, BRW_REGISTER_TYPE_UW),
- inst->TexSrcUnit + 1, /* surface */
- inst->TexSrcUnit, /* sampler */
+ unit + MAX_DRAW_BUFFERS, /* surface */
+ unit, /* sampler */
inst->DstReg.WriteMask,
BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE,
4,
- 4,
+ shadow ? 6 : 4,
0);
+
+ if (shadow)
+ brw_MOV(p, dst[3], brw_imm_f(1.0));
}
static void post_wm_emit( struct brw_wm_compile *c )
}
}
-static void brw_wm_emit_glsl(struct brw_wm_compile *c)
-
+static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
{
#define MAX_IFSN 32
#define MAX_LOOP_DEPTH 32
struct brw_instruction *inst0, *inst1;
int i, if_insn = 0, loop_insn = 0;
struct brw_compile *p = &c->func;
- brw_init_compile(&c->func);
+ struct brw_indirect stack_index = brw_indirect(0, 0);
+
c->reg_index = 0;
prealloc_reg(c);
brw_set_compression_control(p, BRW_COMPRESSION_NONE);
+ brw_MOV(p, get_addr_reg(stack_index), brw_address(c->stack));
+
for (i = 0; i < c->nr_fp_insns; i++) {
struct prog_instruction *inst = &c->prog_instructions[i];
struct prog_instruction *orig_inst;
if ((orig_inst = inst->Data) != 0)
orig_inst->Data = current_insn(p);
+ if (inst->CondUpdate)
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
+ else
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_NONE);
+
switch (inst->Opcode) {
case WM_PIXELXY:
emit_pixel_xy(c, inst);
case WM_CINTERP:
emit_cinterp(c, inst);
break;
+ case WM_WPOSXY:
+ emit_wpos_xy(c, inst);
+ break;
case WM_FB_WRITE:
emit_fb_write(c, inst);
break;
case OPCODE_LRP:
emit_lrp(c, inst);
break;
+ case OPCODE_INT:
+ emit_int(c, inst);
+ break;
case OPCODE_MOV:
emit_mov(c, inst);
break;
case OPCODE_MIN:
emit_min(c, inst);
break;
+ case OPCODE_DDX:
+ emit_ddx(c, inst);
+ break;
+ case OPCODE_DDY:
+ emit_ddy(c, inst);
+ break;
case OPCODE_SLT:
emit_slt(c, inst);
break;
case OPCODE_CAL:
brw_push_insn_state(p);
brw_set_mask_control(p, BRW_MASK_DISABLE);
- brw_set_predicate_control(p, BRW_PREDICATE_NONE);
- brw_ADD(p, c->ret_reg, brw_ip_reg(), brw_imm_d(2*16));
- orig_inst = inst->Data;
- orig_inst->Data = current_insn(p);
- brw_ADD(p, brw_ip_reg(), brw_ip_reg(), brw_imm_d(1*16));
- brw_pop_insn_state(p);
+ brw_set_access_mode(p, BRW_ALIGN_1);
+ brw_ADD(p, deref_1ud(stack_index, 0), brw_ip_reg(), brw_imm_d(3*16));
+ brw_set_access_mode(p, BRW_ALIGN_16);
+ brw_ADD(p, get_addr_reg(stack_index),
+ get_addr_reg(stack_index), brw_imm_d(4));
+ orig_inst = inst->Data;
+ orig_inst->Data = &p->store[p->nr_insn];
+ brw_ADD(p, brw_ip_reg(), brw_ip_reg(), brw_imm_d(1*16));
+ brw_pop_insn_state(p);
break;
+
case OPCODE_RET:
brw_push_insn_state(p);
brw_set_mask_control(p, BRW_MASK_DISABLE);
- brw_set_predicate_control(p, BRW_PREDICATE_NONE);
- brw_MOV(p, brw_ip_reg(), c->ret_reg);
+ brw_ADD(p, get_addr_reg(stack_index),
+ get_addr_reg(stack_index), brw_imm_d(-4));
+ brw_set_access_mode(p, BRW_ALIGN_1);
+ brw_MOV(p, brw_ip_reg(), deref_1ud(stack_index, 0));
+ brw_set_access_mode(p, BRW_ALIGN_16);
brw_pop_insn_state(p);
+
break;
case OPCODE_BGNLOOP:
loop_inst[loop_insn++] = brw_DO(p, BRW_EXECUTE_8);
break;
case OPCODE_BRK:
- brw_set_predicate_control(p, BRW_PREDICATE_NORMAL);
brw_BREAK(p);
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
break;
+ case OPCODE_CONT:
+ brw_CONT(p);
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ break;
case OPCODE_ENDLOOP:
loop_insn--;
inst0 = inst1 = brw_WHILE(p, loop_inst[loop_insn]);
if (inst0->header.opcode == BRW_OPCODE_BREAK) {
inst0->bits3.if_else.jump_count = inst1 - inst0 + 1;
inst0->bits3.if_else.pop_count = 0;
- }
+ } else if (inst0->header.opcode == BRW_OPCODE_CONTINUE) {
+ inst0->bits3.if_else.jump_count = inst1 - inst0;
+ inst0->bits3.if_else.pop_count = 0;
+ }
}
break;
default:
_mesa_printf("unsupported IR in fragment shader %d\n",
inst->Opcode);
}
+ if (inst->CondUpdate)
+ brw_set_predicate_control(p, BRW_PREDICATE_NORMAL);
+ else
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
}
post_wm_emit(c);
+ for (i = 0; i < c->fp->program.Base.NumInstructions; i++)
+ c->fp->program.Base.Instructions[i].Data = NULL;
}
-void brw_wm_glsl_emit(struct brw_wm_compile *c)
+void brw_wm_glsl_emit(struct brw_context *brw, struct brw_wm_compile *c)
{
brw_wm_pass_fp(c);
c->tmp_index = 127;
- brw_wm_emit_glsl(c);
+ brw_wm_emit_glsl(brw, c);
c->prog_data.total_grf = c->reg_index;
c->prog_data.total_scratch = 0;
}