* IN THE SOFTWARE.
*/
-#include "glsl/ir.h"
+#include "compiler/glsl/ir.h"
#include "main/shaderimage.h"
#include "brw_fs.h"
#include "brw_fs_surface_builder.h"
nir_emit_system_values();
/* get the main function and emit it */
- nir_foreach_overload(nir, overload) {
- assert(strcmp(overload->function->name, "main") == 0);
- assert(overload->impl);
- nir_emit_impl(overload->impl);
+ nir_foreach_function(nir, function) {
+ assert(strcmp(function->name, "main") == 0);
+ assert(function->impl);
+ nir_emit_impl(function->impl);
}
}
switch (stage) {
case MESA_SHADER_VERTEX:
+ case MESA_SHADER_TESS_EVAL:
case MESA_SHADER_GEOMETRY: {
unsigned location = var->data.location;
nir_setup_single_output_varying(®, var->type, &location);
break;
}
case MESA_SHADER_FRAGMENT:
- if (var->data.index > 0) {
+ if (key->force_dual_color_blend &&
+ var->data.location == FRAG_RESULT_DATA1) {
+ this->dual_src_output = reg;
+ this->do_dual_src = true;
+ } else if (var->data.index > 0) {
assert(var->data.location == FRAG_RESULT_DATA0);
assert(var->data.index == 1);
this->dual_src_output = reg;
*reg = *v->emit_vs_system_value(SYSTEM_VALUE_INSTANCE_ID);
break;
+ case nir_intrinsic_load_base_instance:
+ assert(v->stage == MESA_SHADER_VERTEX);
+ reg = &v->nir_system_values[SYSTEM_VALUE_BASE_INSTANCE];
+ if (reg->file == BAD_FILE)
+ *reg = *v->emit_vs_system_value(SYSTEM_VALUE_BASE_INSTANCE);
+ break;
+
+ case nir_intrinsic_load_draw_id:
+ assert(v->stage == MESA_SHADER_VERTEX);
+ reg = &v->nir_system_values[SYSTEM_VALUE_DRAW_ID];
+ if (reg->file == BAD_FILE)
+ *reg = *v->emit_vs_system_value(SYSTEM_VALUE_DRAW_ID);
+ break;
+
case nir_intrinsic_load_invocation_id:
assert(v->stage == MESA_SHADER_GEOMETRY);
reg = &v->nir_system_values[SYSTEM_VALUE_INVOCATION_ID];
nir_system_values[i] = fs_reg();
}
- nir_foreach_overload(nir, overload) {
- assert(strcmp(overload->function->name, "main") == 0);
- assert(overload->impl);
- nir_foreach_block(overload->impl, emit_system_values_block, this);
+ nir_foreach_function(nir, function) {
+ assert(strcmp(function->name, "main") == 0);
+ assert(function->impl);
+ nir_foreach_block(function->impl, emit_system_values_block, this);
}
}
case MESA_SHADER_VERTEX:
nir_emit_vs_intrinsic(abld, nir_instr_as_intrinsic(instr));
break;
+ case MESA_SHADER_TESS_EVAL:
+ nir_emit_tes_intrinsic(abld, nir_instr_as_intrinsic(instr));
+ break;
case MESA_SHADER_GEOMETRY:
nir_emit_gs_intrinsic(abld, nir_instr_as_intrinsic(instr));
break;
case nir_op_fmin:
case nir_op_imin:
case nir_op_umin:
- if (devinfo->gen >= 6) {
- inst = bld.emit(BRW_OPCODE_SEL, result, op[0], op[1]);
- inst->conditional_mod = BRW_CONDITIONAL_L;
- } else {
- bld.CMP(bld.null_reg_d(), op[0], op[1], BRW_CONDITIONAL_L);
- inst = bld.SEL(result, op[0], op[1]);
- inst->predicate = BRW_PREDICATE_NORMAL;
- }
+ inst = bld.emit(BRW_OPCODE_SEL, result, op[0], op[1]);
+ inst->conditional_mod = BRW_CONDITIONAL_L;
inst->saturate = instr->dest.saturate;
break;
case nir_op_fmax:
case nir_op_imax:
case nir_op_umax:
- if (devinfo->gen >= 6) {
- inst = bld.emit(BRW_OPCODE_SEL, result, op[0], op[1]);
- inst->conditional_mod = BRW_CONDITIONAL_GE;
- } else {
- bld.CMP(bld.null_reg_d(), op[0], op[1], BRW_CONDITIONAL_GE);
- inst = bld.SEL(result, op[0], op[1]);
- inst->predicate = BRW_PREDICATE_NORMAL;
- }
+ inst = bld.emit(BRW_OPCODE_SEL, result, op[0], op[1]);
+ inst->conditional_mod = BRW_CONDITIONAL_GE;
inst->saturate = instr->dest.saturate;
break;
case nir_op_ubitfield_extract:
case nir_op_ibitfield_extract:
+ unreachable("should have been lowered");
+ case nir_op_ubfe:
+ case nir_op_ibfe:
bld.BFE(result, op[2], op[1], op[0]);
break;
case nir_op_bfm:
break;
case nir_op_bitfield_insert:
- unreachable("not reached: should be handled by "
- "lower_instructions::bitfield_insert_to_bfm_bfi");
+ unreachable("not reached: should have been lowered");
case nir_op_ishl:
bld.SHL(result, op[0], op[1]);
inst->predicate = BRW_PREDICATE_NORMAL;
break;
+ case nir_op_extract_u8:
+ case nir_op_extract_i8: {
+ nir_const_value *byte = nir_src_as_const_value(instr->src[1].src);
+ bld.emit(SHADER_OPCODE_EXTRACT_BYTE,
+ result, op[0], brw_imm_ud(byte->u[0]));
+ break;
+ }
+
+ case nir_op_extract_u16:
+ case nir_op_extract_i16: {
+ nir_const_value *word = nir_src_as_const_value(instr->src[1].src);
+ bld.emit(SHADER_OPCODE_EXTRACT_WORD,
+ result, op[0], brw_imm_ud(word->u[0]));
+ break;
+ }
+
default:
unreachable("unhandled instruction");
}
static brw_reg_type
get_image_base_type(const glsl_type *type)
{
- switch ((glsl_base_type)type->sampler_type) {
+ switch ((glsl_base_type)type->sampled_type) {
case GLSL_TYPE_UINT:
return BRW_REGISTER_TYPE_UD;
case GLSL_TYPE_INT:
}
}
+fs_reg
+fs_visitor::get_indirect_offset(nir_intrinsic_instr *instr)
+{
+ nir_src *offset_src = nir_get_io_offset_src(instr);
+ nir_const_value *const_value = nir_src_as_const_value(*offset_src);
+
+ if (const_value) {
+ /* The only constant offset we should find is 0. brw_nir.c's
+ * add_const_offset_to_base() will fold other constant offsets
+ * into instr->const_index[0].
+ */
+ assert(const_value->u[0] == 0);
+ return fs_reg();
+ }
+
+ return get_nir_src(*offset_src);
+}
+
void
fs_visitor::nir_emit_vs_intrinsic(const fs_builder &bld,
nir_intrinsic_instr *instr)
case nir_intrinsic_load_vertex_id_zero_base:
case nir_intrinsic_load_base_vertex:
- case nir_intrinsic_load_instance_id: {
+ case nir_intrinsic_load_instance_id:
+ case nir_intrinsic_load_base_instance:
+ case nir_intrinsic_load_draw_id: {
gl_system_value sv = nir_system_value_from_intrinsic(instr->intrinsic);
fs_reg val = nir_system_values[sv];
assert(val.file != BAD_FILE);
}
}
+void
+fs_visitor::nir_emit_tes_intrinsic(const fs_builder &bld,
+ nir_intrinsic_instr *instr)
+{
+ assert(stage == MESA_SHADER_TESS_EVAL);
+ struct brw_tes_prog_data *tes_prog_data = (struct brw_tes_prog_data *) prog_data;
+
+ fs_reg dest;
+ if (nir_intrinsic_infos[instr->intrinsic].has_dest)
+ dest = get_nir_dest(instr->dest);
+
+ switch (instr->intrinsic) {
+ case nir_intrinsic_load_primitive_id:
+ bld.MOV(dest, fs_reg(brw_vec1_grf(0, 1)));
+ break;
+ case nir_intrinsic_load_tess_coord:
+ /* gl_TessCoord is part of the payload in g1-3 */
+ for (unsigned i = 0; i < 3; i++) {
+ bld.MOV(offset(dest, bld, i), fs_reg(brw_vec8_grf(1 + i, 0)));
+ }
+ break;
+
+ case nir_intrinsic_load_tess_level_outer:
+ /* When the TES reads gl_TessLevelOuter, we ensure that the patch header
+ * appears as a push-model input. So, we can simply use the ATTR file
+ * rather than issuing URB read messages. The data is stored in the
+ * high DWords in reverse order - DWord 7 contains .x, DWord 6 contains
+ * .y, and so on.
+ */
+ switch (tes_prog_data->domain) {
+ case BRW_TESS_DOMAIN_QUAD:
+ for (unsigned i = 0; i < 4; i++)
+ bld.MOV(offset(dest, bld, i), component(fs_reg(ATTR, 0), 7 - i));
+ break;
+ case BRW_TESS_DOMAIN_TRI:
+ for (unsigned i = 0; i < 3; i++)
+ bld.MOV(offset(dest, bld, i), component(fs_reg(ATTR, 0), 7 - i));
+ break;
+ case BRW_TESS_DOMAIN_ISOLINE:
+ for (unsigned i = 0; i < 2; i++)
+ bld.MOV(offset(dest, bld, i), component(fs_reg(ATTR, 0), 7 - i));
+ break;
+ }
+ break;
+
+ case nir_intrinsic_load_tess_level_inner:
+ /* When the TES reads gl_TessLevelInner, we ensure that the patch header
+ * appears as a push-model input. So, we can simply use the ATTR file
+ * rather than issuing URB read messages.
+ */
+ switch (tes_prog_data->domain) {
+ case BRW_TESS_DOMAIN_QUAD:
+ bld.MOV(dest, component(fs_reg(ATTR, 0), 3));
+ bld.MOV(offset(dest, bld, 1), component(fs_reg(ATTR, 0), 2));
+ break;
+ case BRW_TESS_DOMAIN_TRI:
+ bld.MOV(dest, component(fs_reg(ATTR, 0), 4));
+ break;
+ case BRW_TESS_DOMAIN_ISOLINE:
+ /* ignore - value is undefined */
+ break;
+ }
+ break;
+
+ case nir_intrinsic_load_input:
+ case nir_intrinsic_load_per_vertex_input: {
+ fs_reg indirect_offset = get_indirect_offset(instr);
+ unsigned imm_offset = instr->const_index[0];
+
+ fs_inst *inst;
+ if (indirect_offset.file == BAD_FILE) {
+ /* Arbitrarily only push up to 32 vec4 slots worth of data,
+ * which is 16 registers (since each holds 2 vec4 slots).
+ */
+ const unsigned max_push_slots = 32;
+ if (imm_offset < max_push_slots) {
+ fs_reg src = fs_reg(ATTR, imm_offset / 2, dest.type);
+ for (int i = 0; i < instr->num_components; i++) {
+ bld.MOV(offset(dest, bld, i),
+ component(src, 4 * (imm_offset % 2) + i));
+ }
+ tes_prog_data->base.urb_read_length =
+ MAX2(tes_prog_data->base.urb_read_length,
+ DIV_ROUND_UP(imm_offset + 1, 2));
+ } else {
+ /* Replicate the patch handle to all enabled channels */
+ const fs_reg srcs[] = {
+ retype(brw_vec1_grf(0, 0), BRW_REGISTER_TYPE_UD)
+ };
+ fs_reg patch_handle = bld.vgrf(BRW_REGISTER_TYPE_UD, 1);
+ bld.LOAD_PAYLOAD(patch_handle, srcs, ARRAY_SIZE(srcs), 0);
+
+ inst = bld.emit(SHADER_OPCODE_URB_READ_SIMD8, dest, patch_handle);
+ inst->mlen = 1;
+ inst->offset = imm_offset;
+ inst->base_mrf = -1;
+ inst->regs_written = instr->num_components;
+ }
+ } else {
+ /* Indirect indexing - use per-slot offsets as well. */
+ const fs_reg srcs[] = {
+ retype(brw_vec1_grf(0, 0), BRW_REGISTER_TYPE_UD),
+ indirect_offset
+ };
+ fs_reg payload = bld.vgrf(BRW_REGISTER_TYPE_UD, 2);
+ bld.LOAD_PAYLOAD(payload, srcs, ARRAY_SIZE(srcs), 0);
+
+ inst = bld.emit(SHADER_OPCODE_URB_READ_SIMD8_PER_SLOT, dest, payload);
+ inst->mlen = 2;
+ inst->offset = imm_offset;
+ inst->base_mrf = -1;
+ inst->regs_written = instr->num_components;
+ }
+ break;
+ }
+ default:
+ nir_emit_intrinsic(bld, instr);
+ break;
+ }
+}
+
void
fs_visitor::nir_emit_gs_intrinsic(const fs_builder &bld,
nir_intrinsic_instr *instr)
void
fs_visitor::nir_emit_texture(const fs_builder &bld, nir_tex_instr *instr)
{
+ unsigned texture = instr->texture_index;
unsigned sampler = instr->sampler_index;
+ fs_reg texture_reg(brw_imm_ud(texture));
fs_reg sampler_reg(brw_imm_ud(sampler));
int gather_component = instr->component;
instr->is_array;
int lod_components = 0;
- int UNUSED offset_components = 0;
fs_reg coordinate, shadow_comparitor, lod, lod2, sample_index, mcs, tex_offset;
case nir_tex_src_ms_index:
sample_index = retype(src, BRW_REGISTER_TYPE_UD);
break;
- case nir_tex_src_offset:
- tex_offset = retype(src, BRW_REGISTER_TYPE_D);
- if (instr->is_array)
- offset_components = instr->coord_components - 1;
- else
- offset_components = instr->coord_components;
+
+ case nir_tex_src_offset: {
+ nir_const_value *const_offset =
+ nir_src_as_const_value(instr->src[i].src);
+ if (const_offset) {
+ tex_offset = brw_imm_ud(brw_texture_offset(const_offset->i, 3));
+ } else {
+ tex_offset = retype(src, BRW_REGISTER_TYPE_D);
+ }
break;
+ }
+
case nir_tex_src_projector:
unreachable("should be lowered");
- case nir_tex_src_sampler_offset: {
- /* Figure out the highest possible sampler index and mark it as used */
- uint32_t max_used = sampler + instr->sampler_array_size - 1;
+ case nir_tex_src_texture_offset: {
+ /* Figure out the highest possible texture index and mark it as used */
+ uint32_t max_used = texture + instr->texture_array_size - 1;
if (instr->op == nir_texop_tg4 && devinfo->gen < 8) {
max_used += stage_prog_data->binding_table.gather_texture_start;
} else {
}
brw_mark_surface_used(prog_data, max_used);
+ /* Emit code to evaluate the actual indexing expression */
+ texture_reg = vgrf(glsl_type::uint_type);
+ bld.ADD(texture_reg, src, brw_imm_ud(texture));
+ texture_reg = bld.emit_uniformize(texture_reg);
+ break;
+ }
+
+ case nir_tex_src_sampler_offset: {
/* Emit code to evaluate the actual indexing expression */
sampler_reg = vgrf(glsl_type::uint_type);
bld.ADD(sampler_reg, src, brw_imm_ud(sampler));
if (instr->op == nir_texop_txf_ms ||
instr->op == nir_texop_samples_identical) {
if (devinfo->gen >= 7 &&
- key_tex->compressed_multisample_layout_mask & (1 << sampler)) {
- mcs = emit_mcs_fetch(coordinate, instr->coord_components, sampler_reg);
+ key_tex->compressed_multisample_layout_mask & (1 << texture)) {
+ mcs = emit_mcs_fetch(coordinate, instr->coord_components, texture_reg);
} else {
mcs = brw_imm_ud(0u);
}
}
- for (unsigned i = 0; i < 3; i++) {
- if (instr->const_offset[i] != 0) {
- assert(offset_components == 0);
- tex_offset = brw_imm_ud(brw_texture_offset(instr->const_offset, 3));
- break;
- }
- }
-
enum glsl_base_type dest_base_type =
brw_glsl_base_type_for_nir_type (instr->dest_type);
fs_reg dst = retype(get_nir_dest(instr->dest), BRW_REGISTER_TYPE_D);
fs_inst *inst = bld.emit(SHADER_OPCODE_SAMPLEINFO, dst,
bld.vgrf(BRW_REGISTER_TYPE_D, 1),
- sampler_reg);
+ texture_reg, texture_reg);
inst->mlen = 1;
inst->header_size = 1;
inst->base_mrf = -1;
emit_texture(op, dest_type, coordinate, instr->coord_components,
shadow_comparitor, lod, lod2, lod_components, sample_index,
- tex_offset, mcs, gather_component,
- is_cube_array, sampler, sampler_reg);
+ tex_offset, mcs, gather_component, is_cube_array,
+ texture, texture_reg, sampler, sampler_reg);
fs_reg dest = get_nir_dest(instr->dest);
dest.type = this->result.type;