Skip to content

Commit

Permalink
vc4: Add support for emitting IF nodes.
Browse files Browse the repository at this point in the history
XXX: Need to condition updates to non-SSA NIR values on the execute flags.
XXX: Need to update the uniform pointer on block changes
  • Loading branch information
anholt committed Apr 27, 2016
1 parent eb887f1 commit 8c410e6
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 1 deletion.
63 changes: 62 additions & 1 deletion src/gallium/drivers/vc4/vc4_program.c
Expand Up @@ -43,6 +43,8 @@

static struct qreg
ntq_get_src(struct vc4_compile *c, nir_src src, int i);
static void
ntq_emit_cf_list(struct vc4_compile *c, struct exec_list *list);

static void
resize_qreg_array(struct vc4_compile *c,
Expand Down Expand Up @@ -1654,10 +1656,69 @@ ntq_emit_intrinsic(struct vc4_compile *c, nir_intrinsic_instr *instr)
}
}

/* Clears (activates) the execute flags for any channels whose jump target
* matches this block.
*/
static void
ntq_activate_execute_for_block(struct vc4_compile *c, struct qblock *block)
{
qir_SF(c, qir_SUB(c, c->execute, qir_uniform_ui(c, block->index)));
qir_MOV_cond(c, QPU_COND_ZS, c->execute, qir_uniform_ui(c, 0));
}

static void
ntq_emit_if(struct vc4_compile *c, nir_if *if_stmt)
{
fprintf(stderr, "general IF statements not handled.\n");
struct qblock *prev_block = c->cur_block;
struct qblock *then_block = qir_new_block(c);
struct qblock *else_block = qir_new_block(c);
struct qblock *after_block = qir_new_block(c);

if (c->execute.file == QFILE_NULL)
c->execute = qir_MOV(c, qir_uniform_ui(c, 0));

/* Set ZS for executing (execute == 0) and jumping (if->condition ==
* 0) channels, and then update execute flags for those to point to
* the ELSE block.
*/
qir_SF(c, qir_AND(c,
c->execute,
ntq_get_src(c, if_stmt->condition, 0)));
qir_MOV_cond(c, QPU_COND_ZS, c->execute,
qir_uniform_ui(c, else_block->index));

/* Jump to ELSE if nothing is active for THEN, otherwise fall
* through.
*/
qir_SF(c, c->execute);
qir_BRANCH(c, QPU_COND_BRANCH_ALL_ZC);
qir_link_blocks(prev_block, else_block);
qir_link_blocks(prev_block, then_block);

/* Process the THEN block. */
c->cur_block = then_block;
ntq_emit_cf_list(c, &if_stmt->then_list);

/* Handle the end of the THEN block. First, all currently active
* channels update their execute flags to point to ENDIF
*/
qir_SF(c, c->execute);
qir_MOV_cond(c, QPU_COND_ZS, c->execute,
qir_uniform_ui(c, after_block->index));

/* If everything points at ENDIF, then jump there immediately. */
qir_SF(c, qir_SUB(c, c->execute, qir_uniform_ui(c, after_block->index)));
qir_BRANCH(c, QPU_COND_BRANCH_ALL_ZS);
qir_link_blocks(then_block, after_block);
qir_link_blocks(then_block, else_block);

c->cur_block = else_block;
ntq_activate_execute_for_block(c, else_block);
ntq_emit_cf_list(c, &if_stmt->else_list);
qir_link_blocks(else_block, after_block);

c->cur_block = after_block;
ntq_activate_execute_for_block(c, after_block);
}

static void
Expand Down
22 changes: 22 additions & 0 deletions src/gallium/drivers/vc4/vc4_qir.h
Expand Up @@ -411,6 +411,12 @@ struct vc4_compile {
uint32_t next_ubo_dst_offset;

struct qreg line_x, point_x, point_y;

/* State for whether we're executing on each channel currently. 0 if
* yes, otherwise a block number + 1.
*/
struct qreg execute;

struct qreg discard;

uint8_t vattr_sizes[8];
Expand Down Expand Up @@ -754,6 +760,22 @@ qir_VPM_WRITE(struct vc4_compile *c, struct qreg val)
qir_MOV_dest(c, qir_reg(QFILE_VPM, 0), val);
}

static inline void
qir_MOV_cond(struct vc4_compile *c, uint8_t cond,
struct qreg dest, struct qreg src)
{
qir_MOV_dest(c, dest, src)->cond = cond;
}

static inline struct qinst *
qir_BRANCH(struct vc4_compile *c, uint8_t cond)
{
struct qinst *inst = qir_inst(QOP_BRANCH, c->undef, c->undef, c->undef);
inst->cond = cond;
qir_emit(c, inst);
return inst;
}

#define qir_for_each_block(c, block) \
list_for_each_entry(struct qblock, block, &c->blocks, link)

Expand Down

0 comments on commit 8c410e6

Please sign in to comment.