return true;
}
- ppir_node *move = NULL;
+ assert(ppir_node_has_single_succ(node));
+
+ ppir_node *succ = ppir_node_first_succ(node);
+ ppir_src *src = ppir_node_get_src_for_pred(succ, node);
ppir_dest *dest = ppir_node_get_dest(node);
+ assert(src != NULL);
+
+ switch (succ->type) {
+ case ppir_node_type_alu:
+ case ppir_node_type_branch:
+ /* ALU and branch can consume consts directly */
+ dest->type = src->type = ppir_target_pipeline;
+ /* Reg will be updated in node_to_instr later */
+ dest->pipeline = src->pipeline = ppir_pipeline_reg_const0;
+ return true;
+ default:
+ /* Create a move for everyone else */
+ break;
+ }
- /* const (register) can only be used in alu node, create a move
- * node for other types of node */
- ppir_node_foreach_succ_safe(node, dep) {
- ppir_node *succ = dep->succ;
-
- if (succ->type != ppir_node_type_alu) {
- if (!move) {
- move = ppir_node_create(block, ppir_op_mov, -1, 0);
- if (unlikely(!move))
- return false;
-
- ppir_debug("lower const create move %d for %d\n",
- move->index, node->index);
-
- ppir_alu_node *alu = ppir_node_to_alu(move);
- alu->dest = *dest;
- alu->num_src = 1;
- ppir_node_target_assign(alu->src, dest);
- for (int i = 0; i < 4; i++)
- alu->src->swizzle[i] = i;
- }
+ ppir_node *move = ppir_node_insert_mov(node);
+ if (unlikely(!move))
+ return false;
- ppir_node_replace_pred(dep, move);
- ppir_node_replace_child(succ, node, move);
- }
- }
+ ppir_debug("lower const create move %d for %d\n",
+ move->index, node->index);
- if (move) {
- ppir_node_add_dep(move, node);
- list_addtail(&move->list, &node->list);
- }
+ /* Need to be careful with changing src/dst type here:
+ * it has to be done *after* successors have their children
+ * replaced, otherwise ppir_node_replace_child() won't find
+ * matching src/dst and as result won't work
+ */
+ ppir_src *mov_src = ppir_node_get_src(move, 0);
+ mov_src->type = dest->type = ppir_target_pipeline;
+ mov_src->pipeline = dest->pipeline = ppir_pipeline_reg_const0;
return true;
}
-static ppir_reg *create_reg(ppir_compiler *comp, int num_components)
+static bool ppir_lower_swap_args(ppir_block *block, ppir_node *node)
{
- ppir_reg *r = rzalloc(comp, ppir_reg);
- if (!r)
- return NULL;
+ /* swapped op must be the next op */
+ node->op++;
- r->num_components = num_components;
- r->live_in = INT_MAX;
- r->live_out = 0;
- r->is_head = false;
- list_addtail(&r->list, &comp->reg_list);
+ assert(node->type == ppir_node_type_alu);
+ ppir_alu_node *alu = ppir_node_to_alu(node);
+ assert(alu->num_src == 2);
- return r;
+ ppir_src tmp = alu->src[0];
+ alu->src[0] = alu->src[1];
+ alu->src[1] = tmp;
+ return true;
}
-/* lower vector alu node to multi scalar nodes */
-static bool ppir_lower_vec_to_scalar(ppir_block *block, ppir_node *node)
+static bool ppir_lower_load(ppir_block *block, ppir_node *node)
{
- ppir_alu_node *alu = ppir_node_to_alu(node);
- ppir_dest *dest = &alu->dest;
-
- int n = 0;
- int index[4];
-
- unsigned mask = dest->write_mask;
- while (mask)
- index[n++] = u_bit_scan(&mask);
-
- if (n == 1)
+ ppir_dest *dest = ppir_node_get_dest(node);
+ if (ppir_node_is_root(node) && dest->type == ppir_target_ssa) {
+ ppir_node_delete(node);
return true;
-
- ppir_reg *r;
- /* we need a reg for scalar nodes to store output */
- if (dest->type == ppir_target_register)
- r = dest->reg;
- else {
- r = create_reg(block->comp, n);
- if (!r)
- return false;
-
- /* change all successors to use reg r */
- ppir_node_foreach_succ(node, dep) {
- ppir_node *succ = dep->succ;
- if (succ->type == ppir_node_type_alu) {
- ppir_alu_node *sa = ppir_node_to_alu(succ);
- for (int i = 0; i < sa->num_src; i++) {
- ppir_src *src = sa->src + i;
- if (ppir_node_target_equal(src, dest)) {
- src->type = ppir_target_register;
- src->reg = r;
- }
- }
- }
- else {
- assert(succ->type == ppir_node_type_store);
- ppir_store_node *ss = ppir_node_to_store(succ);
- ppir_src *src = &ss->src;
- src->type = ppir_target_register;
- src->reg = r;
- }
- }
}
- /* create each component's scalar node */
- for (int i = 0; i < n; i++) {
- ppir_node *s = ppir_node_create(block, node->op, -1, 0);
- if (!s)
- return false;
- list_addtail(&s->list, &node->list);
-
- ppir_alu_node *sa = ppir_node_to_alu(s);
- ppir_dest *sd = &sa->dest;
- sd->type = ppir_target_register;
- sd->reg = r;
- sd->modifier = dest->modifier;
- sd->write_mask = 1 << index[i];
-
- for (int j = 0; j < alu->num_src; j++)
- sa->src[j] = alu->src[j];
- sa->num_src = alu->num_src;
-
- /* TODO: need per reg component dependancy */
- ppir_node_foreach_succ(node, dep) {
- ppir_node_add_dep(dep->succ, s);
+ /* load can have multiple successors in case if we duplicated load node
+ * that has load node in source
+ */
+ if ((ppir_node_has_single_src_succ(node) || ppir_node_is_root(node)) &&
+ dest->type != ppir_target_register) {
+ ppir_node *succ = ppir_node_first_succ(node);
+ switch (succ->type) {
+ case ppir_node_type_alu:
+ case ppir_node_type_branch: {
+ ppir_src *src = ppir_node_get_src_for_pred(succ, node);
+ /* Can consume uniforms directly */
+ src->type = dest->type = ppir_target_pipeline;
+ src->pipeline = dest->pipeline = ppir_pipeline_reg_uniform;
+ return true;
}
-
- ppir_node_foreach_pred(node, dep) {
- ppir_node_add_dep(s, dep->pred);
+ default:
+ /* Create mov for everyone else */
+ break;
}
}
- ppir_node_delete(node);
+ ppir_node *move = ppir_node_insert_mov(node);
+ if (unlikely(!move))
+ return false;
+
+ ppir_src *mov_src = ppir_node_get_src(move, 0);
+ mov_src->type = dest->type = ppir_target_pipeline;
+ mov_src->pipeline = dest->pipeline = ppir_pipeline_reg_uniform;
+
return true;
}
-static bool ppir_lower_swap_args(ppir_block *block, ppir_node *node)
+static bool ppir_lower_ddxy(ppir_block *block, ppir_node *node)
{
- /* swapped op must be the next op */
- node->op++;
-
assert(node->type == ppir_node_type_alu);
ppir_alu_node *alu = ppir_node_to_alu(node);
- assert(alu->num_src == 2);
- ppir_src tmp = alu->src[0];
- alu->src[0] = alu->src[1];
- alu->src[1] = tmp;
+ alu->src[1] = alu->src[0];
+ if (node->op == ppir_op_ddx)
+ alu->src[1].negate = !alu->src[1].negate;
+ else if (node->op == ppir_op_ddy)
+ alu->src[0].negate = !alu->src[0].negate;
+ else
+ assert(0);
+
+ alu->num_src = 2;
+
return true;
}
static bool ppir_lower_texture(ppir_block *block, ppir_node *node)
{
ppir_load_texture_node *load_tex = ppir_node_to_load_texture(node);
+ ppir_dest *dest = ppir_node_get_dest(node);
- /* Create load_coords node */
- ppir_load_node *load = ppir_node_create(block, ppir_op_load_coords, -1, 0);
- if (!load)
- return false;
- list_addtail(&load->node.list, &node->list);
-
- ppir_debug("%s create load_coords node %d for %d\n",
- __FUNCTION__, load->node.index, node->index);
-
- load->dest.type = ppir_target_pipeline;
- load->dest.pipeline = ppir_pipeline_reg_discard;
+ if (ppir_node_is_root(node) && dest->type == ppir_target_ssa) {
+ ppir_node_delete(node);
+ return true;
+ }
- load->src = load_tex->src_coords;
+ ppir_node *src_coords = ppir_node_get_src(node, 0)->node;
+ ppir_load_node *load = NULL;
+ if (src_coords && ppir_node_has_single_src_succ(src_coords) &&
+ (src_coords->op == ppir_op_load_coords))
+ load = ppir_node_to_load(src_coords);
+ else {
+ /* Create load_coords node */
+ load = ppir_node_create(block, ppir_op_load_coords_reg, -1, 0);
+ if (!load)
+ return false;
+ list_addtail(&load->node.list, &node->list);
+
+ load->src = load_tex->src[0];
+ load->num_src = 1;
+ if (load_tex->sampler_dim == GLSL_SAMPLER_DIM_CUBE)
+ load->num_components = 3;
+ else
+ load->num_components = 2;
+
+ ppir_debug("%s create load_coords node %d for %d\n",
+ __FUNCTION__, load->node.index, node->index);
+
+ ppir_node_foreach_pred_safe(node, dep) {
+ ppir_node *pred = dep->pred;
+ ppir_node_remove_dep(dep);
+ ppir_node_add_dep(&load->node, pred, ppir_dep_src);
+ }
+ ppir_node_add_dep(node, &load->node, ppir_dep_src);
+ }
- ppir_node_foreach_pred_safe(node, dep) {
- ppir_node *pred = dep->pred;
- ppir_node_remove_dep(dep);
- ppir_node_add_dep(&load->node, pred);
+ assert(load);
+ load_tex->src[0].type = load->dest.type = ppir_target_pipeline;
+ load_tex->src[0].pipeline = load->dest.pipeline = ppir_pipeline_reg_discard;
+
+ if (ppir_node_has_single_src_succ(node)) {
+ ppir_node *succ = ppir_node_first_succ(node);
+ switch (succ->type) {
+ case ppir_node_type_alu:
+ case ppir_node_type_branch: {
+ for (int i = 0; i < ppir_node_get_src_num(succ); i++) {
+ ppir_src *src = ppir_node_get_src(succ, i);
+ if (src->node == node) {
+ /* Can consume samplers directly */
+ src->type = dest->type = ppir_target_pipeline;
+ src->pipeline = dest->pipeline = ppir_pipeline_reg_sampler;
+ }
+ }
+ return true;
+ }
+ default:
+ /* Create mov for everyone else */
+ break;
+ }
}
- ppir_node_add_dep(node, &load->node);
- return true;
-}
+ /* Create move node */
+ ppir_node *move = ppir_node_insert_mov(node);
+ if (unlikely(!move))
+ return false;
-/* Prepare for sin and cos and then lower vector alu node to multi
- * scalar nodes */
-static bool ppir_lower_sin_cos_vec_to_scalar(ppir_block *block, ppir_node *node)
-{
- ppir_alu_node *alu = ppir_node_to_alu(node);
+ ppir_debug("lower texture create move %d for %d\n",
+ move->index, node->index);
- ppir_node *inv_2pi_node = ppir_node_create(block, ppir_op_const, -1, 0);
- if (!inv_2pi_node)
- return false;
- list_addtail(&inv_2pi_node->list, &node->list);
-
- /* For sin and cos, the input has to multiplied by the constant
- * 1/(2*pi), presumably to simplify the hardware. */
- ppir_const_node *inv_2pi_const = ppir_node_to_const(inv_2pi_node);
- inv_2pi_const->constant.num = 1;
- inv_2pi_const->constant.value[0].f = (1.0f/(2.0f * M_PI));
-
- inv_2pi_const->dest.type = ppir_target_ssa;
- inv_2pi_const->dest.ssa.num_components = 1;
- inv_2pi_const->dest.ssa.live_in = INT_MAX;
- inv_2pi_const->dest.ssa.live_out = 0;
- inv_2pi_const->dest.write_mask = 0x01;
-
- ppir_node *mul_node = ppir_node_create(block, ppir_op_mul, -1, 0);
- if (!mul_node)
- return false;
- list_addtail(&mul_node->list, &node->list);
-
- ppir_alu_node *mul_alu = ppir_node_to_alu(mul_node);
- mul_alu->num_src = 2;
- mul_alu->src[0] = alu->src[0];
- mul_alu->src[1].type = ppir_target_ssa;
- mul_alu->src[1].ssa = &inv_2pi_const->dest.ssa;
-
- int num_components = alu->src[0].ssa->num_components;
- mul_alu->dest.type = ppir_target_ssa;
- mul_alu->dest.ssa.num_components = num_components;
- mul_alu->dest.ssa.live_in = INT_MAX;
- mul_alu->dest.ssa.live_out = 0;
- mul_alu->dest.write_mask = u_bit_consecutive(0, num_components);
-
- alu->src[0].type = ppir_target_ssa;
- alu->src[0].ssa = &mul_alu->dest.ssa;
- for (int i = 0; i < 4; i++)
- alu->src->swizzle[i] = i;
-
- ppir_node_foreach_pred_safe(node, dep) {
- ppir_node *pred = dep->pred;
- ppir_node_remove_dep(dep);
- ppir_node_add_dep(mul_node, pred);
- }
- ppir_node_add_dep(node, mul_node);
- ppir_node_add_dep(mul_node, inv_2pi_node);
+ ppir_src *mov_src= ppir_node_get_src(move, 0);
+ mov_src->type = dest->type = ppir_target_pipeline;
+ mov_src->pipeline = dest->pipeline = ppir_pipeline_reg_sampler;
- return ppir_lower_vec_to_scalar(block, node);
+ return true;
}
/* insert a move as the select condition to make sure it can
{
ppir_alu_node *alu = ppir_node_to_alu(node);
- ppir_node *move = ppir_node_create(block, ppir_op_mov, -1, 0);
+ ppir_node *move = ppir_node_create(block, ppir_op_sel_cond, -1, 0);
if (!move)
return false;
list_addtail(&move->list, &node->list);
move_alu->num_src = 1;
ppir_dest *move_dest = &move_alu->dest;
- move_dest->type = ppir_target_ssa;
- move_dest->ssa.num_components = 1;
- move_dest->ssa.live_in = INT_MAX;
- move_dest->ssa.live_out = 0;
+ move_dest->type = ppir_target_pipeline;
+ move_dest->pipeline = ppir_pipeline_reg_fmul;
move_dest->write_mask = 1;
- ppir_node_foreach_pred(node, dep) {
- ppir_node *pred = dep->pred;
- ppir_dest *dest = ppir_node_get_dest(pred);
- if (ppir_node_target_equal(alu->src, dest)) {
- ppir_node_replace_pred(dep, move);
- ppir_node_add_dep(move, pred);
- }
- }
+ ppir_node *pred = alu->src[0].node;
+ ppir_dep *dep = ppir_dep_for_pred(node, pred);
+ if (dep)
+ ppir_node_replace_pred(dep, move);
+ else
+ ppir_node_add_dep(node, move, ppir_dep_src);
- /* move must be the first pred of select node which make sure
- * the float mul slot is free when node to instr
- */
- assert(ppir_node_first_pred(node) == move);
+ /* pred can be a register */
+ if (pred)
+ ppir_node_add_dep(move, pred, ppir_dep_src);
src->swizzle[0] = 0;
- ppir_node_target_assign(alu->src, move_dest);
+ ppir_node_target_assign(alu->src, move);
+
return true;
}
static bool ppir_lower_branch(ppir_block *block, ppir_node *node)
{
ppir_branch_node *branch = ppir_node_to_branch(node);
+
+ /* Unconditional branch */
+ if (branch->num_src == 0)
+ return true;
+
ppir_const_node *zero = ppir_node_create(block, ppir_op_const, -1, 0);
if (!zero)
return false;
- list_addtail(&zero->node.list, &node->list);
-
zero->constant.value[0].f = 0;
zero->constant.num = 1;
- zero->dest.type = ppir_target_ssa;
+ zero->dest.type = ppir_target_pipeline;
+ zero->dest.pipeline = ppir_pipeline_reg_const0;
zero->dest.ssa.num_components = 1;
zero->dest.ssa.live_in = INT_MAX;
zero->dest.ssa.live_out = 0;
* comparision node into branch itself and use current
* way as a fallback for complex conditions.
*/
- branch->src[1].type = ppir_target_ssa;
- branch->src[1].ssa = &zero->dest.ssa;
+ ppir_node_target_assign(&branch->src[1], &zero->node);
- branch->cond_gt = true;
- branch->cond_lt = true;
+ if (branch->negate)
+ branch->cond_eq = true;
+ else {
+ branch->cond_gt = true;
+ branch->cond_lt = true;
+ }
- ppir_node_add_dep(&branch->node, &zero->node);
+ branch->num_src = 2;
+
+ ppir_node_add_dep(&branch->node, &zero->node, ppir_dep_src);
+ list_addtail(&zero->node.list, &node->list);
return true;
}
[ppir_op_abs] = ppir_lower_abs,
[ppir_op_neg] = ppir_lower_neg,
[ppir_op_const] = ppir_lower_const,
- [ppir_op_rcp] = ppir_lower_vec_to_scalar,
- [ppir_op_rsqrt] = ppir_lower_vec_to_scalar,
- [ppir_op_log2] = ppir_lower_vec_to_scalar,
- [ppir_op_exp2] = ppir_lower_vec_to_scalar,
- [ppir_op_sqrt] = ppir_lower_vec_to_scalar,
- [ppir_op_sin] = ppir_lower_sin_cos_vec_to_scalar,
- [ppir_op_cos] = ppir_lower_sin_cos_vec_to_scalar,
+ [ppir_op_ddx] = ppir_lower_ddxy,
+ [ppir_op_ddy] = ppir_lower_ddxy,
[ppir_op_lt] = ppir_lower_swap_args,
[ppir_op_le] = ppir_lower_swap_args,
[ppir_op_load_texture] = ppir_lower_texture,
[ppir_op_trunc] = ppir_lower_trunc,
[ppir_op_sat] = ppir_lower_sat,
[ppir_op_branch] = ppir_lower_branch,
+ [ppir_op_load_uniform] = ppir_lower_load,
+ [ppir_op_load_temp] = ppir_lower_load,
};
bool ppir_lower_prog(ppir_compiler *comp)
}
}
- ppir_node_print_prog(comp);
return true;
}