diff --git a/gsk/gskslstatement.c b/gsk/gskslstatement.c index 128e35ae2d..6ed888b86a 100644 --- a/gsk/gskslstatement.c +++ b/gsk/gskslstatement.c @@ -392,59 +392,54 @@ static void gsk_sl_statement_if_write_spv (const GskSlStatement *statement, GskSpvWriter *writer) { -#if 0 GskSlStatementIf *if_stmt = (GskSlStatementIf *) statement; - guint32 label_id, if_id, else_id, condition_id; + guint32 if_id, else_id, condition_id; + GskSpvCodeBlock *if_block, *else_block, *after_block; condition_id = gsk_sl_expression_write_spv (if_stmt->condition, writer); - if_id = gsk_spv_writer_next_id (writer); - else_id = gsk_spv_writer_next_id (writer); - /* We compute the labels in this funny order to match what glslang does */ - if (if_stmt->else_part) - label_id = gsk_spv_writer_next_id (writer); - else - label_id = else_id; - gsk_spv_writer_add (writer, - GSK_SPV_WRITER_SECTION_CODE, - 3, GSK_SPV_OP_SELECTION_MERGE, - (guint32[2]) { label_id, - 0}); - gsk_spv_writer_add (writer, - GSK_SPV_WRITER_SECTION_CODE, - 4, GSK_SPV_OP_BRANCH_CONDITIONAL, - (guint32[3]) { condition_id, - if_id, - else_id }); - gsk_spv_writer_add (writer, - GSK_SPV_WRITER_SECTION_CODE, - 2, GSK_SPV_OP_LABEL, - (guint32[1]) { if_id }); + gsk_spv_writer_push_new_code_block (writer); + if_block = gsk_spv_writer_pop_code_block (writer); + if_id = gsk_spv_code_block_get_label (if_block); + gsk_spv_writer_push_new_code_block (writer); + after_block = gsk_spv_writer_pop_code_block (writer); + + gsk_spv_writer_push_code_block (writer, if_block); gsk_sl_statement_write_spv (if_stmt->if_part, writer); - gsk_spv_writer_add (writer, - GSK_SPV_WRITER_SECTION_CODE, - 2, GSK_SPV_OP_BRANCH, - (guint32[1]) { label_id }); + gsk_spv_writer_branch (writer, + gsk_spv_code_block_get_label (after_block)); + gsk_spv_writer_pop_code_block (writer); if (if_stmt->else_part) { - gsk_spv_writer_add (writer, - GSK_SPV_WRITER_SECTION_CODE, - 2, GSK_SPV_OP_LABEL, - (guint32[1]) { else_id }); + else_id = gsk_spv_writer_push_new_code_block (writer); gsk_sl_statement_write_spv (if_stmt->else_part, writer); - gsk_spv_writer_add (writer, - GSK_SPV_WRITER_SECTION_CODE, - 2, GSK_SPV_OP_BRANCH, - (guint32[1]) { label_id }); + gsk_spv_writer_branch (writer, + gsk_spv_code_block_get_label (after_block)); + else_block = gsk_spv_writer_pop_code_block (writer); + } + else + { + else_id = gsk_spv_code_block_get_label (after_block); + else_block = NULL; } - gsk_spv_writer_add (writer, - GSK_SPV_WRITER_SECTION_CODE, - 2, GSK_SPV_OP_LABEL, - (guint32[1]) { label_id }); -#endif - g_assert_not_reached (); + gsk_spv_writer_selection_merge (writer, + gsk_spv_code_block_get_label (after_block), + 0); + gsk_spv_writer_branch_conditional (writer, condition_id, if_id, else_id, NULL, 0); + + gsk_spv_writer_push_code_block (writer, if_block); + gsk_spv_writer_commit_code_block (writer); + + if (else_block) + { + gsk_spv_writer_push_code_block (writer, else_block); + gsk_spv_writer_commit_code_block (writer); + } + + gsk_spv_writer_push_code_block (writer, after_block); + gsk_spv_writer_commit_code_block (writer); } static const GskSlStatementClass GSK_SL_STATEMENT_IF = { diff --git a/gsk/gskspvwriter.c b/gsk/gskspvwriter.c index d68cabd479..6249bf260c 100644 --- a/gsk/gskspvwriter.c +++ b/gsk/gskspvwriter.c @@ -25,12 +25,20 @@ #include "gskslvalueprivate.h" #include "gskslvariableprivate.h" +struct _GskSpvCodeBlock +{ + GArray *code; + + guint32 label; +}; + struct _GskSpvWriter { int ref_count; guint32 last_id; GArray *code[GSK_SPV_WRITER_N_SECTIONS]; + GSList *blocks; guint32 entry_point; GHashTable *types; @@ -50,7 +58,7 @@ gsk_spv_writer_new (void) for (i = 0; i < GSK_SPV_WRITER_N_SECTIONS; i++) { - writer->code[i] = g_array_new (FALSE, FALSE, sizeof (guint32)); + writer->code[i] = g_array_new (FALSE, TRUE, sizeof (guint32)); } writer->types = g_hash_table_new_full (gsk_sl_type_hash, gsk_sl_type_equal, @@ -293,9 +301,68 @@ GArray * gsk_spv_writer_get_bytes (GskSpvWriter *writer, GskSpvWriterSection section) { + if (section == GSK_SPV_WRITER_SECTION_CODE && writer->blocks) + return ((GskSpvCodeBlock *) writer->blocks->data)->code; return writer->code[section]; } +guint32 +gsk_spv_writer_push_new_code_block (GskSpvWriter *writer) +{ + GskSpvCodeBlock *block; + + block = g_slice_new0 (GskSpvCodeBlock); + block->code = g_array_new (FALSE, TRUE, sizeof (guint32)); + + gsk_spv_writer_push_code_block (writer, block); + + block->label = gsk_spv_writer_label (writer); + + return block->label; +} + +void +gsk_spv_writer_push_code_block (GskSpvWriter *writer, + GskSpvCodeBlock *block) +{ + writer->blocks = g_slist_prepend (writer->blocks, block); +} + +GskSpvCodeBlock * +gsk_spv_writer_pop_code_block (GskSpvWriter *writer) +{ + GskSpvCodeBlock *result; + + result = writer->blocks->data; + g_assert (result); + + writer->blocks = g_slist_remove (writer->blocks, result); + + return result; +} + +void +gsk_spv_writer_commit_code_block (GskSpvWriter *writer) +{ + GskSpvCodeBlock *block; + GArray *commit_target; + + block = gsk_spv_writer_pop_code_block (writer); + + commit_target = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE); + g_array_append_vals (commit_target, block->code->data, block->code->len); + + g_array_free (block->code, TRUE); + + g_slice_free (GskSpvCodeBlock, block); +} + +guint32 +gsk_spv_code_block_get_label (GskSpvCodeBlock *block) +{ + return block->label; +} + static void copy_4_bytes (gpointer dest, gpointer src) { diff --git a/gsk/gskspvwriterprivate.h b/gsk/gskspvwriterprivate.h index 6be694be62..29e430a38c 100644 --- a/gsk/gskspvwriterprivate.h +++ b/gsk/gskspvwriterprivate.h @@ -31,6 +31,8 @@ G_BEGIN_DECLS #define GSK_SPV_VERSION_MINOR 0 #define GSK_SPV_GENERATOR 0 +typedef struct _GskSpvCodeBlock GskSpvCodeBlock; + typedef enum { GSK_SPV_WRITER_SECTION_HEADER, GSK_SPV_WRITER_SECTION_DEBUG, @@ -73,6 +75,14 @@ guint32 gsk_spv_writer_convert (GskSpvWriter GskSlType *type, GskSlType *new_type); +guint32 gsk_spv_writer_push_new_code_block (GskSpvWriter *writer); +void gsk_spv_writer_push_code_block (GskSpvWriter *writer, + GskSpvCodeBlock *block); +GskSpvCodeBlock * gsk_spv_writer_pop_code_block (GskSpvWriter *writer); +void gsk_spv_writer_commit_code_block (GskSpvWriter *writer); + +guint32 gsk_spv_code_block_get_label (GskSpvCodeBlock *block); + #include "gskspvwritergeneratedprivate.h" G_END_DECLS