* native instructions.
*/
-extern "C" {
#include "main/macros.h"
#include "brw_context.h"
#include "brw_eu.h"
-} /* extern "C" */
-
#include "brw_fs.h"
#include "brw_cfg.h"
case BRW_REGISTER_TYPE_UD:
brw_reg = brw_imm_ud(reg->fixed_hw_reg.dw1.ud);
break;
+ case BRW_REGISTER_TYPE_W:
+ brw_reg = brw_imm_w(reg->fixed_hw_reg.dw1.d);
+ break;
+ case BRW_REGISTER_TYPE_UW:
+ brw_reg = brw_imm_uw(reg->fixed_hw_reg.dw1.ud);
+ break;
case BRW_REGISTER_TYPE_VF:
brw_reg = brw_imm_vf(reg->fixed_hw_reg.dw1.ud);
break;
const void *key,
struct brw_stage_prog_data *prog_data,
struct gl_program *prog,
+ unsigned promoted_constants,
bool runtime_check_aads_emit,
const char *stage_abbrev)
: brw(brw), key(key),
prog_data(prog_data),
- prog(prog), runtime_check_aads_emit(runtime_check_aads_emit),
- debug_flag(false), stage_abbrev(stage_abbrev), mem_ctx(mem_ctx)
+ prog(prog), promoted_constants(promoted_constants),
+ runtime_check_aads_emit(runtime_check_aads_emit), debug_flag(false),
+ stage_abbrev(stage_abbrev), mem_ctx(mem_ctx)
{
ctx = &brw->ctx;
if (inst->opcode == FS_OPCODE_REP_FB_WRITE)
msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE_REPLICATED;
- else if (prog_data->dual_src_blend)
- msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_DUAL_SOURCE_SUBSPAN01;
- else if (dispatch_width == 16)
+ else if (prog_data->dual_src_blend) {
+ if (dispatch_width == 8 || !inst->eot)
+ msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_DUAL_SOURCE_SUBSPAN01;
+ else
+ msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_DUAL_SOURCE_SUBSPAN23;
+ } 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;
+ bool last_render_target = inst->eot ||
+ (prog_data->dual_src_blend && dispatch_width == 16);
+
+
brw_fb_WRITE(p,
dispatch_width,
payload,
nr,
0,
inst->eot,
+ last_render_target,
inst->header_present);
brw_mark_surface_used(&prog_data->base, surf_index);
inst->mlen,
0,
true,
+ true,
inst->header_present);
}
if (brw->gen >= 9) {
/* Skylake requires a message header in order to use SIMD4x2 mode. */
- src = retype(brw_vec8_grf(offset.nr - 1, 0), BRW_REGISTER_TYPE_UD);
+ src = retype(brw_vec4_grf(offset.nr - 1, 0), BRW_REGISTER_TYPE_UD);
mlen = 2;
header_present = true;
brw_push_insn_state(p);
brw_set_default_mask_control(p, BRW_MASK_DISABLE);
- brw_MOV(p, src, retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UD));
+ brw_MOV(p, src, retype(brw_vec4_grf(0, 0), BRW_REGISTER_TYPE_UD));
brw_set_default_access_mode(p, BRW_ALIGN_1);
brw_MOV(p, get_element_ud(src, 2),
brw_pop_insn_state(p);
}
-/**
- * Change the register's data type from UD to W, doubling the strides in order
- * to compensate for halving the data type width.
- */
-static struct brw_reg
-ud_reg_to_w(struct brw_reg r)
-{
- assert(r.type == BRW_REGISTER_TYPE_UD);
- r.type = BRW_REGISTER_TYPE_W;
-
- /* The BRW_*_STRIDE enums are defined so that incrementing the field
- * doubles the real stride.
- */
- if (r.hstride != 0)
- ++r.hstride;
- if (r.vstride != 0)
- ++r.vstride;
-
- return r;
-}
-
void
fs_generator::generate_pack_half_2x16_split(fs_inst *inst,
struct brw_reg dst,
* (HorzStride) of 2. The 16-bit result is stored in the lower word of
* each destination channel and the upper word is not modified.
*/
- struct brw_reg dst_w = ud_reg_to_w(dst);
+ struct brw_reg dst_w = spread(retype(dst, BRW_REGISTER_TYPE_W), 2);
- /* Give each 32-bit channel of dst the form below , where "." means
+ /* Give each 32-bit channel of dst the form below, where "." means
* unchanged.
* 0x....hhhh
*/
* the source data type must be Word (W). The destination type must be
* F (Float).
*/
- struct brw_reg src_w = ud_reg_to_w(src);
+ struct brw_reg src_w = spread(retype(src, BRW_REGISTER_TYPE_W), 2);
/* Each channel of src has the form of unpackHalf2x16's input: 0xhhhhllll.
* For the Y case, we wish to access only the upper word; therefore
this->shader_name = shader_name;
}
+/**
+ * Some hardware doesn't support SIMD16 instructions with 3 sources.
+ */
+static bool
+brw_supports_simd16_3src(const struct brw_context *brw)
+{
+ return brw->is_haswell || brw->gen >= 8;
+}
+
int
fs_generator::generate_code(const cfg_t *cfg, int dispatch_width)
{
brw_set_default_compression_control(p, BRW_COMPRESSION_COMPRESSED);
int start_offset = p->next_insn_offset;
+ int spill_count = 0, fill_count = 0;
int loop_count = 0;
struct annotation_info annotation;
foreach_block_and_inst (block, fs_inst, inst, cfg) {
struct brw_reg src[3], dst;
unsigned int last_insn_offset = p->next_insn_offset;
+ bool multiple_instructions_emitted = false;
if (unlikely(debug_flag))
annotate(brw, &annotation, cfg, inst, p->next_insn_offset);
case BRW_OPCODE_MAD:
assert(brw->gen >= 6);
brw_set_default_access_mode(p, BRW_ALIGN_16);
- if (dispatch_width == 16 && brw->gen < 8 && !brw->is_haswell) {
+ if (dispatch_width == 16 && !brw_supports_simd16_3src(brw)) {
brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
- brw_MAD(p, firsthalf(dst), firsthalf(src[0]), firsthalf(src[1]), firsthalf(src[2]));
+ brw_inst *f = brw_MAD(p, firsthalf(dst), firsthalf(src[0]), firsthalf(src[1]), firsthalf(src[2]));
brw_set_default_compression_control(p, BRW_COMPRESSION_2NDHALF);
- brw_MAD(p, sechalf(dst), sechalf(src[0]), sechalf(src[1]), sechalf(src[2]));
+ brw_inst *s = brw_MAD(p, sechalf(dst), sechalf(src[0]), sechalf(src[1]), sechalf(src[2]));
brw_set_default_compression_control(p, BRW_COMPRESSION_COMPRESSED);
+
+ if (inst->conditional_mod) {
+ brw_inst_set_cond_modifier(brw, f, inst->conditional_mod);
+ brw_inst_set_cond_modifier(brw, s, inst->conditional_mod);
+ multiple_instructions_emitted = true;
+ }
} else {
brw_MAD(p, dst, src[0], src[1], src[2]);
}
case BRW_OPCODE_LRP:
assert(brw->gen >= 6);
brw_set_default_access_mode(p, BRW_ALIGN_16);
- if (dispatch_width == 16 && brw->gen < 8 && !brw->is_haswell) {
+ if (dispatch_width == 16 && !brw_supports_simd16_3src(brw)) {
brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
- brw_LRP(p, firsthalf(dst), firsthalf(src[0]), firsthalf(src[1]), firsthalf(src[2]));
+ brw_inst *f = brw_LRP(p, firsthalf(dst), firsthalf(src[0]), firsthalf(src[1]), firsthalf(src[2]));
brw_set_default_compression_control(p, BRW_COMPRESSION_2NDHALF);
- brw_LRP(p, sechalf(dst), sechalf(src[0]), sechalf(src[1]), sechalf(src[2]));
+ brw_inst *s = brw_LRP(p, sechalf(dst), sechalf(src[0]), sechalf(src[1]), sechalf(src[2]));
brw_set_default_compression_control(p, BRW_COMPRESSION_COMPRESSED);
+
+ if (inst->conditional_mod) {
+ brw_inst_set_cond_modifier(brw, f, inst->conditional_mod);
+ brw_inst_set_cond_modifier(brw, s, inst->conditional_mod);
+ multiple_instructions_emitted = true;
+ }
} else {
brw_LRP(p, dst, src[0], src[1], src[2]);
}
brw_F16TO32(p, dst, src[0]);
break;
case BRW_OPCODE_CMP:
- brw_CMP(p, dst, inst->conditional_mod, src[0], src[1]);
+ /* The Ivybridge/BayTrail WaCMPInstFlagDepClearedEarly workaround says
+ * that when the destination is a GRF that the dependency-clear bit on
+ * the flag register is cleared early.
+ *
+ * Suggested workarounds are to disable coissuing CMP instructions
+ * or to split CMP(16) instructions into two CMP(8) instructions.
+ *
+ * We choose to split into CMP(8) instructions since disabling
+ * coissuing would affect CMP instructions not otherwise affected by
+ * the errata.
+ */
+ if (dispatch_width == 16 && brw->gen == 7 && !brw->is_haswell) {
+ if (dst.file == BRW_GENERAL_REGISTER_FILE) {
+ brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
+ brw_CMP(p, firsthalf(dst), inst->conditional_mod,
+ firsthalf(src[0]), firsthalf(src[1]));
+ brw_set_default_compression_control(p, BRW_COMPRESSION_2NDHALF);
+ brw_CMP(p, sechalf(dst), inst->conditional_mod,
+ sechalf(src[0]), sechalf(src[1]));
+ brw_set_default_compression_control(p, BRW_COMPRESSION_COMPRESSED);
+
+ multiple_instructions_emitted = true;
+ } else if (dst.file == BRW_ARCHITECTURE_REGISTER_FILE) {
+ /* For unknown reasons, the aforementioned workaround is not
+ * sufficient. Overriding the type when the destination is the
+ * null register is necessary but not sufficient by itself.
+ */
+ assert(dst.nr == BRW_ARF_NULL);
+ dst.type = BRW_REGISTER_TYPE_D;
+ brw_CMP(p, dst, inst->conditional_mod, src[0], src[1]);
+ } else {
+ unreachable("not reached");
+ }
+ } else {
+ brw_CMP(p, dst, inst->conditional_mod, src[0], src[1]);
+ }
break;
case BRW_OPCODE_SEL:
brw_SEL(p, dst, src[0], src[1]);
case BRW_OPCODE_BFE:
assert(brw->gen >= 7);
brw_set_default_access_mode(p, BRW_ALIGN_16);
- if (dispatch_width == 16 && brw->gen < 8 && !brw->is_haswell) {
+ if (dispatch_width == 16 && !brw_supports_simd16_3src(brw)) {
brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
brw_BFE(p, firsthalf(dst), firsthalf(src[0]), firsthalf(src[1]), firsthalf(src[2]));
brw_set_default_compression_control(p, BRW_COMPRESSION_2NDHALF);
* Otherwise we would be able to emit compressed instructions like we
* do for the other three-source instructions.
*/
- if (dispatch_width == 16 && brw->gen < 8) {
+ if (dispatch_width == 16 &&
+ (brw->is_haswell || !brw_supports_simd16_3src(brw))) {
brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
brw_BFI2(p, firsthalf(dst), firsthalf(src[0]), firsthalf(src[1]), firsthalf(src[2]));
brw_set_default_compression_control(p, BRW_COMPRESSION_2NDHALF);
case SHADER_OPCODE_GEN4_SCRATCH_WRITE:
generate_scratch_write(inst, src[0]);
+ spill_count++;
break;
case SHADER_OPCODE_GEN4_SCRATCH_READ:
generate_scratch_read(inst, dst);
+ fill_count++;
break;
case SHADER_OPCODE_GEN7_SCRATCH_READ:
generate_scratch_read_gen7(inst, dst);
+ fill_count++;
break;
case SHADER_OPCODE_URB_WRITE_SIMD8:
unreachable("Should be lowered by lower_load_payload()");
}
+ if (multiple_instructions_emitted)
+ continue;
+
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 "
if (unlikely(debug_flag)) {
fprintf(stderr, "Native code for %s\n"
- "SIMD%d shader: %d instructions. %d loops. Compacted %d to %d"
+ "SIMD%d shader: %d instructions. %d loops. %d:%d spills:fills. Promoted %u constants. Compacted %d to %d"
" bytes (%.0f%%)\n",
- shader_name,
- dispatch_width, before_size / 16, loop_count, before_size, after_size,
+ shader_name, dispatch_width, before_size / 16, loop_count,
+ spill_count, fill_count, promoted_constants, before_size, after_size,
100.0f * (before_size - after_size) / before_size);
dump_assembly(p->store, annotation.ann_count, annotation.ann, brw, prog);
MESA_DEBUG_SOURCE_SHADER_COMPILER,
MESA_DEBUG_TYPE_OTHER,
MESA_DEBUG_SEVERITY_NOTIFICATION,
- "%s SIMD%d shader: %d inst, %d loops, "
- "compacted %d to %d bytes.\n",
+ "%s SIMD%d shader: %d inst, %d loops, %d:%d spills:fills, "
+ "Promoted %u constants, compacted %d to %d bytes.\n",
stage_abbrev, dispatch_width, before_size / 16, loop_count,
- before_size, after_size);
+ spill_count, fill_count, promoted_constants, before_size, after_size);
return start_offset;
}