0
0
Fork 0
mirror of https://git.code.sf.net/p/quake/quakeforge synced 2025-04-22 17:45:37 +00:00

[qfcc] Support matrices in spirv output

With a few more fixes, iqm.vert builds nicely.
This commit is contained in:
Bill Currie 2024-12-05 00:26:07 +09:00
parent 5e053fe270
commit c185d2463b
6 changed files with 66 additions and 19 deletions

View file

@ -171,6 +171,7 @@ const type_t *reference_type (const type_t *aux);
const type_t *tagged_reference_type (unsigned tag, const type_t *aux);
const type_t *vector_type (const type_t *ele_type, int width) __attribute__((pure));
const type_t *matrix_type (const type_t *ele_type, int cols, int rows) __attribute__((pure));
const type_t *column_type (const type_t *mat_type) __attribute__((pure));
const type_t *base_type (const type_t *vec_type) __attribute__((pure));
/** Return an integral type of same size as the provided type.

View file

@ -2372,7 +2372,7 @@ array_expr (const expr_t *array, const expr_t *index)
return index;
if (!is_pointer (array_type) && !is_array (array_type)
&& !is_nonscalar (array_type))
&& !is_nonscalar (array_type) && !is_matrix (array_type))
return error (array, "not an array");
if (!is_integral (index_type))
return error (index, "invalid array index type");

View file

@ -47,7 +47,9 @@ get_value (const expr_t *e, int i, int j)
}
if (type_cols (t) > 1) {
auto ind = new_int_expr (i, false);
e = array_expr (e, ind);
auto a = new_array_expr (e, ind);
a->array.type = column_type (t);
e = a;
}
if (type_rows (t) > 1) {
auto ind = new_int_expr (j, false);
@ -127,7 +129,7 @@ construct_by_components (const type_t *type, const expr_t *params,
auto vec = new_expr ();
vec->type = ex_vector;
vec->vector.type = vector_type (base, num_comp);
vec->vector.type = type;
list_gather (&vec->vector.list, components, num_comp);
return vec;
}

View file

@ -170,7 +170,19 @@ proc_array (const expr_t *expr)
}
scoped_src_loc (expr);
auto e = new_array_expr (base, index);
e->array.type = dereference_type (get_type (base));
auto bt = get_type (base);
if (is_reference (bt)) {
bt = dereference_type (bt);
}
const type_t *type;
if (is_matrix (bt)) {
type = column_type (bt);
} else if (is_nonscalar (bt)) {
type = base_type (bt);
} else {
type = dereference_type (bt);
}
e->array.type = type;
return e;
}
@ -230,7 +242,7 @@ static bool
proc_do_list (ex_list_t *out, const ex_list_t *in)
{
int count = list_count (in);
const expr_t *exprs[count + 1];
const expr_t *exprs[count + 1] = {};
list_scatter (in, exprs);
bool ok = true;
for (int i = 0; i < count; i++) {

View file

@ -482,8 +482,8 @@ type_id (const type_t *type, spirvctx_t *ctx)
// quaternion as vec4
auto qtype = vector_type (&type_float, 4);
id = type_id (qtype, ctx);
} else if (type_cols (type) > 1) {
auto ctype = vector_type (base_type (type), type_rows (type));
} else if (is_matrix (type)) {
auto ctype = column_type (type);
unsigned cid = type_id (ctype, ctx);
id = spirv_TypeMatrix (cid, type_cols (type), ctx);
} else if (type_width (type) > 1) {
@ -1109,17 +1109,14 @@ spirv_vector_value (const ex_value_t *value, spirvctx_t *ctx)
auto base = base_type (value->type);
int width = type_width (value->type);
ex_value_t *comp_vals[width];
if (type_size (base) == 1) {
for (int i = 0; i < width; i++) {
comp_vals[i] = new_type_value (base, &value->raw_value + i);
}
} else if (type_size (base) == 2) {
for (int i = 0; i < width; i++) {
comp_vals[i] = new_type_value (base, &value->raw_value + i * 2);
}
} else {
auto val = &value->raw_value;
if (type_size (base) < 1 || type_size (base) > 2) {
internal_error (nullptr, "invalid vector component size");
}
for (int i = 0; i < width; i++) {
comp_vals[i] = new_type_value (base, val);
val += type_size (base);
}
unsigned comp_ids[width];
for (int i = 0; i < width; i++) {
auto e = new_value_expr (comp_vals[i], false);
@ -1138,12 +1135,40 @@ spirv_vector_value (const ex_value_t *value, spirvctx_t *ctx)
return id;
}
static unsigned
spirv_matrix_value (const ex_value_t *value, spirvctx_t *ctx)
{
auto ctype = column_type (value->type);
int count = type_cols (value->type);
ex_value_t *columns[count];
auto val = &value->raw_value;
for (int i = 0; i < count; i++) {
columns[i] = new_type_value (ctype, val);
val += type_size (ctype);
columns[i]->id = spirv_vector_value (columns[i], ctx);
}
auto space = ctx->module->globals;
int tid = type_id (value->type, ctx);
int id = spirv_id (ctx);
auto insn = spirv_new_insn (SpvOpConstantComposite, 3 + count, space);
INSN (insn, 1) = tid;
INSN (insn, 2) = id;
for (int i = 0; i < count; i++) {
INSN (insn, 3 + i) = columns[i]->id;
}
return id;
}
static unsigned
spirv_value (const expr_t *e, spirvctx_t *ctx)
{
auto value = e->value;
if (!value->id) {
if (is_nonscalar (value->type) && type_cols (value->type) == 1) {
if (is_matrix (value->type)) {
return spirv_matrix_value (value, ctx);
}
if (is_nonscalar (value->type)) {
return spirv_vector_value (value, ctx);
}
unsigned tid = type_id (value->type, ctx);
@ -1887,7 +1912,7 @@ spirv_build_element_chain (element_chain_t *element_chain, const type_t *type,
state.offset = state.field->id;
}
} else if (is_matrix (type)) {
state.type = vector_type (base_type (type), type_rows (type));
state.type = column_type (type);
} else if (is_nonscalar (type)) {
state.type = base_type (type);
} else if (is_array (type)) {

View file

@ -855,6 +855,12 @@ matrix_type (const type_t *ele_type, int cols, int rows)
return nullptr;
}
const type_t *
column_type (const type_t *mat_type)
{
return vector_type (base_type (mat_type), type_rows (mat_type));
}
const type_t *
vector_type (const type_t *ele_type, int width)
{
@ -1040,6 +1046,7 @@ unalias_type (const type_t *type)
const type_t *
dereference_type (const type_t *type)
{
// is_ptr is used to catch both pointer and reference
if (!is_ptr (type) && !is_field (type) && !is_array (type)) {
internal_error (0, "dereference non pointer/field/array type");
}
@ -1575,7 +1582,7 @@ is_math (const type_t *type)
if (is_algebra (type)) {
return true;
}
return is_scalar (type) || is_nonscalar (type);
return is_scalar (type) || is_nonscalar (type) || is_matrix (type);
}
bool