inst->function = NULL;
- if (op == TGSI_OPCODE_ARL)
+ if (op == TGSI_OPCODE_ARL || op == TGSI_OPCODE_UARL)
this->num_address_regs = 1;
/* Update indirect addressing status used by TGSI */
glsl_to_tgsi_visitor::emit_arl(ir_instruction *ir,
st_dst_reg dst, st_src_reg src0)
{
- st_src_reg tmp = get_temp(glsl_type::float_type);
+ int op = TGSI_OPCODE_ARL;
- if (src0.type == GLSL_TYPE_INT)
- emit(NULL, TGSI_OPCODE_I2F, st_dst_reg(tmp), src0);
- else if (src0.type == GLSL_TYPE_UINT)
- emit(NULL, TGSI_OPCODE_U2F, st_dst_reg(tmp), src0);
- else
- tmp = src0;
-
- emit(NULL, TGSI_OPCODE_ARL, dst, tmp);
+ if (src0.type == GLSL_TYPE_INT || src0.type == GLSL_TYPE_UINT)
+ op = TGSI_OPCODE_UARL;
+
+ emit(NULL, op, dst, src0);
}
/**
st_src_reg temp = get_temp(native_integers ?
glsl_type::get_instance(ir->operands[0]->type->base_type, 4, 1) :
glsl_type::vec4_type);
- assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
- emit(ir, TGSI_OPCODE_SNE, st_dst_reg(temp), op[0], op[1]);
-
- /* After the dot-product, the value will be an integer on the
- * range [0,4]. Zero becomes 1.0, and positive values become zero.
- */
- emit_dp(ir, result_dst, temp, temp, vector_elements);
- if (result_dst.type == GLSL_TYPE_FLOAT) {
+ if (native_integers) {
+ st_dst_reg temp_dst = st_dst_reg(temp);
+ st_src_reg temp1 = st_src_reg(temp), temp2 = st_src_reg(temp);
+
+ emit(ir, TGSI_OPCODE_SEQ, st_dst_reg(temp), op[0], op[1]);
+
+ /* Emit 1-3 AND operations to combine the SEQ results. */
+ switch (ir->operands[0]->type->vector_elements) {
+ case 2:
+ break;
+ case 3:
+ temp_dst.writemask = WRITEMASK_Y;
+ temp1.swizzle = SWIZZLE_YYYY;
+ temp2.swizzle = SWIZZLE_ZZZZ;
+ emit(ir, TGSI_OPCODE_AND, temp_dst, temp1, temp2);
+ break;
+ case 4:
+ temp_dst.writemask = WRITEMASK_X;
+ temp1.swizzle = SWIZZLE_XXXX;
+ temp2.swizzle = SWIZZLE_YYYY;
+ emit(ir, TGSI_OPCODE_AND, temp_dst, temp1, temp2);
+ temp_dst.writemask = WRITEMASK_Y;
+ temp1.swizzle = SWIZZLE_ZZZZ;
+ temp2.swizzle = SWIZZLE_WWWW;
+ emit(ir, TGSI_OPCODE_AND, temp_dst, temp1, temp2);
+ }
+
+ temp1.swizzle = SWIZZLE_XXXX;
+ temp2.swizzle = SWIZZLE_YYYY;
+ emit(ir, TGSI_OPCODE_AND, result_dst, temp1, temp2);
+ } else {
+ emit(ir, TGSI_OPCODE_SNE, st_dst_reg(temp), op[0], op[1]);
+
+ /* After the dot-product, the value will be an integer on the
+ * range [0,4]. Zero becomes 1.0, and positive values become zero.
+ */
+ emit_dp(ir, result_dst, temp, temp, vector_elements);
+
/* Negating the result of the dot-product gives values on the range
* [-4, 0]. Zero becomes 1.0, and negative values become zero.
* This is achieved using SGE.
st_src_reg sge_src = result_src;
sge_src.negate = ~sge_src.negate;
emit(ir, TGSI_OPCODE_SGE, result_dst, sge_src, st_src_reg_for_float(0.0));
- } else {
- /* The TGSI negate flag doesn't work for integers, so use SEQ 0
- * instead.
- */
- emit(ir, TGSI_OPCODE_SEQ, result_dst, result_src, st_src_reg_for_int(0));
}
} else {
emit(ir, TGSI_OPCODE_SEQ, result_dst, op[0], op[1]);
st_src_reg temp = get_temp(native_integers ?
glsl_type::get_instance(ir->operands[0]->type->base_type, 4, 1) :
glsl_type::vec4_type);
- assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
emit(ir, TGSI_OPCODE_SNE, st_dst_reg(temp), op[0], op[1]);
- /* After the dot-product, the value will be an integer on the
- * range [0,4]. Zero stays zero, and positive values become 1.0.
- */
- glsl_to_tgsi_instruction *const dp =
- emit_dp(ir, result_dst, temp, temp, vector_elements);
- if (this->prog->Target == GL_FRAGMENT_PROGRAM_ARB &&
- result_dst.type == GLSL_TYPE_FLOAT) {
- /* The clamping to [0,1] can be done for free in the fragment
- * shader with a saturate.
- */
- dp->saturate = true;
- } else if (result_dst.type == GLSL_TYPE_FLOAT) {
- /* Negating the result of the dot-product gives values on the range
- * [-4, 0]. Zero stays zero, and negative values become 1.0. This
- * achieved using SLT.
- */
- st_src_reg slt_src = result_src;
- slt_src.negate = ~slt_src.negate;
- emit(ir, TGSI_OPCODE_SLT, result_dst, slt_src, st_src_reg_for_float(0.0));
+ if (native_integers) {
+ st_dst_reg temp_dst = st_dst_reg(temp);
+ st_src_reg temp1 = st_src_reg(temp), temp2 = st_src_reg(temp);
+
+ /* Emit 1-3 OR operations to combine the SNE results. */
+ switch (ir->operands[0]->type->vector_elements) {
+ case 2:
+ break;
+ case 3:
+ temp_dst.writemask = WRITEMASK_Y;
+ temp1.swizzle = SWIZZLE_YYYY;
+ temp2.swizzle = SWIZZLE_ZZZZ;
+ emit(ir, TGSI_OPCODE_OR, temp_dst, temp1, temp2);
+ break;
+ case 4:
+ temp_dst.writemask = WRITEMASK_X;
+ temp1.swizzle = SWIZZLE_XXXX;
+ temp2.swizzle = SWIZZLE_YYYY;
+ emit(ir, TGSI_OPCODE_OR, temp_dst, temp1, temp2);
+ temp_dst.writemask = WRITEMASK_Y;
+ temp1.swizzle = SWIZZLE_ZZZZ;
+ temp2.swizzle = SWIZZLE_WWWW;
+ emit(ir, TGSI_OPCODE_OR, temp_dst, temp1, temp2);
+ }
+
+ temp1.swizzle = SWIZZLE_XXXX;
+ temp2.swizzle = SWIZZLE_YYYY;
+ emit(ir, TGSI_OPCODE_OR, result_dst, temp1, temp2);
} else {
- emit(ir, TGSI_OPCODE_SNE, result_dst, result_src, st_src_reg_for_int(0));
+ /* After the dot-product, the value will be an integer on the
+ * range [0,4]. Zero stays zero, and positive values become 1.0.
+ */
+ glsl_to_tgsi_instruction *const dp =
+ emit_dp(ir, result_dst, temp, temp, vector_elements);
+ if (this->prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
+ /* The clamping to [0,1] can be done for free in the fragment
+ * shader with a saturate.
+ */
+ dp->saturate = true;
+ } else {
+ /* Negating the result of the dot-product gives values on the range
+ * [-4, 0]. Zero stays zero, and negative values become 1.0. This
+ * achieved using SLT.
+ */
+ st_src_reg slt_src = result_src;
+ slt_src.negate = ~slt_src.negate;
+ emit(ir, TGSI_OPCODE_SLT, result_dst, slt_src, st_src_reg_for_float(0.0));
+ }
}
} else {
emit(ir, TGSI_OPCODE_SNE, result_dst, op[0], op[1]);
entry = new(mem_ctx) variable_storage(var,
PROGRAM_INPUT,
var->location);
- if (this->prog->Target == GL_VERTEX_PROGRAM_ARB &&
- var->location >= VERT_ATTRIB_GENERIC0) {
- _mesa_add_attribute(this->prog->Attributes,
- var->name,
- _mesa_sizeof_glsl_type(var->type->gl_type),
- var->type->gl_type,
- var->location - VERT_ATTRIB_GENERIC0);
- }
break;
case ir_var_out:
assert(var->location != -1);
/* Make modifications to fragment program info. */
prog->Parameters = _mesa_combine_parameter_lists(params,
original->prog->Parameters);
- prog->Attributes = _mesa_clone_parameter_list(original->prog->Attributes);
- prog->Varying = _mesa_clone_parameter_list(original->prog->Varying);
_mesa_free_parameter_list(params);
count_resources(v, prog);
fp->glsl_to_tgsi = v;
/* Make modifications to fragment program info. */
prog->Parameters = _mesa_clone_parameter_list(original->prog->Parameters);
- prog->Attributes = _mesa_clone_parameter_list(original->prog->Attributes);
- prog->Varying = _mesa_clone_parameter_list(original->prog->Varying);
count_resources(v, prog);
fp->glsl_to_tgsi = v;
}
if (!prog)
return NULL;
prog->Parameters = _mesa_new_parameter_list();
- prog->Varying = _mesa_new_parameter_list();
- prog->Attributes = _mesa_new_parameter_list();
v->ctx = ctx;
v->prog = prog;
v->shader_program = shader_program;
linked_prog = get_mesa_program(ctx, prog, prog->_LinkedShaders[i]);
if (linked_prog) {
- bool ok = true;
-
- switch (prog->_LinkedShaders[i]->Type) {
- case GL_VERTEX_SHADER:
- _mesa_reference_vertprog(ctx, &prog->VertexProgram,
- (struct gl_vertex_program *)linked_prog);
- ok = ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB,
- linked_prog);
- if (!ok) {
- _mesa_reference_vertprog(ctx, &prog->VertexProgram, NULL);
- }
- break;
- case GL_FRAGMENT_SHADER:
- _mesa_reference_fragprog(ctx, &prog->FragmentProgram,
- (struct gl_fragment_program *)linked_prog);
- ok = ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB,
- linked_prog);
- if (!ok) {
- _mesa_reference_fragprog(ctx, &prog->FragmentProgram, NULL);
- }
- break;
- case GL_GEOMETRY_SHADER:
- _mesa_reference_geomprog(ctx, &prog->GeometryProgram,
- (struct gl_geometry_program *)linked_prog);
- ok = ctx->Driver.ProgramStringNotify(ctx, GL_GEOMETRY_PROGRAM_NV,
- linked_prog);
- if (!ok) {
- _mesa_reference_geomprog(ctx, &prog->GeometryProgram, NULL);
- }
- break;
- }
- if (!ok) {
- _mesa_reference_program(ctx, &prog->_LinkedShaders[i]->Program, NULL);
+ static const GLenum targets[] = {
+ GL_VERTEX_PROGRAM_ARB,
+ GL_FRAGMENT_PROGRAM_ARB,
+ GL_GEOMETRY_PROGRAM_NV
+ };
+
+ _mesa_reference_program(ctx, &prog->_LinkedShaders[i]->Program,
+ linked_prog);
+ if (!ctx->Driver.ProgramStringNotify(ctx, targets[i], linked_prog)) {
+ _mesa_reference_program(ctx, &prog->_LinkedShaders[i]->Program,
+ NULL);
_mesa_reference_program(ctx, &linked_prog, NULL);
return GL_FALSE;
}