#include "glsl_types.h"
#include "s_expression.h"
-const static bool debug = false;
+static const bool debug = false;
+
+namespace {
class ir_reader {
public:
ir_variable *read_declaration(s_expression *);
ir_if *read_if(s_expression *, ir_loop *);
ir_loop *read_loop(s_expression *);
+ ir_call *read_call(s_expression *);
ir_return *read_return(s_expression *);
ir_rvalue *read_rvalue(s_expression *);
ir_assignment *read_assignment(s_expression *);
ir_expression *read_expression(s_expression *);
- ir_call *read_call(s_expression *);
ir_swizzle *read_swizzle(s_expression *);
ir_constant *read_constant(s_expression *);
ir_texture *read_texture(s_expression *);
+ ir_emit_vertex *read_emit_vertex(s_expression *);
+ ir_end_primitive *read_end_primitive(s_expression *);
+ ir_barrier *read_barrier(s_expression *);
ir_dereference *read_dereference(s_expression *);
+ ir_dereference_variable *read_var_ref(s_expression *);
};
+} /* anonymous namespace */
+
ir_reader::ir_reader(_mesa_glsl_parse_state *state) : state(state)
{
this->mem_ctx = state;
void
ir_reader::read(exec_list *instructions, const char *src, bool scan_for_protos)
{
- s_expression *expr = s_expression::read_expression(mem_ctx, src);
+ void *sx_mem_ctx = ralloc_context(NULL);
+ s_expression *expr = s_expression::read_expression(sx_mem_ctx, src);
if (expr == NULL) {
ir_read_error(NULL, "couldn't parse S-Expression.");
return;
}
-
+
if (scan_for_protos) {
scan_for_prototypes(instructions, expr);
if (state->error)
}
read_instructions(instructions, expr, NULL);
- talloc_free(expr);
+ ralloc_free(sx_mem_ctx);
if (debug)
validate_ir_tree(instructions);
state->error = true;
if (state->current_function != NULL)
- state->info_log = talloc_asprintf_append(state->info_log,
- "In function %s:\n",
- state->current_function->function_name());
- state->info_log = talloc_strdup_append(state->info_log, "error: ");
+ ralloc_asprintf_append(&state->info_log, "In function %s:\n",
+ state->current_function->function_name());
+ ralloc_strcat(&state->info_log, "error: ");
va_start(ap, fmt);
- state->info_log = talloc_vasprintf_append(state->info_log, fmt, ap);
+ ralloc_vasprintf_append(&state->info_log, fmt, ap);
va_end(ap);
- state->info_log = talloc_strdup_append(state->info_log, "\n");
+ ralloc_strcat(&state->info_log, "\n");
if (expr != NULL) {
- state->info_log = talloc_strdup_append(state->info_log,
- "...in this context:\n ");
+ ralloc_strcat(&state->info_log, "...in this context:\n ");
expr->print();
- state->info_log = talloc_strdup_append(state->info_log, "\n\n");
+ ralloc_strcat(&state->info_log, "\n\n");
}
}
return glsl_type::get_array_instance(base_type, s_size->value());
}
-
+
s_symbol *type_sym = SX_AS_SYMBOL(expr);
if (type_sym == NULL) {
ir_read_error(expr, "expected <type>");
return;
}
- foreach_iter(exec_list_iterator, it, list->subexpressions) {
- s_list *sub = SX_AS_LIST(it.get());
- if (sub == NULL)
+ foreach_in_list(s_list, sub, &list->subexpressions) {
+ if (!sub->is_list())
continue; // not a (function ...); ignore it.
s_symbol *tag = SX_AS_SYMBOL(sub->subexpressions.get_head());
assert(added);
}
- exec_list_iterator it = ((s_list *) expr)->subexpressions.iterator();
- it.next(); // skip "function" tag
- it.next(); // skip function name
- for (/* nothing */; it.has_next(); it.next()) {
- s_expression *s_sig = (s_expression *) it.get();
+ /* Skip over "function" tag and function name (which are guaranteed to be
+ * present by the above PARTIAL_MATCH call).
+ */
+ exec_node *node = ((s_list *) expr)->subexpressions.head->next->next;
+ for (/* nothing */; !node->is_tail_sentinel(); node = node->next) {
+ s_expression *s_sig = (s_expression *) node;
read_function_sig(f, s_sig, skip_body);
}
return added ? f : NULL;
}
+static bool
+always_available(const _mesa_glsl_parse_state *)
+{
+ return true;
+}
+
void
ir_reader::read_function_sig(ir_function *f, s_expression *expr, bool skip_body)
{
exec_list hir_parameters;
state->symbols->push_scope();
- exec_list_iterator it = paramlist->subexpressions.iterator();
- for (it.next() /* skip "parameters" */; it.has_next(); it.next()) {
- ir_variable *var = read_declaration((s_expression *) it.get());
+ /* Skip over the "parameters" tag. */
+ exec_node *node = paramlist->subexpressions.head->next;
+ for (/* nothing */; !node->is_tail_sentinel(); node = node->next) {
+ ir_variable *var = read_declaration((s_expression *) node);
if (var == NULL)
return;
hir_parameters.push_tail(var);
}
- ir_function_signature *sig = f->exact_matching_signature(&hir_parameters);
+ ir_function_signature *sig =
+ f->exact_matching_signature(state, &hir_parameters);
if (sig == NULL && skip_body) {
/* If scanning for prototypes, generate a new signature. */
- sig = new(mem_ctx) ir_function_signature(return_type);
- sig->is_builtin = true;
+ /* ir_reader doesn't know what languages support a given built-in, so
+ * just say that they're always available. For now, other mechanisms
+ * guarantee the right built-ins are available.
+ */
+ sig = new(mem_ctx) ir_function_signature(return_type, always_available);
f->add_signature(sig);
} else if (sig != NULL) {
const char *badvar = sig->qualifiers_match(&hir_parameters);
return;
}
- foreach_iter(exec_list_iterator, it, list->subexpressions) {
- s_expression *sub = (s_expression*) it.get();
+ foreach_in_list(s_expression, sub, &list->subexpressions) {
ir_instruction *ir = read_instruction(sub, loop_ctx);
if (ir != NULL) {
/* Global variable declarations should be moved to the top, before
inst = read_if(list, loop_ctx);
} else if (strcmp(tag->value(), "loop") == 0) {
inst = read_loop(list);
+ } else if (strcmp(tag->value(), "call") == 0) {
+ inst = read_call(list);
} else if (strcmp(tag->value(), "return") == 0) {
inst = read_return(list);
} else if (strcmp(tag->value(), "function") == 0) {
inst = read_function(list, false);
+ } else if (strcmp(tag->value(), "emit-vertex") == 0) {
+ inst = read_emit_vertex(list);
+ } else if (strcmp(tag->value(), "end-primitive") == 0) {
+ inst = read_end_primitive(list);
+ } else if (strcmp(tag->value(), "barrier") == 0) {
+ inst = read_barrier(list);
} else {
inst = read_rvalue(list);
if (inst == NULL)
ir_variable *var = new(mem_ctx) ir_variable(type, s_name->value(),
ir_var_auto);
- foreach_iter(exec_list_iterator, it, s_quals->subexpressions) {
- s_symbol *qualifier = SX_AS_SYMBOL(it.get());
- if (qualifier == NULL) {
+ foreach_in_list(s_symbol, qualifier, &s_quals->subexpressions) {
+ if (!qualifier->is_symbol()) {
ir_read_error(expr, "qualifier list must contain only symbols");
return NULL;
}
// FINISHME: Check for duplicate/conflicting qualifiers.
if (strcmp(qualifier->value(), "centroid") == 0) {
- var->centroid = 1;
+ var->data.centroid = 1;
+ } else if (strcmp(qualifier->value(), "sample") == 0) {
+ var->data.sample = 1;
+ } else if (strcmp(qualifier->value(), "patch") == 0) {
+ var->data.patch = 1;
} else if (strcmp(qualifier->value(), "invariant") == 0) {
- var->invariant = 1;
+ var->data.invariant = 1;
} else if (strcmp(qualifier->value(), "uniform") == 0) {
- var->mode = ir_var_uniform;
+ var->data.mode = ir_var_uniform;
+ } else if (strcmp(qualifier->value(), "shader_storage") == 0) {
+ var->data.mode = ir_var_shader_storage;
} else if (strcmp(qualifier->value(), "auto") == 0) {
- var->mode = ir_var_auto;
+ var->data.mode = ir_var_auto;
} else if (strcmp(qualifier->value(), "in") == 0) {
- var->mode = ir_var_in;
+ var->data.mode = ir_var_function_in;
+ } else if (strcmp(qualifier->value(), "shader_in") == 0) {
+ var->data.mode = ir_var_shader_in;
+ } else if (strcmp(qualifier->value(), "const_in") == 0) {
+ var->data.mode = ir_var_const_in;
} else if (strcmp(qualifier->value(), "out") == 0) {
- var->mode = ir_var_out;
+ var->data.mode = ir_var_function_out;
+ } else if (strcmp(qualifier->value(), "shader_out") == 0) {
+ var->data.mode = ir_var_shader_out;
} else if (strcmp(qualifier->value(), "inout") == 0) {
- var->mode = ir_var_inout;
+ var->data.mode = ir_var_function_inout;
+ } else if (strcmp(qualifier->value(), "temporary") == 0) {
+ var->data.mode = ir_var_temporary;
+ } else if (strcmp(qualifier->value(), "stream1") == 0) {
+ var->data.stream = 1;
+ } else if (strcmp(qualifier->value(), "stream2") == 0) {
+ var->data.stream = 2;
+ } else if (strcmp(qualifier->value(), "stream3") == 0) {
+ var->data.stream = 3;
} else if (strcmp(qualifier->value(), "smooth") == 0) {
- var->interpolation = ir_var_smooth;
+ var->data.interpolation = INTERP_QUALIFIER_SMOOTH;
} else if (strcmp(qualifier->value(), "flat") == 0) {
- var->interpolation = ir_var_flat;
+ var->data.interpolation = INTERP_QUALIFIER_FLAT;
} else if (strcmp(qualifier->value(), "noperspective") == 0) {
- var->interpolation = ir_var_noperspective;
+ var->data.interpolation = INTERP_QUALIFIER_NOPERSPECTIVE;
} else {
ir_read_error(expr, "unknown qualifier: %s", qualifier->value());
return NULL;
ir_loop *
ir_reader::read_loop(s_expression *expr)
{
- s_expression *s_counter, *s_from, *s_to, *s_inc, *s_body;
+ s_expression *s_body;
- s_pattern pat[] = { "loop", s_counter, s_from, s_to, s_inc, s_body };
- if (!MATCH(expr, pat)) {
- ir_read_error(expr, "expected (loop <counter> <from> <to> "
- "<increment> <body>)");
+ s_pattern loop_pat[] = { "loop", s_body };
+ if (!MATCH(expr, loop_pat)) {
+ ir_read_error(expr, "expected (loop <body>)");
return NULL;
}
- // FINISHME: actually read the count/from/to fields.
-
ir_loop *loop = new(mem_ctx) ir_loop;
+
read_instructions(&loop->body_instructions, s_body, loop);
if (state->error) {
delete loop;
{
s_expression *s_retval;
- s_pattern pat[] = { "return", s_retval};
- if (!MATCH(expr, pat)) {
- ir_read_error(expr, "expected (return <rvalue>)");
- return NULL;
- }
-
- ir_rvalue *retval = read_rvalue(s_retval);
- if (retval == NULL) {
- ir_read_error(NULL, "when reading return value");
+ s_pattern return_value_pat[] = { "return", s_retval};
+ s_pattern return_void_pat[] = { "return" };
+ if (MATCH(expr, return_value_pat)) {
+ ir_rvalue *retval = read_rvalue(s_retval);
+ if (retval == NULL) {
+ ir_read_error(NULL, "when reading return value");
+ return NULL;
+ }
+ return new(mem_ctx) ir_return(retval);
+ } else if (MATCH(expr, return_void_pat)) {
+ return new(mem_ctx) ir_return;
+ } else {
+ ir_read_error(expr, "expected (return <rvalue>) or (return)");
return NULL;
}
-
- return new(mem_ctx) ir_return(retval);
}
rvalue = read_swizzle(list);
} else if (strcmp(tag->value(), "expression") == 0) {
rvalue = read_expression(list);
- } else if (strcmp(tag->value(), "call") == 0) {
- rvalue = read_call(list);
} else if (strcmp(tag->value(), "constant") == 0) {
rvalue = read_constant(list);
} else {
{
s_symbol *name;
s_list *params;
+ s_list *s_return = NULL;
- s_pattern pat[] = { "call", name, params };
- if (!MATCH(expr, pat)) {
- ir_read_error(expr, "expected (call <name> (<param> ...))");
+ ir_dereference_variable *return_deref = NULL;
+
+ s_pattern void_pat[] = { "call", name, params };
+ s_pattern non_void_pat[] = { "call", name, s_return, params };
+ if (MATCH(expr, non_void_pat)) {
+ return_deref = read_var_ref(s_return);
+ if (return_deref == NULL) {
+ ir_read_error(s_return, "when reading a call's return storage");
+ return NULL;
+ }
+ } else if (!MATCH(expr, void_pat)) {
+ ir_read_error(expr, "expected (call <name> [<deref>] (<param> ...))");
return NULL;
}
exec_list parameters;
- foreach_iter(exec_list_iterator, it, params->subexpressions) {
- s_expression *expr = (s_expression*) it.get();
- ir_rvalue *param = read_rvalue(expr);
+ foreach_in_list(s_expression, e, ¶ms->subexpressions) {
+ ir_rvalue *param = read_rvalue(e);
if (param == NULL) {
- ir_read_error(expr, "when reading parameter to function call");
+ ir_read_error(e, "when reading parameter to function call");
return NULL;
}
parameters.push_tail(param);
return NULL;
}
- ir_function_signature *callee = f->matching_signature(¶meters);
+ ir_function_signature *callee =
+ f->matching_signature(state, ¶meters, true);
if (callee == NULL) {
ir_read_error(expr, "couldn't find matching signature for function "
"%s", name->value());
return NULL;
}
- return new(mem_ctx) ir_call(callee, ¶meters);
+ if (callee->return_type == glsl_type::void_type && return_deref) {
+ ir_read_error(expr, "call has return value storage but void type");
+ return NULL;
+ } else if (callee->return_type != glsl_type::void_type && !return_deref) {
+ ir_read_error(expr, "call has non-void type but no return value storage");
+ return NULL;
+ }
+
+ return new(mem_ctx) ir_call(callee, return_deref, ¶meters);
}
ir_expression *
{
s_expression *s_type;
s_symbol *s_op;
- s_expression *s_arg1;
+ s_expression *s_arg[4] = {NULL};
- s_pattern pat[] = { "expression", s_type, s_op, s_arg1 };
+ s_pattern pat[] = { "expression", s_type, s_op, s_arg[0] };
if (!PARTIAL_MATCH(expr, pat)) {
ir_read_error(expr, "expected (expression <type> <operator> "
- "<operand> [<operand>])");
+ "<operand> [<operand>] [<operand>] [<operand>])");
return NULL;
}
- s_expression *s_arg2 = (s_expression *) s_arg1->next; // may be tail sentinel
+ s_arg[1] = (s_expression *) s_arg[0]->next; // may be tail sentinel
+ s_arg[2] = (s_expression *) s_arg[1]->next; // may be tail sentinel or NULL
+ if (s_arg[2])
+ s_arg[3] = (s_expression *) s_arg[2]->next; // may be tail sentinel or NULL
const glsl_type *type = read_type(s_type);
if (type == NULL)
ir_read_error(expr, "invalid operator: %s", s_op->value());
return NULL;
}
-
- unsigned num_operands = ir_expression::get_num_operands(op);
- if (num_operands == 1 && !s_arg1->next->is_tail_sentinel()) {
- ir_read_error(expr, "expected (expression <type> %s <operand>)",
- s_op->value());
- return NULL;
- }
- ir_rvalue *arg1 = read_rvalue(s_arg1);
- ir_rvalue *arg2 = NULL;
- if (arg1 == NULL) {
- ir_read_error(NULL, "when reading first operand of %s", s_op->value());
+ /* Skip "expression" <type> <operation> by subtracting 3. */
+ int num_operands = (int) ((s_list *) expr)->subexpressions.length() - 3;
+
+ int expected_operands = ir_expression::get_num_operands(op);
+ if (num_operands != expected_operands) {
+ ir_read_error(expr, "found %d expression operands, expected %d",
+ num_operands, expected_operands);
return NULL;
}
- if (num_operands == 2) {
- if (s_arg2->is_tail_sentinel() || !s_arg2->next->is_tail_sentinel()) {
- ir_read_error(expr, "expected (expression <type> %s <operand> "
- "<operand>)", s_op->value());
- return NULL;
- }
- arg2 = read_rvalue(s_arg2);
- if (arg2 == NULL) {
- ir_read_error(NULL, "when reading second operand of %s",
- s_op->value());
- return NULL;
+ ir_rvalue *arg[4] = {NULL};
+ for (int i = 0; i < num_operands; i++) {
+ arg[i] = read_rvalue(s_arg[i]);
+ if (arg[i] == NULL) {
+ ir_read_error(NULL, "when reading operand #%d of %s", i, s_op->value());
+ return NULL;
}
}
- return new(mem_ctx) ir_expression(op, type, arg1, arg2);
+ return new(mem_ctx) ir_expression(op, type, arg[0], arg[1], arg[2], arg[3]);
}
ir_swizzle *
if (type->is_array()) {
unsigned elements_supplied = 0;
exec_list elements;
- foreach_iter(exec_list_iterator, it, values->subexpressions) {
- s_expression *elt = (s_expression *) it.get();
+ foreach_in_list(s_expression, elt, &values->subexpressions) {
ir_constant *ir_elt = read_constant(elt);
if (ir_elt == NULL)
return NULL;
return new(mem_ctx) ir_constant(type, &elements);
}
- const glsl_type *const base_type = type->get_base_type();
-
ir_constant_data data = { { 0 } };
// Read in list of values (at most 16).
- int k = 0;
- foreach_iter(exec_list_iterator, it, values->subexpressions) {
+ unsigned k = 0;
+ foreach_in_list(s_expression, expr, &values->subexpressions) {
if (k >= 16) {
ir_read_error(values, "expected at most 16 numbers");
return NULL;
}
- s_expression *expr = (s_expression*) it.get();
-
- if (base_type->base_type == GLSL_TYPE_FLOAT) {
+ if (type->base_type == GLSL_TYPE_FLOAT) {
s_number *value = SX_AS_NUMBER(expr);
if (value == NULL) {
ir_read_error(values, "expected numbers");
return NULL;
}
- switch (base_type->base_type) {
+ switch (type->base_type) {
case GLSL_TYPE_UINT: {
data.u[k] = value->value();
break;
}
++k;
}
+ if (k != type->components()) {
+ ir_read_error(values, "expected %u constant values, found %u",
+ type->components(), k);
+ return NULL;
+ }
return new(mem_ctx) ir_constant(type, &data);
}
-ir_dereference *
-ir_reader::read_dereference(s_expression *expr)
+ir_dereference_variable *
+ir_reader::read_var_ref(s_expression *expr)
{
s_symbol *s_var;
- s_expression *s_subject;
- s_expression *s_index;
- s_symbol *s_field;
-
s_pattern var_pat[] = { "var_ref", s_var };
- s_pattern array_pat[] = { "array_ref", s_subject, s_index };
- s_pattern record_pat[] = { "record_ref", s_subject, s_field };
if (MATCH(expr, var_pat)) {
ir_variable *var = state->symbols->get_variable(s_var->value());
return NULL;
}
return new(mem_ctx) ir_dereference_variable(var);
+ }
+ return NULL;
+}
+
+ir_dereference *
+ir_reader::read_dereference(s_expression *expr)
+{
+ s_expression *s_subject;
+ s_expression *s_index;
+ s_symbol *s_field;
+
+ s_pattern array_pat[] = { "array_ref", s_subject, s_index };
+ s_pattern record_pat[] = { "record_ref", s_subject, s_field };
+
+ ir_dereference_variable *var_ref = read_var_ref(expr);
+ if (var_ref != NULL) {
+ return var_ref;
} else if (MATCH(expr, array_pat)) {
ir_rvalue *subject = read_rvalue(s_subject);
if (subject == NULL) {
}
ir_rvalue *idx = read_rvalue(s_index);
- if (subject == NULL) {
+ if (idx == NULL) {
ir_read_error(NULL, "when reading the index of an array_ref");
return NULL;
}
ir_reader::read_texture(s_expression *expr)
{
s_symbol *tag = NULL;
+ s_expression *s_type = NULL;
s_expression *s_sampler = NULL;
s_expression *s_coord = NULL;
- s_list *s_offset = NULL;
+ s_expression *s_offset = NULL;
s_expression *s_proj = NULL;
s_list *s_shadow = NULL;
s_expression *s_lod = NULL;
+ s_expression *s_sample_index = NULL;
+ s_expression *s_component = NULL;
ir_texture_opcode op = ir_tex; /* silence warning */
s_pattern tex_pattern[] =
- { "tex", s_sampler, s_coord, s_offset, s_proj, s_shadow };
+ { "tex", s_type, s_sampler, s_coord, s_offset, s_proj, s_shadow };
+ s_pattern lod_pattern[] =
+ { "lod", s_type, s_sampler, s_coord };
s_pattern txf_pattern[] =
- { "txf", s_sampler, s_coord, s_offset, s_lod };
+ { "txf", s_type, s_sampler, s_coord, s_offset, s_lod };
+ s_pattern txf_ms_pattern[] =
+ { "txf_ms", s_type, s_sampler, s_coord, s_sample_index };
+ s_pattern txs_pattern[] =
+ { "txs", s_type, s_sampler, s_lod };
+ s_pattern tg4_pattern[] =
+ { "tg4", s_type, s_sampler, s_coord, s_offset, s_component };
+ s_pattern query_levels_pattern[] =
+ { "query_levels", s_type, s_sampler };
+ s_pattern texture_samples_pattern[] =
+ { "samples", s_type, s_sampler };
s_pattern other_pattern[] =
- { tag, s_sampler, s_coord, s_offset, s_proj, s_shadow, s_lod };
+ { tag, s_type, s_sampler, s_coord, s_offset, s_proj, s_shadow, s_lod };
- if (MATCH(expr, tex_pattern)) {
+ if (MATCH(expr, lod_pattern)) {
+ op = ir_lod;
+ } else if (MATCH(expr, tex_pattern)) {
op = ir_tex;
} else if (MATCH(expr, txf_pattern)) {
op = ir_txf;
+ } else if (MATCH(expr, txf_ms_pattern)) {
+ op = ir_txf_ms;
+ } else if (MATCH(expr, txs_pattern)) {
+ op = ir_txs;
+ } else if (MATCH(expr, tg4_pattern)) {
+ op = ir_tg4;
+ } else if (MATCH(expr, query_levels_pattern)) {
+ op = ir_query_levels;
+ } else if (MATCH(expr, texture_samples_pattern)) {
+ op = ir_texture_samples;
} else if (MATCH(expr, other_pattern)) {
op = ir_texture::get_opcode(tag->value());
- if (op == -1)
+ if (op == (ir_texture_opcode) -1)
return NULL;
} else {
- ir_read_error(NULL, "unexpected texture pattern");
+ ir_read_error(NULL, "unexpected texture pattern %s", tag->value());
return NULL;
}
ir_texture *tex = new(mem_ctx) ir_texture(op);
+ // Read return type
+ const glsl_type *type = read_type(s_type);
+ if (type == NULL) {
+ ir_read_error(NULL, "when reading type in (%s ...)",
+ tex->opcode_string());
+ return NULL;
+ }
+
// Read sampler (must be a deref)
ir_dereference *sampler = read_dereference(s_sampler);
if (sampler == NULL) {
tex->opcode_string());
return NULL;
}
- tex->set_sampler(sampler);
+ tex->set_sampler(sampler, type);
- // Read coordinate (any rvalue)
- tex->coordinate = read_rvalue(s_coord);
- if (tex->coordinate == NULL) {
- ir_read_error(NULL, "when reading coordinate in (%s ...)",
- tex->opcode_string());
- return NULL;
- }
+ if (op != ir_txs) {
+ // Read coordinate (any rvalue)
+ tex->coordinate = read_rvalue(s_coord);
+ if (tex->coordinate == NULL) {
+ ir_read_error(NULL, "when reading coordinate in (%s ...)",
+ tex->opcode_string());
+ return NULL;
+ }
- // Read texel offset, i.e. (0 0 0)
- s_int *offset_x;
- s_int *offset_y;
- s_int *offset_z;
- s_pattern offset_pat[] = { offset_x, offset_y, offset_z };
- if (!MATCH(s_offset, offset_pat)) {
- ir_read_error(s_offset, "expected (<int> <int> <int>)");
- return NULL;
+ if (op != ir_txf_ms && op != ir_lod) {
+ // Read texel offset - either 0 or an rvalue.
+ s_int *si_offset = SX_AS_INT(s_offset);
+ if (si_offset == NULL || si_offset->value() != 0) {
+ tex->offset = read_rvalue(s_offset);
+ if (tex->offset == NULL) {
+ ir_read_error(s_offset, "expected 0 or an expression");
+ return NULL;
+ }
+ }
+ }
}
- tex->offsets[0] = offset_x->value();
- tex->offsets[1] = offset_y->value();
- tex->offsets[2] = offset_z->value();
- if (op != ir_txf) {
+ if (op != ir_txf && op != ir_txf_ms &&
+ op != ir_txs && op != ir_lod && op != ir_tg4 &&
+ op != ir_query_levels && op != ir_texture_samples) {
s_int *proj_as_int = SX_AS_INT(s_proj);
if (proj_as_int && proj_as_int->value() == 1) {
tex->projector = NULL;
break;
case ir_txl:
case ir_txf:
+ case ir_txs:
tex->lod_info.lod = read_rvalue(s_lod);
if (tex->lod_info.lod == NULL) {
ir_read_error(NULL, "when reading LOD in (%s ...)",
return NULL;
}
break;
+ case ir_txf_ms:
+ tex->lod_info.sample_index = read_rvalue(s_sample_index);
+ if (tex->lod_info.sample_index == NULL) {
+ ir_read_error(NULL, "when reading sample_index in (txf_ms ...)");
+ return NULL;
+ }
+ break;
case ir_txd: {
s_expression *s_dx, *s_dy;
s_pattern dxdy_pat[] = { s_dx, s_dy };
}
break;
}
+ case ir_tg4:
+ tex->lod_info.component = read_rvalue(s_component);
+ if (tex->lod_info.component == NULL) {
+ ir_read_error(NULL, "when reading component in (tg4 ...)");
+ return NULL;
+ }
+ break;
default:
- // tex doesn't have any extra parameters.
+ // tex and lod don't have any extra parameters.
break;
};
return tex;
}
+
+ir_emit_vertex *
+ir_reader::read_emit_vertex(s_expression *expr)
+{
+ s_expression *s_stream = NULL;
+
+ s_pattern pat[] = { "emit-vertex", s_stream };
+
+ if (MATCH(expr, pat)) {
+ ir_rvalue *stream = read_dereference(s_stream);
+ if (stream == NULL) {
+ ir_read_error(NULL, "when reading stream info in emit-vertex");
+ return NULL;
+ }
+ return new(mem_ctx) ir_emit_vertex(stream);
+ }
+ ir_read_error(NULL, "when reading emit-vertex");
+ return NULL;
+}
+
+ir_end_primitive *
+ir_reader::read_end_primitive(s_expression *expr)
+{
+ s_expression *s_stream = NULL;
+
+ s_pattern pat[] = { "end-primitive", s_stream };
+
+ if (MATCH(expr, pat)) {
+ ir_rvalue *stream = read_dereference(s_stream);
+ if (stream == NULL) {
+ ir_read_error(NULL, "when reading stream info in end-primitive");
+ return NULL;
+ }
+ return new(mem_ctx) ir_end_primitive(stream);
+ }
+ ir_read_error(NULL, "when reading end-primitive");
+ return NULL;
+}
+
+ir_barrier *
+ir_reader::read_barrier(s_expression *expr)
+{
+ s_pattern pat[] = { "barrier" };
+
+ if (MATCH(expr, pat)) {
+ return new(mem_ctx) ir_barrier();
+ }
+ ir_read_error(NULL, "when reading barrier");
+ return NULL;
+}