struct gl_shader_program *prog,
struct gl_fragment_program *fp,
bool dual_source_output,
+ bool runtime_check_aads_emit,
bool debug_flag)
: brw(brw), key(key), prog_data(prog_data), prog(prog), fp(fp),
- dual_source_output(dual_source_output), debug_flag(debug_flag),
+ dual_source_output(dual_source_output),
+ runtime_check_aads_emit(runtime_check_aads_emit), debug_flag(debug_flag),
mem_ctx(mem_ctx)
{
ctx = &brw->ctx;
* included GPU hangs and sparkly rendering on the piglit discard
* tests.
*/
- struct brw_instruction *last_halt = gen6_HALT(p);
- last_halt->bits3.break_cont.uip = 2;
- last_halt->bits3.break_cont.jip = 2;
+ brw_inst *last_halt = gen6_HALT(p);
+ brw_inst_set_uip(brw, last_halt, 2);
+ brw_inst_set_jip(brw, last_halt, 2);
int ip = p->nr_insn;
- foreach_list(node, &this->discard_halt_patches) {
- ip_record *patch_ip = (ip_record *)node;
- struct brw_instruction *patch = &p->store[patch_ip->ip];
+ foreach_in_list(ip_record, patch_ip, &discard_halt_patches) {
+ brw_inst *patch = &p->store[patch_ip->ip];
- assert(patch->header.opcode == BRW_OPCODE_HALT);
+ assert(brw_inst_opcode(brw, patch) == BRW_OPCODE_HALT);
/* HALT takes a half-instruction distance from the pre-incremented IP. */
- patch->bits3.break_cont.uip = (ip - patch_ip->ip) * 2;
+ brw_inst_set_uip(brw, patch, (ip - patch_ip->ip) * 2);
}
this->discard_halt_patches.make_empty();
return true;
}
+void
+fs_generator::fire_fb_write(fs_inst *inst,
+ GLuint base_reg,
+ struct brw_reg implied_header,
+ GLuint nr)
+{
+ uint32_t msg_control;
+
+ if (brw->gen < 6) {
+ brw_push_insn_state(p);
+ brw_set_default_mask_control(p, BRW_MASK_DISABLE);
+ brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
+ brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
+ brw_MOV(p,
+ brw_message_reg(base_reg + 1),
+ brw_vec8_grf(1, 0));
+ brw_pop_insn_state(p);
+ }
+
+ if (this->dual_source_output)
+ msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_DUAL_SOURCE_SUBSPAN01;
+ else if (dispatch_width == 16)
+ msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE;
+ else
+ msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_SINGLE_SOURCE_SUBSPAN01;
+
+ uint32_t surf_index =
+ prog_data->binding_table.render_target_start + inst->target;
+
+ brw_fb_WRITE(p,
+ dispatch_width,
+ base_reg,
+ implied_header,
+ msg_control,
+ surf_index,
+ nr,
+ 0,
+ inst->eot,
+ inst->header_present);
+
+ brw_mark_surface_used(&prog_data->base, surf_index);
+}
+
void
fs_generator::generate_fb_write(fs_inst *inst)
{
- bool eot = inst->eot;
struct brw_reg implied_header;
- uint32_t msg_control;
/* Header is 2 regs, g0 and g1 are the contents. g0 will be implied
* move, here's g1.
*/
- brw_push_insn_state(p);
- brw_set_default_mask_control(p, BRW_MASK_DISABLE);
- brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
- brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
-
if (inst->header_present) {
+ brw_push_insn_state(p);
+ brw_set_default_mask_control(p, BRW_MASK_DISABLE);
+ brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
+ brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
+
/* On HSW, the GPU will use the predicate on SENDC, unless the header is
* present.
*/
implied_header = brw_null_reg();
} else {
implied_header = retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW);
-
- brw_MOV(p,
- brw_message_reg(inst->base_mrf + 1),
- brw_vec8_grf(1, 0));
}
+
+ brw_pop_insn_state(p);
} else {
implied_header = brw_null_reg();
}
- if (this->dual_source_output)
- msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_DUAL_SOURCE_SUBSPAN01;
- else if (dispatch_width == 16)
- msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE;
- else
- msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_SINGLE_SOURCE_SUBSPAN01;
-
- brw_pop_insn_state(p);
-
- uint32_t surf_index =
- prog_data->binding_table.render_target_start + inst->target;
- brw_fb_WRITE(p,
- dispatch_width,
- inst->base_mrf,
- implied_header,
- msg_control,
- surf_index,
- inst->mlen,
- 0,
- eot,
- inst->header_present);
-
- brw_mark_surface_used(&prog_data->base, surf_index);
+ if (!runtime_check_aads_emit) {
+ fire_fb_write(inst, inst->base_mrf, implied_header, inst->mlen);
+ } else {
+ /* This can only happen in gen < 6 */
+ assert(brw->gen < 6);
+
+ struct brw_reg v1_null_ud = vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_UD));
+
+ /* Check runtime bit to detect if we have to send AA data or not */
+ brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
+ brw_AND(p,
+ v1_null_ud,
+ retype(brw_vec1_grf(1, 6), BRW_REGISTER_TYPE_UD),
+ brw_imm_ud(1<<26));
+ brw_inst_set_cond_modifier(brw, brw_last_inst, BRW_CONDITIONAL_NZ);
+
+ int jmp = brw_JMPI(p, brw_imm_ud(0), BRW_PREDICATE_NORMAL) - p->store;
+ brw_inst_set_exec_size(brw, brw_last_inst, BRW_EXECUTE_1);
+ {
+ /* Don't send AA data */
+ fire_fb_write(inst, inst->base_mrf+1, implied_header, inst->mlen-1);
+ }
+ brw_land_fwd_jump(p, jmp);
+ fire_fb_write(inst, inst->base_mrf, implied_header, inst->mlen);
+ }
}
void
}
void
-fs_generator::generate_math1_gen7(fs_inst *inst,
- struct brw_reg dst,
- struct brw_reg src0)
-{
- assert(inst->mlen == 0);
- brw_math(p, dst,
- brw_math_function(inst->opcode),
- 0, src0,
- BRW_MATH_DATA_VECTOR,
- BRW_MATH_PRECISION_FULL);
-}
-
-void
-fs_generator::generate_math2_gen7(fs_inst *inst,
- struct brw_reg dst,
- struct brw_reg src0,
- struct brw_reg src1)
-{
- assert(inst->mlen == 0);
- brw_math2(p, dst, brw_math_function(inst->opcode), src0, src1);
-}
-
-void
-fs_generator::generate_math1_gen6(fs_inst *inst,
- struct brw_reg dst,
- struct brw_reg src0)
-{
- int op = brw_math_function(inst->opcode);
-
- assert(inst->mlen == 0);
-
- brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
- brw_math(p, dst,
- op,
- 0, src0,
- BRW_MATH_DATA_VECTOR,
- BRW_MATH_PRECISION_FULL);
-
- if (dispatch_width == 16) {
- brw_set_default_compression_control(p, BRW_COMPRESSION_2NDHALF);
- brw_math(p, sechalf(dst),
- op,
- 0, sechalf(src0),
- BRW_MATH_DATA_VECTOR,
- BRW_MATH_PRECISION_FULL);
- brw_set_default_compression_control(p, BRW_COMPRESSION_COMPRESSED);
- }
-}
-
-void
-fs_generator::generate_math2_gen6(fs_inst *inst,
- struct brw_reg dst,
- struct brw_reg src0,
- struct brw_reg src1)
+fs_generator::generate_math_gen6(fs_inst *inst,
+ struct brw_reg dst,
+ struct brw_reg src0,
+ struct brw_reg src1)
{
int op = brw_math_function(inst->opcode);
-
- assert(inst->mlen == 0);
+ bool binop = src1.file == BRW_GENERAL_REGISTER_FILE;
brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
- brw_math2(p, dst, op, src0, src1);
+ gen6_math(p, dst, op, src0, src1);
if (dispatch_width == 16) {
brw_set_default_compression_control(p, BRW_COMPRESSION_2NDHALF);
- brw_math2(p, sechalf(dst), op, sechalf(src0), sechalf(src1));
+ gen6_math(p, sechalf(dst), op, sechalf(src0),
+ binop ? sechalf(src1) : brw_null_reg());
brw_set_default_compression_control(p, BRW_COMPRESSION_COMPRESSED);
}
}
assert(inst->mlen >= 1);
brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
- brw_math(p, dst,
- op,
- inst->base_mrf, src,
- BRW_MATH_DATA_VECTOR,
- BRW_MATH_PRECISION_FULL);
+ gen4_math(p, dst,
+ op,
+ inst->base_mrf, src,
+ BRW_MATH_DATA_VECTOR,
+ BRW_MATH_PRECISION_FULL);
if (dispatch_width == 16) {
brw_set_default_compression_control(p, BRW_COMPRESSION_2NDHALF);
- brw_math(p, sechalf(dst),
- op,
- inst->base_mrf + 1, sechalf(src),
- BRW_MATH_DATA_VECTOR,
- BRW_MATH_PRECISION_FULL);
+ gen4_math(p, sechalf(dst),
+ op,
+ inst->base_mrf + 1, sechalf(src),
+ BRW_MATH_DATA_VECTOR,
+ BRW_MATH_PRECISION_FULL);
brw_set_default_compression_control(p, BRW_COMPRESSION_COMPRESSED);
}
assert(inst->mlen >= 1);
- brw_math(p, dst,
- op,
- inst->base_mrf, src,
- BRW_MATH_DATA_VECTOR,
- BRW_MATH_PRECISION_FULL);
+ gen4_math(p, dst,
+ op,
+ inst->base_mrf, src,
+ BRW_MATH_DATA_VECTOR,
+ BRW_MATH_PRECISION_FULL);
}
void
case SHADER_OPCODE_TXD:
if (inst->shadow_compare) {
/* Gen7.5+. Otherwise, lowered by brw_lower_texture_gradients(). */
- assert(brw->is_haswell);
+ assert(brw->gen >= 8 || brw->is_haswell);
msg_type = HSW_SAMPLER_MESSAGE_SAMPLE_DERIV_COMPARE;
} else {
msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_DERIVS;
}
break;
default:
- assert(!"not reached");
- break;
+ unreachable("not reached");
}
} else {
switch (inst->opcode) {
simd_mode = BRW_SAMPLER_SIMD_MODE_SIMD16;
break;
default:
- assert(!"not reached");
- break;
+ unreachable("not reached");
}
}
assert(msg_type != -1);
* offset, and each sampler state is only 16-bytes, so we can't
* exclusively use the offset - we have to use both.
*/
- assert(brw->is_haswell); /* field only exists on Haswell */
+ assert(brw->gen >= 8 || brw->is_haswell);
brw_ADD(p,
get_element_ud(header_reg, 3),
get_element_ud(brw_vec8_grf(0, 0), 3),
brw_push_insn_state(p);
brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
brw_set_default_mask_control(p, BRW_MASK_DISABLE);
- struct brw_instruction *send = brw_next_insn(p, BRW_OPCODE_SEND);
+ brw_inst *send = brw_next_insn(p, BRW_OPCODE_SEND);
brw_pop_insn_state(p);
/* We use the SIMD4x2 mode because we want to end up with 4 components in
struct brw_reg header = brw_vec8_grf(0, 0);
gen6_resolve_implied_move(p, &header, inst->base_mrf);
- struct brw_instruction *send = brw_next_insn(p, BRW_OPCODE_SEND);
- send->header.compression_control = BRW_COMPRESSION_NONE;
+ brw_inst *send = brw_next_insn(p, BRW_OPCODE_SEND);
+ brw_inst_set_qtr_control(brw, send, BRW_COMPRESSION_NONE);
brw_set_dest(p, send, retype(dst, BRW_REGISTER_TYPE_UW));
brw_set_src0(p, send, header);
if (brw->gen < 6)
- send->header.destreg__conditionalmod = inst->base_mrf;
+ brw_inst_set_base_mrf(brw, send, inst->base_mrf);
/* Our surface is set up as floats, regardless of what actual data is
* stored in it.
simd_mode = BRW_SAMPLER_SIMD_MODE_SIMD8;
}
- struct brw_instruction *send = brw_next_insn(p, BRW_OPCODE_SEND);
+ brw_inst *send = brw_next_insn(p, BRW_OPCODE_SEND);
brw_set_dest(p, send, dst);
brw_set_src0(p, send, offset);
brw_set_sampler_message(p, send,
case IMM:
return BRW_IMMEDIATE_VALUE;
default:
- assert(!"not reached");
- return BRW_GENERAL_REGISTER_FILE;
+ unreachable("not reached");
}
}
brw_reg = brw_imm_ud(reg->imm.u);
break;
default:
- assert(!"not reached");
- brw_reg = brw_null_reg();
- break;
+ unreachable("not reached");
}
break;
case HW_REG:
brw_reg = brw_null_reg();
break;
case UNIFORM:
- assert(!"not reached");
- brw_reg = brw_null_reg();
- break;
+ unreachable("not reached");
default:
- assert(!"not reached");
- brw_reg = brw_null_reg();
- break;
+ unreachable("not reached");
}
if (reg->abs)
brw_reg = brw_abs(brw_reg);
}
void
-fs_generator::generate_code(exec_list *instructions,
- struct annotation_info *annotation)
+fs_generator::generate_code(exec_list *instructions)
{
- if (unlikely(debug_flag)) {
- if (prog) {
- fprintf(stderr,
- "Native code for %s fragment shader %d (SIMD%d dispatch):\n",
- prog->Label ? prog->Label : "unnamed",
- prog->Name, dispatch_width);
- } else if (fp) {
- fprintf(stderr,
- "Native code for fragment program %d (SIMD%d dispatch):\n",
- fp->Base.Id, dispatch_width);
- } else {
- fprintf(stderr, "Native code for blorp program (SIMD%d dispatch):\n",
- dispatch_width);
- }
- }
+ int start_offset = p->next_insn_offset;
+
+ struct annotation_info annotation;
+ memset(&annotation, 0, sizeof(annotation));
cfg_t *cfg = NULL;
if (unlikely(debug_flag))
cfg = new(mem_ctx) cfg_t(instructions);
- foreach_list(node, instructions) {
- fs_inst *inst = (fs_inst *)node;
+ foreach_in_list(fs_inst, inst, instructions) {
struct brw_reg src[3], dst;
unsigned int last_insn_offset = p->next_insn_offset;
if (unlikely(debug_flag))
- annotate(brw, annotation, cfg, inst, p->next_insn_offset);
+ annotate(brw, &annotation, cfg, inst, p->next_insn_offset);
for (unsigned int i = 0; i < inst->sources; i++) {
src[i] = brw_reg_from_fs_reg(&inst->src[i]);
case BRW_OPCODE_MAD:
assert(brw->gen >= 6);
brw_set_default_access_mode(p, BRW_ALIGN_16);
- if (dispatch_width == 16 && !brw->is_haswell) {
+ if (dispatch_width == 16 && brw->gen < 8 && !brw->is_haswell) {
brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
brw_MAD(p, dst, src[0], src[1], src[2]);
brw_set_default_compression_control(p, BRW_COMPRESSION_2NDHALF);
case BRW_OPCODE_LRP:
assert(brw->gen >= 6);
brw_set_default_access_mode(p, BRW_ALIGN_16);
- if (dispatch_width == 16 && !brw->is_haswell) {
+ if (dispatch_width == 16 && brw->gen < 8 && !brw->is_haswell) {
brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
brw_LRP(p, dst, src[0], src[1], src[2]);
brw_set_default_compression_control(p, BRW_COMPRESSION_2NDHALF);
case BRW_OPCODE_BFE:
assert(brw->gen >= 7);
brw_set_default_access_mode(p, BRW_ALIGN_16);
- if (dispatch_width == 16 && !brw->is_haswell) {
+ if (dispatch_width == 16 && brw->gen < 8 && !brw->is_haswell) {
brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
brw_BFE(p, dst, src[0], src[1], src[2]);
brw_set_default_compression_control(p, BRW_COMPRESSION_2NDHALF);
case SHADER_OPCODE_LOG2:
case SHADER_OPCODE_SIN:
case SHADER_OPCODE_COS:
+ assert(brw->gen < 6 || inst->mlen == 0);
if (brw->gen >= 7) {
- generate_math1_gen7(inst, dst, src[0]);
+ gen6_math(p, dst, brw_math_function(inst->opcode), src[0],
+ brw_null_reg());
} else if (brw->gen == 6) {
- generate_math1_gen6(inst, dst, src[0]);
+ generate_math_gen6(inst, dst, src[0], brw_null_reg());
} else if (brw->gen == 5 || brw->is_g4x) {
generate_math_g45(inst, dst, src[0]);
} else {
case SHADER_OPCODE_INT_QUOTIENT:
case SHADER_OPCODE_INT_REMAINDER:
case SHADER_OPCODE_POW:
+ assert(brw->gen < 6 || inst->mlen == 0);
if (brw->gen >= 7) {
- generate_math2_gen7(inst, dst, src[0], src[1]);
+ gen6_math(p, dst, brw_math_function(inst->opcode), src[0], src[1]);
} else if (brw->gen == 6) {
- generate_math2_gen6(inst, dst, src[0], src[1]);
+ generate_math_gen6(inst, dst, src[0], src[1]);
} else {
generate_math_gen4(inst, dst, src[0]);
}
*/
if (!patch_discard_jumps_to_fb_writes()) {
if (unlikely(debug_flag)) {
- annotation->ann_count--;
+ annotation.ann_count--;
}
}
break;
_mesa_problem(ctx, "Unsupported opcode %d in FS", inst->opcode);
}
abort();
+
+ case SHADER_OPCODE_LOAD_PAYLOAD:
+ unreachable("Should be lowered by lower_load_payload()");
}
- if (inst->conditional_mod) {
- /* Set the conditional modifier on the last instruction we generated.
- * Also, make sure we only emitted one instruction - anything else
- * doesn't make sense.
- */
- assert(p->next_insn_offset == last_insn_offset + 16);
- struct brw_instruction *last = &p->store[last_insn_offset / 16];
- last->header.destreg__conditionalmod = inst->conditional_mod;
+ if (inst->no_dd_clear || inst->no_dd_check || inst->conditional_mod) {
+ assert(p->next_insn_offset == last_insn_offset + 16 ||
+ !"conditional_mod, no_dd_check, or no_dd_clear set for IR "
+ "emitting more than 1 instruction");
+
+ brw_inst *last = &p->store[last_insn_offset / 16];
+
+ brw_inst_set_cond_modifier(brw, last, inst->conditional_mod);
+ brw_inst_set_no_dd_clear(brw, last, inst->no_dd_clear);
+ brw_inst_set_no_dd_check(brw, last, inst->no_dd_check);
}
}
brw_set_uip_jip(p);
- annotation_finalize(annotation, p->next_insn_offset);
+ annotation_finalize(&annotation, p->next_insn_offset);
+
+ int before_size = p->next_insn_offset - start_offset;
+ brw_compact_instructions(p, start_offset, annotation.ann_count,
+ annotation.ann);
+ int after_size = p->next_insn_offset - start_offset;
+
+ if (unlikely(debug_flag)) {
+ if (prog) {
+ fprintf(stderr,
+ "Native code for %s fragment shader %d (SIMD%d dispatch):\n",
+ prog->Label ? prog->Label : "unnamed",
+ prog->Name, dispatch_width);
+ } else if (fp) {
+ fprintf(stderr,
+ "Native code for fragment program %d (SIMD%d dispatch):\n",
+ fp->Base.Id, dispatch_width);
+ } else {
+ fprintf(stderr, "Native code for blorp program (SIMD%d dispatch):\n",
+ dispatch_width);
+ }
+ fprintf(stderr, "SIMD%d shader: %d instructions. Compacted %d to %d"
+ " bytes (%.0f%%)\n",
+ dispatch_width, before_size / 16, before_size, after_size,
+ 100.0f * (before_size - after_size) / before_size);
+
+ const struct gl_program *prog = fp ? &fp->Base : NULL;
+
+ dump_assembly(p->store, annotation.ann_count, annotation.ann, brw, prog);
+ ralloc_free(annotation.ann);
+ }
}
const unsigned *
{
assert(simd8_instructions || simd16_instructions);
- const struct gl_program *prog = fp ? &fp->Base : NULL;
-
if (simd8_instructions) {
- struct annotation_info annotation;
- memset(&annotation, 0, sizeof(annotation));
-
dispatch_width = 8;
- generate_code(simd8_instructions, &annotation);
- brw_compact_instructions(p, 0, annotation.ann_count, annotation.ann);
-
- if (unlikely(debug_flag)) {
- dump_assembly(p->store, annotation.ann_count, annotation.ann,
- brw, prog, brw_disassemble);
- ralloc_free(annotation.ann);
- }
+ generate_code(simd8_instructions);
}
if (simd16_instructions) {
brw_set_default_compression_control(p, BRW_COMPRESSION_COMPRESSED);
- struct annotation_info annotation;
- memset(&annotation, 0, sizeof(annotation));
-
dispatch_width = 16;
- generate_code(simd16_instructions, &annotation);
- brw_compact_instructions(p, prog_data->prog_offset_16,
- annotation.ann_count, annotation.ann);
-
- if (unlikely(debug_flag)) {
- dump_assembly(p->store, annotation.ann_count, annotation.ann,
- brw, prog, brw_disassemble);
- ralloc_free(annotation.ann);
- }
+ generate_code(simd16_instructions);
}
return brw_get_program(p, assembly_size);