From 39514e4f3d0621a97b51b9b80857c5618942d028 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 18 Nov 2024 12:29:25 +0900 Subject: [PATCH] [qfcc] Implement swizzle and arrays for spir-v Arrays done via the field code since they use the same opcode and logic. For now swizzles are just swizzles and don't support zeroing or negating (but doing one or the other (not both) should be easy). --- tools/qfcc/source/dot_expr.c | 21 ++++++++- tools/qfcc/source/expr.c | 7 ++- tools/qfcc/source/expr_construct.c | 4 +- tools/qfcc/source/expr_process.c | 4 ++ tools/qfcc/source/glsl-declaration.c | 6 --- tools/qfcc/source/target_spirv.c | 64 +++++++++++++++++++++------- 6 files changed, 80 insertions(+), 26 deletions(-) diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 5b61c4d32..6025be7b3 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -383,6 +383,22 @@ print_field (dstring_t *dstr, const expr_t *e, int level, int id, ".", e->loc.line); } +static void +print_array (dstring_t *dstr, const expr_t *e, int level, int id, + const expr_t *next) +{ + int indent = level * 2 + 2; + + _print_expr (dstr, e->array.base, level, id, next); + _print_expr (dstr, e->array.index, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"b\"];\n", indent, "", e, + e->array.base); + dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"i\"];\n", indent, "", e, + e->array.index); + dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e, + "[]", e->loc.line); +} + static void print_subexpr (dstring_t *dstr, const expr_t *e, int level, int id, const expr_t *next) { @@ -715,9 +731,10 @@ print_swizzle (dstring_t *dstr, const expr_t *e, int level, int id, const expr_t static char swizzle_components[] = "xyzw"; int indent = level * 2 + 2; ex_swizzle_t swiz = e->swizzle; + int count = type_width (swiz.type); const char *swizzle = ""; - for (int i = 0; i < 4; i++) { + for (int i = 0; i < count; i++) { if (swiz.zero & (1 << i)) { swizzle = va (0, "%s0", swizzle); } else { @@ -835,7 +852,7 @@ _print_expr (dstring_t *dstr, const expr_t *e, int level, int id, [ex_incop] = nullptr, [ex_cond] = print_cond, [ex_field] = print_field, - [ex_array] = nullptr, + [ex_array] = print_array, [ex_decl] = nullptr, }; int indent = level * 2 + 2; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 6b8e1b03a..fe7cbc4e8 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -666,10 +666,14 @@ const expr_t * new_swizzle_expr (const expr_t *src, const char *swizzle) { src = convert_name (src); - if (src->type == ex_error) { + if (is_error (src)) { return (expr_t *) src; } auto src_type = get_type (src); + if (is_reference (src_type)) { + src_type = dereference_type (src_type); + src = pointer_deref (src); + } int src_width = type_width (src_type); ex_swizzle_t swiz = {}; @@ -720,7 +724,6 @@ new_swizzle_expr (const expr_t *src, const char *swizzle) swiz.source[comp_count++] = ind; } } - swiz.zero |= (0xf << comp_count) & 0xf; swiz.src = src; swiz.type = vector_type (base_type (src_type), comp_count); diff --git a/tools/qfcc/source/expr_construct.c b/tools/qfcc/source/expr_construct.c index 66ed450a4..c2101115e 100644 --- a/tools/qfcc/source/expr_construct.c +++ b/tools/qfcc/source/expr_construct.c @@ -51,7 +51,9 @@ get_value (const expr_t *e, int i, int j) } if (type_rows (t) > 1) { auto ind = new_int_expr (j, false); - e = array_expr (e, ind); + auto a = new_array_expr (e, ind); + a->array.type = base_type (t); + e = a; } return e; } diff --git a/tools/qfcc/source/expr_process.c b/tools/qfcc/source/expr_process.c index efc8c75f0..53ed4cc05 100644 --- a/tools/qfcc/source/expr_process.c +++ b/tools/qfcc/source/expr_process.c @@ -341,6 +341,10 @@ proc_decl (const expr_t *expr) if (decl->assign.dst->type != ex_symbol) { internal_error (decl->assign.dst, "not a symbol"); } + init = expr_process (init); + if (is_error (init)) { + return init; + } pr.loc = decl->assign.dst->loc; sym = decl->assign.dst->symbol; } else if (decl->type == ex_symbol) { diff --git a/tools/qfcc/source/glsl-declaration.c b/tools/qfcc/source/glsl-declaration.c index 28384101e..28caa9246 100644 --- a/tools/qfcc/source/glsl-declaration.c +++ b/tools/qfcc/source/glsl-declaration.c @@ -48,12 +48,6 @@ glsl_parse_declaration (specifier_t spec, symbol_t *sym, const expr_t *init, if (sym->type) { internal_error (0, "unexected typed symbol"); } - if (init) { - init = expr_process (init); - if (is_error (init)) { - return; - } - } auto attributes = glsl_optimize_attributes (spec.attributes); if (sym && sym->sy_type == sy_expr) { auto id_list = sym->expr; diff --git a/tools/qfcc/source/target_spirv.c b/tools/qfcc/source/target_spirv.c index dd9138a21..8b66f063f 100644 --- a/tools/qfcc/source/target_spirv.c +++ b/tools/qfcc/source/target_spirv.c @@ -1259,6 +1259,24 @@ spirv_return (const expr_t *e, spirvctx_t *ctx) return 0; } +static unsigned +spirv_swizzle (const expr_t *e, spirvctx_t *ctx) +{ + int count = type_width (e->swizzle.type); + unsigned src_id = spirv_emit_expr (e->swizzle.src, ctx); + unsigned tid = type_id (e->swizzle.type, ctx); + unsigned id = spirv_id (ctx); + auto insn = spirv_new_insn (SpvOpVectorShuffle, 4 + count, ctx->code_space); + INSN (insn, 1) = tid; + INSN (insn, 2) = id; + INSN (insn, 3) = src_id; + INSN (insn, 4) = src_id; + for (int i = 0; i < count; i++) { + INSN (insn, 5 + i) = e->swizzle.source[i]; + } + return id; +} + static unsigned spirv_extend (const expr_t *e, spirvctx_t *ctx) { @@ -1341,16 +1359,21 @@ spirv_cond (const expr_t *e, spirvctx_t *ctx) } static unsigned -spirv_field (const expr_t *e, spirvctx_t *ctx) +spirv_field_array (const expr_t *e, spirvctx_t *ctx) { auto res_type = get_type (e); ex_list_t list = {}; - // convert the left-branching field expression chain to a list - for (; e->type == ex_field; e = e->field.object) { - list_prepend (&list, e); + // convert the left-branching field/array expression chain to a list + while (e->type == ex_field || e->type == ex_array) { + for (; e->type == ex_field; e = e->field.object) { + list_prepend (&list, e); + } + for (; e->type == ex_array; e = e->array.base) { + list_prepend (&list, e); + } } - int num_fields = list_count (&list); - // e is now the base object of the field expression chain + int num_obj = list_count (&list); + // e is now the base object of the field/array expression chain auto base_type = get_type (e); unsigned base_id = spirv_emit_expr (e, ctx); int op = SpvOpCompositeExtract; @@ -1366,20 +1389,29 @@ spirv_field (const expr_t *e, spirvctx_t *ctx) int acc_type_id = type_id (acc_type, ctx); int id = spirv_id (ctx); - auto insn = spirv_new_insn (op, 4 + num_fields, ctx->code_space); + auto insn = spirv_new_insn (op, 4 + num_obj, ctx->code_space); INSN (insn, 1) = acc_type_id; INSN (insn, 2) = id; INSN (insn, 3) = base_id; auto field_ind = &INSN (insn, 4); for (auto l = list.head; l; l = l->next) { - if (l->expr->field.member->type != ex_symbol) { - internal_error (l->expr->field.member, "not a symbol"); - } - auto sym = l->expr->field.member->symbol; - if (literal_ind) { - *field_ind++ = sym->id; + auto obj = l->expr; + unsigned index; + if (obj->type == ex_field) { + if (obj->field.member->type != ex_symbol) { + internal_error (obj->field.member, "not a symbol"); + } + auto sym = obj->field.member->symbol; + index = sym->id; + } else if (obj->type == ex_array) { + index = expr_integral (obj->array.index); } else { - auto ind = new_uint_expr (sym->id); + internal_error (obj, "what the what?!?"); + } + if (literal_ind) { + *field_ind++ = index; + } else { + auto ind = new_uint_expr (index); *field_ind++ = spirv_emit_expr (ind, ctx); } } @@ -1471,9 +1503,11 @@ spirv_emit_expr (const expr_t *e, spirvctx_t *ctx) [ex_assign] = spirv_assign, [ex_branch] = spirv_branch, [ex_return] = spirv_return, + [ex_swizzle] = spirv_swizzle, [ex_extend] = spirv_extend, [ex_cond] = spirv_cond, - [ex_field] = spirv_field, + [ex_field] = spirv_field_array, + [ex_array] = spirv_field_array, [ex_loop] = spirv_loop, [ex_select] = spirv_select, };