#define BCP_DUMP(q)
#endif
-extern "C" {
#include "r600_pipe.h"
#include "r600_shader.h"
-}
#include <stack>
if ((r = decode_cf(i, eop)))
return r;
- } while (!eop || (i >> 1) <= max_cf);
+ } while (!eop || (i >> 1) < max_cf);
return 0;
}
}
}
+ // GS inputs can add indirect addressing
+ if (sh->target == TARGET_GS) {
+ if (pshader->num_arrays) {
+ for (unsigned i = 0; i < pshader->num_arrays; ++i) {
+ r600_shader_array &a = pshader->arrays[i];
+ sh->add_gpr_array(a.gpr_start, a.gpr_count, a.comp_mask);
+ }
+ }
+ }
+
if (sh->target == TARGET_VS || sh->target == TARGET_ES)
sh->add_input(0, 1, 0x0F);
else if (sh->target == TARGET_GS) {
c->flags |= NF_DONT_HOIST | NF_DONT_MOVE;
}
+ if (flags & CF_EMIT) {
+ // Instruction implicitly depends on prior [EMIT_][CUT]_VERTEX
+ c->src.push_back(sh->get_special_value(SV_GEOMETRY_EMIT));
+ c->dst.push_back(sh->get_special_value(SV_GEOMETRY_EMIT));
+ if (sh->target == TARGET_ES) {
+ // For ES shaders this is an export
+ c->flags |= NF_DONT_KILL;
+ }
+ }
+
if (!burst_count--)
break;
c->bc.end_of_program = eop;
+ } else if (flags & CF_EMIT) {
+ /* quick peephole */
+ cf_node *prev = static_cast<cf_node *>(c->prev);
+ if (c->bc.op == CF_OP_CUT_VERTEX &&
+ prev && prev->is_valid() &&
+ prev->bc.op == CF_OP_EMIT_VERTEX &&
+ c->bc.count == prev->bc.count) {
+ prev->bc.set_op(CF_OP_EMIT_CUT_VERTEX);
+ prev->bc.end_of_program = c->bc.end_of_program;
+ c->remove();
+ }
+ else {
+ c->flags |= NF_DONT_KILL | NF_DONT_HOIST | NF_DONT_MOVE;
+
+ c->src.push_back(sh->get_special_value(SV_GEOMETRY_EMIT));
+ c->dst.push_back(sh->get_special_value(SV_GEOMETRY_EMIT));
+ }
}
}
}
int bc_parser::prepare_loop(cf_node* c) {
+ assert(c->bc.addr-1 < cf_map.size());
cf_node *end = cf_map[c->bc.addr - 1];
assert(end->bc.op == CF_OP_LOOP_END);
}
int bc_parser::prepare_if(cf_node* c) {
+ assert(c->bc.addr-1 < cf_map.size());
cf_node *c_else = NULL, *end = cf_map[c->bc.addr];
+ if (!end)
+ return 0; // not quite sure how this happens, malformed input?
+
BCP_DUMP(
sblog << "parsing JUMP @" << c->bc.id;
sblog << "\n";
if (c_else->parent != c->parent)
c_else = NULL;
- if (end->parent != c->parent)
+ if (end && end->parent != c->parent)
end = NULL;
region_node *reg = sh->create_region();