Move swizzles out of ir_dereference and into their own class.

Also turn generate_swizzle into a static "create" method of the new
class; we'll want to use it for the IR reader as well.

Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
This commit is contained in:
Kenneth Graunke 2010-03-26 01:20:08 -07:00 committed by Ian Romanick
parent fb9fb5f51d
commit affc1413ac
8 changed files with 176 additions and 184 deletions

View file

@ -454,23 +454,10 @@ ast_expression::hir(exec_list *instructions,
YYLTYPE loc;
/* FINISHME: This does not handle 'foo.bar.a.b.c[5].d = 5' */
loc = this->subexpressions[0]->get_location();
const ir_dereference *const ref = op[0]->as_dereference();
if (ref == NULL) {
_mesa_glsl_error(& loc, state, "invalid lvalue in assignment");
if (!op[0]->is_lvalue()) {
_mesa_glsl_error(& loc, state, "non-lvalue in assignment");
error_emitted = true;
type = glsl_error_type;
} else {
const ir_variable *const var = (ir_variable *) ref->var;
if (var != NULL && var->read_only) {
_mesa_glsl_error(& loc, state, "cannot assign to read-only "
"variable `%s'", var->name);
error_emitted = true;
type = glsl_error_type;
}
}
}
@ -612,24 +599,10 @@ ast_expression::hir(exec_list *instructions,
if (!error_emitted) {
YYLTYPE loc;
/* FINISHME: This does not handle 'foo.bar.a.b.c[5].d = 5' */
loc = this->subexpressions[0]->get_location();
const ir_dereference *const ref = op[0]->as_dereference();
if (ref == NULL) {
_mesa_glsl_error(& loc, state, "invalid lvalue in assignment");
if (!op[0]->is_lvalue()) {
_mesa_glsl_error(& loc, state, "non-lvalue in assignment");
error_emitted = true;
type = glsl_error_type;
} else {
const ir_variable *const var = (ir_variable *) ref->var;
if (var != NULL && var->read_only) {
_mesa_glsl_error(& loc, state, "cannot assign to read-only "
"variable `%s'", var->name);
error_emitted = true;
type = glsl_error_type;
}
}
}

View file

@ -178,17 +178,18 @@ generate_vec_body_from_scalar(exec_list *instructions,
/* Generate a single assignment of the parameter to __retval.x and return
* __retval.xxxx for however many vector components there are.
*/
ir_dereference *const lhs = new ir_dereference(declarations[16]);
ir_dereference *const lhs_ref = new ir_dereference(declarations[16]);
ir_dereference *const rhs = new ir_dereference(declarations[0]);
lhs->set_swizzle(0, 0, 0, 0, 1);
ir_swizzle *lhs = new ir_swizzle(lhs_ref, 0, 0, 0, 0, 1);
inst = new ir_assignment(lhs, rhs, NULL);
instructions->push_tail(inst);
ir_dereference *const retval = new ir_dereference(declarations[16]);
ir_dereference *const retref = new ir_dereference(declarations[16]);
retval->set_swizzle(0, 0, 0, 0, declarations[16]->type->vector_elements);
ir_swizzle *retval = new ir_swizzle(retref, 0, 0, 0, 0,
declarations[16]->type->vector_elements);
inst = new ir_return(retval);
instructions->push_tail(inst);
@ -210,11 +211,10 @@ generate_vec_body_from_N_scalars(exec_list *instructions,
* __retval.x and return __retval.
*/
for (unsigned i = 0; i < vec_type->vector_elements; i++) {
ir_dereference *const lhs = new ir_dereference(declarations[16]);
ir_dereference *const lhs_ref = new ir_dereference(declarations[16]);
ir_dereference *const rhs = new ir_dereference(declarations[i]);
lhs->selector.swizzle.x = i;
lhs->selector.swizzle.num_components = 1;
ir_swizzle *lhs = new ir_swizzle(lhs_ref, 1, 0, 0, 0, 1);
inst = new ir_assignment(lhs, rhs, NULL);
instructions->push_tail(inst);
@ -262,10 +262,10 @@ generate_mat_body_from_scalar(exec_list *instructions,
instructions->push_tail(column);
ir_dereference *const lhs = new ir_dereference(column);
ir_dereference *const lhs_ref = new ir_dereference(column);
ir_dereference *const rhs = new ir_dereference(declarations[0]);
lhs->set_swizzle(0, 0, 0, 0, 1);
ir_swizzle *lhs = new ir_swizzle(lhs_ref, 0, 0, 0, 0, 1);
inst = new ir_assignment(lhs, rhs, NULL);
instructions->push_tail(inst);
@ -274,9 +274,9 @@ generate_mat_body_from_scalar(exec_list *instructions,
ir_constant *const zero = new ir_constant(glsl_float_type, &z);
for (unsigned i = 1; i < column_type->vector_elements; i++) {
ir_dereference *const lhs = new ir_dereference(column);
ir_dereference *const lhs_ref = new ir_dereference(column);
lhs->set_swizzle(i, 0, 0, 0, 1);
ir_swizzle *lhs = new ir_swizzle(lhs_ref, i, 0, 0, 0, 1);
inst = new ir_assignment(lhs, zero, NULL);
instructions->push_tail(inst);
@ -285,12 +285,13 @@ generate_mat_body_from_scalar(exec_list *instructions,
for (unsigned i = 0; i < row_type->vector_elements; i++) {
static const unsigned swiz[] = { 1, 1, 1, 0, 1, 1, 1 };
ir_dereference *const rhs = new ir_dereference(column);
ir_dereference *const rhs_ref = new ir_dereference(column);
/* This will be .xyyy when i=0, .yxyy when i=1, etc.
*/
rhs->set_swizzle(swiz[3 - i], swiz[4 - i], swiz[5 - i], swiz[6 - i],
column_type->vector_elements);
ir_swizzle *rhs = new ir_swizzle(rhs_ref, swiz[3 - i], swiz[4 - i],
swiz[5 - i], swiz[6 - i],
column_type->vector_elements);
ir_constant *const idx = new ir_constant(glsl_int_type, &i);
ir_dereference *const lhs = new ir_dereference(declarations[16], idx);
@ -326,11 +327,11 @@ generate_mat_body_from_N_scalars(exec_list *instructions,
ir_dereference *const row_access =
new ir_dereference(declarations[16], row_index);
ir_dereference *const component_access =
ir_dereference *const component_access_ref =
new ir_dereference(row_access);
component_access->selector.swizzle.x = j;
component_access->selector.swizzle.num_components = 1;
ir_swizzle *component_access = new ir_swizzle(component_access_ref,
j, 0, 0, 0, 1);
const unsigned param = (i * row_type->vector_elements) + j;
ir_dereference *const rhs = new ir_dereference(declarations[param]);

View file

@ -28,107 +28,15 @@
#include "glsl_types.h"
#include "ir.h"
#define X 1
#define R 5
#define S 9
#define I 13
static bool
generate_swizzle(const char *str, ir_dereference *deref,
unsigned vector_length)
{
/* For each possible swizzle character, this table encodes the value in
* \c idx_map that represents the 0th element of the vector. For invalid
* swizzle characters (e.g., 'k'), a special value is used that will allow
* detection of errors.
*/
static const unsigned char base_idx[26] = {
/* a b c d e f g h i j k l m */
R, R, I, I, I, I, R, I, I, I, I, I, I,
/* n o p q r s t u v w x y z */
I, I, S, S, R, S, S, I, I, X, X, X, X
};
/* Each valid swizzle character has an entry in the previous table. This
* table encodes the base index encoded in the previous table plus the actual
* index of the swizzle character. When processing swizzles, the first
* character in the string is indexed in the previous table. Each character
* in the string is indexed in this table, and the value found there has the
* value form the first table subtracted. The result must be on the range
* [0,3].
*
* For example, the string "wzyx" will get X from the first table. Each of
* the charcaters will get X+3, X+2, X+1, and X+0 from this table. After
* subtraction, the swizzle values are { 3, 2, 1, 0 }.
*
* The string "wzrg" will get X from the first table. Each of the characters
* will get X+3, X+2, R+0, and R+1 from this table. After subtraction, the
* swizzle values are { 3, 2, 4, 5 }. Since 4 and 5 are outside the range
* [0,3], the error is detected.
*/
static const unsigned char idx_map[26] = {
/* a b c d e f g h i j k l m */
R+3, R+2, 0, 0, 0, 0, R+1, 0, 0, 0, 0, 0, 0,
/* n o p q r s t u v w x y z */
0, 0, S+2, S+3, R+0, S+0, S+1, 0, 0, X+3, X+0, X+1, X+2
};
int swiz_idx[4] = { 0, 0, 0, 0 };
unsigned i;
/* Validate the first character in the swizzle string and look up the base
* index value as described above.
*/
if ((str[0] < 'a') || (str[0] > 'z'))
return false;
const unsigned base = base_idx[str[0] - 'a'];
for (i = 0; (i < 4) && (str[i] != '\0'); i++) {
/* Validate the next character, and, as described above, convert it to a
* swizzle index.
*/
if ((str[i] < 'a') || (str[i] > 'z'))
return false;
swiz_idx[i] = idx_map[str[i] - 'a'] - base;
if ((swiz_idx[i] < 0) || (swiz_idx[i] >= (int) vector_length))
return false;
}
if (str[i] != '\0')
return false;
deref->set_swizzle(swiz_idx[0], swiz_idx[1], swiz_idx[2], swiz_idx[3], i);
return true;
}
struct ir_rvalue *
_mesa_ast_field_selection_to_hir(const ast_expression *expr,
exec_list *instructions,
struct _mesa_glsl_parse_state *state)
{
ir_rvalue *result = NULL;
ir_rvalue *op;
ir_dereference *deref;
YYLTYPE loc;
op = expr->subexpressions[0]->hir(instructions, state);
deref = new ir_dereference(op);
/* Initially assume that the resulting type of the field selection is an
* error. This make the error paths below a bit easier to follow.
*/
deref->type = glsl_error_type;
/* If processing the thing being dereferenced generated an error, bail out
* now. Doing so prevents spurious error messages from being logged below.
*/
if (is_error_type(op->type))
return deref;
/* There are two kinds of field selection. There is the selection of a
* specific field from a structure, and there is the selection of a
@ -136,21 +44,18 @@ _mesa_ast_field_selection_to_hir(const ast_expression *expr,
* by the base type of the thing to which the field selection operator is
* being applied.
*/
loc = expr->get_location();
if (op->type->is_vector()) {
if (generate_swizzle(expr->primary_expression.identifier,
deref, op->type->vector_elements)) {
/* Based on the number of elements in the swizzle and the base type
* (i.e., float, int, unsigned, or bool) of the vector being swizzled,
* generate the type of the resulting value.
*/
deref->type =
glsl_type::get_instance(op->type->base_type,
deref->selector.swizzle.num_components,
1);
YYLTYPE loc = expr->get_location();
if (op->type == glsl_error_type) {
/* silently propagate the error */
} else if (op->type->is_vector()) {
ir_swizzle *swiz = ir_swizzle::create(op,
expr->primary_expression.identifier,
op->type->vector_elements);
if (swiz != NULL) {
result = swiz;
} else {
/* FINISHME: Logging of error messages should be moved into
* FINISHME: generate_swizzle. This allows the generation of more
* FINISHME: ir_swizzle::create. This allows the generation of more
* FINISHME: specific error messages.
*/
_mesa_glsl_error(& loc, state, "Invalid swizzle / mask `%s'",
@ -164,5 +69,5 @@ _mesa_ast_field_selection_to_hir(const ast_expression *expr,
expr->primary_expression.identifier);
}
return deref;
return result ? result : ir_call::get_error_instruction();
}

104
ir.cpp
View file

@ -97,9 +97,9 @@ ir_dereference::ir_dereference(ir_instruction *var,
}
void
ir_dereference::set_swizzle(unsigned x, unsigned y, unsigned z, unsigned w,
unsigned count)
ir_swizzle::ir_swizzle(ir_rvalue *val, unsigned x, unsigned y, unsigned z,
unsigned w, unsigned count)
: val(val)
{
assert((count >= 1) && (count <= 4));
@ -113,14 +113,100 @@ ir_dereference::set_swizzle(unsigned x, unsigned y, unsigned z, unsigned w,
assert(z <= 3);
assert(w <= 3);
selector.swizzle.x = x;
selector.swizzle.y = y;
selector.swizzle.z = z;
selector.swizzle.w = w;
selector.swizzle.num_components = count;
selector.swizzle.has_duplicates = dup_mask != 0;
mask.x = x;
mask.y = y;
mask.z = z;
mask.w = w;
mask.num_components = count;
mask.has_duplicates = dup_mask != 0;
/* Based on the number of elements in the swizzle and the base type
* (i.e., float, int, unsigned, or bool) of the vector being swizzled,
* generate the type of the resulting value.
*/
type = glsl_type::get_instance(val->type->base_type, mask.num_components, 1);
}
#define X 1
#define R 5
#define S 9
#define I 13
ir_swizzle *
ir_swizzle::create(ir_rvalue *val, const char *str, unsigned vector_length)
{
/* For each possible swizzle character, this table encodes the value in
* \c idx_map that represents the 0th element of the vector. For invalid
* swizzle characters (e.g., 'k'), a special value is used that will allow
* detection of errors.
*/
static const unsigned char base_idx[26] = {
/* a b c d e f g h i j k l m */
R, R, I, I, I, I, R, I, I, I, I, I, I,
/* n o p q r s t u v w x y z */
I, I, S, S, R, S, S, I, I, X, X, X, X
};
/* Each valid swizzle character has an entry in the previous table. This
* table encodes the base index encoded in the previous table plus the actual
* index of the swizzle character. When processing swizzles, the first
* character in the string is indexed in the previous table. Each character
* in the string is indexed in this table, and the value found there has the
* value form the first table subtracted. The result must be on the range
* [0,3].
*
* For example, the string "wzyx" will get X from the first table. Each of
* the charcaters will get X+3, X+2, X+1, and X+0 from this table. After
* subtraction, the swizzle values are { 3, 2, 1, 0 }.
*
* The string "wzrg" will get X from the first table. Each of the characters
* will get X+3, X+2, R+0, and R+1 from this table. After subtraction, the
* swizzle values are { 3, 2, 4, 5 }. Since 4 and 5 are outside the range
* [0,3], the error is detected.
*/
static const unsigned char idx_map[26] = {
/* a b c d e f g h i j k l m */
R+3, R+2, 0, 0, 0, 0, R+1, 0, 0, 0, 0, 0, 0,
/* n o p q r s t u v w x y z */
0, 0, S+2, S+3, R+0, S+0, S+1, 0, 0, X+3, X+0, X+1, X+2
};
int swiz_idx[4] = { 0, 0, 0, 0 };
unsigned i;
/* Validate the first character in the swizzle string and look up the base
* index value as described above.
*/
if ((str[0] < 'a') || (str[0] > 'z'))
return NULL;
const unsigned base = base_idx[str[0] - 'a'];
for (i = 0; (i < 4) && (str[i] != '\0'); i++) {
/* Validate the next character, and, as described above, convert it to a
* swizzle index.
*/
if ((str[i] < 'a') || (str[i] > 'z'))
return NULL;
swiz_idx[i] = idx_map[str[i] - 'a'] - base;
if ((swiz_idx[i] < 0) || (swiz_idx[i] >= (int) vector_length))
return NULL;
}
if (str[i] != '\0')
return NULL;
return new ir_swizzle(val, swiz_idx[0], swiz_idx[1], swiz_idx[2],
swiz_idx[3], i);
}
#undef X
#undef R
#undef S
#undef I
ir_variable::ir_variable(const struct glsl_type *type, const char *name)

33
ir.h
View file

@ -394,6 +394,31 @@ struct ir_swizzle_mask {
unsigned has_duplicates:1;
};
class ir_swizzle : public ir_rvalue {
public:
ir_swizzle(ir_rvalue *, unsigned x, unsigned y, unsigned z, unsigned w,
unsigned count);
/**
* Construct an ir_swizzle from the textual representation. Can fail.
*/
static ir_swizzle *create(ir_rvalue *, const char *, unsigned vector_length);
virtual void accept(ir_visitor *v)
{
v->visit(this);
}
bool is_lvalue()
{
return val->is_lvalue();
}
ir_rvalue *val;
ir_swizzle_mask mask;
};
class ir_dereference : public ir_rvalue {
public:
ir_dereference(struct ir_instruction *);
@ -415,13 +440,6 @@ public:
return var != NULL;
}
/**
* Setting the swizzle of a derefernce
*/
void set_swizzle(unsigned x, unsigned y, unsigned z, unsigned w,
unsigned count);
enum {
ir_reference_variable,
ir_reference_array,
@ -438,7 +456,6 @@ public:
union {
ir_rvalue *array_index;
const char *field;
struct ir_swizzle_mask swizzle;
} selector;
};

View file

@ -102,26 +102,34 @@ void ir_print_visitor::visit(ir_expression *ir)
}
void ir_print_visitor::visit(ir_swizzle *ir)
{
const unsigned swiz[4] = {
ir->mask.x,
ir->mask.y,
ir->mask.z,
ir->mask.w,
};
printf("(swiz ");
for (unsigned i = 0; i < ir->mask.num_components; i++) {
printf("%c", "xyzw"[swiz[i]]);
}
printf(" ");
ir->val->accept(this);
printf(")");
}
void ir_print_visitor::visit(ir_dereference *ir)
{
deref_depth++;
switch (ir->mode) {
case ir_dereference::ir_reference_variable: {
const unsigned swiz[4] = {
ir->selector.swizzle.x,
ir->selector.swizzle.y,
ir->selector.swizzle.z,
ir->selector.swizzle.w,
};
printf("(var_ref ");
ir->var->accept(this);
printf("(");
for (unsigned i = 0; i < ir->selector.swizzle.num_components; i++) {
printf("%c", "xyzw"[swiz[i]]);
}
printf(")) ");
printf(") ");
break;
}
case ir_dereference::ir_reference_array:

View file

@ -58,6 +58,7 @@ public:
virtual void visit(ir_function_signature *);
virtual void visit(ir_function *);
virtual void visit(ir_expression *);
virtual void visit(ir_swizzle *);
virtual void visit(ir_dereference *);
virtual void visit(ir_assignment *);
virtual void visit(ir_constant *);

View file

@ -49,6 +49,7 @@ public:
virtual void visit(class ir_function_signature *) = 0;
virtual void visit(class ir_function *) = 0;
virtual void visit(class ir_expression *) = 0;
virtual void visit(class ir_swizzle *) = 0;
virtual void visit(class ir_dereference *) = 0;
virtual void visit(class ir_assignment *) = 0;
virtual void visit(class ir_constant *) = 0;