#include "main/compiler.h"
#include "ir.h"
#include "ir_visitor.h"
-#include "ir_print_visitor.h"
#include "ir_expression_flattening.h"
#include "glsl_types.h"
#include "glsl_parser_extras.h"
#define PROGRAM_ANY_CONST ((1 << PROGRAM_LOCAL_PARAM) | \
(1 << PROGRAM_ENV_PARAM) | \
(1 << PROGRAM_STATE_VAR) | \
- (1 << PROGRAM_NAMED_PARAM) | \
(1 << PROGRAM_CONSTANT) | \
(1 << PROGRAM_UNIFORM))
*/
#define MAX_TEMPS 4096
+/**
+ * Maximum number of arrays
+ */
+#define MAX_ARRAYS 256
+
/* will be 4 for GLSL 4.00 */
#define MAX_GLSL_TEXTURE_OFFSET 1
else
this->swizzle = SWIZZLE_XYZW;
this->negate = 0;
+ this->index2D = 0;
this->type = type ? type->base_type : GLSL_TYPE_ERROR;
this->reladdr = NULL;
}
this->type = type;
this->file = file;
this->index = index;
+ this->index2D = 0;
+ this->swizzle = SWIZZLE_XYZW;
+ this->negate = 0;
+ this->reladdr = NULL;
+ }
+
+ st_src_reg(gl_register_file file, int index, int type, int index2D)
+ {
+ this->type = type;
+ this->file = file;
+ this->index = index;
+ this->index2D = index2D;
this->swizzle = SWIZZLE_XYZW;
this->negate = 0;
this->reladdr = NULL;
this->type = GLSL_TYPE_ERROR;
this->file = PROGRAM_UNDEFINED;
this->index = 0;
+ this->index2D = 0;
this->swizzle = 0;
this->negate = 0;
this->reladdr = NULL;
explicit st_src_reg(st_dst_reg reg);
gl_register_file file; /**< PROGRAM_* from Mesa */
- int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */
+ int index; /**< temporary index, VERT_ATTRIB_*, VARYING_SLOT_*, etc. */
+ int index2D;
GLuint swizzle; /**< SWIZZLE_XYZWONEZERO swizzles from Mesa. */
int negate; /**< NEGATE_XYZW mask from mesa */
int type; /** GLSL_TYPE_* from GLSL IR (enum glsl_base_type) */
explicit st_dst_reg(st_src_reg reg);
gl_register_file file; /**< PROGRAM_* from Mesa */
- int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */
+ int index; /**< temporary index, VERT_ATTRIB_*, VARYING_SLOT_*, etc. */
int writemask; /**< Bitfield of WRITEMASK_[XYZW] */
GLuint cond_mask:4;
int type; /** GLSL_TYPE_* from GLSL IR (enum glsl_base_type) */
this->swizzle = SWIZZLE_XYZW;
this->negate = 0;
this->reladdr = reg.reladdr;
+ this->index2D = 0;
}
st_dst_reg::st_dst_reg(st_src_reg reg)
st_src_reg return_reg;
};
-class glsl_to_tgsi_visitor : public ir_visitor {
+struct glsl_to_tgsi_visitor : public ir_visitor {
public:
glsl_to_tgsi_visitor();
~glsl_to_tgsi_visitor();
int next_temp;
+ unsigned array_sizes[MAX_ARRAYS];
+ unsigned next_array;
+
int num_address_regs;
int samplers_used;
- bool indirect_addr_temps;
bool indirect_addr_consts;
int glsl_version;
bool native_integers;
+ bool have_sqrt;
variable_storage *find_variable_storage(ir_variable *var);
void merge_registers(void);
void renumber_registers(void);
+ void emit_block_mov(ir_assignment *ir, const struct glsl_type *type,
+ st_dst_reg *l, st_src_reg *r);
+
void *mem_ctx;
};
/* Update indirect addressing status used by TGSI */
if (dst.reladdr) {
switch(dst.file) {
- case PROGRAM_TEMPORARY:
- this->indirect_addr_temps = true;
- break;
case PROGRAM_LOCAL_PARAM:
case PROGRAM_ENV_PARAM:
case PROGRAM_STATE_VAR:
- case PROGRAM_NAMED_PARAM:
case PROGRAM_CONSTANT:
case PROGRAM_UNIFORM:
this->indirect_addr_consts = true;
for (i=0; i<3; i++) {
if(inst->src[i].reladdr) {
switch(inst->src[i].file) {
- case PROGRAM_TEMPORARY:
- this->indirect_addr_temps = true;
- break;
case PROGRAM_LOCAL_PARAM:
case PROGRAM_ENV_PARAM:
case PROGRAM_STATE_VAR:
- case PROGRAM_NAMED_PARAM:
case PROGRAM_CONSTANT:
case PROGRAM_UNIFORM:
this->indirect_addr_consts = true;
{
int type = GLSL_TYPE_FLOAT;
+ assert(src0.type != GLSL_TYPE_ARRAY);
+ assert(src0.type != GLSL_TYPE_STRUCT);
+ assert(src1.type != GLSL_TYPE_ARRAY);
+ assert(src1.type != GLSL_TYPE_STRUCT);
+
if (src0.type == GLSL_TYPE_FLOAT || src1.type == GLSL_TYPE_FLOAT)
type = GLSL_TYPE_FLOAT;
else if (native_integers)
* at link time.
*/
return 1;
- default:
- assert(0);
- return 0;
+ case GLSL_TYPE_INTERFACE:
+ case GLSL_TYPE_VOID:
+ case GLSL_TYPE_ERROR:
+ assert(!"Invalid type in type_size");
+ break;
}
+ return 0;
}
/**
st_src_reg src;
src.type = native_integers ? type->base_type : GLSL_TYPE_FLOAT;
- src.file = PROGRAM_TEMPORARY;
- src.index = next_temp;
src.reladdr = NULL;
- next_temp += type_size(type);
+ src.negate = 0;
+
+ if (!options->EmitNoIndirectTemp &&
+ (type->is_array() || type->is_matrix())) {
+
+ src.file = PROGRAM_ARRAY;
+ src.index = next_array << 16 | 0x8000;
+ array_sizes[next_array] = type_size(type);
+ ++next_array;
+
+ } else {
+ src.file = PROGRAM_TEMPORARY;
+ src.index = next_temp;
+ next_temp += type_size(type);
+ }
if (type->is_array() || type->is_record()) {
src.swizzle = SWIZZLE_NOOP;
} else {
src.swizzle = swizzle_for_size(type->vector_elements);
}
- src.negate = 0;
return src;
}
*/
assert((int) ir->num_state_slots == type_size(ir->type));
- storage = new(mem_ctx) variable_storage(ir, PROGRAM_TEMPORARY,
- this->next_temp);
- this->variables.push_tail(storage);
- this->next_temp += type_size(ir->type);
+ dst = st_dst_reg(get_temp(ir->type));
+
+ storage = new(mem_ctx) variable_storage(ir, dst.file, dst.index);
- dst = st_dst_reg(st_src_reg(PROGRAM_TEMPORARY, storage->index,
- native_integers ? ir->type->base_type : GLSL_TYPE_FLOAT));
+ this->variables.push_tail(storage);
}
assert(index == storage->index + (int)i);
}
} else {
- st_src_reg src(PROGRAM_STATE_VAR, index,
- native_integers ? ir->type->base_type : GLSL_TYPE_FLOAT);
+ /* We use GLSL_TYPE_FLOAT here regardless of the actual type of
+ * the data being moved since MOV does not care about the type of
+ * data it is moving, and we don't want to declare registers with
+ * array or struct types.
+ */
+ st_src_reg src(PROGRAM_STATE_VAR, index, GLSL_TYPE_FLOAT);
src.swizzle = slots[i].swizzle;
emit(ir, TGSI_OPCODE_MOV, dst, src);
/* even a float takes up a whole vec4 reg in a struct/array. */
bool
glsl_to_tgsi_visitor::try_emit_sat(ir_expression *ir)
{
- /* Saturates were only introduced to vertex programs in
- * NV_vertex_program3, so don't give them to drivers in the VP.
+ /* Emit saturates in the vertex shader only if SM 3.0 is supported.
*/
- if (this->prog->Target == GL_VERTEX_PROGRAM_ARB)
+ if (this->prog->Target == GL_VERTEX_PROGRAM_ARB &&
+ !st_context(this->ctx)->has_shader_model3) {
return false;
+ }
ir_rvalue *sat_src = ir->as_rvalue_to_saturate();
if (!sat_src)
this->result.file = PROGRAM_UNDEFINED;
ir->operands[operand]->accept(this);
if (this->result.file == PROGRAM_UNDEFINED) {
- ir_print_visitor v;
printf("Failed to get tree for expression operand:\n");
- ir->operands[operand]->accept(&v);
+ ir->operands[operand]->print();
+ printf("\n");
exit(1);
}
op[operand] = this->result;
break;
case ir_unop_sqrt:
- /* sqrt(x) = x * rsq(x). */
- emit_scalar(ir, TGSI_OPCODE_RSQ, result_dst, op[0]);
- emit(ir, TGSI_OPCODE_MUL, result_dst, result_src, op[0]);
- /* For incoming channels <= 0, set the result to 0. */
- op[0].negate = ~op[0].negate;
- emit(ir, TGSI_OPCODE_CMP, result_dst,
- op[0], result_src, st_src_reg_for_float(0.0));
+ if (have_sqrt) {
+ emit_scalar(ir, TGSI_OPCODE_SQRT, result_dst, op[0]);
+ }
+ else {
+ /* sqrt(x) = x * rsq(x). */
+ emit_scalar(ir, TGSI_OPCODE_RSQ, result_dst, op[0]);
+ emit(ir, TGSI_OPCODE_MUL, result_dst, result_src, op[0]);
+ /* For incoming channels <= 0, set the result to 0. */
+ op[0].negate = ~op[0].negate;
+ emit(ir, TGSI_OPCODE_CMP, result_dst,
+ op[0], result_src, st_src_reg_for_float(0.0));
+ }
break;
case ir_unop_rsq:
emit_scalar(ir, TGSI_OPCODE_RSQ, result_dst, op[0]);
assert(!"GLSL 1.30 features unsupported");
break;
+ case ir_binop_ubo_load: {
+ ir_constant *uniform_block = ir->operands[0]->as_constant();
+ ir_constant *const_offset_ir = ir->operands[1]->as_constant();
+ unsigned const_offset = const_offset_ir ? const_offset_ir->value.u[0] : 0;
+ st_src_reg index_reg = get_temp(glsl_type::uint_type);
+ st_src_reg cbuf;
+
+ cbuf.type = glsl_type::vec4_type->base_type;
+ cbuf.file = PROGRAM_CONSTANT;
+ cbuf.index = 0;
+ cbuf.index2D = uniform_block->value.u[0] + 1;
+ cbuf.reladdr = NULL;
+ cbuf.negate = 0;
+
+ assert(ir->type->is_vector() || ir->type->is_scalar());
+
+ if (const_offset_ir) {
+ index_reg = st_src_reg_for_int(const_offset / 16);
+ } else {
+ emit(ir, TGSI_OPCODE_USHR, st_dst_reg(index_reg), op[1], st_src_reg_for_int(4));
+ }
+
+ cbuf.swizzle = swizzle_for_size(ir->type->vector_elements);
+ cbuf.swizzle += MAKE_SWIZZLE4(const_offset % 16 / 4,
+ const_offset % 16 / 4,
+ const_offset % 16 / 4,
+ const_offset % 16 / 4);
+
+ cbuf.reladdr = ralloc(mem_ctx, st_src_reg);
+ memcpy(cbuf.reladdr, &index_reg, sizeof(index_reg));
+
+ if (ir->type->base_type == GLSL_TYPE_BOOL) {
+ emit(ir, TGSI_OPCODE_USNE, result_dst, cbuf, st_src_reg_for_int(0));
+ } else {
+ emit(ir, TGSI_OPCODE_MOV, result_dst, cbuf);
+ }
+ break;
+ }
+ case ir_triop_lrp:
+ /* note: we have to reorder the three args here */
+ emit(ir, TGSI_OPCODE_LRP, result_dst, op[2], op[1], op[0]);
+ break;
+ case ir_unop_pack_snorm_2x16:
+ case ir_unop_pack_unorm_2x16:
+ case ir_unop_pack_half_2x16:
+ case ir_unop_pack_snorm_4x8:
+ case ir_unop_pack_unorm_4x8:
+ case ir_unop_unpack_snorm_2x16:
+ case ir_unop_unpack_unorm_2x16:
+ case ir_unop_unpack_half_2x16:
+ case ir_unop_unpack_half_2x16_split_x:
+ case ir_unop_unpack_half_2x16_split_y:
+ case ir_unop_unpack_snorm_4x8:
+ case ir_unop_unpack_unorm_4x8:
+ case ir_binop_pack_half_2x16_split:
+ case ir_unop_bitfield_reverse:
+ case ir_unop_bit_count:
+ case ir_unop_find_msb:
+ case ir_unop_find_lsb:
+ case ir_binop_bfm:
+ case ir_triop_bfi:
+ case ir_triop_bitfield_extract:
+ case ir_quadop_bitfield_insert:
case ir_quadop_vector:
- /* This operation should have already been handled.
+ case ir_binop_vector_extract:
+ case ir_triop_vector_insert:
+ /* This operation is not supported, or should have already been handled.
*/
- assert(!"Should not get here.");
+ assert(!"Invalid ir opcode in glsl_to_tgsi_visitor::visit()");
break;
}
var->location);
this->variables.push_tail(entry);
break;
- case ir_var_in:
- case ir_var_inout:
+ case ir_var_shader_in:
/* The linker assigns locations for varyings and attributes,
* including deprecated builtins (like gl_Color), user-assign
* generic attributes (glBindVertexLocation), and
* user-defined varyings.
- *
- * FINISHME: We would hit this path for function arguments. Fix!
*/
assert(var->location != -1);
entry = new(mem_ctx) variable_storage(var,
PROGRAM_INPUT,
var->location);
break;
- case ir_var_out:
+ case ir_var_shader_out:
assert(var->location != -1);
entry = new(mem_ctx) variable_storage(var,
PROGRAM_OUTPUT,
break;
case ir_var_auto:
case ir_var_temporary:
- entry = new(mem_ctx) variable_storage(var, PROGRAM_TEMPORARY,
- this->next_temp);
+ st_src_reg src = get_temp(var->type);
+
+ entry = new(mem_ctx) variable_storage(var, src.file, src.index);
this->variables.push_tail(entry);
- next_temp += type_size(var->type);
break;
}
else
src.swizzle = SWIZZLE_NOOP;
+ /* Change the register type to the element type of the array. */
+ src.type = ir->type->base_type;
+
this->result = src;
}
this->result.swizzle = SWIZZLE_NOOP;
this->result.index += offset;
+ this->result.type = ir->type->base_type;
}
/**
return switch_order;
}
+void
+glsl_to_tgsi_visitor::emit_block_mov(ir_assignment *ir, const struct glsl_type *type,
+ st_dst_reg *l, st_src_reg *r)
+{
+ if (type->base_type == GLSL_TYPE_STRUCT) {
+ for (unsigned int i = 0; i < type->length; i++) {
+ emit_block_mov(ir, type->fields.structure[i].type, l, r);
+ }
+ return;
+ }
+
+ if (type->is_array()) {
+ for (unsigned int i = 0; i < type->length; i++) {
+ emit_block_mov(ir, type->fields.array, l, r);
+ }
+ return;
+ }
+
+ if (type->is_matrix()) {
+ const struct glsl_type *vec_type;
+
+ vec_type = glsl_type::get_instance(GLSL_TYPE_FLOAT,
+ type->vector_elements, 1);
+
+ for (int i = 0; i < type->matrix_columns; i++) {
+ emit_block_mov(ir, vec_type, l, r);
+ }
+ return;
+ }
+
+ assert(type->is_scalar() || type->is_vector());
+
+ r->type = type->base_type;
+ emit(ir, TGSI_OPCODE_MOV, *l, *r);
+ l->index++;
+ r->index++;
+}
+
void
glsl_to_tgsi_visitor::visit(ir_assignment *ir)
{
assert(!ir->lhs->type->is_scalar() && !ir->lhs->type->is_vector());
l.writemask = WRITEMASK_XYZW;
} else if (ir->lhs->type->is_scalar() &&
- ir->lhs->variable_referenced()->mode == ir_var_out) {
+ ir->lhs->variable_referenced()->mode == ir_var_shader_out) {
/* FINISHME: This hack makes writing to gl_FragDepth, which lives in the
* FINISHME: W component of fragment shader output zero, work correctly.
*/
if (native_integers) {
/* This is necessary because TGSI's CMP instruction expects the
* condition to be a float, and we store booleans as integers.
- * If TGSI had a UCMP instruction or similar, this extra
- * instruction would not be necessary.
+ * TODO: really want to avoid i2f path and use UCMP. Requires
+ * changes to process_move_condition though too.
*/
condition_temp = get_temp(glsl_type::vec4_type);
condition.negate = 0;
new_inst->saturate = inst->saturate;
inst->dead_mask = inst->dst.writemask;
} else {
- for (i = 0; i < type_size(ir->lhs->type); i++) {
- emit(ir, TGSI_OPCODE_MOV, l, r);
- l.index++;
- r.index++;
- }
+ emit_block_mov(ir, ir->rhs->type, &l, &r);
}
}
storage = find_variable_storage(param);
assert(!storage);
- storage = new(mem_ctx) variable_storage(param, PROGRAM_TEMPORARY,
- this->next_temp);
- this->variables.push_tail(storage);
+ st_src_reg src = get_temp(param->type);
- this->next_temp += type_size(param->type);
+ storage = new(mem_ctx) variable_storage(param, src.file, src.index);
+ this->variables.push_tail(storage);
}
if (!sig->return_type->is_void()) {
ir_rvalue *param_rval = (ir_rvalue *)iter.get();
ir_variable *param = (ir_variable *)sig_iter.get();
- if (param->mode == ir_var_in ||
- param->mode == ir_var_inout) {
+ if (param->mode == ir_var_function_in ||
+ param->mode == ir_var_function_inout) {
variable_storage *storage = find_variable_storage(param);
assert(storage);
ir_rvalue *param_rval = (ir_rvalue *)iter.get();
ir_variable *param = (ir_variable *)sig_iter.get();
- if (param->mode == ir_var_out ||
- param->mode == ir_var_inout) {
+ if (param->mode == ir_var_function_out ||
+ param->mode == ir_var_function_inout) {
variable_storage *storage = find_variable_storage(param);
assert(storage);
void
glsl_to_tgsi_visitor::visit(ir_texture *ir)
{
- st_src_reg result_src, coord, lod_info, projector, dx, dy, offset;
- st_dst_reg result_dst, coord_dst;
+ st_src_reg result_src, coord, cube_sc, lod_info, projector, dx, dy, offset, sample_index;
+ st_dst_reg result_dst, coord_dst, cube_sc_dst;
glsl_to_tgsi_instruction *inst = NULL;
unsigned opcode = TGSI_OPCODE_NOP;
+ const glsl_type *sampler_type = ir->sampler->type;
+ bool is_cube_array = false;
+
+ /* if we are a cube array sampler */
+ if ((sampler_type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE &&
+ sampler_type->sampler_array)) {
+ is_cube_array = true;
+ }
if (ir->coordinate) {
ir->coordinate->accept(this);
*/
coord = get_temp(glsl_type::vec4_type);
coord_dst = st_dst_reg(coord);
+ coord_dst.writemask = (1 << ir->coordinate->type->vector_elements) - 1;
emit(ir, TGSI_OPCODE_MOV, coord_dst, this->result);
}
/* Storage for our result. Ideally for an assignment we'd be using
* the actual storage for the result here, instead.
*/
- result_src = get_temp(glsl_type::vec4_type);
+ result_src = get_temp(ir->type);
result_dst = st_dst_reg(result_src);
switch (ir->op) {
case ir_tex:
- opcode = TGSI_OPCODE_TEX;
+ opcode = (is_cube_array && ir->shadow_comparitor) ? TGSI_OPCODE_TEX2 : TGSI_OPCODE_TEX;
+ if (ir->offset) {
+ ir->offset->accept(this);
+ offset = this->result;
+ }
break;
case ir_txb:
- opcode = TGSI_OPCODE_TXB;
+ opcode = is_cube_array ? TGSI_OPCODE_TXB2 : TGSI_OPCODE_TXB;
ir->lod_info.bias->accept(this);
lod_info = this->result;
+ if (ir->offset) {
+ ir->offset->accept(this);
+ offset = this->result;
+ }
break;
case ir_txl:
- opcode = TGSI_OPCODE_TXL;
+ opcode = is_cube_array ? TGSI_OPCODE_TXL2 : TGSI_OPCODE_TXL;
ir->lod_info.lod->accept(this);
lod_info = this->result;
+ if (ir->offset) {
+ ir->offset->accept(this);
+ offset = this->result;
+ }
break;
case ir_txd:
opcode = TGSI_OPCODE_TXD;
dx = this->result;
ir->lod_info.grad.dPdy->accept(this);
dy = this->result;
+ if (ir->offset) {
+ ir->offset->accept(this);
+ offset = this->result;
+ }
break;
case ir_txs:
opcode = TGSI_OPCODE_TXQ;
ir->lod_info.lod->accept(this);
lod_info = this->result;
if (ir->offset) {
- ir->offset->accept(this);
- offset = this->result;
+ ir->offset->accept(this);
+ offset = this->result;
}
break;
+ case ir_txf_ms:
+ opcode = TGSI_OPCODE_TXF;
+ ir->lod_info.sample_index->accept(this);
+ sample_index = this->result;
+ break;
+ case ir_lod:
+ assert(!"Unexpected ir_lod opcode");
+ break;
}
- const glsl_type *sampler_type = ir->sampler->type;
-
if (ir->projector) {
if (opcode == TGSI_OPCODE_TEX) {
/* Slot the projector in as the last component of the coord. */
*/
ir->shadow_comparitor->accept(this);
- /* XXX This will need to be updated for cubemap array samplers. */
- if ((sampler_type->sampler_dimensionality == GLSL_SAMPLER_DIM_2D &&
- sampler_type->sampler_array) ||
- sampler_type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE) {
- coord_dst.writemask = WRITEMASK_W;
- } else {
- coord_dst.writemask = WRITEMASK_Z;
+ if (is_cube_array) {
+ cube_sc = get_temp(glsl_type::float_type);
+ cube_sc_dst = st_dst_reg(cube_sc);
+ cube_sc_dst.writemask = WRITEMASK_X;
+ emit(ir, TGSI_OPCODE_MOV, cube_sc_dst, this->result);
+ cube_sc_dst.writemask = WRITEMASK_X;
+ }
+ else {
+ if ((sampler_type->sampler_dimensionality == GLSL_SAMPLER_DIM_2D &&
+ sampler_type->sampler_array) ||
+ sampler_type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE) {
+ coord_dst.writemask = WRITEMASK_W;
+ } else {
+ coord_dst.writemask = WRITEMASK_Z;
+ }
+
+ emit(ir, TGSI_OPCODE_MOV, coord_dst, this->result);
+ coord_dst.writemask = WRITEMASK_XYZW;
}
-
- emit(ir, TGSI_OPCODE_MOV, coord_dst, this->result);
- coord_dst.writemask = WRITEMASK_XYZW;
}
- if (opcode == TGSI_OPCODE_TXL || opcode == TGSI_OPCODE_TXB ||
+ if (ir->op == ir_txf_ms) {
+ coord_dst.writemask = WRITEMASK_W;
+ emit(ir, TGSI_OPCODE_MOV, coord_dst, sample_index);
+ coord_dst.writemask = WRITEMASK_XYZW;
+ } else if (opcode == TGSI_OPCODE_TXL || opcode == TGSI_OPCODE_TXB ||
opcode == TGSI_OPCODE_TXF) {
/* TGSI stores LOD or LOD bias in the last channel of the coords. */
coord_dst.writemask = WRITEMASK_W;
inst = emit(ir, opcode, result_dst, lod_info);
else if (opcode == TGSI_OPCODE_TXF) {
inst = emit(ir, opcode, result_dst, coord);
- } else
+ } else if (opcode == TGSI_OPCODE_TXL2 || opcode == TGSI_OPCODE_TXB2) {
+ inst = emit(ir, opcode, result_dst, coord, lod_info);
+ } else if (opcode == TGSI_OPCODE_TEX2) {
+ inst = emit(ir, opcode, result_dst, coord, cube_sc);
+ } else
inst = emit(ir, opcode, result_dst, coord);
if (ir->shadow_comparitor)
inst->tex_target = TEXTURE_3D_INDEX;
break;
case GLSL_SAMPLER_DIM_CUBE:
- inst->tex_target = TEXTURE_CUBE_INDEX;
+ inst->tex_target = (sampler_type->sampler_array)
+ ? TEXTURE_CUBE_ARRAY_INDEX : TEXTURE_CUBE_INDEX;
break;
case GLSL_SAMPLER_DIM_RECT:
inst->tex_target = TEXTURE_RECT_INDEX;
break;
case GLSL_SAMPLER_DIM_BUF:
- assert(!"FINISHME: Implement ARB_texture_buffer_object");
+ inst->tex_target = TEXTURE_BUFFER_INDEX;
break;
case GLSL_SAMPLER_DIM_EXTERNAL:
inst->tex_target = TEXTURE_EXTERNAL_INDEX;
break;
+ case GLSL_SAMPLER_DIM_MS:
+ inst->tex_target = (sampler_type->sampler_array)
+ ? TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX : TEXTURE_2D_MULTISAMPLE_INDEX;
+ break;
default:
assert(!"Should not get here.");
}
void
glsl_to_tgsi_visitor::visit(ir_if *ir)
{
- glsl_to_tgsi_instruction *cond_inst, *if_inst;
- glsl_to_tgsi_instruction *prev_inst;
-
- prev_inst = (glsl_to_tgsi_instruction *)this->instructions.get_tail();
+ unsigned if_opcode;
+ glsl_to_tgsi_instruction *if_inst;
ir->condition->accept(this);
assert(this->result.file != PROGRAM_UNDEFINED);
- if (this->options->EmitCondCodes) {
- cond_inst = (glsl_to_tgsi_instruction *)this->instructions.get_tail();
+ if_opcode = native_integers ? TGSI_OPCODE_UIF : TGSI_OPCODE_IF;
- /* See if we actually generated any instruction for generating
- * the condition. If not, then cook up a move to a temp so we
- * have something to set cond_update on.
- */
- if (cond_inst == prev_inst) {
- st_src_reg temp = get_temp(glsl_type::bool_type);
- cond_inst = emit(ir->condition, TGSI_OPCODE_MOV, st_dst_reg(temp), result);
- }
- cond_inst->cond_update = GL_TRUE;
-
- if_inst = emit(ir->condition, TGSI_OPCODE_IF);
- if_inst->dst.cond_mask = COND_NE;
- } else {
- if_inst = emit(ir->condition, TGSI_OPCODE_IF, undef_dst, this->result);
- }
+ if_inst = emit(ir->condition, if_opcode, undef_dst, this->result);
this->instructions.push_tail(if_inst);
{
result.file = PROGRAM_UNDEFINED;
next_temp = 1;
+ next_array = 0;
next_signature_id = 1;
num_immediates = 0;
current_function = NULL;
num_address_regs = 0;
samplers_used = 0;
- indirect_addr_temps = false;
indirect_addr_consts = false;
glsl_version = 0;
native_integers = false;
"Couldn't find uniform for initializer %s\n", name);
return;
}
- int loc = _mesa_uniform_merge_location_offset(index, offset);
+ int loc = _mesa_uniform_merge_location_offset(shader_program, index, offset);
for (unsigned int i = 0; i < (type->is_array() ? type->length : 1); i++) {
ir_constant *element;
assert(inst->dst.index < MAX_TEMPS);
prevWriteMask = tempWrites[inst->dst.index];
tempWrites[inst->dst.index] |= inst->dst.writemask;
- }
+ } else
+ continue;
/* For a CMP to be considered a conditional write, the destination
* register and source register two must be the same. */
break;
case TGSI_OPCODE_IF:
+ case TGSI_OPCODE_UIF:
++level;
break;
/* If this is a copy, add it to the ACP. */
if (inst->op == TGSI_OPCODE_MOV &&
inst->dst.file == PROGRAM_TEMPORARY &&
+ !(inst->dst.file == inst->src[0].file &&
+ inst->dst.index == inst->src[0].index) &&
!inst->dst.reladdr &&
!inst->saturate &&
!inst->src[0].reladdr &&
break;
case TGSI_OPCODE_IF:
+ case TGSI_OPCODE_UIF:
++level;
/* fallthrough to default case to mark the condition as read */
v->next_temp = original->next_temp;
v->num_address_regs = original->num_address_regs;
v->samplers_used = prog->SamplersUsed = original->samplers_used;
- v->indirect_addr_temps = original->indirect_addr_temps;
v->indirect_addr_consts = original->indirect_addr_consts;
memcpy(&v->immediates, &original->immediates, sizeof(v->immediates));
v->num_immediates = original->num_immediates;
* Get initial pixel color from the texture.
* TEX colorTemp, fragment.texcoord[0], texture[0], 2D;
*/
- coord = st_src_reg(PROGRAM_INPUT, FRAG_ATTRIB_TEX0, glsl_type::vec2_type);
+ coord = st_src_reg(PROGRAM_INPUT, VARYING_SLOT_TEX0, glsl_type::vec2_type);
src0 = v->get_temp(glsl_type::vec4_type);
dst0 = st_dst_reg(src0);
inst = v->emit(NULL, TGSI_OPCODE_TEX, dst0, coord);
inst->sampler = 0;
inst->tex_target = TEXTURE_2D_INDEX;
- prog->InputsRead |= FRAG_BIT_TEX0;
+ prog->InputsRead |= VARYING_BIT_TEX0;
prog->SamplersUsed |= (1 << 0); /* mark sampler 0 as used */
v->samplers_used |= (1 << 0);
for (int i=0; i<3; i++) {
src_regs[i] = inst->src[i];
if (src_regs[i].file == PROGRAM_INPUT &&
- src_regs[i].index == FRAG_ATTRIB_COL0)
+ src_regs[i].index == VARYING_SLOT_COL0)
{
src_regs[i].file = PROGRAM_TEMPORARY;
src_regs[i].index = src0.index;
v->next_temp = original->next_temp;
v->num_address_regs = original->num_address_regs;
v->samplers_used = prog->SamplersUsed = original->samplers_used;
- v->indirect_addr_temps = original->indirect_addr_temps;
v->indirect_addr_consts = original->indirect_addr_consts;
memcpy(&v->immediates, &original->immediates, sizeof(v->immediates));
v->num_immediates = original->num_immediates;
/* TEX tmp0, fragment.texcoord[0], texture[0], 2D; */
- coord = st_src_reg(PROGRAM_INPUT, FRAG_ATTRIB_TEX0, glsl_type::vec2_type);
+ coord = st_src_reg(PROGRAM_INPUT, VARYING_SLOT_TEX0, glsl_type::vec2_type);
src0 = v->get_temp(glsl_type::vec4_type);
dst0 = st_dst_reg(src0);
inst = v->emit(NULL, TGSI_OPCODE_TEX, dst0, coord);
inst->sampler = samplerIndex;
inst->tex_target = TEXTURE_2D_INDEX;
- prog->InputsRead |= FRAG_BIT_TEX0;
+ prog->InputsRead |= VARYING_BIT_TEX0;
prog->SamplersUsed |= (1 << samplerIndex); /* mark sampler as used */
v->samplers_used |= (1 << samplerIndex);
struct ureg_program *ureg;
struct ureg_dst temps[MAX_TEMPS];
+ struct ureg_dst arrays[MAX_ARRAYS];
struct ureg_src *constants;
struct ureg_src *immediates;
struct ureg_dst outputs[PIPE_MAX_SHADER_OUTPUTS];
struct ureg_src samplers[PIPE_MAX_SAMPLERS];
struct ureg_src systemValues[SYSTEM_VALUE_MAX];
+ unsigned array_sizes[MAX_ARRAYS];
+
const GLuint *inputMapping;
const GLuint *outputMapping;
gl_register_file file,
GLuint index)
{
+ unsigned array;
+
switch(file) {
case PROGRAM_UNDEFINED:
return ureg_dst_undef();
case PROGRAM_TEMPORARY:
+ assert(index >= 0);
+ assert(index < (int) Elements(t->temps));
+
if (ureg_dst_is_undef(t->temps[index]))
t->temps[index] = ureg_DECL_local_temporary(t->ureg);
return t->temps[index];
+ case PROGRAM_ARRAY:
+ array = index >> 16;
+
+ assert(array >= 0);
+ assert(array < (int) Elements(t->arrays));
+
+ if (ureg_dst_is_undef(t->arrays[array]))
+ t->arrays[array] = ureg_DECL_array_temporary(
+ t->ureg, t->array_sizes[array], TRUE);
+
+ return ureg_dst_array_offset(t->arrays[array],
+ (int)(index & 0xFFFF) - 0x8000);
+
case PROGRAM_OUTPUT:
if (t->procType == TGSI_PROCESSOR_VERTEX)
- assert(index < VERT_RESULT_MAX);
+ assert(index < VARYING_SLOT_MAX);
else if (t->procType == TGSI_PROCESSOR_FRAGMENT)
assert(index < FRAG_RESULT_MAX);
else
- assert(index < GEOM_RESULT_MAX);
+ assert(index < VARYING_SLOT_MAX);
assert(t->outputMapping[index] < Elements(t->outputs));
static struct ureg_src
src_register(struct st_translate *t,
gl_register_file file,
- GLuint index)
+ GLint index, GLint index2D)
{
switch(file) {
case PROGRAM_UNDEFINED:
return ureg_src_undef();
case PROGRAM_TEMPORARY:
- assert(index >= 0);
- assert(index < Elements(t->temps));
- if (ureg_dst_is_undef(t->temps[index]))
- t->temps[index] = ureg_DECL_local_temporary(t->ureg);
- return ureg_src(t->temps[index]);
+ case PROGRAM_ARRAY:
+ return ureg_src(dst_register(t, file, index));
- case PROGRAM_NAMED_PARAM:
case PROGRAM_ENV_PARAM:
case PROGRAM_LOCAL_PARAM:
case PROGRAM_UNIFORM:
return t->constants[index];
case PROGRAM_STATE_VAR:
case PROGRAM_CONSTANT: /* ie, immediate */
- if (index < 0)
+ if (index2D) {
+ struct ureg_src src;
+ src = ureg_src_register(TGSI_FILE_CONSTANT, 0);
+ src.Dimension = 1;
+ src.DimensionIndex = index2D;
+ return src;
+ } else if (index < 0)
return ureg_DECL_constant(t->ureg, 0);
else
return t->constants[index];
return ureg_src(t->address[index]);
case PROGRAM_SYSTEM_VALUE:
- assert(index < Elements(t->systemValues));
+ assert(index < (int) Elements(t->systemValues));
return t->systemValues[index];
default:
case TGSI_PROCESSOR_VERTEX:
/* XXX if the geometry shader is present, this must be done there
* instead of here. */
- if (dst_reg->index == VERT_RESULT_COL0 ||
- dst_reg->index == VERT_RESULT_COL1 ||
- dst_reg->index == VERT_RESULT_BFC0 ||
- dst_reg->index == VERT_RESULT_BFC1) {
+ if (dst_reg->index == VARYING_SLOT_COL0 ||
+ dst_reg->index == VARYING_SLOT_COL1 ||
+ dst_reg->index == VARYING_SLOT_BFC0 ||
+ dst_reg->index == VARYING_SLOT_BFC1) {
dst = ureg_saturate(dst);
}
break;
}
}
- if (dst_reg->reladdr != NULL)
+ if (dst_reg->reladdr != NULL) {
+ assert(dst_reg->file != PROGRAM_TEMPORARY);
dst = ureg_dst_indirect(dst, ureg_src(t->address[0]));
+ }
return dst;
}
static struct ureg_src
translate_src(struct st_translate *t, const st_src_reg *src_reg)
{
- struct ureg_src src = src_register(t, src_reg->file, src_reg->index);
+ struct ureg_src src = src_register(t, src_reg->file, src_reg->index, src_reg->index2D);
src = ureg_swizzle(src,
GET_SWZ(src_reg->swizzle, 0) & 0x3,
src = ureg_negate(src);
if (src_reg->reladdr != NULL) {
- /* Normally ureg_src_indirect() would be used here, but a stupid compiler
- * bug in g++ makes ureg_src_indirect (an inline C function) erroneously
- * set the bit for src.Negate. So we have to do the operation manually
- * here to work around the compiler's problems. */
- /*src = ureg_src_indirect(src, ureg_src(t->address[0]));*/
- struct ureg_src addr = ureg_src(t->address[0]);
- src.Indirect = 1;
- src.IndirectFile = addr.File;
- src.IndirectIndex = addr.Index;
- src.IndirectSwizzle = addr.SwizzleX;
-
- if (src_reg->file != PROGRAM_INPUT &&
- src_reg->file != PROGRAM_OUTPUT) {
- /* If src_reg->index was negative, it was set to zero in
- * src_register(). Reassign it now. But don't do this
- * for input/output regs since they get remapped while
- * const buffers don't.
- */
- src.Index = src_reg->index;
- }
+ assert(src_reg->file != PROGRAM_TEMPORARY);
+ src = ureg_src_indirect(src, ureg_src(t->address[0]));
}
return src;
const struct tgsi_texture_offset *in_offset)
{
struct tgsi_texture_offset offset;
+ struct ureg_src imm_src;
assert(in_offset->File == PROGRAM_IMMEDIATE);
+ imm_src = t->immediates[in_offset->Index];
+ offset.File = imm_src.File;
+ offset.Index = imm_src.Index;
+ offset.SwizzleX = imm_src.SwizzleX;
+ offset.SwizzleY = imm_src.SwizzleY;
+ offset.SwizzleZ = imm_src.SwizzleZ;
offset.File = TGSI_FILE_IMMEDIATE;
- offset.Index = in_offset->Index;
- offset.SwizzleX = in_offset->SwizzleX;
- offset.SwizzleY = in_offset->SwizzleY;
- offset.SwizzleZ = in_offset->SwizzleZ;
+ offset.Padding = 0;
return offset;
}
unsigned num_dst;
unsigned num_src;
+ unsigned tex_target;
num_dst = num_inst_dst_regs(inst->op);
num_src = num_inst_src_regs(inst->op);
case TGSI_OPCODE_ELSE:
case TGSI_OPCODE_ENDLOOP:
case TGSI_OPCODE_IF:
+ case TGSI_OPCODE_UIF:
assert(num_dst == 0);
ureg_label_insn(ureg,
inst->op,
case TGSI_OPCODE_TXP:
case TGSI_OPCODE_TXQ:
case TGSI_OPCODE_TXF:
+ case TGSI_OPCODE_TEX2:
+ case TGSI_OPCODE_TXB2:
+ case TGSI_OPCODE_TXL2:
src[num_src++] = t->samplers[inst->sampler];
for (i = 0; i < inst->tex_offset_num_offset; i++) {
texoffsets[i] = translate_tex_offset(t, &inst->tex_offsets[i]);
}
+ tex_target = st_translate_texture_target(inst->tex_target, inst->tex_shadow);
+
ureg_tex_insn(ureg,
inst->op,
- dst, num_dst,
- st_translate_texture_target(inst->tex_target, inst->tex_shadow),
+ dst, num_dst,
+ tex_target,
texoffsets, inst->tex_offset_num_offset,
src, num_src);
return;
struct ureg_src wpostrans = ureg_DECL_constant( ureg, wposTransConst );
struct ureg_dst wpos_temp = ureg_DECL_temporary( ureg );
- struct ureg_src wpos_input = t->inputs[t->inputMapping[FRAG_ATTRIB_WPOS]];
+ struct ureg_src wpos_input = t->inputs[t->inputMapping[VARYING_SLOT_POS]];
/* First, apply the coordinate shift: */
if (adjX || adjY[0] || adjY[1]) {
/* Use wpos_temp as position input from here on:
*/
- t->inputs[t->inputMapping[FRAG_ATTRIB_WPOS]] = ureg_src(wpos_temp);
+ t->inputs[t->inputMapping[VARYING_SLOT_POS]] = ureg_src(wpos_temp);
}
{
struct ureg_program *ureg = t->ureg;
struct ureg_dst face_temp = ureg_DECL_temporary(ureg);
- struct ureg_src face_input = t->inputs[t->inputMapping[FRAG_ATTRIB_FACE]];
+ struct ureg_src face_input = t->inputs[t->inputMapping[VARYING_SLOT_FACE]];
/* MOV_SAT face_temp, input[face] */
face_temp = ureg_saturate(face_temp);
ureg_MOV(ureg, face_temp, face_input);
/* Use face_temp as face input from here on: */
- t->inputs[t->inputMapping[FRAG_ATTRIB_FACE]] = ureg_src(face_temp);
+ t->inputs[t->inputMapping[VARYING_SLOT_FACE]] = ureg_src(face_temp);
}
static void
emit_edgeflags(struct st_translate *t)
{
struct ureg_program *ureg = t->ureg;
- struct ureg_dst edge_dst = t->outputs[t->outputMapping[VERT_RESULT_EDGE]];
+ struct ureg_dst edge_dst = t->outputs[t->outputMapping[VARYING_SLOT_EDGE]];
struct ureg_src edge_src = t->inputs[t->inputMapping[VERT_ATTRIB_EDGEFLAG]];
ureg_MOV(ureg, edge_dst, edge_src);
is_centroid[i]);
}
- if (proginfo->InputsRead & FRAG_BIT_WPOS) {
+ if (proginfo->InputsRead & VARYING_BIT_POS) {
/* Must do this after setting up t->inputs, and before
* emitting constant references, below:
*/
emit_wpos(st_context(ctx), t, proginfo, ureg);
}
- if (proginfo->InputsRead & FRAG_BIT_FACE)
+ if (proginfo->InputsRead & VARYING_BIT_FACE)
emit_face_var(t);
/*
}
}
- if (program->indirect_addr_temps) {
- /* If temps are accessed with indirect addressing, declare temporaries
- * in sequential order. Else, we declare them on demand elsewhere.
- * (Note: the number of temporaries is equal to program->next_temp)
- */
- for (i = 0; i < (unsigned)program->next_temp; i++) {
- /* XXX use TGSI_FILE_TEMPORARY_ARRAY when it's supported by ureg */
- t->temps[i] = ureg_DECL_local_temporary(t->ureg);
- }
- }
+ /* Copy over array sizes
+ */
+ memcpy(t->array_sizes, program->array_sizes, sizeof(unsigned) * program->next_array);
/* Emit constants and uniforms. TGSI uses a single index space for these,
* so we put all the translated regs in t->constants.
*/
if (proginfo->Parameters) {
- t->constants = (struct ureg_src *)CALLOC(proginfo->Parameters->NumParameters * sizeof(t->constants[0]));
+ t->constants = (struct ureg_src *)
+ calloc(proginfo->Parameters->NumParameters, sizeof(t->constants[0]));
if (t->constants == NULL) {
ret = PIPE_ERROR_OUT_OF_MEMORY;
goto out;
case PROGRAM_ENV_PARAM:
case PROGRAM_LOCAL_PARAM:
case PROGRAM_STATE_VAR:
- case PROGRAM_NAMED_PARAM:
case PROGRAM_UNIFORM:
t->constants[i] = ureg_DECL_constant(ureg, i);
break;
}
}
}
+
+ if (program->shader_program) {
+ unsigned num_ubos = program->shader_program->NumUniformBlocks;
+
+ for (i = 0; i < num_ubos; i++) {
+ ureg_DECL_constant2D(t->ureg, 0, program->shader_program->UniformBlocks[i].UniformBufferSize / 4, i + 1);
+ }
+ }
/* Emit immediate values.
*/
- t->immediates = (struct ureg_src *)CALLOC(program->num_immediates * sizeof(struct ureg_src));
+ t->immediates = (struct ureg_src *)
+ calloc(program->num_immediates, sizeof(struct ureg_src));
if (t->immediates == NULL) {
ret = PIPE_ERROR_OUT_OF_MEMORY;
goto out;
assert(i == program->num_immediates);
/* texture samplers */
- for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
+ for (i = 0; i < ctx->Const.FragmentProgram.MaxTextureImageUnits; i++) {
if (program->samplers_used & (1 << i)) {
t->samplers[i] = ureg_DECL_sampler(ureg, i);
}
out:
if (t) {
- FREE(t->insn);
- FREE(t->labels);
- FREE(t->constants);
- FREE(t->immediates);
+ free(t->insn);
+ free(t->labels);
+ free(t->constants);
+ free(t->immediates);
if (t->error) {
debug_printf("%s: translate error flag set\n", __FUNCTION__);
}
- FREE(t);
+ free(t);
}
return ret;
bool progress;
struct gl_shader_compiler_options *options =
&ctx->ShaderCompilerOptions[_mesa_shader_type_to_index(shader->Type)];
+ struct pipe_screen *pscreen = ctx->st->pipe->screen;
+ unsigned ptarget;
switch (shader->Type) {
case GL_VERTEX_SHADER:
target = GL_VERTEX_PROGRAM_ARB;
+ ptarget = PIPE_SHADER_VERTEX;
target_string = "vertex";
break;
case GL_FRAGMENT_SHADER:
target = GL_FRAGMENT_PROGRAM_ARB;
+ ptarget = PIPE_SHADER_FRAGMENT;
target_string = "fragment";
break;
case GL_GEOMETRY_SHADER:
target = GL_GEOMETRY_PROGRAM_NV;
+ ptarget = PIPE_SHADER_GEOMETRY;
target_string = "geometry";
break;
default:
v->glsl_version = ctx->Const.GLSLVersion;
v->native_integers = ctx->Const.NativeIntegers;
+ v->have_sqrt = pscreen->get_shader_param(pscreen, ptarget,
+ PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED);
+
_mesa_generate_parameters_list_for_uniforms(shader_program, shader,
prog->Parameters);
v->copy_propagate();
while (v->eliminate_dead_code_advanced());
- /* FIXME: These passes to optimize temporary registers don't work when there
- * is indirect addressing of the temporary register space. We need proper
- * array support so that we don't have to give up these passes in every
- * shader that uses arrays.
- */
- if (!v->indirect_addr_temps) {
- v->eliminate_dead_code();
- v->merge_registers();
- v->renumber_registers();
- }
+ v->eliminate_dead_code();
+ v->merge_registers();
+ v->renumber_registers();
/* Write the END instruction. */
v->emit(NULL, TGSI_OPCODE_END);
const struct gl_shader_compiler_options *options =
&ctx->ShaderCompilerOptions[_mesa_shader_type_to_index(prog->_LinkedShaders[i]->Type)];
- do {
- unsigned what_to_lower = MOD_TO_FRACT | DIV_TO_MUL_RCP |
- EXP_TO_EXP2 | LOG_TO_LOG2;
- if (options->EmitNoPow)
- what_to_lower |= POW_TO_EXP2;
- if (!ctx->Const.NativeIntegers)
- what_to_lower |= INT_DIV_TO_MUL_RCP;
+ /* If there are forms of indirect addressing that the driver
+ * cannot handle, perform the lowering pass.
+ */
+ if (options->EmitNoIndirectInput || options->EmitNoIndirectOutput ||
+ options->EmitNoIndirectTemp || options->EmitNoIndirectUniform) {
+ lower_variable_index_to_cond_assign(ir,
+ options->EmitNoIndirectInput,
+ options->EmitNoIndirectOutput,
+ options->EmitNoIndirectTemp,
+ options->EmitNoIndirectUniform);
+ }
- progress = false;
+ if (ctx->Extensions.ARB_shading_language_packing) {
+ unsigned lower_inst = LOWER_PACK_SNORM_2x16 |
+ LOWER_UNPACK_SNORM_2x16 |
+ LOWER_PACK_UNORM_2x16 |
+ LOWER_UNPACK_UNORM_2x16 |
+ LOWER_PACK_SNORM_4x8 |
+ LOWER_UNPACK_SNORM_4x8 |
+ LOWER_UNPACK_UNORM_4x8 |
+ LOWER_PACK_UNORM_4x8 |
+ LOWER_PACK_HALF_2x16 |
+ LOWER_UNPACK_HALF_2x16;
+
+ lower_packing_builtins(ir, lower_inst);
+ }
- /* Lowering */
- do_mat_op_to_vec(ir);
- lower_instructions(ir, what_to_lower);
+ do_mat_op_to_vec(ir);
+ lower_instructions(ir,
+ MOD_TO_FRACT |
+ DIV_TO_MUL_RCP |
+ EXP_TO_EXP2 |
+ LOG_TO_LOG2 |
+ (options->EmitNoPow ? POW_TO_EXP2 : 0) |
+ (!ctx->Const.NativeIntegers ? INT_DIV_TO_MUL_RCP : 0));
+
+ lower_ubo_reference(prog->_LinkedShaders[i], ir);
+ do_vec_index_to_cond_assign(ir);
+ lower_vector_insert(ir, true);
+ lower_quadop_vector(ir, false);
+ lower_noise(ir);
+ if (options->MaxIfDepth == 0) {
+ 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->MaxUnrollIterations)
+ options->MaxUnrollIterations, options)
|| progress;
- progress = lower_quadop_vector(ir, false) || progress;
-
- if (options->MaxIfDepth == 0)
- progress = lower_discard(ir) || progress;
-
progress = lower_if_to_cond_assign(ir, options->MaxIfDepth) || progress;
- if (options->EmitNoNoise)
- progress = lower_noise(ir) || progress;
-
- /* If there are forms of indirect addressing that the driver
- * cannot handle, perform the lowering pass.
- */
- if (options->EmitNoIndirectInput || options->EmitNoIndirectOutput
- || options->EmitNoIndirectTemp || options->EmitNoIndirectUniform)
- progress =
- lower_variable_index_to_cond_assign(ir,
- options->EmitNoIndirectInput,
- options->EmitNoIndirectOutput,
- options->EmitNoIndirectTemp,
- options->EmitNoIndirectUniform)
- || progress;
-
- progress = do_vec_index_to_cond_assign(ir) || progress;
} while (progress);
validate_ir_tree(ir);