void *mem_ctx,
const struct brw_wm_prog_key *key,
struct brw_wm_prog_data *prog_data,
- struct gl_shader_program *prog,
+ struct gl_shader_program *shader_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),
- runtime_check_aads_emit(runtime_check_aads_emit), debug_flag(debug_flag),
- mem_ctx(mem_ctx)
+ : brw(brw), stage(MESA_SHADER_FRAGMENT), key(key),
+ prog_data(&prog_data->base), shader_prog(shader_prog),
+ prog(&fp->Base), runtime_check_aads_emit(runtime_check_aads_emit),
+ debug_flag(debug_flag), mem_ctx(mem_ctx)
{
ctx = &brw->ctx;
if (brw->gen < 6 || this->discard_halt_patches.is_empty())
return false;
+ int scale = brw_jump_scale(brw);
+
/* There is a somewhat strange undocumented requirement of using
* HALT, according to the simulator. If some channel has HALTed to
* a particular UIP, then by the end of the program, every channel
* tests.
*/
brw_inst *last_halt = gen6_HALT(p);
- brw_inst_set_uip(brw, last_halt, 2);
- brw_inst_set_jip(brw, last_halt, 2);
+ brw_inst_set_uip(brw, last_halt, 1 * scale);
+ brw_inst_set_jip(brw, last_halt, 1 * scale);
int ip = p->nr_insn;
- foreach_list(node, &this->discard_halt_patches) {
- ip_record *patch_ip = (ip_record *)node;
+ foreach_in_list(ip_record, patch_ip, &discard_halt_patches) {
brw_inst *patch = &p->store[patch_ip->ip];
assert(brw_inst_opcode(brw, patch) == BRW_OPCODE_HALT);
/* HALT takes a half-instruction distance from the pre-incremented IP. */
- brw_inst_set_uip(brw, patch, (ip - patch_ip->ip) * 2);
+ brw_inst_set_uip(brw, patch, (ip - patch_ip->ip) * scale);
}
this->discard_halt_patches.make_empty();
{
uint32_t msg_control;
+ assert(stage == MESA_SHADER_FRAGMENT);
+ brw_wm_prog_data *prog_data = (brw_wm_prog_data*) this->prog_data;
+
if (brw->gen < 6) {
brw_push_insn_state(p);
brw_set_default_mask_control(p, BRW_MASK_DISABLE);
brw_pop_insn_state(p);
}
- if (this->dual_source_output)
+ 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)
msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE;
void
fs_generator::generate_fb_write(fs_inst *inst)
{
+ assert(stage == MESA_SHADER_FRAGMENT);
+ gl_fragment_program *fp = (gl_fragment_program *) prog;
struct brw_reg implied_header;
+ assert(stage == MESA_SHADER_FRAGMENT);
+ brw_wm_prog_data *prog_data = (brw_wm_prog_data*) this->prog_data;
+
/* Header is 2 regs, g0 and g1 are the contents. g0 will be implied
* move, here's g1.
*/
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_set_default_flag_reg(p, 0, 0);
/* On HSW, the GPU will use the predicate on SENDC, unless the header is
* present.
*/
- if ((fp && fp->UsesKill) || key->alpha_test_func) {
+ if (prog_data->uses_kill || key->alpha_test_func) {
struct brw_reg pixel_mask;
if (brw->gen >= 6)
struct brw_reg src1)
{
int op = brw_math_function(inst->opcode);
- bool binop = src1.file == BRW_GENERAL_REGISTER_FILE;
+ bool binop = src1.file != BRW_ARCHITECTURE_REGISTER_FILE;
brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
gen6_math(p, dst, op, src0, src1);
}
void
-fs_generator::generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src)
+fs_generator::generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src,
+ struct brw_reg sampler_index)
{
int msg_type = -1;
int rlen = 4;
}
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);
src.nr++;
}
+ assert(sampler_index.type == BRW_REGISTER_TYPE_UD);
+
/* Load the message header if present. If there's a texture offset,
* we need to set it up explicitly and load the offset bitfield.
* Otherwise, we can use an implied move from g0 to the first message reg.
brw_imm_ud(inst->texture_offset));
}
- if (inst->sampler >= 16) {
- /* The "Sampler Index" field can only store values between 0 and 15.
- * However, we can add an offset to the "Sampler State Pointer"
- * field, effectively selecting a different set of 16 samplers.
- *
- * The "Sampler State Pointer" needs to be aligned to a 32-byte
- * offset, and each sampler state is only 16-bytes, so we can't
- * exclusively use the offset - we have to use both.
- */
- 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_imm_ud(16 * (inst->sampler / 16) *
- sizeof(gen7_sampler_state)));
- }
+ brw_adjust_sampler_state_pointer(p, header_reg, sampler_index, dst);
brw_pop_insn_state(p);
}
}
- uint32_t surface_index = ((inst->opcode == SHADER_OPCODE_TG4 ||
- inst->opcode == SHADER_OPCODE_TG4_OFFSET)
- ? prog_data->base.binding_table.gather_texture_start
- : prog_data->base.binding_table.texture_start) + inst->sampler;
-
- brw_SAMPLE(p,
- retype(dst, BRW_REGISTER_TYPE_UW),
- inst->base_mrf,
- src,
- surface_index,
- inst->sampler % 16,
- msg_type,
- rlen,
- inst->mlen,
- inst->header_present,
- simd_mode,
- return_format);
-
- brw_mark_surface_used(&prog_data->base, surface_index);
+ uint32_t base_binding_table_index = (inst->opcode == SHADER_OPCODE_TG4 ||
+ inst->opcode == SHADER_OPCODE_TG4_OFFSET)
+ ? prog_data->binding_table.gather_texture_start
+ : prog_data->binding_table.texture_start;
+
+ if (sampler_index.file == BRW_IMMEDIATE_VALUE) {
+ uint32_t sampler = sampler_index.dw1.ud;
+
+ brw_SAMPLE(p,
+ retype(dst, BRW_REGISTER_TYPE_UW),
+ inst->base_mrf,
+ src,
+ sampler + base_binding_table_index,
+ sampler % 16,
+ msg_type,
+ rlen,
+ inst->mlen,
+ inst->header_present,
+ simd_mode,
+ return_format);
+
+ brw_mark_surface_used(prog_data, sampler + base_binding_table_index);
+ } else {
+ /* Non-const sampler index */
+ /* Note: this clobbers `dst` as a temporary before emitting the send */
+
+ struct brw_reg addr = vec1(retype(brw_address_reg(0), BRW_REGISTER_TYPE_UD));
+ struct brw_reg temp = vec1(retype(dst, BRW_REGISTER_TYPE_UD));
+
+ struct brw_reg sampler_reg = vec1(retype(sampler_index, BRW_REGISTER_TYPE_UD));
+
+ brw_push_insn_state(p);
+ brw_set_default_mask_control(p, BRW_MASK_DISABLE);
+ brw_set_default_access_mode(p, BRW_ALIGN_1);
+
+ /* Some care required: `sampler` and `temp` may alias:
+ * addr = sampler & 0xff
+ * temp = (sampler << 8) & 0xf00
+ * addr = addr | temp
+ */
+ brw_ADD(p, addr, sampler_reg, brw_imm_ud(base_binding_table_index));
+ brw_SHL(p, temp, sampler_reg, brw_imm_ud(8u));
+ brw_AND(p, temp, temp, brw_imm_ud(0x0f00));
+ brw_AND(p, addr, addr, brw_imm_ud(0x0ff));
+ brw_OR(p, addr, addr, temp);
+
+ /* a0.0 |= <descriptor> */
+ brw_inst *insn_or = brw_next_insn(p, BRW_OPCODE_OR);
+ brw_set_sampler_message(p, insn_or,
+ 0 /* surface */,
+ 0 /* sampler */,
+ msg_type,
+ rlen,
+ inst->mlen /* mlen */,
+ inst->header_present /* header */,
+ simd_mode,
+ return_format);
+ brw_inst_set_exec_size(p->brw, insn_or, BRW_EXECUTE_1);
+ brw_inst_set_src1_reg_type(p->brw, insn_or, BRW_REGISTER_TYPE_UD);
+ brw_set_src0(p, insn_or, addr);
+ brw_set_dest(p, insn_or, addr);
+
+
+ /* dst = send(offset, a0.0) */
+ brw_inst *insn_send = brw_next_insn(p, BRW_OPCODE_SEND);
+ brw_set_dest(p, insn_send, dst);
+ brw_set_src0(p, insn_send, src);
+ brw_set_indirect_send_descriptor(p, insn_send, BRW_SFID_SAMPLER, addr);
+
+ brw_pop_insn_state(p);
+
+ /* visitor knows more than we do about the surface limit required,
+ * so has already done marking.
+ */
+ }
}
* appropriate swizzling.
*/
void
-fs_generator::generate_ddx(fs_inst *inst, struct brw_reg dst, struct brw_reg src)
+fs_generator::generate_ddx(fs_inst *inst, struct brw_reg dst, struct brw_reg src,
+ struct brw_reg quality)
{
unsigned vstride, width;
+ assert(quality.file == BRW_IMMEDIATE_VALUE);
+ assert(quality.type == BRW_REGISTER_TYPE_D);
+
+ int quality_value = quality.dw1.d;
- if (key->high_quality_derivatives) {
+ if (quality_value == BRW_DERIVATIVE_FINE ||
+ (key->high_quality_derivatives && quality_value != BRW_DERIVATIVE_COARSE)) {
/* produce accurate derivatives */
vstride = BRW_VERTICAL_STRIDE_2;
width = BRW_WIDTH_2;
*/
void
fs_generator::generate_ddy(fs_inst *inst, struct brw_reg dst, struct brw_reg src,
- bool negate_value)
+ struct brw_reg quality, bool negate_value)
{
- if (key->high_quality_derivatives) {
+ assert(quality.file == BRW_IMMEDIATE_VALUE);
+ assert(quality.type == BRW_REGISTER_TYPE_D);
+
+ int quality_value = quality.dw1.d;
+
+ if (quality_value == BRW_DERIVATIVE_FINE ||
+ (key->high_quality_derivatives && quality_value != BRW_DERIVATIVE_COARSE)) {
/* From the Ivy Bridge PRM, volume 4 part 3, section 3.3.9 (Register
* Region Restrictions):
*
brw_oword_block_read(p, dst, brw_message_reg(inst->base_mrf),
read_offset, surf_index);
- brw_mark_surface_used(&prog_data->base, surf_index);
+ brw_mark_surface_used(prog_data, surf_index);
}
void
struct brw_reg offset)
{
assert(inst->mlen == 0);
-
- assert(index.file == BRW_IMMEDIATE_VALUE &&
- index.type == BRW_REGISTER_TYPE_UD);
- uint32_t surf_index = index.dw1.ud;
+ assert(index.type == BRW_REGISTER_TYPE_UD);
assert(offset.file == BRW_GENERAL_REGISTER_FILE);
/* Reference just the dword we need, to avoid angering validate_reg(). */
offset = brw_vec1_grf(offset.nr, 0);
- brw_push_insn_state(p);
- brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
- brw_set_default_mask_control(p, BRW_MASK_DISABLE);
- 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
* the destination loaded consecutively from the same offset (which appears
* in the first component, and the rest are ignored).
*/
dst.width = BRW_WIDTH_4;
- brw_set_dest(p, send, dst);
- brw_set_src0(p, send, offset);
- brw_set_sampler_message(p, send,
- surf_index,
- 0, /* LD message ignores sampler unit */
- GEN5_SAMPLER_MESSAGE_SAMPLE_LD,
- 1, /* rlen */
- 1, /* mlen */
- false, /* no header */
- BRW_SAMPLER_SIMD_MODE_SIMD4X2,
- 0);
- brw_mark_surface_used(&prog_data->base, surf_index);
+ if (index.file == BRW_IMMEDIATE_VALUE) {
+
+ uint32_t surf_index = index.dw1.ud;
+
+ brw_push_insn_state(p);
+ brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
+ brw_set_default_mask_control(p, BRW_MASK_DISABLE);
+ brw_inst *send = brw_next_insn(p, BRW_OPCODE_SEND);
+ brw_pop_insn_state(p);
+
+ brw_set_dest(p, send, dst);
+ brw_set_src0(p, send, offset);
+ brw_set_sampler_message(p, send,
+ surf_index,
+ 0, /* LD message ignores sampler unit */
+ GEN5_SAMPLER_MESSAGE_SAMPLE_LD,
+ 1, /* rlen */
+ 1, /* mlen */
+ false, /* no header */
+ BRW_SAMPLER_SIMD_MODE_SIMD4X2,
+ 0);
+
+ brw_mark_surface_used(prog_data, surf_index);
+
+ } else {
+
+ struct brw_reg addr = vec1(retype(brw_address_reg(0), BRW_REGISTER_TYPE_UD));
+
+ brw_push_insn_state(p);
+ brw_set_default_mask_control(p, BRW_MASK_DISABLE);
+ brw_set_default_access_mode(p, BRW_ALIGN_1);
+
+ /* a0.0 = surf_index & 0xff */
+ brw_inst *insn_and = brw_next_insn(p, BRW_OPCODE_AND);
+ brw_inst_set_exec_size(p->brw, insn_and, BRW_EXECUTE_1);
+ brw_set_dest(p, insn_and, addr);
+ brw_set_src0(p, insn_and, vec1(retype(index, BRW_REGISTER_TYPE_UD)));
+ brw_set_src1(p, insn_and, brw_imm_ud(0x0ff));
+
+
+ /* a0.0 |= <descriptor> */
+ brw_inst *insn_or = brw_next_insn(p, BRW_OPCODE_OR);
+ brw_set_sampler_message(p, insn_or,
+ 0 /* surface */,
+ 0 /* sampler */,
+ GEN5_SAMPLER_MESSAGE_SAMPLE_LD,
+ 1 /* rlen */,
+ 1 /* mlen */,
+ false /* header */,
+ BRW_SAMPLER_SIMD_MODE_SIMD4X2,
+ 0);
+ brw_inst_set_exec_size(p->brw, insn_or, BRW_EXECUTE_1);
+ brw_inst_set_src1_reg_type(p->brw, insn_or, BRW_REGISTER_TYPE_UD);
+ brw_set_src0(p, insn_or, addr);
+ brw_set_dest(p, insn_or, addr);
+
+
+ /* dst = send(offset, a0.0) */
+ brw_inst *insn_send = brw_next_insn(p, BRW_OPCODE_SEND);
+ brw_set_dest(p, insn_send, dst);
+ brw_set_src0(p, insn_send, offset);
+ brw_set_indirect_send_descriptor(p, insn_send, BRW_SFID_SAMPLER, addr);
+
+ brw_pop_insn_state(p);
+
+ /* visitor knows more than we do about the surface limit required,
+ * so has already done marking.
+ */
+
+ }
}
void
simd_mode,
return_format);
- brw_mark_surface_used(&prog_data->base, surf_index);
+ brw_mark_surface_used(prog_data, surf_index);
}
void
*/
assert(!inst->header_present);
assert(!inst->mlen);
-
- assert(index.file == BRW_IMMEDIATE_VALUE &&
- index.type == BRW_REGISTER_TYPE_UD);
- uint32_t surf_index = index.dw1.ud;
+ assert(index.type == BRW_REGISTER_TYPE_UD);
uint32_t simd_mode, rlen, mlen;
if (dispatch_width == 16) {
simd_mode = BRW_SAMPLER_SIMD_MODE_SIMD8;
}
- 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,
- surf_index,
- 0, /* LD message ignores sampler unit */
- GEN5_SAMPLER_MESSAGE_SAMPLE_LD,
- rlen,
- mlen,
- false, /* no header */
- simd_mode,
- 0);
+ if (index.file == BRW_IMMEDIATE_VALUE) {
- brw_mark_surface_used(&prog_data->base, surf_index);
+ uint32_t surf_index = index.dw1.ud;
+
+ 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,
+ surf_index,
+ 0, /* LD message ignores sampler unit */
+ GEN5_SAMPLER_MESSAGE_SAMPLE_LD,
+ rlen,
+ mlen,
+ false, /* no header */
+ simd_mode,
+ 0);
+
+ brw_mark_surface_used(prog_data, surf_index);
+
+ } else {
+
+ struct brw_reg addr = vec1(retype(brw_address_reg(0), BRW_REGISTER_TYPE_UD));
+
+ brw_push_insn_state(p);
+ brw_set_default_mask_control(p, BRW_MASK_DISABLE);
+ brw_set_default_access_mode(p, BRW_ALIGN_1);
+
+ /* a0.0 = surf_index & 0xff */
+ brw_inst *insn_and = brw_next_insn(p, BRW_OPCODE_AND);
+ brw_inst_set_exec_size(p->brw, insn_and, BRW_EXECUTE_1);
+ brw_set_dest(p, insn_and, addr);
+ brw_set_src0(p, insn_and, vec1(retype(index, BRW_REGISTER_TYPE_UD)));
+ brw_set_src1(p, insn_and, brw_imm_ud(0x0ff));
+
+
+ /* a0.0 |= <descriptor> */
+ brw_inst *insn_or = brw_next_insn(p, BRW_OPCODE_OR);
+ brw_set_sampler_message(p, insn_or,
+ 0 /* surface */,
+ 0 /* sampler */,
+ GEN5_SAMPLER_MESSAGE_SAMPLE_LD,
+ rlen /* rlen */,
+ mlen /* mlen */,
+ false /* header */,
+ simd_mode,
+ 0);
+ brw_inst_set_exec_size(p->brw, insn_or, BRW_EXECUTE_1);
+ brw_inst_set_src1_reg_type(p->brw, insn_or, BRW_REGISTER_TYPE_UD);
+ brw_set_src0(p, insn_or, addr);
+ brw_set_dest(p, insn_or, addr);
+
+
+ /* dst = send(offset, a0.0) */
+ brw_inst *insn_send = brw_next_insn(p, BRW_OPCODE_SEND);
+ brw_set_dest(p, insn_send, dst);
+ brw_set_src0(p, insn_send, offset);
+ brw_set_indirect_send_descriptor(p, insn_send, BRW_SFID_SAMPLER, addr);
+
+ brw_pop_insn_state(p);
+
+ /* visitor knows more than we do about the surface limit required,
+ * so has already done marking.
+ */
+ }
}
/**
brw_pop_insn_state(p);
}
+void
+fs_generator::generate_pixel_interpolator_query(fs_inst *inst,
+ struct brw_reg dst,
+ struct brw_reg src,
+ struct brw_reg msg_data,
+ unsigned msg_type)
+{
+ assert(msg_data.file == BRW_IMMEDIATE_VALUE &&
+ msg_data.type == BRW_REGISTER_TYPE_UD);
+
+ brw_pixel_interpolator_query(p,
+ retype(dst, BRW_REGISTER_TYPE_UW),
+ src,
+ inst->pi_noperspective,
+ msg_type,
+ msg_data.dw1.ud,
+ inst->mlen,
+ inst->regs_written);
+}
+
static uint32_t brw_file_from_reg(fs_reg *reg)
{
case IMM:
return BRW_IMMEDIATE_VALUE;
default:
- assert(!"not reached");
- return BRW_GENERAL_REGISTER_FILE;
+ unreachable("not reached");
}
}
case IMM:
switch (reg->type) {
case BRW_REGISTER_TYPE_F:
- brw_reg = brw_imm_f(reg->imm.f);
+ brw_reg = brw_imm_f(reg->fixed_hw_reg.dw1.f);
break;
case BRW_REGISTER_TYPE_D:
- brw_reg = brw_imm_d(reg->imm.i);
+ brw_reg = brw_imm_d(reg->fixed_hw_reg.dw1.d);
break;
case BRW_REGISTER_TYPE_UD:
- brw_reg = brw_imm_ud(reg->imm.u);
+ brw_reg = brw_imm_ud(reg->fixed_hw_reg.dw1.ud);
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);
brw_MOV(p, payload_offset, offset);
brw_MOV(p, payload_value, value);
brw_shader_time_add(p, payload,
- prog_data->base.binding_table.shader_time_start);
+ prog_data->binding_table.shader_time_start);
brw_pop_insn_state(p);
- brw_mark_surface_used(&prog_data->base,
- prog_data->base.binding_table.shader_time_start);
+ brw_mark_surface_used(prog_data,
+ prog_data->binding_table.shader_time_start);
}
void
atomic_op.dw1.ud, surf_index.dw1.ud,
inst->mlen, dispatch_width / 8);
- brw_mark_surface_used(&prog_data->base, surf_index.dw1.ud);
+ brw_mark_surface_used(prog_data, surf_index.dw1.ud);
}
void
surf_index.dw1.ud,
inst->mlen, dispatch_width / 8);
- brw_mark_surface_used(&prog_data->base, surf_index.dw1.ud);
+ brw_mark_surface_used(prog_data, surf_index.dw1.ud);
}
void
-fs_generator::generate_code(exec_list *instructions)
+fs_generator::generate_code(const cfg_t *cfg)
{
int start_offset = p->next_insn_offset;
+ int loop_count = 0;
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_block_and_inst (block, fs_inst, inst, cfg) {
struct brw_reg src[3], dst;
unsigned int last_insn_offset = p->next_insn_offset;
brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
break;
case BRW_OPCODE_CONTINUE:
- /* FINISHME: We need to write the loop instruction support still. */
- if (brw->gen >= 6)
- gen6_CONT(p);
- else
- brw_CONT(p);
+ brw_CONT(p);
brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
break;
case BRW_OPCODE_WHILE:
brw_WHILE(p);
+ loop_count++;
break;
case SHADER_OPCODE_RCP:
case SHADER_OPCODE_INT_REMAINDER:
case SHADER_OPCODE_POW:
assert(brw->gen < 6 || inst->mlen == 0);
- if (brw->gen >= 7) {
+ if (brw->gen >= 7 && inst->opcode == SHADER_OPCODE_POW) {
gen6_math(p, dst, brw_math_function(inst->opcode), src[0], src[1]);
- } else if (brw->gen == 6) {
+ } else if (brw->gen >= 6) {
generate_math_gen6(inst, dst, src[0], src[1]);
} else {
generate_math_gen4(inst, dst, src[0]);
case SHADER_OPCODE_LOD:
case SHADER_OPCODE_TG4:
case SHADER_OPCODE_TG4_OFFSET:
- generate_tex(inst, dst, src[0]);
+ generate_tex(inst, dst, src[0], src[1]);
break;
case FS_OPCODE_DDX:
- generate_ddx(inst, dst, src[0]);
+ generate_ddx(inst, dst, src[0], src[1]);
break;
case FS_OPCODE_DDY:
/* Make sure fp->UsesDFdy flag got set (otherwise there's no
* guarantee that key->render_to_fbo is set).
*/
- assert(fp->UsesDFdy);
- generate_ddy(inst, dst, src[0], key->render_to_fbo);
+ assert(stage == MESA_SHADER_FRAGMENT &&
+ ((gl_fragment_program *) prog)->UsesDFdy);
+ generate_ddy(inst, dst, src[0], src[1], key->render_to_fbo);
break;
case SHADER_OPCODE_GEN4_SCRATCH_WRITE:
generate_varying_pull_constant_load_gen7(inst, dst, src[0], src[1]);
break;
+ case FS_OPCODE_REP_FB_WRITE:
case FS_OPCODE_FB_WRITE:
generate_fb_write(inst);
break;
}
break;
+ case FS_OPCODE_INTERPOLATE_AT_CENTROID:
+ generate_pixel_interpolator_query(inst, dst, src[0], src[1],
+ GEN7_PIXEL_INTERPOLATOR_LOC_CENTROID);
+ break;
+
+ case FS_OPCODE_INTERPOLATE_AT_SAMPLE:
+ generate_pixel_interpolator_query(inst, dst, src[0], src[1],
+ GEN7_PIXEL_INTERPOLATOR_LOC_SAMPLE);
+ break;
+
+ case FS_OPCODE_INTERPOLATE_AT_SHARED_OFFSET:
+ generate_pixel_interpolator_query(inst, dst, src[0], src[1],
+ GEN7_PIXEL_INTERPOLATOR_LOC_SHARED_OFFSET);
+ break;
+
+ case FS_OPCODE_INTERPOLATE_AT_PER_SLOT_OFFSET:
+ generate_pixel_interpolator_query(inst, dst, src[0], src[1],
+ GEN7_PIXEL_INTERPOLATOR_LOC_PER_SLOT_OFFSET);
+ break;
+
default:
if (inst->opcode < (int) ARRAY_SIZE(opcode_descs)) {
_mesa_problem(ctx, "Unsupported opcode `%s' in FS",
abort();
case SHADER_OPCODE_LOAD_PAYLOAD:
- assert(!"Should be lowered by lower_load_payload()");
- break;
+ unreachable("Should be lowered by lower_load_payload()");
}
if (inst->no_dd_clear || inst->no_dd_check || inst->conditional_mod) {
int after_size = p->next_insn_offset - start_offset;
if (unlikely(debug_flag)) {
- if (prog) {
+ if (shader_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) {
+ shader_prog->Label ? shader_prog->Label : "unnamed",
+ shader_prog->Name, dispatch_width);
+ } else if (prog) {
fprintf(stderr,
"Native code for fragment program %d (SIMD%d dispatch):\n",
- fp->Base.Id, dispatch_width);
+ prog->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"
+ fprintf(stderr, "SIMD%d shader: %d instructions. %d loops. Compacted %d to %d"
" bytes (%.0f%%)\n",
- dispatch_width, before_size / 16, before_size, after_size,
+ dispatch_width, before_size / 16, loop_count, 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 *
-fs_generator::generate_assembly(exec_list *simd8_instructions,
- exec_list *simd16_instructions,
+fs_generator::generate_assembly(const cfg_t *simd8_cfg,
+ const cfg_t *simd16_cfg,
unsigned *assembly_size)
{
- assert(simd8_instructions || simd16_instructions);
+ assert(simd8_cfg || simd16_cfg);
- if (simd8_instructions) {
+ if (simd8_cfg) {
dispatch_width = 8;
- generate_code(simd8_instructions);
+ generate_code(simd8_cfg);
}
- if (simd16_instructions) {
+ if (simd16_cfg) {
/* align to 64 byte boundary. */
while (p->next_insn_offset % 64) {
brw_NOP(p);
}
+ assert(stage == MESA_SHADER_FRAGMENT);
+ brw_wm_prog_data *prog_data = (brw_wm_prog_data*) this->prog_data;
+
/* Save off the start of this SIMD16 program */
prog_data->prog_offset_16 = p->next_insn_offset;
brw_set_default_compression_control(p, BRW_COMPRESSION_COMPRESSED);
dispatch_width = 16;
- generate_code(simd16_instructions);
+ generate_code(simd16_cfg);
}
return brw_get_program(p, assembly_size);