class immediate_storage : public exec_node {
public:
- immediate_storage(gl_constant_value *values, int size32, int type)
+ immediate_storage(gl_constant_value *values, int size32, GLenum type)
{
memcpy(this->values, values, size32 * sizeof(gl_constant_value));
this->size32 = size32;
/* doubles are stored across 2 gl_constant_values */
gl_constant_value values[4];
int size32; /**< Number of 32-bit components (1-4) */
- int type; /**< GL_DOUBLE, GL_FLOAT, GL_INT, GL_BOOL, or GL_UNSIGNED_INT */
+ GLenum type; /**< GL_DOUBLE, GL_FLOAT, GL_INT, GL_BOOL, or GL_UNSIGNED_INT */
};
static const st_src_reg undef_src = st_src_reg(PROGRAM_UNDEFINED, 0, GLSL_TYPE_ERROR);
return GLSL_TYPE_ERROR;
}
+struct hwatomic_decl {
+ unsigned location;
+ unsigned binding;
+ unsigned size;
+ unsigned array_id;
+};
+
struct glsl_to_tgsi_visitor : public ir_visitor {
public:
glsl_to_tgsi_visitor();
unsigned num_outputs;
unsigned num_output_arrays;
+ struct hwatomic_decl atomic_info[PIPE_MAX_HW_ATOMIC_BUFFERS];
+ unsigned num_atomics;
+ unsigned num_atomic_arrays;
int num_address_regs;
uint32_t samplers_used;
glsl_base_type sampler_types[PIPE_MAX_SAMPLERS];
- int sampler_targets[PIPE_MAX_SAMPLERS]; /**< One of TGSI_TEXTURE_* */
+ enum tgsi_texture_type sampler_targets[PIPE_MAX_SAMPLERS];
int images_used;
- int image_targets[PIPE_MAX_SHADER_IMAGES];
- unsigned image_formats[PIPE_MAX_SHADER_IMAGES];
+ enum tgsi_texture_type image_targets[PIPE_MAX_SHADER_IMAGES];
+ enum pipe_format image_formats[PIPE_MAX_SHADER_IMAGES];
bool indirect_addr_consts;
int wpos_transform_const;
- int glsl_version;
bool native_integers;
bool have_sqrt;
bool have_fma;
bool use_shared_memory;
bool has_tex_txf_lz;
bool precise;
+ bool need_uarl;
variable_storage *find_variable_storage(ir_variable *var);
int add_constant(gl_register_file file, gl_constant_value values[8],
- int size, int datatype, uint16_t *swizzle_out);
+ int size, GLenum datatype, uint16_t *swizzle_out);
st_src_reg get_temp(const glsl_type *type);
void reladdr_to_temp(ir_instruction *ir, st_src_reg *reg, int *num_reladdr);
void visit_membar_intrinsic(ir_call *);
void visit_shared_intrinsic(ir_call *);
void visit_image_intrinsic(ir_call *);
- void visit_generic_intrinsic(ir_call *, unsigned op);
+ void visit_generic_intrinsic(ir_call *, enum tgsi_opcode op);
st_src_reg result;
/** List of glsl_to_tgsi_instruction */
exec_list instructions;
- glsl_to_tgsi_instruction *emit_asm(ir_instruction *ir, unsigned op,
+ glsl_to_tgsi_instruction *emit_asm(ir_instruction *ir, enum tgsi_opcode op,
st_dst_reg dst = undef_dst,
st_src_reg src0 = undef_src,
st_src_reg src1 = undef_src,
st_src_reg src2 = undef_src,
st_src_reg src3 = undef_src);
- glsl_to_tgsi_instruction *emit_asm(ir_instruction *ir, unsigned op,
+ glsl_to_tgsi_instruction *emit_asm(ir_instruction *ir, enum tgsi_opcode op,
st_dst_reg dst, st_dst_reg dst1,
st_src_reg src0 = undef_src,
st_src_reg src1 = undef_src,
st_src_reg src2 = undef_src,
st_src_reg src3 = undef_src);
- unsigned get_opcode(unsigned op,
- st_dst_reg dst,
- st_src_reg src0, st_src_reg src1);
+ enum tgsi_opcode get_opcode(enum tgsi_opcode op,
+ st_dst_reg dst,
+ st_src_reg src0, st_src_reg src1);
/**
* Emit the correct dot-product instruction for the type of arguments
st_src_reg src1,
unsigned elements);
- void emit_scalar(ir_instruction *ir, unsigned op,
+ void emit_scalar(ir_instruction *ir, enum tgsi_opcode op,
st_dst_reg dst, st_src_reg src0);
- void emit_scalar(ir_instruction *ir, unsigned op,
+ void emit_scalar(ir_instruction *ir, enum tgsi_opcode op,
st_dst_reg dst, st_src_reg src0, st_src_reg src1);
void emit_arl(ir_instruction *ir, st_dst_reg dst, st_src_reg src0);
void *mem_ctx;
};
-static st_dst_reg address_reg = st_dst_reg(PROGRAM_ADDRESS, WRITEMASK_X, GLSL_TYPE_FLOAT, 0);
-static st_dst_reg address_reg2 = st_dst_reg(PROGRAM_ADDRESS, WRITEMASK_X, GLSL_TYPE_FLOAT, 1);
-static st_dst_reg sampler_reladdr = st_dst_reg(PROGRAM_ADDRESS, WRITEMASK_X, GLSL_TYPE_FLOAT, 2);
+static st_dst_reg address_reg = st_dst_reg(PROGRAM_ADDRESS, WRITEMASK_X,
+ GLSL_TYPE_FLOAT, 0);
+static st_dst_reg address_reg2 = st_dst_reg(PROGRAM_ADDRESS, WRITEMASK_X,
+ GLSL_TYPE_FLOAT, 1);
+static st_dst_reg sampler_reladdr = st_dst_reg(PROGRAM_ADDRESS, WRITEMASK_X,
+ GLSL_TYPE_FLOAT, 2);
static void
-fail_link(struct gl_shader_program *prog, const char *fmt, ...) PRINTFLIKE(2, 3);
+fail_link(struct gl_shader_program *prog, const char *fmt, ...)
+ PRINTFLIKE(2, 3);
static void
fail_link(struct gl_shader_program *prog, const char *fmt, ...)
ralloc_vasprintf_append(&prog->data->InfoLog, fmt, args);
va_end(args);
- prog->data->LinkStatus = linking_failure;
+ prog->data->LinkStatus = LINKING_FAILURE;
}
int
glsl_to_tgsi_instruction *
-glsl_to_tgsi_visitor::emit_asm(ir_instruction *ir, unsigned op,
+glsl_to_tgsi_visitor::emit_asm(ir_instruction *ir, enum tgsi_opcode op,
st_dst_reg dst, st_dst_reg dst1,
st_src_reg src0, st_src_reg src1,
st_src_reg src2, st_src_reg src3)
* sources into temps.
*/
num_reladdr += dst.reladdr != NULL || dst.reladdr2;
- num_reladdr += dst1.reladdr != NULL || dst1.reladdr2;
+ assert(!dst1.reladdr); /* should be lowered in earlier passes */
num_reladdr += src0.reladdr != NULL || src0.reladdr2 != NULL;
num_reladdr += src1.reladdr != NULL || src1.reladdr2 != NULL;
num_reladdr += src2.reladdr != NULL || src2.reladdr2 != NULL;
emit_arl(ir, address_reg2, *dst.reladdr2);
num_reladdr--;
}
- if (dst1.reladdr) {
- emit_arl(ir, address_reg, *dst1.reladdr);
- num_reladdr--;
- }
+
assert(num_reladdr == 0);
/* inst->op has only 8 bits. */
/* Update indirect addressing status used by TGSI */
if (dst.reladdr || dst.reladdr2) {
- switch(dst.file) {
+ switch (dst.file) {
case PROGRAM_STATE_VAR:
case PROGRAM_CONSTANT:
case PROGRAM_UNIFORM:
}
else {
for (i = 0; i < 4; i++) {
- if(inst->src[i].reladdr) {
- switch(inst->src[i].file) {
+ if (inst->src[i].reladdr) {
+ switch (inst->src[i].file) {
case PROGRAM_STATE_VAR:
case PROGRAM_CONSTANT:
case PROGRAM_UNIFORM:
*/
for (j = 0; j < 2; j++) {
dst_is_64bit[j] = glsl_base_type_is_64bit(inst->dst[j].type);
- if (!dst_is_64bit[j] && inst->dst[j].file == PROGRAM_OUTPUT && inst->dst[j].type == GLSL_TYPE_ARRAY) {
- enum glsl_base_type type = find_array_type(this->outputs, this->num_outputs, inst->dst[j].array_id);
+ if (!dst_is_64bit[j] && inst->dst[j].file == PROGRAM_OUTPUT &&
+ inst->dst[j].type == GLSL_TYPE_ARRAY) {
+ enum glsl_base_type type = find_array_type(this->outputs,
+ this->num_outputs,
+ inst->dst[j].array_id);
if (glsl_base_type_is_64bit(type))
dst_is_64bit[j] = true;
}
int initial_src_swz[4], initial_src_idx[4];
int initial_dst_idx[2], initial_dst_writemask[2];
/* select the writemask for dst0 or dst1 */
- unsigned writemask = inst->dst[1].file == PROGRAM_UNDEFINED ? inst->dst[0].writemask : inst->dst[1].writemask;
+ unsigned writemask = inst->dst[1].file == PROGRAM_UNDEFINED
+ ? inst->dst[0].writemask : inst->dst[1].writemask;
/* copy out the writemask, index and swizzles for all src/dsts. */
for (j = 0; j < 2; j++) {
int i = u_bit_scan(&writemask);
- /* before emitting the instruction, see if we have to adjust load / store
- * address */
- if (i > 1 && (inst->op == TGSI_OPCODE_LOAD || inst->op == TGSI_OPCODE_STORE) &&
+ /* before emitting the instruction, see if we have to adjust
+ * load / store address */
+ if (i > 1 && (inst->op == TGSI_OPCODE_LOAD ||
+ inst->op == TGSI_OPCODE_STORE) &&
addr.file == PROGRAM_UNDEFINED) {
/* We have to advance the buffer address by 16 */
addr = get_temp(glsl_type::uint_type);
dinst->dst[j].writemask = (i & 1) ? WRITEMASK_ZW : WRITEMASK_XY;
dinst->dst[j].index = initial_dst_idx[j];
if (i > 1) {
- if (dinst->op == TGSI_OPCODE_LOAD || dinst->op == TGSI_OPCODE_STORE)
+ if (dinst->op == TGSI_OPCODE_LOAD ||
+ dinst->op == TGSI_OPCODE_STORE)
dinst->src[0] = addr;
if (dinst->op != TGSI_OPCODE_STORE)
dinst->dst[j].index++;
}
} else {
- /* if we aren't writing to a double, just get the bit of the initial writemask
- for this channel */
+ /* if we aren't writing to a double, just get the bit of the
+ * initial writemask for this channel
+ */
dinst->dst[j].writemask = initial_dst_writemask[j] & (1 << i);
}
}
}
if (swz & 1)
- dinst->src[j].swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, SWIZZLE_Z, SWIZZLE_W);
+ dinst->src[j].swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W,
+ SWIZZLE_Z, SWIZZLE_W);
else
- dinst->src[j].swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_X, SWIZZLE_Y);
+ dinst->src[j].swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
+ SWIZZLE_X, SWIZZLE_Y);
} else {
/* some opcodes are special case in what they use as sources
- - [FUI]2D/[UI]2I64 is a float/[u]int src0, DLDEXP is integer src1 */
- if (op == TGSI_OPCODE_F2D || op == TGSI_OPCODE_U2D || op == TGSI_OPCODE_I2D ||
+ * - [FUI]2D/[UI]2I64 is a float/[u]int src0, (D)LDEXP is
+ * integer src1
+ */
+ if (op == TGSI_OPCODE_F2D || op == TGSI_OPCODE_U2D ||
+ op == TGSI_OPCODE_I2D ||
op == TGSI_OPCODE_I2I64 || op == TGSI_OPCODE_U2I64 ||
- op == TGSI_OPCODE_DLDEXP ||
+ op == TGSI_OPCODE_DLDEXP || op == TGSI_OPCODE_LDEXP ||
(op == TGSI_OPCODE_UCMP && dst_is_64bit[0])) {
dinst->src[j].swizzle = MAKE_SWIZZLE4(swz, swz, swz, swz);
}
}
glsl_to_tgsi_instruction *
-glsl_to_tgsi_visitor::emit_asm(ir_instruction *ir, unsigned op,
+glsl_to_tgsi_visitor::emit_asm(ir_instruction *ir, enum tgsi_opcode op,
st_dst_reg dst,
st_src_reg src0, st_src_reg src1,
st_src_reg src2, st_src_reg src3)
* Determines whether to use an integer, unsigned integer, or float opcode
* based on the operands and input opcode, then emits the result.
*/
-unsigned
-glsl_to_tgsi_visitor::get_opcode(unsigned op,
+enum tgsi_opcode
+glsl_to_tgsi_visitor::get_opcode(enum tgsi_opcode op,
st_dst_reg dst,
st_src_reg src0, st_src_reg src1)
{
op = TGSI_OPCODE_##c; \
break;
- switch(op) {
+ switch (op) {
/* Some instructions are initially selected without considering the type.
* This fixes the type:
*
casecomp(SGE, FSGE, ISGE, USGE, DSGE, I64SGE, U64SGE);
casecomp(SLT, FSLT, ISLT, USLT, DSLT, I64SLT, U64SLT);
- default: break;
+ default:
+ break;
}
assert(op != TGSI_OPCODE_LAST);
st_dst_reg dst, st_src_reg src0, st_src_reg src1,
unsigned elements)
{
- static const unsigned dot_opcodes[] = {
+ static const enum tgsi_opcode dot_opcodes[] = {
TGSI_OPCODE_DP2, TGSI_OPCODE_DP3, TGSI_OPCODE_DP4
};
* to produce dest channels.
*/
void
-glsl_to_tgsi_visitor::emit_scalar(ir_instruction *ir, unsigned op,
+glsl_to_tgsi_visitor::emit_scalar(ir_instruction *ir, enum tgsi_opcode op,
st_dst_reg dst,
st_src_reg orig_src0, st_src_reg orig_src1)
{
}
void
-glsl_to_tgsi_visitor::emit_scalar(ir_instruction *ir, unsigned op,
+glsl_to_tgsi_visitor::emit_scalar(ir_instruction *ir, enum tgsi_opcode op,
st_dst_reg dst, st_src_reg src0)
{
st_src_reg undef = undef_src;
glsl_to_tgsi_visitor::emit_arl(ir_instruction *ir,
st_dst_reg dst, st_src_reg src0)
{
- int op = TGSI_OPCODE_ARL;
+ enum tgsi_opcode op = TGSI_OPCODE_ARL;
+
+ if (src0.type == GLSL_TYPE_INT || src0.type == GLSL_TYPE_UINT) {
+ if (!this->need_uarl && src0.is_legal_tgsi_address_operand())
+ return;
- if (src0.type == GLSL_TYPE_INT || src0.type == GLSL_TYPE_UINT)
op = TGSI_OPCODE_UARL;
+ }
assert(dst.file == PROGRAM_ADDRESS);
if (dst.index >= this->num_address_regs)
int
glsl_to_tgsi_visitor::add_constant(gl_register_file file,
- gl_constant_value values[8], int size, int datatype,
+ gl_constant_value values[8], int size,
+ GLenum datatype,
uint16_t *swizzle_out)
{
if (file == PROGRAM_CONSTANT) {
GLuint swizzle = swizzle_out ? *swizzle_out : 0;
- int result = _mesa_add_typed_unnamed_constant(this->prog->Parameters, values,
- size, datatype, &swizzle);
+ int result = _mesa_add_typed_unnamed_constant(this->prog->Parameters,
+ values, size, datatype,
+ &swizzle);
if (swizzle_out)
*swizzle_out = swizzle;
return result;
immediate_storage *entry;
int size32 = size * ((datatype == GL_DOUBLE ||
datatype == GL_INT64_ARB ||
- datatype == GL_UNSIGNED_INT64_ARB)? 2 : 1);
+ datatype == GL_UNSIGNED_INT64_ARB) ? 2 : 1);
int i;
/* Search immediate storage to see if we already have an identical
for (i = 0; i * 4 < size32; i++) {
int slot_size = MIN2(size32 - (i * 4), 4);
/* Add this immediate to the list. */
- entry = new(mem_ctx) immediate_storage(&values[i * 4], slot_size, datatype);
+ entry = new(mem_ctx) immediate_storage(&values[i * 4],
+ slot_size, datatype);
this->immediates.push_tail(entry);
this->num_immediates++;
}
* emit_asm() might have actually split the op into pieces, e.g. for
* double stores. We have to go back and fix up all the generated ops.
*/
- unsigned op = inst->op;
+ enum tgsi_opcode op = inst->op;
do {
inst->resource = *buf;
if (access)
for (unsigned int i = 0; i < ir->get_num_state_slots(); i++) {
int index = _mesa_add_state_reference(this->prog->Parameters,
- (gl_state_index *)slots[i].tokens);
+ slots[i].tokens);
if (storage->file == PROGRAM_STATE_VAR) {
if (storage->index == -1) {
* instruction.
*/
bool
-glsl_to_tgsi_visitor::try_emit_mad_for_and_not(ir_expression *ir, int try_operand)
+glsl_to_tgsi_visitor::try_emit_mad_for_and_not(ir_expression *ir,
+ int try_operand)
{
const int other_operand = 1 - try_operand;
st_src_reg a, b;
if (!reg->reladdr && !reg->reladdr2)
return;
- if (reg->reladdr) emit_arl(ir, address_reg, *reg->reladdr);
- if (reg->reladdr2) emit_arl(ir, address_reg2, *reg->reladdr2);
+ if (reg->reladdr)
+ emit_arl(ir, address_reg, *reg->reladdr);
+ if (reg->reladdr2)
+ emit_arl(ir, address_reg2, *reg->reladdr2);
if (*num_reladdr != 1) {
- st_src_reg temp = get_temp(reg->type == GLSL_TYPE_DOUBLE ? glsl_type::dvec4_type : glsl_type::vec4_type);
+ st_src_reg temp = get_temp(glsl_type::get_instance(reg->type, 4, 1));
emit_asm(ir, TGSI_OPCODE_MOV, st_dst_reg(temp), *reg);
*reg = temp;
st_dst_reg result_dst;
int vector_elements = ir->operands[0]->type->vector_elements;
- if (ir->operands[1]) {
+ if (ir->operands[1] &&
+ ir->operation != ir_binop_interpolate_at_offset &&
+ ir->operation != ir_binop_interpolate_at_sample) {
+ st_src_reg *swz_op = NULL;
+ if (vector_elements > ir->operands[1]->type->vector_elements) {
+ assert(ir->operands[1]->type->vector_elements == 1);
+ swz_op = &op[1];
+ } else if (vector_elements < ir->operands[1]->type->vector_elements) {
+ assert(ir->operands[0]->type->vector_elements == 1);
+ swz_op = &op[0];
+ }
+ if (swz_op) {
+ uint16_t swizzle_x = GET_SWZ(swz_op->swizzle, 0);
+ swz_op->swizzle = MAKE_SWIZZLE4(swizzle_x, swizzle_x,
+ swizzle_x, swizzle_x);
+ }
vector_elements = MAX2(vector_elements,
ir->operands[1]->type->vector_elements);
}
+ if (ir->operands[2] &&
+ ir->operands[2]->type->vector_elements != vector_elements) {
+ /* This can happen with ir_triop_lrp, i.e. glsl mix */
+ assert(ir->operands[2]->type->vector_elements == 1);
+ uint16_t swizzle_x = GET_SWZ(op[2].swizzle, 0);
+ op[2].swizzle = MAKE_SWIZZLE4(swizzle_x, swizzle_x,
+ swizzle_x, swizzle_x);
+ }
this->result.file = PROGRAM_UNDEFINED;
* 0.0 and 1.0, 1-x also implements !x.
*/
op[0].negate = ~op[0].negate;
- emit_asm(ir, TGSI_OPCODE_ADD, result_dst, op[0], st_src_reg_for_float(1.0));
+ emit_asm(ir, TGSI_OPCODE_ADD, result_dst, op[0],
+ st_src_reg_for_float(1.0));
}
break;
case ir_unop_neg:
- if (result_dst.type == GLSL_TYPE_INT64 || result_dst.type == GLSL_TYPE_UINT64)
+ if (result_dst.type == GLSL_TYPE_INT64 ||
+ result_dst.type == GLSL_TYPE_UINT64)
emit_asm(ir, TGSI_OPCODE_I64NEG, result_dst, op[0]);
- else if (result_dst.type == GLSL_TYPE_INT || result_dst.type == GLSL_TYPE_UINT)
+ else if (result_dst.type == GLSL_TYPE_INT ||
+ result_dst.type == GLSL_TYPE_UINT)
emit_asm(ir, TGSI_OPCODE_INEG, result_dst, op[0]);
else if (result_dst.type == GLSL_TYPE_DOUBLE)
emit_asm(ir, TGSI_OPCODE_DNEG, result_dst, op[0]);
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 if (result_dst.type == GLSL_TYPE_INT64 || result_dst.type == GLSL_TYPE_UINT64)
+ else if (result_dst.type == GLSL_TYPE_INT64 ||
+ result_dst.type == GLSL_TYPE_UINT64)
emit_asm(ir, TGSI_OPCODE_I64ABS, result_dst, op[0]);
else
emit_asm(ir, TGSI_OPCODE_IABS, result_dst, op[0]);
* is a FBO or the window system buffer, respectively.
* It is then multiplied with the source operand of DDY.
*/
- static const gl_state_index transform_y_state[STATE_LENGTH]
+ static const gl_state_index16 transform_y_state[STATE_LENGTH]
= { STATE_INTERNAL, STATE_FB_WPOS_Y_TRANSFORM };
unsigned transform_y_index =
case ir_binop_less:
emit_asm(ir, TGSI_OPCODE_SLT, result_dst, op[0], op[1]);
break;
- case ir_binop_greater:
- emit_asm(ir, TGSI_OPCODE_SLT, result_dst, op[1], op[0]);
- break;
- case ir_binop_lequal:
- emit_asm(ir, TGSI_OPCODE_SGE, result_dst, op[1], op[0]);
- break;
case ir_binop_gequal:
emit_asm(ir, TGSI_OPCODE_SGE, result_dst, op[0], op[1]);
break;
*/
st_src_reg sge_src = result_src;
sge_src.negate = ~sge_src.negate;
- emit_asm(ir, TGSI_OPCODE_SGE, result_dst, sge_src, st_src_reg_for_float(0.0));
+ emit_asm(ir, TGSI_OPCODE_SGE, result_dst, sge_src,
+ st_src_reg_for_float(0.0));
}
} else {
emit_asm(ir, TGSI_OPCODE_SEQ, result_dst, op[0], op[1]);
*/
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.
+ /* 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_asm(ir, TGSI_OPCODE_SLT, result_dst, slt_src, st_src_reg_for_float(0.0));
+ emit_asm(ir, TGSI_OPCODE_SLT, result_dst, slt_src,
+ st_src_reg_for_float(0.0));
}
}
} else {
emit_asm(ir, TGSI_OPCODE_ADD, result_dst, op[0], op[1]);
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 if floats are being used as boolean values.
+ * shader with a saturate if floats are being used as boolean
+ * values.
*/
add->saturate = true;
} else {
/* Negating the result of the addition gives values on the range
- * [-2, 0]. Zero stays zero, and negative values become 1.0. This
- * is achieved using SLT.
+ * [-2, 0]. Zero stays zero, and negative values become 1.0
+ * This is achieved using SLT.
*/
st_src_reg slt_src = result_src;
slt_src.negate = ~slt_src.negate;
- emit_asm(ir, TGSI_OPCODE_SLT, result_dst, slt_src, st_src_reg_for_float(0.0));
+ emit_asm(ir, TGSI_OPCODE_SLT, result_dst, slt_src,
+ st_src_reg_for_float(0.0));
}
}
break;
/* fallthrough to next case otherwise */
case ir_unop_b2f:
if (native_integers) {
- emit_asm(ir, TGSI_OPCODE_AND, result_dst, op[0], st_src_reg_for_float(1.0));
+ emit_asm(ir, TGSI_OPCODE_AND, result_dst, op[0],
+ st_src_reg_for_float(1.0));
break;
}
/* fallthrough to next case otherwise */
* GLSL requires that int(bool) return 1 for true and 0 for false.
* This conversion is done with AND, but it could be done with NEG.
*/
- emit_asm(ir, TGSI_OPCODE_AND, result_dst, op[0], st_src_reg_for_int(1));
+ emit_asm(ir, TGSI_OPCODE_AND, result_dst, op[0],
+ st_src_reg_for_int(1));
} else {
/* Booleans and integers are both stored as floats when native
* integers are disabled.
result_src.type = GLSL_TYPE_FLOAT;
break;
case ir_unop_f2b:
- emit_asm(ir, TGSI_OPCODE_SNE, result_dst, op[0], st_src_reg_for_float(0.0));
+ emit_asm(ir, TGSI_OPCODE_SNE, result_dst, op[0],
+ st_src_reg_for_float(0.0));
break;
case ir_unop_d2b:
- emit_asm(ir, TGSI_OPCODE_SNE, result_dst, op[0], st_src_reg_for_double(0.0));
+ emit_asm(ir, TGSI_OPCODE_SNE, result_dst, op[0],
+ st_src_reg_for_double(0.0));
break;
case ir_unop_i2b:
if (native_integers)
- emit_asm(ir, TGSI_OPCODE_USNE, result_dst, op[0], st_src_reg_for_int(0));
+ emit_asm(ir, TGSI_OPCODE_USNE, result_dst, op[0],
+ st_src_reg_for_int(0));
else
- emit_asm(ir, TGSI_OPCODE_SNE, result_dst, op[0], st_src_reg_for_float(0.0));
+ emit_asm(ir, TGSI_OPCODE_SNE, result_dst, op[0],
+ st_src_reg_for_float(0.0));
break;
case ir_unop_bitcast_u642d:
case ir_unop_bitcast_i642d:
case ir_binop_lshift:
case ir_binop_rshift:
if (native_integers) {
- unsigned opcode = ir->operation == ir_binop_lshift ? TGSI_OPCODE_SHL
- : TGSI_OPCODE_ISHR;
+ enum tgsi_opcode opcode = ir->operation == ir_binop_lshift
+ ? TGSI_OPCODE_SHL : TGSI_OPCODE_ISHR;
st_src_reg count;
if (glsl_base_type_is_64bit(op[0].type)) {
/* GLSL shift operations have 32-bit shift counts, but TGSI uses
* 64 bits.
*/
- count = get_temp(glsl_type::u64vec(ir->operands[1]->type->components()));
+ count = get_temp(glsl_type::u64vec(ir->operands[1]
+ ->type->components()));
emit_asm(ir, TGSI_OPCODE_U2I64, st_dst_reg(count), op[1]);
} else {
count = op[1];
break;
case ir_binop_interpolate_at_offset: {
/* The y coordinate needs to be flipped for the default fb */
- static const gl_state_index transform_y_state[STATE_LENGTH]
+ static const gl_state_index16 transform_y_state[STATE_LENGTH]
= { STATE_INTERNAL, STATE_FB_WPOS_Y_TRANSFORM };
unsigned transform_y_index =
case ir_binop_ldexp:
if (ir->operands[0]->type->is_double()) {
emit_asm(ir, TGSI_OPCODE_DLDEXP, result_dst, op[0], op[1]);
+ } else if (ir->operands[0]->type->is_float()) {
+ emit_asm(ir, TGSI_OPCODE_LDEXP, result_dst, op[0], op[1]);
} else {
assert(!"Invalid ldexp for non-double opcode in glsl_to_tgsi_visitor::visit()");
}
case ir_unop_get_buffer_size: {
ir_constant *const_offset = ir->operands[0]->as_constant();
+ int buf_base = ctx->st->has_hw_atomics
+ ? 0 : ctx->Const.Program[shader->Stage].MaxAtomicBuffers;
st_src_reg buffer(
PROGRAM_BUFFER,
- ctx->Const.Program[shader->Stage].MaxAtomicBuffers +
- (const_offset ? const_offset->value.u[0] : 0),
+ buf_base + (const_offset ? const_offset->value.u[0] : 0),
GLSL_TYPE_UINT);
if (!const_offset) {
buffer.reladdr = ralloc(mem_ctx, st_src_reg);
temp_dst.writemask = WRITEMASK_X;
if (vector_elements > 3)
temp_dst.writemask |= WRITEMASK_Z;
- op[0].swizzle = MAKE_SWIZZLE4(GET_SWZ(orig_swz, 2), GET_SWZ(orig_swz, 2),
- GET_SWZ(orig_swz, 3), GET_SWZ(orig_swz, 3));
+ op[0].swizzle = MAKE_SWIZZLE4(GET_SWZ(orig_swz, 2),
+ GET_SWZ(orig_swz, 2),
+ GET_SWZ(orig_swz, 3),
+ GET_SWZ(orig_swz, 3));
if (ir->operation == ir_unop_u2i64 || ir->operation == ir_unop_u2u64)
emit_asm(ir, TGSI_OPCODE_MOV, temp_dst, op[0]);
else
- emit_asm(ir, TGSI_OPCODE_AND, temp_dst, op[0], st_src_reg_for_int(1));
+ emit_asm(ir, TGSI_OPCODE_AND, temp_dst, op[0],
+ st_src_reg_for_int(1));
}
break;
}
for (el = 0; el < vector_elements; el++) {
unsigned swz = GET_SWZ(orig_swz, el);
if (swz & 1)
- op[0].swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z);
+ op[0].swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_Z,
+ SWIZZLE_Z, SWIZZLE_Z);
else
- op[0].swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X);
+ op[0].swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X,
+ SWIZZLE_X, SWIZZLE_X);
if (swz > 2)
op[0].index = orig_idx + 1;
op[0].type = GLSL_TYPE_UINT;
break;
}
case ir_unop_i642b:
- emit_asm(ir, TGSI_OPCODE_U64SNE, result_dst, op[0], st_src_reg_for_int64(0));
+ emit_asm(ir, TGSI_OPCODE_U64SNE, result_dst, op[0],
+ st_src_reg_for_int64(0));
break;
case ir_unop_i642f:
emit_asm(ir, TGSI_OPCODE_I642F, result_dst, op[0]);
/* a is - 0 + - 0 +
* (a < 0) T F F ( a < 0) T F F
* (0 < a) F F T (-a < 0) F F T
- * (a <= 0) T T F (-a < 0) F F T (swap order of other operands)
- * (0 <= a) F T T ( a < 0) T F F (swap order of other operands)
- * (a > 0) F F T (-a < 0) F F T
- * (0 > a) T F F ( a < 0) T F F
* (a >= 0) F T T ( a < 0) T F F (swap order of other operands)
* (0 >= a) T T F (-a < 0) F F T (swap order of other operands)
*
negate = zero_on_left;
break;
- case ir_binop_greater:
- switch_order = false;
- negate = !zero_on_left;
- break;
-
- case ir_binop_lequal:
- switch_order = true;
- negate = !zero_on_left;
- break;
-
case ir_binop_gequal:
switch_order = true;
negate = zero_on_left;
if (type->is_matrix()) {
const struct glsl_type *vec_type;
- vec_type = glsl_type::get_instance(type->is_double() ? GLSL_TYPE_DOUBLE : GLSL_TYPE_FLOAT,
+ vec_type = glsl_type::get_instance(type->is_double()
+ ? GLSL_TYPE_DOUBLE : GLSL_TYPE_FLOAT,
type->vector_elements, 1);
for (int i = 0; i < type->matrix_columns; i++) {
r->type = type->base_type;
if (cond) {
st_src_reg l_src = st_src_reg(*l);
- l_src.swizzle = swizzle_for_size(type->vector_elements);
+
+ if (l_src.file == PROGRAM_OUTPUT &&
+ this->prog->Target == GL_FRAGMENT_PROGRAM_ARB &&
+ (l_src.index == FRAG_RESULT_DEPTH ||
+ l_src.index == FRAG_RESULT_STENCIL)) {
+ /* This is a special case because the source swizzles will be shifted
+ * later to account for the difference between GLSL (where they're
+ * plain floats) and TGSI (where they're Z and Y components). */
+ l_src.swizzle = SWIZZLE_XXXX;
+ }
if (native_integers) {
emit_asm(ir, TGSI_OPCODE_UCMP, *l, *cond,
} else if (ir->write_mask == 0) {
assert(!ir->lhs->type->is_scalar() && !ir->lhs->type->is_vector());
- unsigned num_elements = ir->lhs->type->without_array()->vector_elements;
+ unsigned num_elements =
+ ir->lhs->type->without_array()->vector_elements;
if (num_elements) {
l.writemask = u_bit_consecutive(0, num_elements);
for (i = 0; i < ir->type->matrix_columns; i++) {
switch (ir->type->base_type) {
case GLSL_TYPE_FLOAT:
- values = (gl_constant_value *) &ir->value.f[i * ir->type->vector_elements];
+ values = (gl_constant_value *)
+ &ir->value.f[i * ir->type->vector_elements];
src = st_src_reg(file, -1, ir->type->base_type);
src.index = add_constant(file,
emit_asm(ir, TGSI_OPCODE_MOV, mat_column, src);
break;
case GLSL_TYPE_DOUBLE:
- values = (gl_constant_value *) &ir->value.d[i * ir->type->vector_elements];
+ values = (gl_constant_value *)
+ &ir->value.d[i * ir->type->vector_elements];
src = st_src_reg(file, -1, ir->type->base_type);
src.index = add_constant(file,
values,
&src.swizzle);
if (ir->type->vector_elements >= 2) {
mat_column.writemask = WRITEMASK_XY;
- src.swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_X, SWIZZLE_Y);
+ src.swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
+ SWIZZLE_X, SWIZZLE_Y);
emit_asm(ir, TGSI_OPCODE_MOV, mat_column, src);
} else {
mat_column.writemask = WRITEMASK_X;
- src.swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X);
+ src.swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X,
+ SWIZZLE_X, SWIZZLE_X);
emit_asm(ir, TGSI_OPCODE_MOV, mat_column, src);
}
src.index++;
if (ir->type->vector_elements > 2) {
if (ir->type->vector_elements == 4) {
mat_column.writemask = WRITEMASK_ZW;
- src.swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_X, SWIZZLE_Y);
+ src.swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
+ SWIZZLE_X, SWIZZLE_Y);
emit_asm(ir, TGSI_OPCODE_MOV, mat_column, src);
} else {
mat_column.writemask = WRITEMASK_Z;
- src.swizzle = MAKE_SWIZZLE4(SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y);
+ src.swizzle = MAKE_SWIZZLE4(SWIZZLE_Y, SWIZZLE_Y,
+ SWIZZLE_Y, SWIZZLE_Y);
emit_asm(ir, TGSI_OPCODE_MOV, mat_column, src);
mat_column.writemask = WRITEMASK_XYZW;
src.swizzle = SWIZZLE_XYZW;
exec_node *param = ir->actual_parameters.get_head();
ir_dereference *deref = static_cast<ir_dereference *>(param);
ir_variable *location = deref->variable_referenced();
-
- st_src_reg buffer(
- PROGRAM_BUFFER, location->data.binding, GLSL_TYPE_ATOMIC_UINT);
-
+ bool has_hw_atomics = st_context(ctx)->has_hw_atomics;
/* Calculate the surface offset */
st_src_reg offset;
unsigned array_size = 0, base = 0;
uint16_t index = 0;
+ st_src_reg resource;
get_deref_offsets(deref, &array_size, &base, &index, &offset, false);
- if (offset.file != PROGRAM_UNDEFINED) {
- emit_asm(ir, TGSI_OPCODE_MUL, st_dst_reg(offset),
- offset, st_src_reg_for_int(ATOMIC_COUNTER_SIZE));
- emit_asm(ir, TGSI_OPCODE_ADD, st_dst_reg(offset),
- offset, st_src_reg_for_int(location->data.offset + index * ATOMIC_COUNTER_SIZE));
+ if (has_hw_atomics) {
+ variable_storage *entry = find_variable_storage(location);
+ st_src_reg buffer(PROGRAM_HW_ATOMIC, 0, GLSL_TYPE_ATOMIC_UINT,
+ location->data.binding);
+
+ if (!entry) {
+ entry = new(mem_ctx) variable_storage(location, PROGRAM_HW_ATOMIC,
+ num_atomics);
+ _mesa_hash_table_insert(this->variables, location, entry);
+
+ atomic_info[num_atomics].location = location->data.location;
+ atomic_info[num_atomics].binding = location->data.binding;
+ atomic_info[num_atomics].size = location->type->arrays_of_arrays_size();
+ if (atomic_info[num_atomics].size == 0)
+ atomic_info[num_atomics].size = 1;
+ atomic_info[num_atomics].array_id = 0;
+ num_atomics++;
+ }
+
+ if (offset.file != PROGRAM_UNDEFINED) {
+ if (atomic_info[entry->index].array_id == 0) {
+ num_atomic_arrays++;
+ atomic_info[entry->index].array_id = num_atomic_arrays;
+ }
+ buffer.array_id = atomic_info[entry->index].array_id;
+ }
+
+ buffer.index = index;
+ buffer.index += location->data.offset / ATOMIC_COUNTER_SIZE;
+ buffer.has_index2 = true;
+
+ if (offset.file != PROGRAM_UNDEFINED) {
+ buffer.reladdr = ralloc(mem_ctx, st_src_reg);
+ *buffer.reladdr = offset;
+ emit_arl(ir, sampler_reladdr, offset);
+ }
+ offset = st_src_reg_for_int(0);
+
+ resource = buffer;
} else {
- offset = st_src_reg_for_int(location->data.offset + index * ATOMIC_COUNTER_SIZE);
+ st_src_reg buffer(PROGRAM_BUFFER, location->data.binding,
+ GLSL_TYPE_ATOMIC_UINT);
+
+ if (offset.file != PROGRAM_UNDEFINED) {
+ emit_asm(ir, TGSI_OPCODE_MUL, st_dst_reg(offset),
+ offset, st_src_reg_for_int(ATOMIC_COUNTER_SIZE));
+ emit_asm(ir, TGSI_OPCODE_ADD, st_dst_reg(offset),
+ offset, st_src_reg_for_int(location->data.offset + index * ATOMIC_COUNTER_SIZE));
+ } else {
+ offset = st_src_reg_for_int(location->data.offset + index * ATOMIC_COUNTER_SIZE);
+ }
+ resource = buffer;
}
ir->return_deref->accept(this);
val->accept(this);
st_src_reg data = this->result, data2 = undef_src;
- unsigned opcode;
+ enum tgsi_opcode opcode;
switch (ir->callee->intrinsic_id) {
case ir_intrinsic_atomic_counter_add:
opcode = TGSI_OPCODE_ATOMUADD;
inst = emit_asm(ir, opcode, dst, offset, data, data2);
}
- inst->resource = buffer;
+ inst->resource = resource;
}
void
ir_rvalue *offset = ((ir_instruction *)param)->as_rvalue();
ir_constant *const_block = block->as_constant();
-
+ int buf_base = st_context(ctx)->has_hw_atomics
+ ? 0 : ctx->Const.Program[shader->Stage].MaxAtomicBuffers;
st_src_reg buffer(
PROGRAM_BUFFER,
- ctx->Const.Program[shader->Stage].MaxAtomicBuffers +
- (const_block ? const_block->value.u[0] : 0),
+ buf_base + (const_block ? const_block->value.u[0] : 0),
GLSL_TYPE_UINT);
if (!const_block) {
if (ir->callee->intrinsic_id == ir_intrinsic_ssbo_load) {
inst = emit_asm(ir, TGSI_OPCODE_LOAD, dst, off);
if (dst.type == GLSL_TYPE_BOOL)
- emit_asm(ir, TGSI_OPCODE_USNE, dst, st_src_reg(dst), st_src_reg_for_int(0));
+ emit_asm(ir, TGSI_OPCODE_USNE, dst, st_src_reg(dst),
+ st_src_reg_for_int(0));
} else if (ir->callee->intrinsic_id == ir_intrinsic_ssbo_store) {
param = param->get_next();
ir_rvalue *val = ((ir_instruction *)param)->as_rvalue();
val->accept(this);
st_src_reg data = this->result, data2 = undef_src;
- unsigned opcode;
+ enum tgsi_opcode opcode;
switch (ir->callee->intrinsic_id) {
case ir_intrinsic_ssbo_atomic_add:
opcode = TGSI_OPCODE_ATOMUADD;
val->accept(this);
st_src_reg data = this->result, data2 = undef_src;
- unsigned opcode;
+ enum tgsi_opcode opcode;
switch (ir->callee->intrinsic_id) {
case ir_intrinsic_shared_atomic_add:
opcode = TGSI_OPCODE_ATOMUADD;
glsl_to_tgsi_instruction *inst;
+ st_src_reg bindless;
+ if (imgvar->contains_bindless()) {
+ img->accept(this);
+ bindless = this->result;
+ }
+
if (ir->callee->intrinsic_id == ir_intrinsic_image_size) {
dst.writemask = WRITEMASK_XYZ;
inst = emit_asm(ir, TGSI_OPCODE_RESQ, dst);
assert(param->is_tail_sentinel());
- unsigned opcode;
+ enum tgsi_opcode opcode;
switch (ir->callee->intrinsic_id) {
case ir_intrinsic_image_load:
opcode = TGSI_OPCODE_LOAD;
}
if (imgvar->contains_bindless()) {
- img->accept(this);
- inst->resource = this->result;
+ inst->resource = bindless;
inst->resource.swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
SWIZZLE_X, SWIZZLE_Y);
} else {
}
void
-glsl_to_tgsi_visitor::visit_generic_intrinsic(ir_call *ir, unsigned op)
+glsl_to_tgsi_visitor::visit_generic_intrinsic(ir_call *ir, enum tgsi_opcode op)
{
ir->return_deref->accept(this);
st_dst_reg dst = st_dst_reg(this->result);
st_src_reg levels_src, reladdr;
st_dst_reg result_dst, coord_dst, cube_sc_dst;
glsl_to_tgsi_instruction *inst = NULL;
- unsigned opcode = TGSI_OPCODE_NOP;
+ enum tgsi_opcode opcode = TGSI_OPCODE_NOP;
const glsl_type *sampler_type = ir->sampler->type;
unsigned sampler_array_size = 1, sampler_base = 0;
bool is_cube_array = false, is_cube_shadow = false;
}
}
- /* If projection is done and the opcode is not TGSI_OPCODE_TXP, then the shadow
- * comparator was put in the correct place (and projected) by the code,
- * above, that handles by-hand projection.
+ /* If projection is done and the opcode is not TGSI_OPCODE_TXP, then the
+ * shadow comparator was put in the correct place (and projected) by the
+ * code, above, that handles by-hand projection.
*/
if (ir->shadow_comparator && (!ir->projector || opcode == TGSI_OPCODE_TXP)) {
/* Slot the shadow value in as the second to last component of the
emit_arl(ir, sampler_reladdr, reladdr);
}
+ st_src_reg bindless;
+ if (var->contains_bindless()) {
+ ir->sampler->accept(this);
+ bindless = this->result;
+ }
+
if (opcode == TGSI_OPCODE_TXD)
inst = emit_asm(ir, opcode, result_dst, coord, dx, dy);
else if (opcode == TGSI_OPCODE_TXQ) {
inst->tex_shadow = GL_TRUE;
if (var->contains_bindless()) {
- ir->sampler->accept(this);
- inst->resource = this->result;
+ inst->resource = bindless;
inst->resource.swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
SWIZZLE_X, SWIZZLE_Y);
} else {
if (ir->offset) {
if (!inst->tex_offsets)
- inst->tex_offsets = rzalloc_array(inst, st_src_reg, MAX_GLSL_TEXTURE_OFFSET);
+ inst->tex_offsets = rzalloc_array(inst, st_src_reg,
+ MAX_GLSL_TEXTURE_OFFSET);
- for (i = 0; i < MAX_GLSL_TEXTURE_OFFSET && offset[i].file != PROGRAM_UNDEFINED; i++)
+ for (i = 0; i < MAX_GLSL_TEXTURE_OFFSET &&
+ offset[i].file != PROGRAM_UNDEFINED; i++)
inst->tex_offsets[i] = offset[i];
inst->tex_offset_num_offset = i;
}
void
glsl_to_tgsi_visitor::visit(ir_if *ir)
{
- unsigned if_opcode;
+ enum tgsi_opcode if_opcode;
glsl_to_tgsi_instruction *if_inst;
ir->condition->accept(this);
num_outputs = 0;
num_input_arrays = 0;
num_output_arrays = 0;
+ num_atomics = 0;
+ num_atomic_arrays = 0;
num_immediates = 0;
num_address_regs = 0;
samplers_used = 0;
images_used = 0;
indirect_addr_consts = false;
wpos_transform_const = -1;
- glsl_version = 0;
native_integers = false;
mem_ctx = ralloc_context(NULL);
ctx = NULL;
{
v->samplers_used = 0;
v->images_used = 0;
+ prog->info.textures_used_by_txf = 0;
foreach_in_list(glsl_to_tgsi_instruction, inst, &v->instructions) {
if (inst->info->is_tex) {
v->sampler_targets[idx] =
st_translate_texture_target(inst->tex_target, inst->tex_shadow);
- if (inst->tex_shadow) {
- prog->ShadowSamplers |= 1 << (inst->resource.index + i);
+ if (inst->op == TGSI_OPCODE_TXF || inst->op == TGSI_OPCODE_TXF_LZ) {
+ prog->info.textures_used_by_txf |= 1u << idx;
}
}
}
&& !(inst->dst[0].writemask & prevWriteMask)
&& inst->src[2].file == inst->dst[0].file
&& inst->src[2].index == inst->dst[0].index
- && inst->dst[0].writemask == get_src_arg_mask(inst->dst[0], inst->src[2])) {
+ && inst->dst[0].writemask ==
+ get_src_arg_mask(inst->dst[0], inst->src[2])) {
inst->op = TGSI_OPCODE_MOV;
inst->info = tgsi_get_opcode_info(inst->op);
free(tempWrites);
}
+static void
+rename_temp_handle_src(struct rename_reg_pair *renames, st_src_reg *src)
+{
+ if (src && src->file == PROGRAM_TEMPORARY) {
+ int old_idx = src->index;
+ if (renames[old_idx].valid)
+ src->index = renames[old_idx].new_reg;
+ }
+}
+
/* Replaces all references to a temporary register index with another index. */
void
glsl_to_tgsi_visitor::rename_temp_registers(struct rename_reg_pair *renames)
foreach_in_list(glsl_to_tgsi_instruction, inst, &this->instructions) {
unsigned j;
for (j = 0; j < num_inst_src_regs(inst); j++) {
- if (inst->src[j].file == PROGRAM_TEMPORARY) {
- int old_idx = inst->src[j].index;
- if (renames[old_idx].valid)
- inst->src[j].index = renames[old_idx].new_reg;
- }
+ rename_temp_handle_src(renames, &inst->src[j]);
+ rename_temp_handle_src(renames, inst->src[j].reladdr);
+ rename_temp_handle_src(renames, inst->src[j].reladdr2);
}
for (j = 0; j < inst->tex_offset_num_offset; j++) {
- if (inst->tex_offsets[j].file == PROGRAM_TEMPORARY) {
- int old_idx = inst->tex_offsets[j].index;
- if (renames[old_idx].valid)
- inst->tex_offsets[j].index = renames[old_idx].new_reg;
- }
+ rename_temp_handle_src(renames, &inst->tex_offsets[j]);
+ rename_temp_handle_src(renames, inst->tex_offsets[j].reladdr);
+ rename_temp_handle_src(renames, inst->tex_offsets[j].reladdr2);
}
- if (inst->resource.file == PROGRAM_TEMPORARY) {
- int old_idx = inst->resource.index;
- if (renames[old_idx].valid)
- inst->resource.index = renames[old_idx].new_reg;
- }
+ rename_temp_handle_src(renames, &inst->resource);
+ rename_temp_handle_src(renames, inst->resource.reladdr);
+ rename_temp_handle_src(renames, inst->resource.reladdr2);
for (j = 0; j < num_inst_dst_regs(inst); j++) {
if (inst->dst[j].file == PROGRAM_TEMPORARY) {
int old_idx = inst->dst[j].index;
if (renames[old_idx].valid)
- inst->dst[j].index = renames[old_idx].new_reg;}
+ inst->dst[j].index = renames[old_idx].new_reg;
+ }
+ rename_temp_handle_src(renames, inst->dst[j].reladdr);
+ rename_temp_handle_src(renames, inst->dst[j].reladdr2);
}
}
}
}
if (inst->op == TGSI_OPCODE_BGNLOOP) {
- if(depth++ == 0)
+ if (depth++ == 0)
loop_start = i;
} else if (inst->op == TGSI_OPCODE_ENDLOOP) {
if (--depth == 0)
}
}
if (inst->op == TGSI_OPCODE_BGNLOOP) {
- if(depth++ == 0)
+ if (depth++ == 0)
loop_start = i;
} else if (inst->op == TGSI_OPCODE_ENDLOOP) {
if (--depth == 0)
last_reads[inst->tex_offsets[j].index] = (depth == 0) ? i : -2;
}
if (inst->op == TGSI_OPCODE_BGNLOOP) {
- if(depth++ == 0)
+ if (depth++ == 0)
loop_start = i;
} else if (inst->op == TGSI_OPCODE_ENDLOOP) {
if (--depth == 0) {
!inst->dst[0].reladdr2 &&
!inst->saturate &&
inst->src[0].file != PROGRAM_ARRAY &&
+ (inst->src[0].file != PROGRAM_OUTPUT ||
+ this->shader->Stage != MESA_SHADER_TESS_CTRL) &&
!inst->src[0].reladdr &&
!inst->src[0].reladdr2 &&
!inst->src[0].negate &&
ralloc_free(acp);
}
+static void
+dead_code_handle_reladdr(glsl_to_tgsi_instruction **writes, st_src_reg *reladdr)
+{
+ if (reladdr && reladdr->file == PROGRAM_TEMPORARY) {
+ /* Clear where it's used as src. */
+ int swz = GET_SWZ(reladdr->swizzle, 0);
+ writes[4 * reladdr->index + swz] = NULL;
+ }
+}
+
/*
* On a basic block basis, tracks available PROGRAM_TEMPORARY registers for dead
* code elimination.
write_level[4 * r + c] = level-1;
}
}
- if(inst->op == TGSI_OPCODE_ENDIF)
+ if (inst->op == TGSI_OPCODE_ENDIF)
--level;
break;
writes[4 * inst->src[i].index + c] = NULL;
}
}
+ dead_code_handle_reladdr(writes, inst->src[i].reladdr);
+ dead_code_handle_reladdr(writes, inst->src[i].reladdr2);
}
for (unsigned i = 0; i < inst->tex_offset_num_offset; i++) {
if (inst->tex_offsets[i].file == PROGRAM_TEMPORARY && inst->tex_offsets[i].reladdr){
writes[4 * inst->tex_offsets[i].index + c] = NULL;
}
}
+ dead_code_handle_reladdr(writes, inst->tex_offsets[i].reladdr);
+ dead_code_handle_reladdr(writes, inst->tex_offsets[i].reladdr2);
}
if (inst->resource.file == PROGRAM_TEMPORARY) {
writes[4 * inst->resource.index + c] = NULL;
}
}
+ dead_code_handle_reladdr(writes, inst->resource.reladdr);
+ dead_code_handle_reladdr(writes, inst->resource.reladdr2);
+ for (unsigned i = 0; i < ARRAY_SIZE(inst->dst); i++) {
+ dead_code_handle_reladdr(writes, inst->dst[i].reladdr);
+ dead_code_handle_reladdr(writes, inst->dst[i].reladdr2);
+ }
break;
}
/* We never delete inst, but we may delete its successor. */
foreach_in_list(glsl_to_tgsi_instruction, inst, &this->instructions) {
glsl_to_tgsi_instruction *inst2;
- bool merged;
+ unsigned defined;
+
if (num_inst_dst_regs(inst) != 2)
continue;
inst->dst[1].file != PROGRAM_UNDEFINED)
continue;
- inst2 = (glsl_to_tgsi_instruction *) inst->next;
- do {
+ assert(inst->dst[0].file != PROGRAM_UNDEFINED ||
+ inst->dst[1].file != PROGRAM_UNDEFINED);
+
+ if (inst->dst[0].file == PROGRAM_UNDEFINED)
+ defined = 1;
+ else
+ defined = 0;
- if (inst->src[0].file == inst2->src[0].file &&
+ inst2 = (glsl_to_tgsi_instruction *) inst->next;
+ while (!inst2->is_tail_sentinel()) {
+ if (inst->op == inst2->op &&
+ inst2->dst[defined].file == PROGRAM_UNDEFINED &&
+ inst->src[0].file == inst2->src[0].file &&
inst->src[0].index == inst2->src[0].index &&
inst->src[0].type == inst2->src[0].type &&
inst->src[0].swizzle == inst2->src[0].swizzle)
break;
inst2 = (glsl_to_tgsi_instruction *) inst2->next;
- } while (inst2);
+ }
- if (!inst2)
+ if (inst2->is_tail_sentinel()) {
+ /* Undefined destinations are not allowed, substitute with an unused
+ * temporary register.
+ */
+ st_src_reg tmp = get_temp(glsl_type::vec4_type);
+ inst->dst[defined ^ 1] = st_dst_reg(tmp);
+ inst->dst[defined ^ 1].writemask = 0;
continue;
- merged = false;
- if (inst->dst[0].file == PROGRAM_UNDEFINED) {
- merged = true;
- inst->dst[0] = inst2->dst[0];
- } else if (inst->dst[1].file == PROGRAM_UNDEFINED) {
- inst->dst[1] = inst2->dst[1];
- merged = true;
}
- if (merged) {
- inst2->remove();
- delete inst2;
- }
+ inst->dst[defined ^ 1] = inst2->dst[defined ^ 1];
+ inst2->remove();
+ delete inst2;
}
}
void
glsl_to_tgsi_visitor::merge_registers(void)
{
-
struct lifetime *lifetimes =
rzalloc_array(mem_ctx, struct lifetime, this->next_temp);
struct ureg_src buffers[PIPE_MAX_SHADER_BUFFERS];
struct ureg_src images[PIPE_MAX_SHADER_IMAGES];
struct ureg_src systemValues[SYSTEM_VALUE_MAX];
+ struct ureg_src hw_atomics[PIPE_MAX_HW_ATOMIC_BUFFERS];
struct ureg_src shared_memory;
unsigned *array_sizes;
struct inout_decl *input_decls;
const ubyte *outputMapping;
unsigned procType; /**< PIPE_SHADER_VERTEX/FRAGMENT */
+ bool need_uarl;
};
/** Map Mesa's SYSTEM_VALUE_x to TGSI_SEMANTIC_x */
-unsigned
+enum tgsi_semantic
_mesa_sysval_to_semantic(unsigned sysval)
{
switch (sysval) {
static struct ureg_src
emit_immediate(struct st_translate *t,
gl_constant_value values[4],
- int type, int size)
+ GLenum type, int size)
{
struct ureg_program *ureg = t->ureg;
- switch(type)
- {
+ switch (type) {
case GL_FLOAT:
return ureg_DECL_immediate(ureg, &values[0].f, size);
case GL_DOUBLE:
{
unsigned array;
- switch(file) {
+ switch (file) {
case PROGRAM_UNDEFINED:
return ureg_dst_undef();
return t->outputs[t->outputMapping[index]];
}
else {
- struct inout_decl *decl = find_inout_array(t->output_decls, t->num_output_decls, array_id);
+ struct inout_decl *decl =
+ find_inout_array(t->output_decls,
+ t->num_output_decls, array_id);
unsigned mesa_index = decl->mesa_index;
int slot = t->outputMapping[mesa_index];
}
}
+static struct ureg_src
+translate_src(struct st_translate *t, const st_src_reg *src_reg);
+
+static struct ureg_src
+translate_addr(struct st_translate *t, const st_src_reg *reladdr,
+ unsigned addr_index)
+{
+ if (t->need_uarl || !reladdr->is_legal_tgsi_address_operand())
+ return ureg_src(t->address[addr_index]);
+
+ return translate_src(t, reladdr);
+}
+
/**
* Create a TGSI ureg_dst register from an st_dst_reg.
*/
if (dst_reg->reladdr != NULL) {
assert(dst_reg->file != PROGRAM_TEMPORARY);
- dst = ureg_dst_indirect(dst, ureg_src(t->address[0]));
+ dst = ureg_dst_indirect(dst, translate_addr(t, dst_reg->reladdr, 0));
}
if (dst_reg->has_index2) {
if (dst_reg->reladdr2)
- dst = ureg_dst_dimension_indirect(dst, ureg_src(t->address[1]),
+ dst = ureg_dst_dimension_indirect(dst,
+ translate_addr(t, dst_reg->reladdr2, 1),
dst_reg->index2D);
else
dst = ureg_dst_dimension(dst, dst_reg->index2D);
int index = src_reg->index;
int double_reg2 = src_reg->double_reg2 ? 1 : 0;
- switch(src_reg->file) {
+ switch (src_reg->file) {
case PROGRAM_UNDEFINED:
src = ureg_imm4f(t->ureg, 0, 0, 0, 0);
break;
case PROGRAM_TEMPORARY:
case PROGRAM_ARRAY:
- src = ureg_src(dst_register(t, src_reg->file, src_reg->index, src_reg->array_id));
+ src = ureg_src(dst_register(t, src_reg->file, src_reg->index,
+ src_reg->array_id));
break;
case PROGRAM_OUTPUT: {
- struct ureg_dst dst = dst_register(t, src_reg->file, src_reg->index, src_reg->array_id);
+ struct ureg_dst dst = dst_register(t, src_reg->file, src_reg->index,
+ src_reg->array_id);
assert(dst.WriteMask != 0);
unsigned shift = ffs(dst.WriteMask) - 1;
src = ureg_swizzle(ureg_src(dst),
src = t->inputs[t->inputMapping[index] + double_reg2];
}
else {
- struct inout_decl *decl = find_inout_array(t->input_decls, t->num_input_decls,
+ struct inout_decl *decl = find_inout_array(t->input_decls,
+ t->num_input_decls,
src_reg->array_id);
unsigned mesa_index = decl->mesa_index;
int slot = t->inputMapping[mesa_index];
src = t->systemValues[src_reg->index];
break;
+ case PROGRAM_HW_ATOMIC:
+ src = ureg_src_array_register(TGSI_FILE_HW_ATOMIC, src_reg->index,
+ src_reg->array_id);
+ break;
+
default:
assert(!"unknown src register file");
return ureg_src_undef();
* and UBO constant buffers (buffer, position).
*/
if (src_reg->reladdr2)
- src = ureg_src_dimension_indirect(src, ureg_src(t->address[1]),
+ src = ureg_src_dimension_indirect(src,
+ translate_addr(t, src_reg->reladdr2, 1),
src_reg->index2D);
else
src = ureg_src_dimension(src, src_reg->index2D);
if (src_reg->reladdr != NULL) {
assert(src_reg->file != PROGRAM_TEMPORARY);
- src = ureg_src_indirect(src, ureg_src(t->address[0]));
+ src = ureg_src_indirect(src, translate_addr(t, src_reg->reladdr, 0));
}
return src;
int num_dst;
int num_src;
- unsigned tex_target = 0;
+ enum tgsi_texture_type tex_target = TGSI_TEXTURE_BUFFER;
num_dst = num_inst_dst_regs(inst);
num_src = num_inst_src_regs(inst);
for (i = 0; i < num_src; i++)
src[i] = translate_src(t, &inst->src[i]);
- switch(inst->op) {
+ switch (inst->op) {
case TGSI_OPCODE_BGNLOOP:
case TGSI_OPCODE_ELSE:
case TGSI_OPCODE_ENDLOOP:
assert(src[num_src].File != TGSI_FILE_NULL);
if (inst->resource.reladdr)
src[num_src] =
- ureg_src_indirect(src[num_src], ureg_src(t->address[2]));
+ ureg_src_indirect(src[num_src],
+ translate_addr(t, inst->resource.reladdr, 2));
num_src++;
for (i = 0; i < (int)inst->tex_offset_num_offset; i++) {
texoffsets[i] = translate_tex_offset(t, &inst->tex_offsets[i]);
src[0] = t->shared_memory;
} else if (inst->resource.file == PROGRAM_BUFFER) {
src[0] = t->buffers[inst->resource.index];
+ } else if (inst->resource.file == PROGRAM_HW_ATOMIC) {
+ src[0] = translate_src(t, &inst->resource);
} else if (inst->resource.file == PROGRAM_CONSTANT) {
assert(inst->resource.has_index2);
src[0] = ureg_src_register(TGSI_FILE_CONSTBUF, inst->resource.index);
tex_target = st_translate_texture_target(inst->tex_target, inst->tex_shadow);
}
if (inst->resource.reladdr)
- src[0] = ureg_src_indirect(src[0], ureg_src(t->address[2]));
+ src[0] = ureg_src_indirect(src[0],
+ translate_addr(t, inst->resource.reladdr, 2));
assert(src[0].File != TGSI_FILE_NULL);
ureg_memory_insn(ureg, inst->op, dst, num_dst, src, num_src,
inst->buffer_access,
}
dst[0] = ureg_writemask(dst[0], inst->dst[0].writemask);
if (inst->resource.reladdr)
- dst[0] = ureg_dst_indirect(dst[0], ureg_src(t->address[2]));
+ dst[0] = ureg_dst_indirect(dst[0],
+ translate_addr(t, inst->resource.reladdr, 2));
assert(dst[0].File != TGSI_FILE_NULL);
ureg_memory_insn(ureg, inst->op, dst, num_dst, src, num_src,
inst->buffer_access,
* where T = INPUT[WPOS] is inverted by Y.
*/
struct ureg_src wpostrans = ureg_DECL_constant(ureg, wpos_transform_const);
- struct ureg_dst wpos_temp = ureg_DECL_temporary( ureg );
+ struct ureg_dst wpos_temp = ureg_DECL_temporary(ureg);
struct ureg_src *wpos =
ctx->Const.GLSLFragCoordIsSysVal ?
&t->systemValues[SYSTEM_VALUE_FRAG_COORD] :
} else {
/* MOV wpos_temp, input[wpos]
*/
- ureg_MOV( ureg, wpos_temp, wpos_input );
+ ureg_MOV(ureg, wpos_temp, wpos_input);
}
/* Now the conditional y flip: STATE_FB_WPOS_Y_TRANSFORM.xy/zw will be
if (invert) {
/* MAD wpos_temp.y, wpos_input, wpostrans.xxxx, wpostrans.yyyy
*/
- ureg_MAD( ureg,
- ureg_writemask(wpos_temp, TGSI_WRITEMASK_Y ),
- wpos_input,
- ureg_scalar(wpostrans, 0),
- ureg_scalar(wpostrans, 1));
+ ureg_MAD(ureg,
+ ureg_writemask(wpos_temp, TGSI_WRITEMASK_Y),
+ wpos_input,
+ ureg_scalar(wpostrans, 0),
+ ureg_scalar(wpostrans, 1));
} else {
/* MAD wpos_temp.y, wpos_input, wpostrans.zzzz, wpostrans.wwww
*/
- ureg_MAD( ureg,
- ureg_writemask(wpos_temp, TGSI_WRITEMASK_Y ),
- wpos_input,
- ureg_scalar(wpostrans, 2),
- ureg_scalar(wpostrans, 3));
+ ureg_MAD(ureg,
+ ureg_writemask(wpos_temp, TGSI_WRITEMASK_Y),
+ wpos_input,
+ ureg_scalar(wpostrans, 2),
+ ureg_scalar(wpostrans, 3));
}
/* Use wpos_temp as position input from here on:
std::sort(decls, decls + count, sorter);
}
-static unsigned
+static enum tgsi_interpolate_mode
st_translate_interp(enum glsl_interp_mode glsl_qual, GLuint varying)
{
switch (glsl_qual) {
const ubyte outputSemanticName[],
const ubyte outputSemanticIndex[])
{
+ struct pipe_screen *screen = st_context(ctx)->pipe->screen;
struct st_translate *t;
unsigned i;
struct gl_program_constants *frag_const =
assert(numInputs <= ARRAY_SIZE(t->inputs));
assert(numOutputs <= ARRAY_SIZE(t->outputs));
+ ASSERT_BITFIELD_SIZE(st_src_reg, type, GLSL_TYPE_ERROR);
+ ASSERT_BITFIELD_SIZE(st_dst_reg, type, GLSL_TYPE_ERROR);
+ ASSERT_BITFIELD_SIZE(glsl_to_tgsi_instruction, tex_type, GLSL_TYPE_ERROR);
+ ASSERT_BITFIELD_SIZE(glsl_to_tgsi_instruction, image_format, PIPE_FORMAT_COUNT);
+ ASSERT_BITFIELD_SIZE(glsl_to_tgsi_instruction, tex_target,
+ (gl_texture_index) (NUM_TEXTURE_TARGETS - 1));
+ ASSERT_BITFIELD_SIZE(glsl_to_tgsi_instruction, image_format,
+ (enum pipe_format) (PIPE_FORMAT_COUNT - 1));
+ ASSERT_BITFIELD_SIZE(glsl_to_tgsi_instruction, op,
+ (enum tgsi_opcode) (TGSI_OPCODE_LAST - 1));
+
t = CALLOC_STRUCT(st_translate);
if (!t) {
ret = PIPE_ERROR_OUT_OF_MEMORY;
}
t->procType = procType;
+ t->need_uarl = !screen->get_param(screen, PIPE_CAP_TGSI_ANY_REG_AS_ADDRESS);
t->inputMapping = inputMapping;
t->outputMapping = outputMapping;
t->ureg = ureg;
tgsi_usage_mask = TGSI_WRITEMASK_XYZW;
}
- unsigned interp_mode = 0;
- unsigned interp_location = 0;
+ enum tgsi_interpolate_mode interp_mode = TGSI_INTERPOLATE_CONSTANT;
+ enum tgsi_interpolate_loc interp_location = TGSI_INTERPOLATE_LOC_CENTER;
if (procType == PIPE_SHADER_FRAGMENT) {
assert(interpMode);
interp_mode = interpMode[slot] != TGSI_INTERPOLATE_COUNT ?
- interpMode[slot] :
+ (enum tgsi_interpolate_mode) interpMode[slot] :
st_translate_interp(decl->interp, inputSlotToAttr[slot]);
- interp_location = decl->interp_loc;
+ interp_location = (enum tgsi_interpolate_loc) decl->interp_loc;
}
src = ureg_DECL_fs_input_cyl_centroid_layout(ureg,
- inputSemanticName[slot], inputSemanticIndex[slot],
+ (enum tgsi_semantic) inputSemanticName[slot],
+ inputSemanticIndex[slot],
interp_mode, 0, interp_location, slot, tgsi_usage_mask,
decl->array_id, decl->size);
}
dst = ureg_DECL_output_layout(ureg,
- outputSemanticName[slot], outputSemanticIndex[slot],
+ (enum tgsi_semantic) outputSemanticName[slot],
+ outputSemanticIndex[slot],
decl->gs_out_streams,
slot, tgsi_usage_mask, decl->array_id, decl->size);
/* Declare misc input registers
*/
{
- GLbitfield sysInputs = proginfo->info.system_values_read;
+ GLbitfield64 sysInputs = proginfo->info.system_values_read;
for (i = 0; sysInputs; i++) {
- if (sysInputs & (1 << i)) {
- unsigned semName = _mesa_sysval_to_semantic(i);
+ if (sysInputs & (1ull << i)) {
+ enum tgsi_semantic semName = _mesa_sysval_to_semantic(i);
t->systemValues[i] = ureg_DECL_system_value(ureg, semName, 0);
(void) pscreen;
if (!ctx->Const.NativeIntegers) {
struct ureg_dst temp = ureg_DECL_local_temporary(t->ureg);
- ureg_U2F( t->ureg, ureg_writemask(temp, TGSI_WRITEMASK_X), t->systemValues[i]);
+ ureg_U2F(t->ureg, ureg_writemask(temp, TGSI_WRITEMASK_X),
+ t->systemValues[i]);
t->systemValues[i] = ureg_scalar(ureg_src(temp), 0);
}
}
emit_wpos(st_context(ctx), t, proginfo, ureg,
program->wpos_transform_const);
- sysInputs &= ~(1 << i);
+ sysInputs &= ~(1ull << i);
}
}
}
t->num_constants = proginfo->Parameters->NumParameters;
for (i = 0; i < proginfo->Parameters->NumParameters; i++) {
+ unsigned pvo = proginfo->Parameters->ParameterValueOffset[i];
+
switch (proginfo->Parameters->Parameters[i].Type) {
case PROGRAM_STATE_VAR:
case PROGRAM_UNIFORM:
t->constants[i] = ureg_DECL_constant(ureg, i);
else
t->constants[i] = emit_immediate(t,
- proginfo->Parameters->ParameterValues[i],
+ proginfo->Parameters->ParameterValues + pvo,
proginfo->Parameters->Parameters[i].DataType,
4);
break;
/* texture samplers */
for (i = 0; i < frag_const->MaxTextureImageUnits; i++) {
if (program->samplers_used & (1u << i)) {
- unsigned type = st_translate_texture_type(program->sampler_types[i]);
+ enum tgsi_return_type type =
+ st_translate_texture_type(program->sampler_types[i]);
t->samplers[i] = ureg_DECL_sampler(ureg, i);
- ureg_DECL_sampler_view( ureg, i, program->sampler_targets[i],
- type, type, type, type );
+ ureg_DECL_sampler_view(ureg, i, program->sampler_targets[i],
+ type, type, type, type);
}
}
{
struct gl_program *prog = program->prog;
- for (i = 0; i < prog->info.num_abos; i++) {
- unsigned index = prog->sh.AtomicBuffers[i]->Binding;
- assert(index < frag_const->MaxAtomicBuffers);
- t->buffers[index] = ureg_DECL_buffer(ureg, index, true);
+ if (!st_context(ctx)->has_hw_atomics) {
+ for (i = 0; i < prog->info.num_abos; i++) {
+ unsigned index = prog->sh.AtomicBuffers[i]->Binding;
+ assert(index < frag_const->MaxAtomicBuffers);
+ t->buffers[index] = ureg_DECL_buffer(ureg, index, true);
+ }
+ } else {
+ for (i = 0; i < program->num_atomics; i++) {
+ struct hwatomic_decl *ainfo = &program->atomic_info[i];
+ gl_uniform_storage *uni_storage = &prog->sh.data->UniformStorage[ainfo->location];
+ int base = uni_storage->offset / ATOMIC_COUNTER_SIZE;
+ ureg_DECL_hw_atomic(ureg, base, base + ainfo->size - 1, ainfo->binding,
+ ainfo->array_id);
+ }
}
assert(prog->info.num_ssbos <= frag_const->MaxShaderStorageBlocks);
for (i = 0; i < prog->info.num_ssbos; i++) {
- unsigned index = frag_const->MaxAtomicBuffers + i;
+ unsigned index = i;
+ if (!st_context(ctx)->has_hw_atomics)
+ index += frag_const->MaxAtomicBuffers;
+
t->buffers[index] = ureg_DECL_buffer(ureg, index, false);
}
}
v->shader_program = shader_program;
v->shader = shader;
v->options = options;
- 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_FMA_SUPPORTED);
v->has_tex_txf_lz = pscreen->get_param(pscreen,
PIPE_CAP_TGSI_TEX_TXF_LZ);
+ v->need_uarl = !pscreen->get_param(pscreen, PIPE_CAP_TGSI_ANY_REG_AS_ADDRESS);
v->variables = _mesa_hash_table_create(v->mem_ctx, _mesa_hash_pointer,
_mesa_key_pointer_equal);
/* Perform optimizations on the instructions in the glsl_to_tgsi_visitor. */
v->simplify_cmp();
-
- if (shader->Stage != MESA_SHADER_TESS_CTRL &&
- shader->Stage != MESA_SHADER_TESS_EVAL)
- v->copy_propagate();
+ v->copy_propagate();
while (v->eliminate_dead_code());
_mesa_copy_linked_program_data(shader_program, shader);
shrink_array_declarations(v->inputs, v->num_inputs,
&prog->info.inputs_read,
- prog->info.double_inputs_read,
+ prog->info.vs.double_inputs_read,
&prog->info.patch_inputs_read);
shrink_array_declarations(v->outputs, v->num_outputs,
&prog->info.outputs_written, 0ULL,
/* This must be done before the uniform storage is associated. */
if (shader->Stage == MESA_SHADER_FRAGMENT &&
(prog->info.inputs_read & VARYING_BIT_POS ||
- prog->info.system_values_read & (1 << SYSTEM_VALUE_FRAG_COORD))) {
- static const gl_state_index wposTransformState[STATE_LENGTH] = {
+ prog->info.system_values_read & (1ull << SYSTEM_VALUE_FRAG_COORD))) {
+ static const gl_state_index16 wposTransformState[STATE_LENGTH] = {
STATE_INTERNAL, STATE_FB_WPOS_Y_TRANSFORM
};
GLboolean
st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
{
+ struct pipe_screen *pscreen = ctx->st->pipe->screen;
+
+ enum pipe_shader_ir preferred_ir = (enum pipe_shader_ir)
+ pscreen->get_shader_param(pscreen, PIPE_SHADER_VERTEX,
+ PIPE_SHADER_CAP_PREFERRED_IR);
+ bool use_nir = preferred_ir == PIPE_SHADER_IR_NIR;
+
/* Return early if we are loading the shader from on-disk cache */
- if (st_load_tgsi_from_disk_cache(ctx, prog)) {
+ if (st_load_ir_from_disk_cache(ctx, prog, use_nir)) {
return GL_TRUE;
}
- struct pipe_screen *pscreen = ctx->st->pipe->screen;
assert(prog->data->LinkStatus);
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED);
bool have_dfrexp = pscreen->get_shader_param(pscreen, ptarget,
PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED);
+ bool have_ldexp = pscreen->get_shader_param(pscreen, ptarget,
+ PIPE_SHADER_CAP_TGSI_LDEXP_SUPPORTED);
unsigned if_threshold = pscreen->get_shader_param(pscreen, ptarget,
PIPE_SHADER_CAP_LOWER_IF_THRESHOLD);
do_mat_op_to_vec(ir);
if (stage == MESA_SHADER_FRAGMENT)
- lower_blend_equation_advanced(shader);
+ lower_blend_equation_advanced(
+ shader, ctx->Extensions.KHR_blend_equation_advanced_coherent);
lower_instructions(ir,
MOD_TO_FLOOR |
FDIV_TO_MUL_RCP |
EXP_TO_EXP2 |
LOG_TO_LOG2 |
- LDEXP_TO_ARITH |
+ (have_ldexp ? 0 : LDEXP_TO_ARITH) |
(have_dfrexp ? 0 : DFREXP_DLDEXP_TO_ARITH) |
CARRY_TO_ARITH |
BORROW_TO_ARITH |
build_program_resource_list(ctx, prog);
+ if (use_nir)
+ return st_link_nir(ctx, prog);
+
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
struct gl_linked_shader *shader = prog->_LinkedShaders[i];
if (shader == NULL)
continue;
- enum pipe_shader_type ptarget =
- pipe_shader_type_from_mesa(shader->Stage);
- enum pipe_shader_ir preferred_ir = (enum pipe_shader_ir)
- pscreen->get_shader_param(pscreen, ptarget,
- PIPE_SHADER_CAP_PREFERRED_IR);
-
- struct gl_program *linked_prog = NULL;
- if (preferred_ir == PIPE_SHADER_IR_NIR) {
- /* TODO only for GLSL VS/FS/CS for now: */
- switch (shader->Stage) {
- case MESA_SHADER_VERTEX:
- case MESA_SHADER_FRAGMENT:
- case MESA_SHADER_COMPUTE:
- linked_prog = st_nir_get_mesa_program(ctx, prog, shader);
- default:
- break;
- }
- } else {
- linked_prog = get_mesa_program_tgsi(ctx, prog, shader);
- }
+ struct gl_program *linked_prog =
+ get_mesa_program_tgsi(ctx, prog, shader);
+ st_set_prog_affected_state_flags(linked_prog);
if (linked_prog) {
- st_set_prog_affected_state_flags(linked_prog);
if (!ctx->Driver.ProgramStringNotify(ctx,
_mesa_shader_stage_to_program(i),
linked_prog)) {