X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fi965%2Fbrw_vec4_visitor.cpp;h=edb8b2a10edd7216b157fb467e562859b270aa9f;hb=9195191e50429d9cf25e6498f9fb108758ac2be6;hp=dac8cf91a63dc7f73b4322b5a3b83d416097f531;hpb=9bd8d90646572a170bd96a72d2f8d5739df381be;p=mesa.git diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp index dac8cf91a63..edb8b2a10ed 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp @@ -25,6 +25,7 @@ extern "C" { #include "main/macros.h" #include "program/prog_parameter.h" +#include "program/sampler.h" } namespace brw { @@ -182,6 +183,9 @@ vec4_visitor::IF(src_reg src0, src_reg src1, uint32_t condition) vec4_instruction *inst; + resolve_ud_negate(&src0); + resolve_ud_negate(&src1); + inst = new(mem_ctx) vec4_instruction(this, BRW_OPCODE_IF, dst_null_d(), src0, src1); inst->conditional_mod = condition; @@ -209,6 +213,9 @@ vec4_visitor::CMP(dst_reg dst, src_reg src0, src_reg src1, uint32_t condition) dst.fixed_hw_reg.type = dst.type; } + resolve_ud_negate(&src0); + resolve_ud_negate(&src1); + inst = new(mem_ctx) vec4_instruction(this, BRW_OPCODE_CMP, dst, src0, src1); inst->conditional_mod = condition; @@ -306,7 +313,9 @@ vec4_visitor::emit_math(opcode opcode, dst_reg dst, src_reg src) return; } - if (intel->gen >= 6) { + if (intel->gen >= 7) { + emit(opcode, dst, src); + } else if (intel->gen == 6) { return emit_math1_gen6(opcode, dst, src); } else { return emit_math1_gen4(opcode, dst, src); @@ -326,10 +335,12 @@ vec4_visitor::emit_math2_gen6(enum opcode opcode, */ expanded = src_reg(this, glsl_type::vec4_type); + expanded.type = src0.type; emit(MOV(dst_reg(expanded), src0)); src0 = expanded; expanded = src_reg(this, glsl_type::vec4_type); + expanded.type = src1.type; emit(MOV(dst_reg(expanded), src1)); src1 = expanded; @@ -338,6 +349,7 @@ vec4_visitor::emit_math2_gen6(enum opcode opcode, * writemasks. */ dst_reg temp_dst = dst_reg(this, glsl_type::vec4_type); + temp_dst.type = dst.type; emit(opcode, temp_dst, src0, src1); @@ -360,9 +372,19 @@ void vec4_visitor::emit_math(enum opcode opcode, dst_reg dst, src_reg src0, src_reg src1) { - assert(opcode == SHADER_OPCODE_POW); + switch (opcode) { + case SHADER_OPCODE_POW: + case SHADER_OPCODE_INT_QUOTIENT: + case SHADER_OPCODE_INT_REMAINDER: + break; + default: + assert(!"not reached: unsupported binary math opcode"); + return; + } - if (intel->gen >= 6) { + if (intel->gen >= 7) { + emit(opcode, dst, src0, src1); + } else if (intel->gen == 6) { return emit_math2_gen6(opcode, dst, src0, src1); } else { return emit_math2_gen4(opcode, dst, src0, src1); @@ -432,7 +454,11 @@ vec4_visitor::virtual_grf_alloc(int size) virtual_grf_array_size *= 2; virtual_grf_sizes = reralloc(mem_ctx, virtual_grf_sizes, int, virtual_grf_array_size); + virtual_grf_reg_map = reralloc(mem_ctx, virtual_grf_reg_map, int, + virtual_grf_array_size); } + virtual_grf_reg_map[virtual_grf_count] = virtual_grf_reg_count; + virtual_grf_reg_count += size; virtual_grf_sizes[virtual_grf_count] = size; return virtual_grf_count++; } @@ -481,9 +507,7 @@ vec4_visitor::setup_uniform_values(int loc, const glsl_type *type) float *values = &this->vp->Base.Parameters->ParameterValues[loc][0].f; if (type->is_matrix()) { - const glsl_type *column = glsl_type::get_instance(GLSL_TYPE_FLOAT, - type->vector_elements, - 1); + const glsl_type *column = type->column_type(); for (unsigned int i = 0; i < type->matrix_columns; i++) { offset += setup_uniform_values(loc + offset, column); @@ -539,6 +563,37 @@ vec4_visitor::setup_uniform_values(int loc, const glsl_type *type) } } +void +vec4_visitor::setup_uniform_clipplane_values() +{ + gl_clip_plane *clip_planes = brw_select_clip_planes(ctx); + + /* Pre-Gen6, we compact clip planes. For example, if the user + * enables just clip planes 0, 1, and 3, we will enable clip planes + * 0, 1, and 2 in the hardware, and we'll move clip plane 3 to clip + * plane 2. This simplifies the implementation of the Gen6 clip + * thread. + * + * In Gen6 and later, we don't compact clip planes, because this + * simplifies the implementation of gl_ClipDistance. + */ + int compacted_clipplane_index = 0; + for (int i = 0; i < c->key.nr_userclip_plane_consts; ++i) { + if (intel->gen < 6 && + !(c->key.userclip_planes_enabled_gen_4_5 & (1 << i))) { + continue; + } + this->uniform_vector_size[this->uniforms] = 4; + this->userplane[compacted_clipplane_index] = dst_reg(UNIFORM, this->uniforms); + this->userplane[compacted_clipplane_index].type = BRW_REGISTER_TYPE_F; + for (int j = 0; j < 4; ++j) { + c->prog_data.param[this->uniforms * 4 + j] = &clip_planes[i][j]; + } + ++compacted_clipplane_index; + ++this->uniforms; + } +} + /* Our support for builtin uniforms is even scarier than non-builtin. * It sits on top of the PROG_STATE_VAR parameters that are * automatically updated from GL context state. @@ -597,6 +652,8 @@ vec4_visitor::emit_bool_to_cond_code(ir_rvalue *ir, uint32_t *predicate) for (unsigned int i = 0; i < expr->get_num_operands(); i++) { expr->operands[i]->accept(this); op[i] = this->result; + + resolve_ud_negate(&op[i]); } switch (expr->operation) { @@ -672,6 +729,8 @@ vec4_visitor::emit_bool_to_cond_code(ir_rvalue *ir, uint32_t *predicate) ir->accept(this); + resolve_ud_negate(&this->result); + if (intel->gen >= 6) { vec4_instruction *inst = emit(AND(dst_null_d(), this->result, src_reg(1))); @@ -788,6 +847,7 @@ vec4_visitor::visit(ir_variable *ir) continue; dst_reg dst = *reg; + dst.type = brw_type_for_base_type(ir->type); dst.writemask = (1 << c->key.gl_fixed_input_size[i]) - 1; emit(MUL(dst, src_reg(dst), src_reg(1.0f / 65536.0f))); } @@ -799,7 +859,9 @@ vec4_visitor::visit(ir_variable *ir) for (int i = 0; i < type_size(ir->type); i++) { output_reg[ir->location + i] = *reg; output_reg[ir->location + i].reg_offset = i; - output_reg[ir->location + i].type = BRW_REGISTER_TYPE_F; + output_reg[ir->location + i].type = + brw_type_for_base_type(ir->type->get_scalar_type()); + output_reg_annotation[ir->location + i] = ir->name; } break; @@ -823,6 +885,27 @@ vec4_visitor::visit(ir_variable *ir) } break; + case ir_var_system_value: + /* VertexID is stored by the VF as the last vertex element, but + * we don't represent it with a flag in inputs_read, so we call + * it VERT_ATTRIB_MAX, which setup_attributes() picks up on. + */ + reg = new(mem_ctx) dst_reg(ATTR, VERT_ATTRIB_MAX); + prog_data->uses_vertexid = true; + + switch (ir->location) { + case SYSTEM_VALUE_VERTEX_ID: + reg->writemask = WRITEMASK_X; + break; + case SYSTEM_VALUE_INSTANCE_ID: + reg->writemask = WRITEMASK_Y; + break; + default: + assert(!"not reached"); + break; + } + break; + default: assert(!"not reached"); } @@ -918,7 +1001,7 @@ vec4_visitor::visit(ir_function *ir) } } -GLboolean +bool vec4_visitor::try_emit_sat(ir_expression *ir) { ir_rvalue *sat_src = ir->as_rvalue_to_saturate(); @@ -1089,9 +1172,14 @@ vec4_visitor::visit(ir_expression *ir) } break; case ir_binop_div: - assert(!"not reached: should be handled by ir_div_to_mul_rcp"); + /* Floating point should be lowered by DIV_TO_MUL_RCP in the compiler. */ + assert(ir->type->is_integer()); + emit_math(SHADER_OPCODE_INT_QUOTIENT, result_dst, op[0], op[1]); + break; case ir_binop_mod: - assert(!"ir_binop_mod should have been converted to b * fract(a/b)"); + /* Floating point should be lowered by MOD_TO_FRACT in the compiler. */ + assert(ir->type->is_integer()); + emit_math(SHADER_OPCODE_INT_REMAINDER, result_dst, op[0], op[1]); break; case ir_binop_less: @@ -1201,16 +1289,26 @@ vec4_visitor::visit(ir_expression *ir) break; case ir_binop_min: - emit(CMP(result_dst, op[0], op[1], BRW_CONDITIONAL_L)); + if (intel->gen >= 6) { + inst = emit(BRW_OPCODE_SEL, result_dst, op[0], op[1]); + inst->conditional_mod = BRW_CONDITIONAL_L; + } else { + emit(CMP(result_dst, op[0], op[1], BRW_CONDITIONAL_L)); - inst = emit(BRW_OPCODE_SEL, result_dst, op[0], op[1]); - inst->predicate = BRW_PREDICATE_NORMAL; + inst = emit(BRW_OPCODE_SEL, result_dst, op[0], op[1]); + inst->predicate = BRW_PREDICATE_NORMAL; + } break; case ir_binop_max: - emit(CMP(result_dst, op[0], op[1], BRW_CONDITIONAL_G)); + if (intel->gen >= 6) { + inst = emit(BRW_OPCODE_SEL, result_dst, op[0], op[1]); + inst->conditional_mod = BRW_CONDITIONAL_G; + } else { + emit(CMP(result_dst, op[0], op[1], BRW_CONDITIONAL_G)); - inst = emit(BRW_OPCODE_SEL, result_dst, op[0], op[1]); - inst->predicate = BRW_PREDICATE_NORMAL; + inst = emit(BRW_OPCODE_SEL, result_dst, op[0], op[1]); + inst->predicate = BRW_PREDICATE_NORMAL; + } break; case ir_binop_pow: @@ -1231,8 +1329,14 @@ vec4_visitor::visit(ir_expression *ir) break; case ir_binop_lshift: + inst = emit(BRW_OPCODE_SHL, result_dst, op[0], op[1]); + break; + case ir_binop_rshift: - assert(!"GLSL 1.30 features unsupported"); + if (ir->type->base_type == GLSL_TYPE_INT) + inst = emit(BRW_OPCODE_ASR, result_dst, op[0], op[1]); + else + inst = emit(BRW_OPCODE_SHR, result_dst, op[0], op[1]); break; case ir_quadop_vector: @@ -1442,8 +1546,6 @@ vec4_visitor::emit_block_move(dst_reg *dst, src_reg *src, dst->writemask = (1 << type->vector_elements) - 1; - /* Do we need to worry about swizzling a swizzle? */ - assert(src->swizzle = BRW_SWIZZLE_NOOP); src->swizzle = swizzle_for_size(type->vector_elements); vec4_instruction *inst = emit(MOV(*dst, *src)); @@ -1490,7 +1592,8 @@ vec4_visitor::try_rewrite_rhs_to_dst(ir_assignment *ir, * potentially reswizzle the operands of many instructions so that * we could handle out of order channels, but don't yet. */ - for (int i = 0; i < 4; i++) { + + for (unsigned i = 0; i < 4; i++) { if (dst.writemask & (1 << i)) { if (!(last_rhs_inst->dst.writemask & (1 << i))) return false; @@ -1525,6 +1628,15 @@ vec4_visitor::visit(ir_assignment *ir) emit_bool_to_cond_code(ir->condition, &predicate); } + /* emit_block_move doesn't account for swizzles in the source register. + * This should be ok, since the source register is a structure or an + * array, and those can't be swizzled. But double-check to be sure. + */ + assert(src.swizzle == + (ir->rhs->type->is_matrix() + ? swizzle_for_size(ir->rhs->type->vector_elements) + : BRW_SWIZZLE_NOOP)); + emit_block_move(&dst, &src, ir->rhs->type, predicate); return; } @@ -1609,22 +1721,45 @@ vec4_visitor::emit_constant_values(dst_reg *dst, ir_constant *ir) if (ir->type->is_matrix()) { for (int i = 0; i < ir->type->matrix_columns; i++) { + float *vec = &ir->value.f[i * ir->type->vector_elements]; + for (int j = 0; j < ir->type->vector_elements; j++) { dst->writemask = 1 << j; dst->type = BRW_REGISTER_TYPE_F; - emit(MOV(*dst, - src_reg(ir->value.f[i * ir->type->vector_elements + j]))); + emit(MOV(*dst, src_reg(vec[j]))); } dst->reg_offset++; } return; } + int remaining_writemask = (1 << ir->type->vector_elements) - 1; + for (int i = 0; i < ir->type->vector_elements; i++) { + if (!(remaining_writemask & (1 << i))) + continue; + dst->writemask = 1 << i; dst->type = brw_type_for_base_type(ir->type); + /* Find other components that match the one we're about to + * write. Emits fewer instructions for things like vec4(0.5, + * 1.5, 1.5, 1.5). + */ + for (int j = i + 1; j < ir->type->vector_elements; j++) { + if (ir->type->base_type == GLSL_TYPE_BOOL) { + if (ir->value.b[i] == ir->value.b[j]) + dst->writemask |= (1 << j); + } else { + /* u, i, and f storage all line up, so no need for a + * switch case for comparing each type. + */ + if (ir->value.u[i] == ir->value.u[j]) + dst->writemask |= (1 << j); + } + } + switch (ir->type->base_type) { case GLSL_TYPE_FLOAT: emit(MOV(*dst, src_reg(ir->value.f[i]))); @@ -1642,6 +1777,8 @@ vec4_visitor::emit_constant_values(dst_reg *dst, ir_constant *ir) assert(!"Non-float/uint/int/bool constant"); break; } + + remaining_writemask &= ~dst->writemask; } dst->reg_offset++; } @@ -1664,12 +1801,178 @@ vec4_visitor::visit(ir_call *ir) void vec4_visitor::visit(ir_texture *ir) { - /* FINISHME: Implement vertex texturing. - * - * With 0 vertex samplers available, the linker will reject - * programs that do vertex texturing, but after our visitor has - * run. - */ + int sampler = _mesa_get_sampler_uniform_value(ir->sampler, prog, &vp->Base); + sampler = vp->Base.SamplerUnits[sampler]; + + /* Should be lowered by do_lower_texture_projection */ + assert(!ir->projector); + + vec4_instruction *inst = NULL; + switch (ir->op) { + case ir_tex: + case ir_txl: + inst = new(mem_ctx) vec4_instruction(this, SHADER_OPCODE_TXL); + break; + case ir_txd: + inst = new(mem_ctx) vec4_instruction(this, SHADER_OPCODE_TXD); + break; + case ir_txf: + inst = new(mem_ctx) vec4_instruction(this, SHADER_OPCODE_TXF); + break; + case ir_txs: + inst = new(mem_ctx) vec4_instruction(this, SHADER_OPCODE_TXS); + break; + case ir_txb: + assert(!"TXB is not valid for vertex shaders."); + } + + /* Texel offsets go in the message header; Gen4 also requires headers. */ + inst->header_present = ir->offset || intel->gen < 5; + inst->base_mrf = 2; + inst->mlen = inst->header_present + 1; /* always at least one */ + inst->sampler = sampler; + inst->dst = dst_reg(this, ir->type); + inst->shadow_compare = ir->shadow_comparitor != NULL; + + if (ir->offset != NULL) + inst->texture_offset = brw_texture_offset(ir->offset->as_constant()); + + /* MRF for the first parameter */ + int param_base = inst->base_mrf + inst->header_present; + + if (ir->op == ir_txs) { + ir->lod_info.lod->accept(this); + int writemask = intel->gen == 4 ? WRITEMASK_W : WRITEMASK_X; + emit(MOV(dst_reg(MRF, param_base, ir->lod_info.lod->type, writemask), + this->result)); + } else { + int i, coord_mask = 0, zero_mask = 0; + /* Load the coordinate */ + /* FINISHME: gl_clamp_mask and saturate */ + for (i = 0; i < ir->coordinate->type->vector_elements; i++) + coord_mask |= (1 << i); + for (; i < 4; i++) + zero_mask |= (1 << i); + + ir->coordinate->accept(this); + emit(MOV(dst_reg(MRF, param_base, ir->coordinate->type, coord_mask), + this->result)); + emit(MOV(dst_reg(MRF, param_base, ir->coordinate->type, zero_mask), + src_reg(0))); + /* Load the shadow comparitor */ + if (ir->shadow_comparitor) { + ir->shadow_comparitor->accept(this); + emit(MOV(dst_reg(MRF, param_base + 1, ir->shadow_comparitor->type, + WRITEMASK_X), + this->result)); + inst->mlen++; + } + + /* Load the LOD info */ + if (ir->op == ir_txl) { + int mrf, writemask; + if (intel->gen >= 5) { + mrf = param_base + 1; + if (ir->shadow_comparitor) { + writemask = WRITEMASK_Y; + /* mlen already incremented */ + } else { + writemask = WRITEMASK_X; + inst->mlen++; + } + } else /* intel->gen == 4 */ { + mrf = param_base; + writemask = WRITEMASK_Z; + } + ir->lod_info.lod->accept(this); + emit(MOV(dst_reg(MRF, mrf, ir->lod_info.lod->type, writemask), + this->result)); + } else if (ir->op == ir_txf) { + ir->lod_info.lod->accept(this); + emit(MOV(dst_reg(MRF, param_base, ir->lod_info.lod->type, WRITEMASK_W), + this->result)); + } else if (ir->op == ir_txd) { + const glsl_type *type = ir->lod_info.grad.dPdx->type; + + ir->lod_info.grad.dPdx->accept(this); + src_reg dPdx = this->result; + ir->lod_info.grad.dPdy->accept(this); + src_reg dPdy = this->result; + + if (intel->gen >= 5) { + dPdx.swizzle = BRW_SWIZZLE4(SWIZZLE_X,SWIZZLE_X,SWIZZLE_Y,SWIZZLE_Y); + dPdy.swizzle = BRW_SWIZZLE4(SWIZZLE_X,SWIZZLE_X,SWIZZLE_Y,SWIZZLE_Y); + emit(MOV(dst_reg(MRF, param_base + 1, type, WRITEMASK_XZ), dPdx)); + emit(MOV(dst_reg(MRF, param_base + 1, type, WRITEMASK_YW), dPdy)); + inst->mlen++; + + if (ir->type->vector_elements == 3) { + dPdx.swizzle = BRW_SWIZZLE_ZZZZ; + dPdy.swizzle = BRW_SWIZZLE_ZZZZ; + emit(MOV(dst_reg(MRF, param_base + 2, type, WRITEMASK_X), dPdx)); + emit(MOV(dst_reg(MRF, param_base + 2, type, WRITEMASK_Y), dPdy)); + inst->mlen++; + } + } else /* intel->gen == 4 */ { + emit(MOV(dst_reg(MRF, param_base + 1, type, WRITEMASK_XYZ), dPdx)); + emit(MOV(dst_reg(MRF, param_base + 2, type, WRITEMASK_XYZ), dPdy)); + inst->mlen += 2; + } + } + } + + emit(inst); + + swizzle_result(ir, src_reg(inst->dst), sampler); +} + +void +vec4_visitor::swizzle_result(ir_texture *ir, src_reg orig_val, int sampler) +{ + this->result = orig_val; + + int s = c->key.tex.swizzles[sampler]; + + if (ir->op == ir_txs || ir->type == glsl_type::float_type + || s == SWIZZLE_NOOP) + return; + + int zero_mask = 0, one_mask = 0, copy_mask = 0; + int swizzle[4]; + + for (int i = 0; i < 4; i++) { + switch (GET_SWZ(s, i)) { + case SWIZZLE_ZERO: + zero_mask |= (1 << i); + break; + case SWIZZLE_ONE: + one_mask |= (1 << i); + break; + default: + copy_mask |= (1 << i); + swizzle[i] = GET_SWZ(s, i); + break; + } + } + + this->result = src_reg(this, ir->type); + dst_reg swizzled_result(this->result); + + if (copy_mask) { + orig_val.swizzle = BRW_SWIZZLE4(swizzle[0], swizzle[1], swizzle[2], swizzle[3]); + swizzled_result.writemask = copy_mask; + emit(MOV(swizzled_result, orig_val)); + } + + if (zero_mask) { + swizzled_result.writemask = zero_mask; + emit(MOV(swizzled_result, src_reg(0.0f))); + } + + if (one_mask) { + swizzled_result.writemask = one_mask; + emit(MOV(swizzled_result, src_reg(1.0f))); + } } void @@ -1741,8 +2044,10 @@ vec4_visitor::emit_psiz_and_flags(struct brw_reg reg) { if (intel->gen < 6 && ((c->prog_data.outputs_written & BITFIELD64_BIT(VERT_RESULT_PSIZ)) || - c->key.nr_userclip || brw->has_negative_rhw_bug)) { + c->key.userclip_active || brw->has_negative_rhw_bug)) { dst_reg header1 = dst_reg(this, glsl_type::uvec4_type); + dst_reg header1_w = header1; + header1_w.writemask = WRITEMASK_W; GLuint i; emit(MOV(header1, 0u)); @@ -1751,20 +2056,19 @@ vec4_visitor::emit_psiz_and_flags(struct brw_reg reg) src_reg psiz = src_reg(output_reg[VERT_RESULT_PSIZ]); current_annotation = "Point size"; - header1.writemask = WRITEMASK_W; - emit(MUL(header1, psiz, src_reg((float)(1 << 11)))); - emit(AND(header1, src_reg(header1), 0x7ff << 8)); + emit(MUL(header1_w, psiz, src_reg((float)(1 << 11)))); + emit(AND(header1_w, src_reg(header1_w), 0x7ff << 8)); } current_annotation = "Clipping flags"; - for (i = 0; i < c->key.nr_userclip; i++) { + for (i = 0; i < c->key.nr_userclip_plane_consts; i++) { vec4_instruction *inst; inst = emit(DP4(dst_null_f(), src_reg(output_reg[VERT_RESULT_HPOS]), - src_reg(c->userplane[i]))); + src_reg(this->userplane[i]))); inst->conditional_mod = BRW_CONDITIONAL_L; - emit(OR(header1, src_reg(header1), 1u << i)); + inst = emit(OR(header1_w, src_reg(header1_w), 1u << i)); inst->predicate = BRW_PREDICATE_NORMAL; } @@ -1792,7 +2096,6 @@ vec4_visitor::emit_psiz_and_flags(struct brw_reg reg) #endif } - header1.writemask = WRITEMASK_XYZW; emit(MOV(retype(reg, BRW_REGISTER_TYPE_UD), src_reg(header1))); } else if (intel->gen < 6) { emit(MOV(retype(reg, BRW_REGISTER_TYPE_UD), 0u)); @@ -1816,23 +2119,62 @@ vec4_visitor::emit_clip_distances(struct brw_reg reg, int offset) return; } - for (int i = 0; i + offset < c->key.nr_userclip && i < 4; ++i) { + /* From the GLSL 1.30 spec, section 7.1 (Vertex Shader Special Variables): + * + * "If a linked set of shaders forming the vertex stage contains no + * static write to gl_ClipVertex or gl_ClipDistance, but the + * application has requested clipping against user clip planes through + * the API, then the coordinate written to gl_Position is used for + * comparison against the user clip planes." + * + * This function is only called if the shader didn't write to + * gl_ClipDistance. Accordingly, we use gl_ClipVertex to perform clipping + * if the user wrote to it; otherwise we use gl_Position. + */ + gl_vert_result clip_vertex = VERT_RESULT_CLIP_VERTEX; + if (!(c->prog_data.outputs_written + & BITFIELD64_BIT(VERT_RESULT_CLIP_VERTEX))) { + clip_vertex = VERT_RESULT_HPOS; + } + + for (int i = 0; i + offset < c->key.nr_userclip_plane_consts && i < 4; + ++i) { emit(DP4(dst_reg(brw_writemask(reg, 1 << i)), - src_reg(output_reg[VERT_RESULT_HPOS]), - src_reg(c->userplane[i + offset]))); + src_reg(output_reg[clip_vertex]), + src_reg(this->userplane[i + offset]))); + } +} + +void +vec4_visitor::emit_generic_urb_slot(dst_reg reg, int vert_result) +{ + assert (vert_result < VERT_RESULT_MAX); + reg.type = output_reg[vert_result].type; + current_annotation = output_reg_annotation[vert_result]; + /* Copy the register, saturating if necessary */ + vec4_instruction *inst = emit(MOV(reg, + src_reg(output_reg[vert_result]))); + if ((vert_result == VERT_RESULT_COL0 || + vert_result == VERT_RESULT_COL1 || + vert_result == VERT_RESULT_BFC0 || + vert_result == VERT_RESULT_BFC1) && + c->key.clamp_vertex_color) { + inst->saturate = true; } } void vec4_visitor::emit_urb_slot(int mrf, int vert_result) { - struct brw_reg reg = brw_message_reg(mrf); + struct brw_reg hw_reg = brw_message_reg(mrf); + dst_reg reg = dst_reg(MRF, mrf); + reg.type = BRW_REGISTER_TYPE_F; switch (vert_result) { case VERT_RESULT_PSIZ: /* PSIZ is always in slot 0, and is coupled with other flags. */ current_annotation = "indices, point width, clip flags"; - emit_psiz_and_flags(reg); + emit_psiz_and_flags(hw_reg); break; case BRW_VERT_RESULT_NDC: current_annotation = "NDC"; @@ -1843,31 +2185,20 @@ vec4_visitor::emit_urb_slot(int mrf, int vert_result) current_annotation = "gl_Position"; emit(MOV(reg, src_reg(output_reg[VERT_RESULT_HPOS]))); break; - case BRW_VERT_RESULT_CLIP0: - current_annotation = "user clip distances"; - emit_clip_distances(reg, 0); - break; - case BRW_VERT_RESULT_CLIP1: - current_annotation = "user clip distances"; - emit_clip_distances(reg, 4); + case VERT_RESULT_CLIP_DIST0: + case VERT_RESULT_CLIP_DIST1: + if (this->c->key.uses_clip_distance) { + emit_generic_urb_slot(reg, vert_result); + } else { + current_annotation = "user clip distances"; + emit_clip_distances(hw_reg, (vert_result - VERT_RESULT_CLIP_DIST0) * 4); + } break; case BRW_VERT_RESULT_PAD: /* No need to write to this slot */ break; - default: { - assert (vert_result < VERT_RESULT_MAX); - current_annotation = NULL; - /* Copy the register, saturating if necessary */ - vec4_instruction *inst = emit(MOV(reg, - src_reg(output_reg[vert_result]))); - if ((vert_result == VERT_RESULT_COL0 || - vert_result == VERT_RESULT_COL1 || - vert_result == VERT_RESULT_BFC0 || - vert_result == VERT_RESULT_BFC1) && - c->key.clamp_vertex_color) { - inst->saturate = true; - } - } + default: + emit_generic_urb_slot(reg, vert_result); break; } } @@ -1921,7 +2252,7 @@ vec4_visitor::emit_urb_writes() /* FINISHME: edgeflag */ - brw_compute_vue_map(&c->vue_map, intel, c->key.nr_userclip, + brw_compute_vue_map(&c->vue_map, intel, c->key.userclip_active, c->prog_data.outputs_written); /* First mrf is the g0-based message header containing URB handles and such, @@ -1947,6 +2278,7 @@ vec4_visitor::emit_urb_writes() } } + current_annotation = "URB write"; vec4_instruction *inst = emit(VS_OPCODE_URB_WRITE); inst->base_mrf = base_mrf; inst->mlen = align_interleaved_urb_mlen(brw, mrf - base_mrf); @@ -1962,6 +2294,7 @@ vec4_visitor::emit_urb_writes() emit_urb_slot(mrf++, c->vue_map.slot_to_vert_result[slot]); } + current_annotation = "URB write"; inst = emit(VS_OPCODE_URB_WRITE); inst->base_mrf = base_mrf; inst->mlen = align_interleaved_urb_mlen(brw, mrf - base_mrf); @@ -1973,11 +2306,6 @@ vec4_visitor::emit_urb_writes() */ inst->offset = (max_usable_mrf - base_mrf) / 2; } - - if (intel->gen == 6) - c->prog_data.urb_entry_size = ALIGN(c->vue_map.num_slots, 8) / 8; - else - c->prog_data.urb_entry_size = ALIGN(c->vue_map.num_slots, 4) / 4; } src_reg @@ -2208,7 +2536,7 @@ vec4_visitor::move_uniform_array_access_to_pull_constants() if (pull_constant_loc[uniform] == -1) { const float **values = &prog_data->param[uniform * 4]; - pull_constant_loc[uniform] = prog_data->nr_pull_params; + pull_constant_loc[uniform] = prog_data->nr_pull_params / 4; for (int j = 0; j < uniform_size[uniform] * 4; j++) { prog_data->pull_param[prog_data->nr_pull_params++] = values[j]; @@ -2239,6 +2567,18 @@ vec4_visitor::move_uniform_array_access_to_pull_constants() split_uniform_registers(); } +void +vec4_visitor::resolve_ud_negate(src_reg *reg) +{ + if (reg->type != BRW_REGISTER_TYPE_UD || + !reg->negate) + return; + + src_reg temp = src_reg(this, glsl_type::uvec4_type); + emit(BRW_OPCODE_MOV, dst_reg(temp), *reg); + *reg = temp; +} + vec4_visitor::vec4_visitor(struct brw_vs_compile *c, struct gl_shader_program *prog, struct brw_shader *shader) @@ -2258,7 +2598,8 @@ vec4_visitor::vec4_visitor(struct brw_vs_compile *c, this->current_annotation = NULL; this->c = c; - this->vp = prog->VertexProgram; + this->vp = (struct gl_vertex_program *) + prog->_LinkedShaders[MESA_SHADER_VERTEX]->Program; this->prog_data = &c->prog_data; this->variable_ht = hash_table_ctor(0, @@ -2269,14 +2610,14 @@ vec4_visitor::vec4_visitor(struct brw_vs_compile *c, this->virtual_grf_use = NULL; this->virtual_grf_sizes = NULL; this->virtual_grf_count = 0; + this->virtual_grf_reg_map = NULL; + this->virtual_grf_reg_count = 0; this->virtual_grf_array_size = 0; this->live_intervals_valid = false; - this->uniforms = 0; + this->max_grf = intel->gen >= 7 ? GEN7_MRF_HACK_START : BRW_MAX_GRF; - this->variable_ht = hash_table_ctor(0, - hash_table_pointer_hash, - hash_table_pointer_compare); + this->uniforms = 0; } vec4_visitor::~vec4_visitor()