/** * This just eliminates instructions with null dst so far. */ static void eliminate_dead_code(struct toy_compiler *tc) { struct toy_inst *inst; tc_head(tc); while ((inst = tc_next(tc)) != NULL) { switch (inst->opcode) { case GEN6_OPCODE_IF: case GEN6_OPCODE_ELSE: case GEN6_OPCODE_ENDIF: case GEN6_OPCODE_WHILE: case GEN6_OPCODE_BREAK: case GEN6_OPCODE_CONT: case GEN6_OPCODE_SEND: case GEN6_OPCODE_SENDC: case GEN6_OPCODE_NOP: /* never eliminated */ break; default: if (tdst_is_null(inst->dst) || !inst->dst.writemask) { /* math is always GEN6_COND_NORMAL */ if ((inst->opcode == GEN6_OPCODE_MATH || inst->cond_modifier == GEN6_COND_NORMAL) && !inst->acc_wr_ctrl) tc_discard_inst(tc, inst); } break; } } }
static void fs_lower_opcode_derivative(struct toy_compiler *tc, struct toy_inst *inst) { struct toy_dst dst[4]; struct toy_src src[4]; int i; tdst_transpose(inst->dst, dst); tsrc_transpose(inst->src[0], src); /* * Every four fragments are from a 2x2 subspan, with * * fragment 1 on the top-left, * fragment 2 on the top-right, * fragment 3 on the bottom-left, * fragment 4 on the bottom-right. * * DDX should thus produce * * dst = src.yyww - src.xxzz * * and DDY should produce * * dst = src.zzww - src.xxyy * * But since we are in BRW_ALIGN_1, swizzling does not work and we have to * play with the region parameters. */ if (inst->opcode == TOY_OPCODE_DDX) { for (i = 0; i < 4; i++) { struct toy_src left, right; left = tsrc_rect(src[i], TOY_RECT_220); right = tsrc_offset(left, 0, 1); tc_ADD(tc, dst[i], right, tsrc_negate(left)); } } else { for (i = 0; i < 4; i++) { struct toy_src top, bottom; /* approximate with dst = src.zzzz - src.xxxx */ top = tsrc_rect(src[i], TOY_RECT_440); bottom = tsrc_offset(top, 0, 2); tc_ADD(tc, dst[i], bottom, tsrc_negate(top)); } } tc_discard_inst(tc, inst); }
static void vs_lower_opcode_tgsi_indirect(struct vs_compile_context *vcc, struct toy_inst *inst) { struct toy_compiler *tc = &vcc->tc; enum tgsi_file_type file; int dim, idx; struct toy_src indirect_dim, indirect_idx; assert(inst->src[0].file == TOY_FILE_IMM); file = inst->src[0].val32; assert(inst->src[1].file == TOY_FILE_IMM); dim = inst->src[1].val32; indirect_dim = inst->src[2]; assert(inst->src[3].file == TOY_FILE_IMM); idx = inst->src[3].val32; indirect_idx = inst->src[4]; /* no dimension indirection */ assert(indirect_dim.file == TOY_FILE_IMM); dim += indirect_dim.val32; switch (inst->opcode) { case TOY_OPCODE_TGSI_INDIRECT_FETCH: if (file == TGSI_FILE_CONSTANT) { if (idx) { struct toy_dst tmp = tc_alloc_tmp(tc); tc_ADD(tc, tmp, indirect_idx, tsrc_imm_d(idx)); indirect_idx = tsrc_from(tmp); } if (ilo_dev_gen(tc->dev) >= ILO_GEN(7)) vs_lower_opcode_tgsi_const_gen7(vcc, inst->dst, dim, indirect_idx); else vs_lower_opcode_tgsi_const_gen6(vcc, inst->dst, dim, indirect_idx); break; } /* fall through */ case TOY_OPCODE_TGSI_INDIRECT_STORE: default: tc_fail(tc, "unhandled TGSI indirection"); break; } tc_discard_inst(tc, inst); }
static void fs_lower_opcode_kil(struct toy_compiler *tc, struct toy_inst *inst) { struct toy_dst pixel_mask_dst; struct toy_src f0, pixel_mask; struct toy_inst *tmp; /* lower half of r1.7:ud */ pixel_mask_dst = tdst_uw(tdst(TOY_FILE_GRF, 1, 7 * 4)); pixel_mask = tsrc_rect(tsrc_from(pixel_mask_dst), TOY_RECT_010); f0 = tsrc_rect(tsrc_uw(tsrc(TOY_FILE_ARF, BRW_ARF_FLAG, 0)), TOY_RECT_010); /* KILP or KIL */ if (tsrc_is_null(inst->src[0])) { struct toy_src dummy = tsrc_uw(tsrc(TOY_FILE_GRF, 0, 0)); struct toy_dst f0_dst = tdst_uw(tdst(TOY_FILE_ARF, BRW_ARF_FLAG, 0)); /* create a mask that masks out all pixels */ tmp = tc_MOV(tc, f0_dst, tsrc_rect(tsrc_imm_uw(0xffff), TOY_RECT_010)); tmp->exec_size = BRW_EXECUTE_1; tmp->mask_ctrl = BRW_MASK_DISABLE; tc_CMP(tc, tdst_null(), dummy, dummy, BRW_CONDITIONAL_NEQ); /* swapping the two src operands breaks glBitmap()!? */ tmp = tc_AND(tc, pixel_mask_dst, f0, pixel_mask); tmp->exec_size = BRW_EXECUTE_1; tmp->mask_ctrl = BRW_MASK_DISABLE; } else { struct toy_src src[4]; int i; tsrc_transpose(inst->src[0], src); /* mask out killed pixels */ for (i = 0; i < 4; i++) { tc_CMP(tc, tdst_null(), src[i], tsrc_imm_f(0.0f), BRW_CONDITIONAL_GE); /* swapping the two src operands breaks glBitmap()!? */ tmp = tc_AND(tc, pixel_mask_dst, f0, pixel_mask); tmp->exec_size = BRW_EXECUTE_1; tmp->mask_ctrl = BRW_MASK_DISABLE; } } tc_discard_inst(tc, inst); }
static void gs_lower_opcode_tgsi_direct(struct gs_compile_context *gcc, struct toy_inst *inst) { struct toy_compiler *tc = &gcc->tc; int dim, idx; assert(inst->src[0].file == TOY_FILE_IMM); dim = inst->src[0].val32; assert(inst->src[1].file == TOY_FILE_IMM); idx = inst->src[1].val32; switch (inst->opcode) { case TOY_OPCODE_TGSI_IN: gs_lower_opcode_tgsi_in(gcc, inst->dst, dim, idx); /* fetch all dimensions */ if (dim == 0) { int i; for (i = 1; i < gcc->in_vue_count; i++) { const int vrf = toy_tgsi_get_vrf(&gcc->tgsi, TGSI_FILE_INPUT, i, idx); struct toy_dst dst; if (vrf < 0) continue; dst = tdst(TOY_FILE_VRF, vrf, 0); gs_lower_opcode_tgsi_in(gcc, dst, i, idx); } } break; case TOY_OPCODE_TGSI_IMM: assert(!dim); gs_lower_opcode_tgsi_imm(gcc, inst->dst, idx); break; case TOY_OPCODE_TGSI_CONST: case TOY_OPCODE_TGSI_SV: default: tc_fail(tc, "unhandled TGSI fetch"); break; } tc_discard_inst(tc, inst); }
static void vs_lower_opcode_tgsi_direct(struct vs_compile_context *vcc, struct toy_inst *inst) { struct toy_compiler *tc = &vcc->tc; int dim, idx; assert(inst->src[0].file == TOY_FILE_IMM); dim = inst->src[0].val32; assert(inst->src[1].file == TOY_FILE_IMM); idx = inst->src[1].val32; switch (inst->opcode) { case TOY_OPCODE_TGSI_IN: vs_lower_opcode_tgsi_in(vcc, inst->dst, dim, idx); break; case TOY_OPCODE_TGSI_CONST: if (ilo_dev_gen(tc->dev) >= ILO_GEN(7)) vs_lower_opcode_tgsi_const_gen7(vcc, inst->dst, dim, inst->src[1]); else vs_lower_opcode_tgsi_const_gen6(vcc, inst->dst, dim, inst->src[1]); break; case TOY_OPCODE_TGSI_SV: vs_lower_opcode_tgsi_sv(vcc, inst->dst, dim, idx); break; case TOY_OPCODE_TGSI_IMM: assert(!dim); vs_lower_opcode_tgsi_imm(vcc, inst->dst, idx); break; default: tc_fail(tc, "unhandled TGSI fetch"); break; } tc_discard_inst(tc, inst); }
static void gs_lower_virtual_opcodes(struct gs_compile_context *gcc) { struct toy_compiler *tc = &gcc->tc; struct toy_inst *inst; tc_head(tc); while ((inst = tc_next(tc)) != NULL) { switch (inst->opcode) { case TOY_OPCODE_TGSI_IN: case TOY_OPCODE_TGSI_CONST: case TOY_OPCODE_TGSI_SV: case TOY_OPCODE_TGSI_IMM: gs_lower_opcode_tgsi_direct(gcc, inst); break; case TOY_OPCODE_TGSI_INDIRECT_FETCH: case TOY_OPCODE_TGSI_INDIRECT_STORE: /* TODO similar to VS */ tc_fail(tc, "no indirection support"); tc_discard_inst(tc, inst); break; case TOY_OPCODE_TGSI_TEX: case TOY_OPCODE_TGSI_TXB: case TOY_OPCODE_TGSI_TXD: case TOY_OPCODE_TGSI_TXL: case TOY_OPCODE_TGSI_TXP: case TOY_OPCODE_TGSI_TXF: case TOY_OPCODE_TGSI_TXQ: case TOY_OPCODE_TGSI_TXQ_LZ: case TOY_OPCODE_TGSI_TEX2: case TOY_OPCODE_TGSI_TXB2: case TOY_OPCODE_TGSI_TXL2: case TOY_OPCODE_TGSI_SAMPLE: case TOY_OPCODE_TGSI_SAMPLE_I: case TOY_OPCODE_TGSI_SAMPLE_I_MS: case TOY_OPCODE_TGSI_SAMPLE_B: case TOY_OPCODE_TGSI_SAMPLE_C: case TOY_OPCODE_TGSI_SAMPLE_C_LZ: case TOY_OPCODE_TGSI_SAMPLE_D: case TOY_OPCODE_TGSI_SAMPLE_L: case TOY_OPCODE_TGSI_GATHER4: case TOY_OPCODE_TGSI_SVIEWINFO: case TOY_OPCODE_TGSI_SAMPLE_POS: case TOY_OPCODE_TGSI_SAMPLE_INFO: /* TODO similar to VS */ tc_fail(tc, "no sampling support"); tc_discard_inst(tc, inst); break; case TOY_OPCODE_EMIT: gs_lower_opcode_emit(gcc, inst); tc_discard_inst(tc, inst); break; case TOY_OPCODE_ENDPRIM: gs_lower_opcode_endprim(gcc, inst); tc_discard_inst(tc, inst); break; default: break; } } tc_head(tc); while ((inst = tc_next(tc)) != NULL) { switch (inst->opcode) { case TOY_OPCODE_INV: case TOY_OPCODE_LOG: case TOY_OPCODE_EXP: case TOY_OPCODE_SQRT: case TOY_OPCODE_RSQ: case TOY_OPCODE_SIN: case TOY_OPCODE_COS: case TOY_OPCODE_FDIV: case TOY_OPCODE_POW: case TOY_OPCODE_INT_DIV_QUOTIENT: case TOY_OPCODE_INT_DIV_REMAINDER: toy_compiler_lower_math(tc, inst); break; case TOY_OPCODE_URB_WRITE: toy_compiler_lower_to_send(tc, inst, false, GEN6_SFID_URB); break; default: if (inst->opcode > 127) tc_fail(tc, "unhandled virtual opcode"); break; } } }