this->index = index;
this->swizzle = swizzle_for_type(type, component);
this->negate = 0;
+ this->abs = 0;
this->index2D = 0;
this->type = type ? type->base_type : GLSL_TYPE_ERROR;
this->reladdr = NULL;
this->index2D = 0;
this->swizzle = SWIZZLE_XYZW;
this->negate = 0;
+ this->abs = 0;
this->reladdr = NULL;
this->reladdr2 = NULL;
this->has_index2 = false;
this->index2D = index2D;
this->swizzle = SWIZZLE_XYZW;
this->negate = 0;
+ this->abs = 0;
this->reladdr = NULL;
this->reladdr2 = NULL;
this->has_index2 = false;
this->index2D = 0;
this->swizzle = 0;
this->negate = 0;
+ this->abs = 0;
this->reladdr = NULL;
this->reladdr2 = NULL;
this->has_index2 = false;
int16_t index2D;
uint16_t swizzle; /**< SWIZZLE_XYZWONEZERO swizzles from Mesa. */
int negate:4; /**< NEGATE_XYZW mask from mesa */
+ unsigned abs:1;
enum glsl_base_type type:4; /** GLSL_TYPE_* from GLSL IR (enum glsl_base_type) */
unsigned has_index2:1;
gl_register_file file:5; /**< PROGRAM_* from Mesa */
/** Register index should be offset by the integer in this reg. */
st_src_reg *reladdr;
st_src_reg *reladdr2;
+
+ st_src_reg get_abs()
+ {
+ st_src_reg reg = *this;
+ reg.negate = 0;
+ reg.abs = 1;
+ return reg;
+ }
};
class st_dst_reg {
this->index = reg.index;
this->swizzle = SWIZZLE_XYZW;
this->negate = 0;
+ this->abs = 0;
this->reladdr = reg.reladdr;
this->index2D = reg.index2D;
this->reladdr2 = reg.reladdr2;
case2iu(ISHR, USHR);
case3fid(SSG, ISSG, DSSG);
- case3fid(ABS, IABS, DABS);
case2iu(IBFE, UBFE);
case2iu(IMSB, UMSB);
src.type = native_integers ? type->base_type : GLSL_TYPE_FLOAT;
src.reladdr = NULL;
src.negate = 0;
+ src.abs = 0;
if (!options->EmitNoIndirectTemp && type_has_array_or_matrix(type)) {
if (next_array >= max_num_arrays) {
emit_asm(ir, TGSI_OPCODE_MOV, result_dst, op[0]);
break;
case ir_unop_abs:
- emit_asm(ir, TGSI_OPCODE_ABS, result_dst, op[0]);
+ if (result_dst.type == GLSL_TYPE_FLOAT)
+ emit_asm(ir, TGSI_OPCODE_MOV, result_dst, op[0].get_abs());
+ else if (result_dst.type == GLSL_TYPE_DOUBLE)
+ emit_asm(ir, TGSI_OPCODE_DABS, result_dst, op[0]);
+ else
+ emit_asm(ir, TGSI_OPCODE_IABS, result_dst, op[0]);
break;
case ir_unop_sign:
emit_asm(ir, TGSI_OPCODE_SSG, result_dst, op[0]);
* we want, I choose to use ABS to match DX9 and pre-GLSL RSQ
* behavior.
*/
- emit_scalar(ir, TGSI_OPCODE_ABS, result_dst, op[0]);
- emit_scalar(ir, TGSI_OPCODE_RSQ, result_dst, result_src);
+ emit_scalar(ir, TGSI_OPCODE_RSQ, result_dst, op[0].get_abs());
emit_scalar(ir, TGSI_OPCODE_RCP, result_dst, result_src);
}
break;
case ir_unop_bitcast_f2i:
case ir_unop_bitcast_f2u:
/* Make sure we don't propagate the negate modifier to integer opcodes. */
- if (op[0].negate)
+ if (op[0].negate || op[0].abs)
emit_asm(ir, TGSI_OPCODE_MOV, result_dst, op[0]);
else
result_src = op[0];
cbuf.index = 0;
cbuf.reladdr = NULL;
cbuf.negate = 0;
+ cbuf.abs = 0;
assert(ir->type->is_vector() || ir->type->is_scalar());
switch (ir->op) {
case ir_tex:
- opcode = (is_cube_array && ir->shadow_comparitor) ? TGSI_OPCODE_TEX2 : TGSI_OPCODE_TEX;
+ opcode = (is_cube_array && ir->shadow_comparator) ? TGSI_OPCODE_TEX2 : TGSI_OPCODE_TEX;
if (ir->offset) {
ir->offset->accept(this);
offset[0] = this->result;
* the shadow comparator value must also be projected.
*/
st_src_reg tmp_src = coord;
- if (ir->shadow_comparitor) {
+ if (ir->shadow_comparator) {
/* Slot the shadow value in as the second to last component of the
* coord.
*/
- ir->shadow_comparitor->accept(this);
+ ir->shadow_comparator->accept(this);
tmp_src = get_temp(glsl_type::vec4_type);
st_dst_reg tmp_dst = st_dst_reg(tmp_src);
* comparator was put in the correct place (and projected) by the code,
* above, that handles by-hand projection.
*/
- if (ir->shadow_comparitor && (!ir->projector || opcode == TGSI_OPCODE_TXP)) {
+ if (ir->shadow_comparator && (!ir->projector || opcode == TGSI_OPCODE_TXP)) {
/* Slot the shadow value in as the second to last component of the
* coord.
*/
- ir->shadow_comparitor->accept(this);
+ ir->shadow_comparator->accept(this);
if (is_cube_array) {
cube_sc = get_temp(glsl_type::float_type);
} else if (opcode == TGSI_OPCODE_TEX2) {
inst = emit_asm(ir, opcode, result_dst, coord, cube_sc);
} else if (opcode == TGSI_OPCODE_TG4) {
- if (is_cube_array && ir->shadow_comparitor) {
+ if (is_cube_array && ir->shadow_comparator) {
inst = emit_asm(ir, opcode, result_dst, coord, cube_sc);
} else {
inst = emit_asm(ir, opcode, result_dst, coord, component);
} else
inst = emit_asm(ir, opcode, result_dst, coord);
- if (ir->shadow_comparitor)
+ if (ir->shadow_comparator)
inst->tex_shadow = GL_TRUE;
inst->resource.index = sampler_index;
inst->src[0].file != PROGRAM_ARRAY &&
!inst->src[0].reladdr &&
!inst->src[0].reladdr2 &&
- !inst->src[0].negate) {
+ !inst->src[0].negate &&
+ !inst->src[0].abs) {
for (int i = 0; i < 4; i++) {
if (inst->dst[0].writemask & (1 << i)) {
acp[4 * inst->dst[0].index + i] = inst;
GET_SWZ(src_reg->swizzle, 2) & 0x3,
GET_SWZ(src_reg->swizzle, 3) & 0x3);
+ if (src_reg->abs)
+ src = ureg_abs(src);
+
if ((src_reg->negate & 0xf) == NEGATE_XYZW)
src = ureg_negate(src);
return prog;
}
+/* See if there are unsupported control flow statements. */
+class ir_control_flow_info_visitor : public ir_hierarchical_visitor {
+private:
+ const struct gl_shader_compiler_options *options;
+public:
+ ir_control_flow_info_visitor(const struct gl_shader_compiler_options *options)
+ : options(options),
+ unsupported(false)
+ {
+ }
+
+ virtual ir_visitor_status visit_enter(ir_function *ir)
+ {
+ /* Other functions are skipped (same as glsl_to_tgsi). */
+ if (strcmp(ir->name, "main") == 0)
+ return visit_continue;
+
+ return visit_continue_with_parent;
+ }
+
+ virtual ir_visitor_status visit_enter(ir_call *ir)
+ {
+ if (!ir->callee->is_intrinsic()) {
+ unsupported = true; /* it's a function call */
+ return visit_stop;
+ }
+ return visit_continue;
+ }
+
+ virtual ir_visitor_status visit_enter(ir_return *ir)
+ {
+ if (options->EmitNoMainReturn) {
+ unsupported = true;
+ return visit_stop;
+ }
+ return visit_continue;
+ }
+
+ bool unsupported;
+};
+
+static bool
+has_unsupported_control_flow(exec_list *ir,
+ const struct gl_shader_compiler_options *options)
+{
+ ir_control_flow_info_visitor visitor(options);
+ visit_list_elements(&visitor, ir);
+ return visitor.unsupported;
+}
extern "C" {
if (prog->_LinkedShaders[i] == NULL)
continue;
- bool progress;
exec_list *ir = prog->_LinkedShaders[i]->ir;
gl_shader_stage stage = prog->_LinkedShaders[i]->Stage;
const struct gl_shader_compiler_options *options =
lower_discard(ir);
}
- do {
- progress = false;
-
- progress = do_lower_jumps(ir, true, true, options->EmitNoMainReturn, options->EmitNoCont, options->EmitNoLoops) || progress;
-
- progress = do_common_optimization(ir, true, true, options,
- ctx->Const.NativeIntegers)
- || progress;
-
- progress = lower_if_to_cond_assign((gl_shader_stage)i, ir,
- options->MaxIfDepth, if_threshold) ||
- progress;
-
- } while (progress);
+ if (ctx->Const.GLSLOptimizeConservatively) {
+ /* Do it once and repeat only if there's unsupported control flow. */
+ do {
+ do_common_optimization(ir, true, true, options,
+ ctx->Const.NativeIntegers);
+ lower_if_to_cond_assign((gl_shader_stage)i, ir,
+ options->MaxIfDepth, if_threshold);
+ } while (has_unsupported_control_flow(ir, options));
+ } else {
+ /* Repeat it until it stops making changes. */
+ bool progress;
+ do {
+ progress = do_common_optimization(ir, true, true, options,
+ ctx->Const.NativeIntegers);
+ progress |= lower_if_to_cond_assign((gl_shader_stage)i, ir,
+ options->MaxIfDepth, if_threshold);
+ } while (progress);
+ }
validate_ir_tree(ir);
}
struct pipe_stream_output_info *so)
{
struct gl_transform_feedback_info *info =
- &glsl_to_tgsi->shader_program->LinkedTransformFeedback;
+ glsl_to_tgsi->shader_program->xfb_program->sh.LinkedTransformFeedback;
st_translate_stream_output_info2(info, outputMapping, so);
}