mesa, glsl_to_tgsi: add native support for integers in shaders

Disabled by default on all drivers.  To enable it, change ctx->GLSLVersion to 130
in st_extensions.c.  Currently, softpipe is the only driver with integer support.
This commit is contained in:
Bryan Cain 2011-06-13 18:12:56 -05:00
parent f95169deb4
commit b191382c60
5 changed files with 328 additions and 60 deletions

View File

@ -165,6 +165,21 @@ struct glsl_type {
static const glsl_type *const mat4x3_type;
static const glsl_type *const mat4_type;
/*@}*/
/**
* Get the built-in instance of the vec4 type for a specific base type
*/
static const glsl_type *get_vec4_type(glsl_base_type base_type)
{
if (base_type == GLSL_TYPE_FLOAT)
return vec4_type;
else if (base_type == GLSL_TYPE_INT)
return ivec4_type;
else if (base_type == GLSL_TYPE_UINT)
return uvec4_type;
else
return NULL;
}
/**

View File

@ -454,8 +454,9 @@ get_uniform(struct gl_context *ctx, GLuint program, GLint location,
for (i = 0; i < rows; i++) {
const int base = paramPos + offset + i;
for (j = 0; j < cols; j++ ) {
params[k++] = (GLint)
prog->Parameters->ParameterValues[base][j].f;
params[k++] = ctx->Const.GLSLVersion <= 120 ?
(GLint) prog->Parameters->ParameterValues[base][j].f :
prog->Parameters->ParameterValues[base][j].i;
}
}
}
@ -467,8 +468,9 @@ get_uniform(struct gl_context *ctx, GLuint program, GLint location,
for (i = 0; i < rows; i++) {
const int base = paramPos + offset + i;
for (j = 0; j < cols; j++ ) {
params[k++] = (GLuint)
prog->Parameters->ParameterValues[base][j].f;
params[k++] = ctx->Const.GLSLVersion <= 120 ?
(GLuint) prog->Parameters->ParameterValues[base][j].f :
prog->Parameters->ParameterValues[base][j].u;
}
}
}
@ -735,42 +737,52 @@ set_program_uniform(struct gl_context *ctx, struct gl_program *program,
/* loop over number of array elements */
for (k = 0; k < count; k++) {
GLfloat *uniformVal;
gl_constant_value *uniformVal;
if (offset + k >= slots) {
/* Extra array data is ignored */
break;
}
/* uniformVal (the destination) is always float[4] */
/* uniformVal (the destination) is always gl_constant_value[4] */
uniformVal = program->Parameters->ParameterValues[index + offset + k];
if (basicType == GL_INT) {
/* convert user's ints to floats */
const GLint *iValues = ((const GLint *) values) + k * elems;
for (i = 0; i < elems; i++) {
uniformVal[i] = (GLfloat) iValues[i];
if (ctx->Const.GLSLVersion <= 120)
uniformVal[i].f = (GLfloat) iValues[i];
else
uniformVal[i].i = iValues[i];
}
}
else if (basicType == GL_UNSIGNED_INT) {
/* convert user's uints to floats */
const GLuint *iValues = ((const GLuint *) values) + k * elems;
for (i = 0; i < elems; i++) {
uniformVal[i] = (GLfloat) iValues[i];
if (ctx->Const.GLSLVersion <= 120)
uniformVal[i].f = (GLfloat)(GLuint) iValues[i];
else
uniformVal[i].u = iValues[i];
}
}
else {
const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
assert(basicType == GL_FLOAT);
for (i = 0; i < elems; i++) {
uniformVal[i] = fValues[i];
uniformVal[i].f = fValues[i];
}
}
/* if the uniform is bool-valued, convert to 1.0 or 0.0 */
/* if the uniform is bool-valued, convert to 1 or 0 */
if (isUniformBool) {
for (i = 0; i < elems; i++) {
uniformVal[i] = uniformVal[i] ? 1.0f : 0.0f;
if (basicType == GL_FLOAT)
uniformVal[i].b = uniformVal[i].f != 0.0f ? 1 : 0;
else
uniformVal[i].b = uniformVal[i].u ? 1 : 0;
if (ctx->Const.GLSLVersion <= 120)
uniformVal[i].f = uniformVal[i].b ? 1.0f : 0.0f;
}
}
}

View File

@ -241,9 +241,9 @@ _mesa_add_named_constant(struct gl_program_parameter_list *paramList,
* \return index/position of the new parameter in the parameter list.
*/
GLint
_mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList,
_mesa_add_typed_unnamed_constant(struct gl_program_parameter_list *paramList,
const gl_constant_value values[4], GLuint size,
GLuint *swizzleOut)
GLenum datatype, GLuint *swizzleOut)
{
GLint pos;
ASSERT(size >= 1);
@ -276,7 +276,7 @@ _mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList,
/* add a new parameter to store this constant */
pos = _mesa_add_parameter(paramList, PROGRAM_CONSTANT, NULL,
size, GL_NONE, values, NULL, 0x0);
size, datatype, values, NULL, 0x0);
if (pos >= 0 && swizzleOut) {
if (size == 1)
*swizzleOut = SWIZZLE_XXXX;
@ -286,6 +286,28 @@ _mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList,
return pos;
}
/**
* Add a new unnamed constant to the parameter list. This will be used
* when a fragment/vertex program contains something like this:
* MOV r, { 0, 1, 2, 3 };
* If swizzleOut is non-null we'll search the parameter list for an
* existing instance of the constant which matches with a swizzle.
*
* \param paramList the parameter list
* \param values four float values
* \param swizzleOut returns swizzle mask for accessing the constant
* \return index/position of the new parameter in the parameter list.
* \sa _mesa_add_typed_unnamed_constant
*/
GLint
_mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList,
const gl_constant_value values[4], GLuint size,
GLuint *swizzleOut)
{
return _mesa_add_typed_unnamed_constant(paramList, values, size, GL_NONE,
swizzleOut);
}
/**
* Add parameter representing a varying variable.
*/

View File

@ -134,6 +134,11 @@ _mesa_add_named_constant(struct gl_program_parameter_list *paramList,
const char *name, const gl_constant_value values[4],
GLuint size);
extern GLint
_mesa_add_typed_unnamed_constant(struct gl_program_parameter_list *paramList,
const gl_constant_value values[4], GLuint size,
GLenum datatype, GLuint *swizzleOut);
extern GLint
_mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList,
const gl_constant_value values[4], GLuint size,

View File

@ -96,11 +96,13 @@ public:
else
this->swizzle = SWIZZLE_XYZW;
this->negate = 0;
this->type = type ? type->base_type : GLSL_TYPE_ERROR;
this->reladdr = NULL;
}
st_src_reg(gl_register_file file, int index)
st_src_reg(gl_register_file file, int index, int type)
{
this->type = type;
this->file = file;
this->index = index;
this->swizzle = SWIZZLE_XYZW;
@ -110,6 +112,7 @@ public:
st_src_reg()
{
this->type = GLSL_TYPE_ERROR;
this->file = PROGRAM_UNDEFINED;
this->index = 0;
this->swizzle = 0;
@ -123,23 +126,26 @@ public:
int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */
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) */
/** Register index should be offset by the integer in this reg. */
st_src_reg *reladdr;
};
class st_dst_reg {
public:
st_dst_reg(gl_register_file file, int writemask)
st_dst_reg(gl_register_file file, int writemask, int type)
{
this->file = file;
this->index = 0;
this->writemask = writemask;
this->cond_mask = COND_TR;
this->reladdr = NULL;
this->type = type;
}
st_dst_reg()
{
this->type = GLSL_TYPE_ERROR;
this->file = PROGRAM_UNDEFINED;
this->index = 0;
this->writemask = 0;
@ -153,12 +159,14 @@ public:
int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */
int writemask; /**< Bitfield of WRITEMASK_[XYZW] */
GLuint cond_mask:4;
int type; /** GLSL_TYPE_* from GLSL IR (enum glsl_base_type) */
/** Register index should be offset by the integer in this reg. */
st_src_reg *reladdr;
};
st_src_reg::st_src_reg(st_dst_reg reg)
{
this->type = reg.type;
this->file = reg.file;
this->index = reg.index;
this->swizzle = SWIZZLE_XYZW;
@ -168,6 +176,7 @@ st_src_reg::st_src_reg(st_dst_reg reg)
st_dst_reg::st_dst_reg(st_src_reg reg)
{
this->type = reg.type;
this->file = reg.file;
this->index = reg.index;
this->writemask = WRITEMASK_XYZW;
@ -267,6 +276,8 @@ public:
int samplers_used;
bool indirect_addr_temps;
bool indirect_addr_consts;
int glsl_version;
variable_storage *find_variable_storage(ir_variable *var);
@ -276,6 +287,8 @@ public:
void reladdr_to_temp(ir_instruction *ir, st_src_reg *reg, int *num_reladdr);
st_src_reg st_src_reg_for_float(float val);
st_src_reg st_src_reg_for_int(int val);
st_src_reg st_src_reg_for_type(int type, int val);
/**
* \name Visit methods
@ -327,6 +340,10 @@ public:
glsl_to_tgsi_instruction *emit(ir_instruction *ir, unsigned op,
st_dst_reg dst,
st_src_reg src0, st_src_reg src1, st_src_reg src2);
unsigned get_opcode(ir_instruction *ir, unsigned op,
st_dst_reg dst,
st_src_reg src0, st_src_reg src1);
/**
* Emit the correct dot-product instruction for the type of arguments
@ -343,6 +360,8 @@ public:
void emit_scalar(ir_instruction *ir, unsigned 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 emit_scs(ir_instruction *ir, unsigned op,
st_dst_reg dst, const st_src_reg &src);
@ -372,9 +391,9 @@ public:
static st_src_reg undef_src = st_src_reg(PROGRAM_UNDEFINED, 0, NULL);
static st_dst_reg undef_dst = st_dst_reg(PROGRAM_UNDEFINED, SWIZZLE_NOOP);
static st_dst_reg undef_dst = st_dst_reg(PROGRAM_UNDEFINED, SWIZZLE_NOOP, GLSL_TYPE_ERROR);
static st_dst_reg address_reg = st_dst_reg(PROGRAM_ADDRESS, WRITEMASK_X);
static st_dst_reg address_reg = st_dst_reg(PROGRAM_ADDRESS, WRITEMASK_X, GLSL_TYPE_FLOAT);
static void
fail_link(struct gl_shader_program *prog, const char *fmt, ...) PRINTFLIKE(2, 3);
@ -432,6 +451,8 @@ glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op,
{
glsl_to_tgsi_instruction *inst = new(mem_ctx) glsl_to_tgsi_instruction();
int num_reladdr = 0, i;
op = get_opcode(ir, op, dst, src0, src1);
/* If we have to do relative addressing, we want to load the ARL
* reg directly for one of the regs, and preload the other reladdr
@ -447,7 +468,7 @@ glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op,
reladdr_to_temp(ir, &src0, &num_reladdr);
if (dst.reladdr) {
emit(ir, TGSI_OPCODE_ARL, address_reg, *dst.reladdr);
emit_arl(ir, address_reg, *dst.reladdr);
num_reladdr--;
}
assert(num_reladdr == 0);
@ -531,6 +552,62 @@ glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op)
return emit(ir, op, undef_dst, undef_src, undef_src, undef_src);
}
/**
* Determines whether to use an integer, unsigned integer, or float opcode
* based on the operands and input opcode, then emits the result.
*
* TODO: type checking for remaining TGSI opcodes
*/
unsigned
glsl_to_tgsi_visitor::get_opcode(ir_instruction *ir, unsigned op,
st_dst_reg dst,
st_src_reg src0, st_src_reg src1)
{
int type = GLSL_TYPE_FLOAT;
if (src0.type == GLSL_TYPE_FLOAT || src1.type == GLSL_TYPE_FLOAT)
type = GLSL_TYPE_FLOAT;
else if (glsl_version >= 130)
type = src0.type;
#define case4(c, f, i, u) \
case TGSI_OPCODE_##c: \
if (type == GLSL_TYPE_INT) op = TGSI_OPCODE_##i; \
else if (type == GLSL_TYPE_UINT) op = TGSI_OPCODE_##u; \
else op = TGSI_OPCODE_##f; \
break;
#define case3(f, i, u) case4(f, f, i, u)
#define case2fi(f, i) case4(f, f, i, i)
#define case2iu(i, u) case4(i, LAST, i, u)
switch(op) {
case2fi(ADD, UADD);
case2fi(MUL, UMUL);
case2fi(MAD, UMAD);
case3(DIV, IDIV, UDIV);
case3(MAX, IMAX, UMAX);
case3(MIN, IMIN, UMIN);
case2iu(MOD, UMOD);
case2fi(SEQ, USEQ);
case2fi(SNE, USNE);
case3(SGE, ISGE, USGE);
case3(SLT, ISLT, USLT);
case2iu(SHL, SHL);
case2iu(ISHR, USHR);
case2iu(NOT, NOT);
case2iu(AND, AND);
case2iu(OR, OR);
case2iu(XOR, XOR);
default: break;
}
assert(op != TGSI_OPCODE_LAST);
return op;
}
void
glsl_to_tgsi_visitor::emit_dp(ir_instruction *ir,
st_dst_reg dst, st_src_reg src0, st_src_reg src1,
@ -607,6 +684,22 @@ glsl_to_tgsi_visitor::emit_scalar(ir_instruction *ir, unsigned op,
emit_scalar(ir, op, dst, src0, undef);
}
void
glsl_to_tgsi_visitor::emit_arl(ir_instruction *ir,
st_dst_reg dst, st_src_reg src0)
{
st_src_reg tmp = get_temp(glsl_type::float_type);
if (src0.type == GLSL_TYPE_INT)
emit(ir, TGSI_OPCODE_I2F, st_dst_reg(tmp), src0);
else if (src0.type == GLSL_TYPE_UINT)
emit(ir, TGSI_OPCODE_U2F, st_dst_reg(tmp), src0);
else
tmp = src0;
emit(ir, TGSI_OPCODE_ARL, dst, tmp);
}
/**
* Emit an TGSI_OPCODE_SCS instruction
*
@ -705,16 +798,41 @@ glsl_to_tgsi_visitor::emit_scs(ir_instruction *ir, unsigned op,
struct st_src_reg
glsl_to_tgsi_visitor::st_src_reg_for_float(float val)
{
st_src_reg src(PROGRAM_CONSTANT, -1, NULL);
st_src_reg src(PROGRAM_CONSTANT, -1, GLSL_TYPE_FLOAT);
union gl_constant_value uval;
uval.f = val;
src.index = _mesa_add_unnamed_constant(this->prog->Parameters,
&uval, 1, &src.swizzle);
src.index = _mesa_add_typed_unnamed_constant(this->prog->Parameters,
&uval, 1, GL_FLOAT, &src.swizzle);
return src;
}
struct st_src_reg
glsl_to_tgsi_visitor::st_src_reg_for_int(int val)
{
st_src_reg src(PROGRAM_CONSTANT, -1, GLSL_TYPE_INT);
union gl_constant_value uval;
assert(glsl_version >= 130);
uval.i = val;
src.index = _mesa_add_typed_unnamed_constant(this->prog->Parameters,
&uval, 1, GL_INT, &src.swizzle);
return src;
}
struct st_src_reg
glsl_to_tgsi_visitor::st_src_reg_for_type(int type, int val)
{
if (glsl_version >= 130)
return type == GLSL_TYPE_FLOAT ? st_src_reg_for_float(val) :
st_src_reg_for_int(val);
else
return st_src_reg_for_float(val);
}
static int
type_size(const struct glsl_type *type)
{
@ -759,8 +877,7 @@ type_size(const struct glsl_type *type)
/**
* In the initial pass of codegen, we assign temporary numbers to
* intermediate results. (not SSA -- variable assignments will reuse
* storage). Actual register allocation for the Mesa VM occurs in a
* pass over the Mesa IR later.
* storage).
*/
st_src_reg
glsl_to_tgsi_visitor::get_temp(const glsl_type *type)
@ -769,6 +886,7 @@ glsl_to_tgsi_visitor::get_temp(const glsl_type *type)
int swizzle[4];
int i;
src.type = type->base_type;
src.file = PROGRAM_TEMPORARY;
src.index = next_temp;
src.reladdr = NULL;
@ -875,7 +993,8 @@ glsl_to_tgsi_visitor::visit(ir_variable *ir)
this->variables.push_tail(storage);
this->next_temp += type_size(ir->type);
dst = st_dst_reg(st_src_reg(PROGRAM_TEMPORARY, storage->index, NULL));
dst = st_dst_reg(st_src_reg(PROGRAM_TEMPORARY, storage->index,
glsl_version >= 130 ? ir->type->base_type : GLSL_TYPE_FLOAT));
}
@ -890,7 +1009,8 @@ glsl_to_tgsi_visitor::visit(ir_variable *ir)
assert(index == storage->index + (int)i);
}
} else {
st_src_reg src(PROGRAM_STATE_VAR, index, NULL);
st_src_reg src(PROGRAM_STATE_VAR, index,
glsl_version >= 130 ? ir->type->base_type : 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. */
@ -1058,7 +1178,7 @@ glsl_to_tgsi_visitor::reladdr_to_temp(ir_instruction *ir,
if (!reg->reladdr)
return;
emit(ir, TGSI_OPCODE_ARL, address_reg, *reg->reladdr);
emit_arl(ir, address_reg, *reg->reladdr);
if (*num_reladdr != 1) {
st_src_reg temp = get_temp(glsl_type::vec4_type);
@ -1131,13 +1251,19 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
switch (ir->operation) {
case ir_unop_logic_not:
emit(ir, TGSI_OPCODE_SEQ, result_dst, op[0], st_src_reg_for_float(0.0));
emit(ir, TGSI_OPCODE_SEQ, result_dst, op[0], st_src_reg_for_type(result_dst.type, 0));
break;
case ir_unop_neg:
op[0].negate = ~op[0].negate;
result_src = op[0];
assert(result_dst.type == GLSL_TYPE_FLOAT || result_dst.type == GLSL_TYPE_INT);
if (result_dst.type == GLSL_TYPE_INT)
emit(ir, TGSI_OPCODE_INEG, result_dst, op[0]);
else {
op[0].negate = ~op[0].negate;
result_src = op[0];
}
break;
case ir_unop_abs:
assert(result_dst.type == GLSL_TYPE_FLOAT);
emit(ir, TGSI_OPCODE_ABS, result_dst, op[0]);
break;
case ir_unop_sign:
@ -1200,9 +1326,16 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
emit(ir, TGSI_OPCODE_MUL, result_dst, op[0], op[1]);
break;
case ir_binop_div:
assert(!"not reached: should be handled by ir_div_to_mul_rcp");
if (result_dst.type == GLSL_TYPE_FLOAT)
assert(!"not reached: should be handled by ir_div_to_mul_rcp");
else
emit(ir, TGSI_OPCODE_DIV, result_dst, op[0], op[1]);
break;
case ir_binop_mod:
assert(!"ir_binop_mod should have been converted to b * fract(a/b)");
if (result_dst.type == GLSL_TYPE_FLOAT)
assert(!"ir_binop_mod should have been converted to b * fract(a/b)");
else
emit(ir, TGSI_OPCODE_MOD, result_dst, op[0], op[1]);
break;
case ir_binop_less:
@ -1227,7 +1360,10 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
/* "==" operator producing a scalar boolean. */
if (ir->operands[0]->type->is_vector() ||
ir->operands[1]->type->is_vector()) {
st_src_reg temp = get_temp(glsl_type::vec4_type);
st_src_reg temp = get_temp(glsl_version >= 130 ?
glsl_type::get_vec4_type(ir->operands[0]->type->base_type) :
glsl_type::vec4_type);
assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
emit(ir, TGSI_OPCODE_SNE, st_dst_reg(temp), op[0], op[1]);
emit_dp(ir, result_dst, temp, temp, vector_elements);
emit(ir, TGSI_OPCODE_SEQ, result_dst, result_src, st_src_reg_for_float(0.0));
@ -1239,7 +1375,10 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
/* "!=" operator producing a scalar boolean. */
if (ir->operands[0]->type->is_vector() ||
ir->operands[1]->type->is_vector()) {
st_src_reg temp = get_temp(glsl_type::vec4_type);
st_src_reg temp = get_temp(glsl_version >= 130 ?
glsl_type::get_vec4_type(ir->operands[0]->type->base_type) :
glsl_type::vec4_type);
assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
emit(ir, TGSI_OPCODE_SNE, st_dst_reg(temp), op[0], op[1]);
emit_dp(ir, result_dst, temp, temp, vector_elements);
emit(ir, TGSI_OPCODE_SNE, result_dst, result_src, st_src_reg_for_float(0.0));
@ -1291,17 +1430,24 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
break;
case ir_unop_i2f:
case ir_unop_b2f:
if (glsl_version >= 130) {
emit(ir, TGSI_OPCODE_I2F, result_dst, op[0]);
break;
}
case ir_unop_b2i:
/* Mesa IR lacks types, ints are stored as truncated floats. */
/* Booleans are stored as integers (or floats in GLSL 1.20 and lower). */
result_src = op[0];
break;
case ir_unop_f2i:
emit(ir, TGSI_OPCODE_TRUNC, result_dst, op[0]);
if (glsl_version >= 130)
emit(ir, TGSI_OPCODE_F2I, result_dst, op[0]);
else
emit(ir, TGSI_OPCODE_TRUNC, result_dst, op[0]);
break;
case ir_unop_f2b:
case ir_unop_i2b:
emit(ir, TGSI_OPCODE_SNE, result_dst,
op[0], st_src_reg_for_float(0.0));
emit(ir, TGSI_OPCODE_SNE, result_dst, op[0],
st_src_reg_for_type(result_dst.type, 0));
break;
case ir_unop_trunc:
emit(ir, TGSI_OPCODE_TRUNC, result_dst, op[0]);
@ -1329,12 +1475,40 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
break;
case ir_unop_bit_not:
if (glsl_version >= 130) {
emit(ir, TGSI_OPCODE_NOT, result_dst, op[0]);
break;
}
case ir_unop_u2f:
if (glsl_version >= 130) {
emit(ir, TGSI_OPCODE_U2F, result_dst, op[0]);
break;
}
case ir_binop_lshift:
if (glsl_version >= 130) {
emit(ir, TGSI_OPCODE_SHL, result_dst, op[0]);
break;
}
case ir_binop_rshift:
if (glsl_version >= 130) {
emit(ir, TGSI_OPCODE_ISHR, result_dst, op[0]);
break;
}
case ir_binop_bit_and:
if (glsl_version >= 130) {
emit(ir, TGSI_OPCODE_AND, result_dst, op[0]);
break;
}
case ir_binop_bit_xor:
if (glsl_version >= 130) {
emit(ir, TGSI_OPCODE_XOR, result_dst, op[0]);
break;
}
case ir_binop_bit_or:
if (glsl_version >= 130) {
emit(ir, TGSI_OPCODE_OR, result_dst, op[0]);
break;
}
case ir_unop_round_even:
assert(!"GLSL 1.30 features unsupported");
break;
@ -1729,7 +1903,8 @@ glsl_to_tgsi_visitor::visit(ir_constant *ir)
{
st_src_reg src;
GLfloat stack_vals[4] = { 0 };
GLfloat *values = stack_vals;
gl_constant_value *values = (gl_constant_value *) stack_vals;
GLenum gl_type = GL_NONE;
unsigned int i;
/* Unfortunately, 4 floats is all we can get into
@ -1737,7 +1912,6 @@ glsl_to_tgsi_visitor::visit(ir_constant *ir)
* aggregate constant and move each constant value into it. If we
* get lucky, copy propagation will eliminate the extra moves.
*/
if (ir->type->base_type == GLSL_TYPE_STRUCT) {
st_src_reg temp_base = get_temp(ir->type);
st_dst_reg temp = st_dst_reg(temp_base);
@ -1789,13 +1963,13 @@ glsl_to_tgsi_visitor::visit(ir_constant *ir)
for (i = 0; i < ir->type->matrix_columns; i++) {
assert(ir->type->base_type == GLSL_TYPE_FLOAT);
values = &ir->value.f[i * ir->type->vector_elements];
values = (gl_constant_value *) &ir->value.f[i * ir->type->vector_elements];
src = st_src_reg(PROGRAM_CONSTANT, -1, NULL);
src = st_src_reg(PROGRAM_CONSTANT, -1, ir->type->base_type);
src.index = _mesa_add_unnamed_constant(this->prog->Parameters,
(gl_constant_value *) values,
ir->type->vector_elements,
&src.swizzle);
values,
ir->type->vector_elements,
&src.swizzle);
emit(ir, TGSI_OPCODE_MOV, mat_column, src);
mat_column.index++;
@ -1808,21 +1982,36 @@ glsl_to_tgsi_visitor::visit(ir_constant *ir)
src.file = PROGRAM_CONSTANT;
switch (ir->type->base_type) {
case GLSL_TYPE_FLOAT:
values = &ir->value.f[0];
gl_type = GL_FLOAT;
for (i = 0; i < ir->type->vector_elements; i++) {
values[i].f = ir->value.f[i];
}
break;
case GLSL_TYPE_UINT:
gl_type = glsl_version >= 130 ? GL_UNSIGNED_INT : GL_FLOAT;
for (i = 0; i < ir->type->vector_elements; i++) {
values[i] = ir->value.u[i];
if (glsl_version >= 130)
values[i].u = ir->value.u[i];
else
values[i].f = ir->value.u[i];
}
break;
case GLSL_TYPE_INT:
gl_type = glsl_version >= 130 ? GL_INT : GL_FLOAT;
for (i = 0; i < ir->type->vector_elements; i++) {
values[i] = ir->value.i[i];
if (glsl_version >= 130)
values[i].i = ir->value.i[i];
else
values[i].f = ir->value.i[i];
}
break;
case GLSL_TYPE_BOOL:
gl_type = glsl_version >= 130 ? GL_BOOL : GL_FLOAT;
for (i = 0; i < ir->type->vector_elements; i++) {
values[i] = ir->value.b[i];
if (glsl_version >= 130)
values[i].b = ir->value.b[i];
else
values[i].f = ir->value.b[i];
}
break;
default:
@ -1830,9 +2019,8 @@ glsl_to_tgsi_visitor::visit(ir_constant *ir)
}
this->result = st_src_reg(PROGRAM_CONSTANT, -1, ir->type);
this->result.index = _mesa_add_unnamed_constant(this->prog->Parameters,
(gl_constant_value *) values,
ir->type->vector_elements,
this->result.index = _mesa_add_typed_unnamed_constant(this->prog->Parameters,
values, ir->type->vector_elements, gl_type,
&this->result.swizzle);
}
@ -2535,6 +2723,7 @@ glsl_to_tgsi_visitor::remove_output_reads(gl_register_file type)
{
GLuint i;
GLint outputMap[VERT_RESULT_MAX];
GLint outputTypes[VERT_RESULT_MAX];
GLuint numVaryingReads = 0;
GLboolean usedTemps[MAX_PROGRAM_TEMPS];
GLuint firstTemp = 0;
@ -2562,6 +2751,7 @@ glsl_to_tgsi_visitor::remove_output_reads(gl_register_file type)
outputMap[var] = _mesa_find_free_register(usedTemps,
MAX_PROGRAM_TEMPS,
firstTemp);
outputTypes[var] = inst->src[j].type;
firstTemp = outputMap[var] + 1;
}
inst->src[j].file = PROGRAM_TEMPORARY;
@ -2587,8 +2777,8 @@ glsl_to_tgsi_visitor::remove_output_reads(gl_register_file type)
for (i = 0; i < VERT_RESULT_MAX; i++) {
if (outputMap[i] >= 0) {
/* MOV VAR[i], TEMP[tmp]; */
st_src_reg src = st_src_reg(PROGRAM_TEMPORARY, outputMap[i]);
st_dst_reg dst = st_dst_reg(type, WRITEMASK_XYZW);
st_src_reg src = st_src_reg(PROGRAM_TEMPORARY, outputMap[i], outputTypes[i]);
st_dst_reg dst = st_dst_reg(type, WRITEMASK_XYZW, outputTypes[i]);
dst.index = i;
this->emit(NULL, TGSI_OPCODE_MOV, dst, src);
}
@ -3762,10 +3952,33 @@ st_translate_program(
if (program->indirect_addr_consts)
t->constants[i] = ureg_DECL_constant( ureg, i );
else
t->constants[i] =
ureg_DECL_immediate( ureg,
(GLfloat *) proginfo->Parameters->ParameterValues[i],
4 );
switch(proginfo->Parameters->Parameters[i].DataType)
{
case GL_FLOAT:
case GL_FLOAT_VEC2:
case GL_FLOAT_VEC3:
case GL_FLOAT_VEC4:
t->constants[i] = ureg_DECL_immediate(ureg, (float *)proginfo->Parameters->ParameterValues[i], 4);
break;
case GL_INT:
case GL_INT_VEC2:
case GL_INT_VEC3:
case GL_INT_VEC4:
t->constants[i] = ureg_DECL_immediate_int(ureg, (int *)proginfo->Parameters->ParameterValues[i], 4);
break;
case GL_UNSIGNED_INT:
case GL_UNSIGNED_INT_VEC2:
case GL_UNSIGNED_INT_VEC3:
case GL_UNSIGNED_INT_VEC4:
case GL_BOOL:
case GL_BOOL_VEC2:
case GL_BOOL_VEC3:
case GL_BOOL_VEC4:
t->constants[i] = ureg_DECL_immediate_uint(ureg, (unsigned *)proginfo->Parameters->ParameterValues[i], 4);
break;
default:
assert(!"should not get here");
}
break;
default:
break;
@ -3874,6 +4087,7 @@ get_mesa_program(struct gl_context *ctx,
v->prog = prog;
v->shader_program = shader_program;
v->options = options;
v->glsl_version = ctx->Const.GLSLVersion;
add_uniforms_to_parameters_list(shader_program, shader, prog);