[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).
This commit is contained in:
Bill Currie 2024-11-18 12:29:25 +09:00
parent 34277b2050
commit 39514e4f3d
6 changed files with 80 additions and 26 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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;
}

View file

@ -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) {

View file

@ -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;

View file

@ -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,
};