mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-04-07 01:42:04 +00:00
[qfcc] Implement vector expressions for spir-v
And fix a little goof with VectorShuffle (c&p coding bites again).
This commit is contained in:
parent
39514e4f3d
commit
9b2240aaf8
6 changed files with 109 additions and 91 deletions
|
@ -44,6 +44,7 @@ typedef struct {
|
|||
void (*vararg_int) (const expr_t *e);
|
||||
|
||||
const expr_t *(*initialized_temp) (const type_t *type, const expr_t *src);
|
||||
const expr_t *(*assign_vector) (const expr_t *dst, const expr_t *src);
|
||||
|
||||
unsigned label_id;
|
||||
} target_t;
|
||||
|
|
|
@ -217,93 +217,6 @@ check_types_compatible (const expr_t *dst, const expr_t *src)
|
|||
return type_mismatch (dst, src, '=');
|
||||
}
|
||||
|
||||
static void
|
||||
copy_qv_elements (expr_t *block, const expr_t *dst, const expr_t *src)
|
||||
{
|
||||
const expr_t *dx, *sx;
|
||||
const expr_t *dy, *sy;
|
||||
const expr_t *dz, *sz;
|
||||
const expr_t *dw, *sw;
|
||||
const expr_t *ds, *ss;
|
||||
const expr_t *dv, *sv;
|
||||
int count = list_count (&src->vector.list);
|
||||
const expr_t *components[count];
|
||||
list_scatter (&src->vector.list, components);
|
||||
|
||||
if (is_vector (src->vector.type)) {
|
||||
// guaranteed to have three elements
|
||||
sx = components[0];
|
||||
sy = components[1];
|
||||
sz = components[2];
|
||||
dx = field_expr (dst, new_name_expr ("x"));
|
||||
dy = field_expr (dst, new_name_expr ("y"));
|
||||
dz = field_expr (dst, new_name_expr ("z"));
|
||||
append_expr (block, assign_expr (dx, sx));
|
||||
append_expr (block, assign_expr (dy, sy));
|
||||
append_expr (block, assign_expr (dz, sz));
|
||||
} else {
|
||||
// guaranteed to have two or four elements
|
||||
if (count == 4) {
|
||||
// four vals: x, y, z, w
|
||||
sx = components[0];
|
||||
sy = components[1];
|
||||
sz = components[2];
|
||||
sw = components[3];
|
||||
dx = field_expr (dst, new_name_expr ("x"));
|
||||
dy = field_expr (dst, new_name_expr ("y"));
|
||||
dz = field_expr (dst, new_name_expr ("z"));
|
||||
dw = field_expr (dst, new_name_expr ("w"));
|
||||
append_expr (block, assign_expr (dx, sx));
|
||||
append_expr (block, assign_expr (dy, sy));
|
||||
append_expr (block, assign_expr (dz, sz));
|
||||
append_expr (block, assign_expr (dw, sw));
|
||||
} else {
|
||||
// v, s
|
||||
sv = components[0];
|
||||
ss = components[1];
|
||||
dv = field_expr (dst, new_name_expr ("v"));
|
||||
ds = field_expr (dst, new_name_expr ("s"));
|
||||
append_expr (block, assign_expr (dv, sv));
|
||||
append_expr (block, assign_expr (ds, ss));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
copy_elements (expr_t *block, const expr_t *dst, const expr_t *src, int base)
|
||||
{
|
||||
int index = 0;
|
||||
for (auto li = src->vector.list.head; li; li = li->next) {
|
||||
auto e = li->expr;
|
||||
if (e->type == ex_vector) {
|
||||
index += copy_elements (block, dst, e, index + base);
|
||||
} else {
|
||||
auto type = get_type (e);
|
||||
auto dst_ele = new_offset_alias_expr (type, dst, index + base);
|
||||
append_expr (block, assign_expr (dst_ele, e));
|
||||
index += type_width (type);
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
static const expr_t *
|
||||
assign_vector_expr (const expr_t *dst, const expr_t *src)
|
||||
{
|
||||
if (src->type == ex_vector && dst->type != ex_vector) {
|
||||
expr_t *block = new_block_expr (0);
|
||||
|
||||
if (options.code.progsversion < PROG_VERSION) {
|
||||
copy_qv_elements (block, dst, src);
|
||||
} else {
|
||||
copy_elements (block, dst, src, 0);
|
||||
}
|
||||
block->block.result = dst;
|
||||
return block;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __attribute__((pure))
|
||||
is_memset (const expr_t *e)
|
||||
{
|
||||
|
@ -386,8 +299,8 @@ assign_expr (const expr_t *dst, const expr_t *src)
|
|||
// check_types_compatible will take care of everything
|
||||
return expr;
|
||||
}
|
||||
if ((expr = assign_vector_expr (dst, src))) {
|
||||
return expr;
|
||||
if (src->type == ex_vector) {
|
||||
return current_target.assign_vector (dst, src);
|
||||
}
|
||||
} else {
|
||||
src = convert_nil (src, dst_type);
|
||||
|
|
|
@ -105,7 +105,7 @@ new_vector_list (const expr_t *expr_list)
|
|||
break;
|
||||
case 3:
|
||||
// shuffle any vectors to the beginning of the list (there should
|
||||
// be only one, but futhre...)
|
||||
// be only one, but future...)
|
||||
for (int i = 1; i < count; i++) {
|
||||
if (is_nonscalar (get_type (elements[i]))) {
|
||||
auto t = elements[i];
|
||||
|
|
|
@ -205,10 +205,39 @@ ruamoko_build_code (function_t *func, const expr_t *statements)
|
|||
defspace_alloc_aligned_highwater (space, 0, STACK_ALIGN);
|
||||
}
|
||||
|
||||
static int
|
||||
copy_elements (expr_t *block, const expr_t *dst, const expr_t *src, int base)
|
||||
{
|
||||
int index = 0;
|
||||
for (auto li = src->vector.list.head; li; li = li->next) {
|
||||
auto e = li->expr;
|
||||
if (e->type == ex_vector) {
|
||||
index += copy_elements (block, dst, e, index + base);
|
||||
} else {
|
||||
auto type = get_type (e);
|
||||
auto dst_ele = new_offset_alias_expr (type, dst, index + base);
|
||||
append_expr (block, assign_expr (dst_ele, e));
|
||||
index += type_width (type);
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
static const expr_t *
|
||||
ruamoko_assign_vector (const expr_t *dst, const expr_t *src)
|
||||
{
|
||||
expr_t *block = new_block_expr (0);
|
||||
|
||||
copy_elements (block, dst, src, 0);
|
||||
block->block.result = dst;
|
||||
return block;
|
||||
}
|
||||
|
||||
target_t ruamoko_target = {
|
||||
.value_too_large = ruamoko_value_too_large,
|
||||
.build_scope = ruamoko_build_scope,
|
||||
.build_code = ruamoko_build_code,
|
||||
.declare_sym = declare_def,
|
||||
.initialized_temp = initialized_temp_expr,
|
||||
.assign_vector = ruamoko_assign_vector,
|
||||
};
|
||||
|
|
|
@ -1266,7 +1266,7 @@ spirv_swizzle (const expr_t *e, spirvctx_t *ctx)
|
|||
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);
|
||||
auto insn = spirv_new_insn (SpvOpVectorShuffle, 5 + count, ctx->code_space);
|
||||
INSN (insn, 1) = tid;
|
||||
INSN (insn, 2) = id;
|
||||
INSN (insn, 3) = src_id;
|
||||
|
@ -1822,10 +1822,29 @@ spirv_initialized_temp (const type_t *type, const expr_t *src)
|
|||
return new;
|
||||
}
|
||||
|
||||
static const expr_t *
|
||||
spirv_assign_vector (const expr_t *dst, const expr_t *src)
|
||||
{
|
||||
int count = list_count (&src->vector.list);
|
||||
const expr_t *elements[count];
|
||||
list_scatter (&src->vector.list, elements);
|
||||
|
||||
scoped_src_loc (src);
|
||||
auto new = new_compound_init ();
|
||||
new->compound.type = src->vector.type;
|
||||
for (int i = 0; i < count; i++) {
|
||||
auto ele = new_element (elements[i], nullptr);
|
||||
append_init_element (&new->compound, ele);
|
||||
}
|
||||
|
||||
return new_assign_expr (dst, new);;
|
||||
}
|
||||
|
||||
target_t spirv_target = {
|
||||
.value_too_large = spirv_value_too_large,
|
||||
.build_scope = spirv_build_scope,
|
||||
.build_code = spirv_build_code,
|
||||
.declare_sym = spirv_declare_sym,
|
||||
.initialized_temp = spirv_initialized_temp,
|
||||
.assign_vector = spirv_assign_vector,
|
||||
};
|
||||
|
|
|
@ -139,6 +139,60 @@ vararg_int (const expr_t *e)
|
|||
}
|
||||
}
|
||||
|
||||
static const expr_t *
|
||||
v6p_assign_vector (const expr_t *dst, const expr_t *src)
|
||||
{
|
||||
expr_t *block = new_block_expr (0);
|
||||
const expr_t *dx, *sx;
|
||||
const expr_t *dy, *sy;
|
||||
const expr_t *dz, *sz;
|
||||
const expr_t *dw, *sw;
|
||||
const expr_t *ds, *ss;
|
||||
const expr_t *dv, *sv;
|
||||
int count = list_count (&src->vector.list);
|
||||
const expr_t *components[count];
|
||||
list_scatter (&src->vector.list, components);
|
||||
|
||||
if (is_vector (src->vector.type)) {
|
||||
// guaranteed to have three elements
|
||||
sx = components[0];
|
||||
sy = components[1];
|
||||
sz = components[2];
|
||||
dx = field_expr (dst, new_name_expr ("x"));
|
||||
dy = field_expr (dst, new_name_expr ("y"));
|
||||
dz = field_expr (dst, new_name_expr ("z"));
|
||||
append_expr (block, assign_expr (dx, sx));
|
||||
append_expr (block, assign_expr (dy, sy));
|
||||
append_expr (block, assign_expr (dz, sz));
|
||||
} else {
|
||||
// guaranteed to have two or four elements
|
||||
if (count == 4) {
|
||||
// four vals: x, y, z, w
|
||||
sx = components[0];
|
||||
sy = components[1];
|
||||
sz = components[2];
|
||||
sw = components[3];
|
||||
dx = field_expr (dst, new_name_expr ("x"));
|
||||
dy = field_expr (dst, new_name_expr ("y"));
|
||||
dz = field_expr (dst, new_name_expr ("z"));
|
||||
dw = field_expr (dst, new_name_expr ("w"));
|
||||
append_expr (block, assign_expr (dx, sx));
|
||||
append_expr (block, assign_expr (dy, sy));
|
||||
append_expr (block, assign_expr (dz, sz));
|
||||
append_expr (block, assign_expr (dw, sw));
|
||||
} else {
|
||||
// v, s
|
||||
sv = components[0];
|
||||
ss = components[1];
|
||||
dv = field_expr (dst, new_name_expr ("v"));
|
||||
ds = field_expr (dst, new_name_expr ("s"));
|
||||
append_expr (block, assign_expr (dv, sv));
|
||||
append_expr (block, assign_expr (ds, ss));
|
||||
}
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
||||
target_t v6_target = {
|
||||
.value_too_large = v6_value_too_large,
|
||||
.build_scope = v6p_build_scope,
|
||||
|
@ -146,6 +200,7 @@ target_t v6_target = {
|
|||
.declare_sym = declare_def,
|
||||
.vararg_int = vararg_int,
|
||||
.initialized_temp = initialized_temp_expr,
|
||||
.assign_vector = v6p_assign_vector,
|
||||
};
|
||||
|
||||
target_t v6p_target = {
|
||||
|
@ -155,4 +210,5 @@ target_t v6p_target = {
|
|||
.declare_sym = declare_def,
|
||||
.vararg_int = vararg_int,
|
||||
.initialized_temp = initialized_temp_expr,
|
||||
.assign_vector = v6p_assign_vector,
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue