mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-25 05:01:24 +00:00
[qfcc] Implement matrix construction for constants
Non-constant matrices are not implemented yet, and it turns out vector-matrix multiplication produces incorrect vector types (for vec4*mat3x4)
This commit is contained in:
parent
1e5d500f8b
commit
a4eefa6204
3 changed files with 127 additions and 12 deletions
|
@ -747,6 +747,9 @@ const expr_t *new_vector_list (const expr_t *e);
|
||||||
const expr_t *new_vector_value (const type_t *ele_type, int width,
|
const expr_t *new_vector_value (const type_t *ele_type, int width,
|
||||||
int count, const expr_t **elements,
|
int count, const expr_t **elements,
|
||||||
bool implicit);
|
bool implicit);
|
||||||
|
const expr_t *new_matrix_value (const type_t *ele_type, int cols, int rows,
|
||||||
|
int count, const expr_t **elements,
|
||||||
|
bool implicit);
|
||||||
const expr_t *vector_to_compound (const expr_t *vector);
|
const expr_t *vector_to_compound (const expr_t *vector);
|
||||||
|
|
||||||
/** Create a new entity constant expression node.
|
/** Create a new entity constant expression node.
|
||||||
|
|
|
@ -59,20 +59,23 @@ get_value (const expr_t *e, int i, int j)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const expr_t *
|
static const expr_t *
|
||||||
math_constructor (const type_t *type, const expr_t *params, const expr_t *e)
|
construct_by_components (const type_t *type, const expr_t *params,
|
||||||
|
const expr_t *e)
|
||||||
{
|
{
|
||||||
auto base = base_type (type);
|
auto base = base_type (type);
|
||||||
int num_comp = type->width;
|
int num_comp = type_rows (type) * type_cols (type);
|
||||||
const expr_t *components[num_comp] = {};
|
const expr_t *components[num_comp] = {};
|
||||||
|
|
||||||
int num_param = list_count (¶ms->list);
|
int num_param = list_count (¶ms->list);
|
||||||
const expr_t *param_exprs[num_param + 1] = {};
|
const expr_t *param_exprs[num_param + 1] = {};
|
||||||
list_scatter_rev (¶ms->list, param_exprs);
|
list_scatter_rev (¶ms->list, param_exprs);
|
||||||
|
|
||||||
bool all_constant = true;
|
bool all_constant = true;
|
||||||
bool all_implicit = true;
|
bool all_implicit = true;
|
||||||
|
|
||||||
int p = 0;
|
int c = 0, p = 0;
|
||||||
for (int c = 0; c < num_comp; ) {
|
int err = -1;
|
||||||
|
while (c < num_comp) {
|
||||||
if (p < num_param) {
|
if (p < num_param) {
|
||||||
auto pexpr = param_exprs[p++];
|
auto pexpr = param_exprs[p++];
|
||||||
auto ptype = get_type (pexpr);
|
auto ptype = get_type (pexpr);
|
||||||
|
@ -84,7 +87,8 @@ math_constructor (const type_t *type, const expr_t *params, const expr_t *e)
|
||||||
ptype = dereference_type (ptype);
|
ptype = dereference_type (ptype);
|
||||||
}
|
}
|
||||||
if (!is_math (ptype)) {
|
if (!is_math (ptype)) {
|
||||||
components[c++] = error (pexpr, "invalid type for conversion");
|
err = c++;
|
||||||
|
components[err] = error (pexpr, "invalid type for conversion");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < type_cols (ptype) && c < num_comp; i++) {
|
for (int i = 0; i < type_cols (ptype) && c < num_comp; i++) {
|
||||||
|
@ -96,9 +100,15 @@ math_constructor (const type_t *type, const expr_t *params, const expr_t *e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
components[c++] = new_nil_expr ();
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (err >= 0) {
|
||||||
|
return components[err];
|
||||||
|
}
|
||||||
|
if (c < num_comp) {
|
||||||
|
return error (e, "too few parameters for %s", type->name);
|
||||||
|
}
|
||||||
if (p < num_param) {
|
if (p < num_param) {
|
||||||
return error (e, "too may parameters for %s", type->name);
|
return error (e, "too may parameters for %s", type->name);
|
||||||
}
|
}
|
||||||
|
@ -106,8 +116,13 @@ math_constructor (const type_t *type, const expr_t *params, const expr_t *e)
|
||||||
return components[0];
|
return components[0];
|
||||||
}
|
}
|
||||||
if (all_constant) {
|
if (all_constant) {
|
||||||
return new_vector_value (base, num_comp, num_comp, components,
|
if (is_matrix (type)) {
|
||||||
all_implicit);
|
return new_matrix_value (base, type_cols (type), type_rows (type),
|
||||||
|
num_comp, components, all_implicit);
|
||||||
|
} else {
|
||||||
|
return new_vector_value (base, type_width (type),
|
||||||
|
num_comp, components, all_implicit);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto vec = new_expr ();
|
auto vec = new_expr ();
|
||||||
|
@ -117,6 +132,90 @@ math_constructor (const type_t *type, const expr_t *params, const expr_t *e)
|
||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const expr_t *
|
||||||
|
construct_diagonal (const type_t *type, const expr_t *scalar, const expr_t *e)
|
||||||
|
{
|
||||||
|
scoped_src_loc (scalar);
|
||||||
|
int cols = type_cols (type);
|
||||||
|
int rows = type_rows (type);
|
||||||
|
const expr_t *components[cols * rows + 1] = {};
|
||||||
|
auto zero = new_nil_expr ();
|
||||||
|
|
||||||
|
for (int i = 0; i < cols; i++) {
|
||||||
|
for (int j = 0; j < rows; j++) {
|
||||||
|
components[i * rows + j] = i == j ? scalar : zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto params = new_list_expr (nullptr);
|
||||||
|
list_gather (¶ms->list, components, cols * rows);
|
||||||
|
return construct_by_components (type, params, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const expr_t *
|
||||||
|
construct_matrix (const type_t *type, const expr_t *matrix, const expr_t *e)
|
||||||
|
{
|
||||||
|
scoped_src_loc (matrix);
|
||||||
|
int cols = type_cols (type);
|
||||||
|
int rows = type_rows (type);
|
||||||
|
int src_cols = type_cols (get_type (matrix));
|
||||||
|
int src_rows = type_rows (get_type (matrix));
|
||||||
|
const expr_t *components[cols * rows + 1] = {};
|
||||||
|
auto zero = new_nil_expr ();
|
||||||
|
|
||||||
|
for (int i = 0; i < cols; i++) {
|
||||||
|
for (int j = 0; j < rows; j++) {
|
||||||
|
const expr_t *val;
|
||||||
|
if (i < src_cols && j < src_rows) {
|
||||||
|
val = get_value (matrix, i, j);
|
||||||
|
} else {
|
||||||
|
val = zero;
|
||||||
|
}
|
||||||
|
components[i * rows + j] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto params = new_list_expr (nullptr);
|
||||||
|
list_gather (¶ms->list, components, cols * rows);
|
||||||
|
return construct_by_components (type, params, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const expr_t *
|
||||||
|
construct_broadcast (const type_t *type, const expr_t *scalar, const expr_t *e)
|
||||||
|
{
|
||||||
|
scoped_src_loc (scalar);
|
||||||
|
int width = type_width (type);
|
||||||
|
const expr_t *components[width + 1] = {};
|
||||||
|
|
||||||
|
for (int i = 0; i < width; i++) {
|
||||||
|
components[i] = scalar;
|
||||||
|
}
|
||||||
|
auto params = new_list_expr (nullptr);
|
||||||
|
list_gather (¶ms->list, components, width);
|
||||||
|
return construct_by_components (type, params, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const expr_t *
|
||||||
|
math_constructor (const type_t *type, const expr_t *params, const expr_t *e)
|
||||||
|
{
|
||||||
|
int num_param = list_count (¶ms->list);
|
||||||
|
const expr_t *param_exprs[num_param + 1] = {};
|
||||||
|
list_scatter_rev (¶ms->list, param_exprs);
|
||||||
|
|
||||||
|
if (num_param == 1 && is_scalar (get_type (param_exprs[0]))) {
|
||||||
|
if (is_matrix (type)) {
|
||||||
|
return construct_diagonal (type, param_exprs[0], e);
|
||||||
|
}
|
||||||
|
if (is_vector (type)) {
|
||||||
|
return construct_broadcast (type, param_exprs[0], e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (num_param == 1 && is_matrix (get_type (param_exprs[0]))) {
|
||||||
|
if (is_matrix (type)) {
|
||||||
|
return construct_matrix (type, param_exprs[0], e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return construct_by_components (type, params, e);
|
||||||
|
}
|
||||||
|
|
||||||
const expr_t *
|
const expr_t *
|
||||||
constructor_expr (const expr_t *e, const expr_t *params)
|
constructor_expr (const expr_t *e, const expr_t *params)
|
||||||
{
|
{
|
||||||
|
@ -124,9 +223,6 @@ constructor_expr (const expr_t *e, const expr_t *params)
|
||||||
if (is_algebra (type)) {
|
if (is_algebra (type)) {
|
||||||
return error (e, "algebra not implemented");
|
return error (e, "algebra not implemented");
|
||||||
}
|
}
|
||||||
if (is_matrix (type)) {
|
|
||||||
return error (e, "matrix not implemented");
|
|
||||||
}
|
|
||||||
if (is_math (type)) {
|
if (is_math (type)) {
|
||||||
return math_constructor (type, params, e);
|
return math_constructor (type, params, e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ new_vector_value (const type_t *ele_type, int width, int count,
|
||||||
const expr_t **elements, bool implicit)
|
const expr_t **elements, bool implicit)
|
||||||
{
|
{
|
||||||
const type_t *vec_type = vector_type (ele_type, width);
|
const type_t *vec_type = vector_type (ele_type, width);
|
||||||
pr_type_t value[type_size (vec_type)];
|
pr_type_t value[type_size (vec_type)] = {};
|
||||||
|
|
||||||
for (int i = 0, offs = 0; i < count; i++) {
|
for (int i = 0, offs = 0; i < count; i++) {
|
||||||
auto src_type = get_type (elements[i]);
|
auto src_type = get_type (elements[i]);
|
||||||
|
@ -52,6 +52,22 @@ new_vector_value (const type_t *ele_type, int width, int count,
|
||||||
return new_value_expr (new_type_value (vec_type, value), implicit);
|
return new_value_expr (new_type_value (vec_type, value), implicit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const expr_t *
|
||||||
|
new_matrix_value (const type_t *ele_type, int cols, int rows, int count,
|
||||||
|
const expr_t **elements, bool implicit)
|
||||||
|
{
|
||||||
|
const type_t *mat_type = matrix_type (ele_type, cols, rows);
|
||||||
|
pr_type_t value[type_size (mat_type)] = {};
|
||||||
|
|
||||||
|
for (int i = 0, offs = 0; i < count; i++) {
|
||||||
|
auto src_type = get_type (elements[i]);
|
||||||
|
value_store (value + offs, src_type, elements[i]);
|
||||||
|
offs += type_size (src_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_value_expr (new_type_value (mat_type, value), implicit);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const expr_t *
|
const expr_t *
|
||||||
new_vector_list (const expr_t *expr_list)
|
new_vector_list (const expr_t *expr_list)
|
||||||
|
|
Loading…
Reference in a new issue