zink/spirv: implement if-statements
Acked-by: Jordan Justen <jordan.l.justen@intel.com>
This commit is contained in:
parent
8bbf86e7bc
commit
11ad9bfc35
|
@ -1142,13 +1142,33 @@ emit_tex(struct ntv_context *ctx, nir_tex_instr *tex)
|
|||
static void
|
||||
start_block(struct ntv_context *ctx, SpvId label)
|
||||
{
|
||||
assert(!ctx->block_started);
|
||||
/* terminate previous block if needed */
|
||||
if (ctx->block_started)
|
||||
spirv_builder_emit_branch(&ctx->builder, label);
|
||||
|
||||
/* start new block */
|
||||
spirv_builder_label(&ctx->builder, label);
|
||||
ctx->block_started = true;
|
||||
}
|
||||
|
||||
static void
|
||||
branch(struct ntv_context *ctx, SpvId label)
|
||||
{
|
||||
assert(ctx->block_started);
|
||||
spirv_builder_emit_branch(&ctx->builder, label);
|
||||
ctx->block_started = false;
|
||||
}
|
||||
|
||||
static void
|
||||
branch_conditional(struct ntv_context *ctx, SpvId condition, SpvId then_id,
|
||||
SpvId else_id)
|
||||
{
|
||||
assert(ctx->block_started);
|
||||
spirv_builder_emit_branch_conditional(&ctx->builder, condition,
|
||||
then_id, else_id);
|
||||
ctx->block_started = false;
|
||||
}
|
||||
|
||||
static void
|
||||
emit_block(struct ntv_context *ctx, struct nir_block *block)
|
||||
{
|
||||
|
@ -1189,6 +1209,50 @@ emit_block(struct ntv_context *ctx, struct nir_block *block)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
emit_cf_list(struct ntv_context *ctx, struct exec_list *list);
|
||||
|
||||
static SpvId
|
||||
get_src_bool(struct ntv_context *ctx, nir_src *src)
|
||||
{
|
||||
SpvId def = get_src_uint(ctx, src);
|
||||
assert(nir_src_bit_size(*src) == 32);
|
||||
unsigned num_components = nir_src_num_components(*src);
|
||||
return uvec_to_bvec(ctx, def, num_components);
|
||||
}
|
||||
|
||||
static void
|
||||
emit_if(struct ntv_context *ctx, nir_if *if_stmt)
|
||||
{
|
||||
SpvId condition = get_src_bool(ctx, &if_stmt->condition);
|
||||
|
||||
SpvId header_id = spirv_builder_new_id(&ctx->builder);
|
||||
SpvId then_id = block_label(ctx, nir_if_first_then_block(if_stmt));
|
||||
SpvId endif_id = spirv_builder_new_id(&ctx->builder);
|
||||
SpvId else_id = endif_id;
|
||||
|
||||
bool has_else = !exec_list_is_empty(&if_stmt->else_list);
|
||||
if (has_else) {
|
||||
assert(nir_if_first_else_block(if_stmt)->index < ctx->num_blocks);
|
||||
else_id = block_label(ctx, nir_if_first_else_block(if_stmt));
|
||||
}
|
||||
|
||||
/* create a header-block */
|
||||
start_block(ctx, header_id);
|
||||
spirv_builder_emit_selection_merge(&ctx->builder, endif_id,
|
||||
SpvSelectionControlMaskNone);
|
||||
branch_conditional(ctx, condition, then_id, else_id);
|
||||
|
||||
emit_cf_list(ctx, &if_stmt->then_list);
|
||||
|
||||
if (has_else) {
|
||||
branch(ctx, endif_id);
|
||||
emit_cf_list(ctx, &if_stmt->else_list);
|
||||
}
|
||||
|
||||
start_block(ctx, endif_id);
|
||||
}
|
||||
|
||||
static void
|
||||
emit_cf_list(struct ntv_context *ctx, struct exec_list *list)
|
||||
{
|
||||
|
@ -1199,7 +1263,7 @@ emit_cf_list(struct ntv_context *ctx, struct exec_list *list)
|
|||
break;
|
||||
|
||||
case nir_cf_node_if:
|
||||
unreachable("nir_cf_node_if not supported");
|
||||
emit_if(ctx, nir_cf_node_as_if(node));
|
||||
break;
|
||||
|
||||
case nir_cf_node_loop:
|
||||
|
|
|
@ -432,6 +432,61 @@ spirv_builder_emit_vector_shuffle(struct spirv_builder *b, SpvId result_type,
|
|||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
spirv_builder_emit_branch(struct spirv_builder *b, SpvId label)
|
||||
{
|
||||
spirv_buffer_prepare(&b->instructions, 2);
|
||||
spirv_buffer_emit_word(&b->instructions, SpvOpBranch | (2 << 16));
|
||||
spirv_buffer_emit_word(&b->instructions, label);
|
||||
}
|
||||
|
||||
void
|
||||
spirv_builder_emit_selection_merge(struct spirv_builder *b, SpvId merge_block,
|
||||
SpvSelectionControlMask selection_control)
|
||||
{
|
||||
spirv_buffer_prepare(&b->instructions, 3);
|
||||
spirv_buffer_emit_word(&b->instructions, SpvOpSelectionMerge | (3 << 16));
|
||||
spirv_buffer_emit_word(&b->instructions, merge_block);
|
||||
spirv_buffer_emit_word(&b->instructions, selection_control);
|
||||
}
|
||||
|
||||
void
|
||||
spirv_builder_emit_branch_conditional(struct spirv_builder *b, SpvId condition,
|
||||
SpvId true_label, SpvId false_label)
|
||||
{
|
||||
spirv_buffer_prepare(&b->instructions, 4);
|
||||
spirv_buffer_emit_word(&b->instructions, SpvOpBranchConditional | (4 << 16));
|
||||
spirv_buffer_emit_word(&b->instructions, condition);
|
||||
spirv_buffer_emit_word(&b->instructions, true_label);
|
||||
spirv_buffer_emit_word(&b->instructions, false_label);
|
||||
}
|
||||
|
||||
SpvId
|
||||
spirv_builder_emit_phi(struct spirv_builder *b, SpvId result_type,
|
||||
size_t num_vars, size_t *position)
|
||||
{
|
||||
SpvId result = spirv_builder_new_id(b);
|
||||
|
||||
assert(num_vars > 0);
|
||||
int words = 3 + 2 * num_vars;
|
||||
spirv_buffer_prepare(&b->instructions, words);
|
||||
spirv_buffer_emit_word(&b->instructions, SpvOpPhi | (words << 16));
|
||||
spirv_buffer_emit_word(&b->instructions, result_type);
|
||||
spirv_buffer_emit_word(&b->instructions, result);
|
||||
*position = b->instructions.num_words;
|
||||
for (int i = 0; i < 2 * num_vars; ++i)
|
||||
spirv_buffer_emit_word(&b->instructions, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
spirv_builder_set_phi_operand(struct spirv_builder *b, size_t position,
|
||||
size_t index, SpvId variable, SpvId parent)
|
||||
{
|
||||
b->instructions.words[position + index * 2 + 0] = variable;
|
||||
b->instructions.words[position + index * 2 + 1] = parent;
|
||||
}
|
||||
|
||||
SpvId
|
||||
spirv_builder_emit_image_sample_implicit_lod(struct spirv_builder *b,
|
||||
SpvId result_type,
|
||||
|
|
|
@ -175,6 +175,26 @@ spirv_builder_emit_vector_shuffle(struct spirv_builder *b, SpvId result_type,
|
|||
const uint32_t components[],
|
||||
size_t num_components);
|
||||
|
||||
void
|
||||
spirv_builder_emit_branch(struct spirv_builder *b, SpvId label);
|
||||
|
||||
void
|
||||
spirv_builder_emit_selection_merge(struct spirv_builder *b, SpvId merge_block,
|
||||
SpvSelectionControlMask selection_control);
|
||||
|
||||
void
|
||||
spirv_builder_emit_branch_conditional(struct spirv_builder *b, SpvId condition,
|
||||
SpvId true_label, SpvId false_label);
|
||||
|
||||
SpvId
|
||||
spirv_builder_emit_phi(struct spirv_builder *b, SpvId result_type,
|
||||
size_t num_vars, size_t *position);
|
||||
|
||||
void
|
||||
spirv_builder_set_phi_operand(struct spirv_builder *b, size_t position,
|
||||
size_t index, SpvId variable, SpvId parent);
|
||||
|
||||
|
||||
SpvId
|
||||
spirv_builder_emit_image_sample_implicit_lod(struct spirv_builder *b,
|
||||
SpvId result_type,
|
||||
|
|
Loading…
Reference in New Issue