2021-01-27 08:29:44 -08:00
|
|
|
/*
|
|
|
|
* HLSL parser
|
|
|
|
*
|
|
|
|
* Copyright 2008 Stefan Dösinger
|
|
|
|
* Copyright 2012 Matteo Bruni for CodeWeavers
|
|
|
|
* Copyright 2019-2020 Zebediah Figura for CodeWeavers
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
2021-02-04 14:33:49 -08:00
|
|
|
|
|
|
|
%code requires
|
|
|
|
{
|
|
|
|
|
2021-01-27 08:29:44 -08:00
|
|
|
#include "hlsl.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
|
2021-02-12 08:48:55 -08:00
|
|
|
#define HLSL_YYLTYPE struct vkd3d_shader_location
|
2021-02-04 14:33:52 -08:00
|
|
|
|
2022-07-14 18:23:43 -07:00
|
|
|
struct parse_fields
|
|
|
|
{
|
|
|
|
struct hlsl_struct_field *fields;
|
|
|
|
size_t count, capacity;
|
|
|
|
};
|
|
|
|
|
2021-02-04 14:33:49 -08:00
|
|
|
struct parse_parameter
|
|
|
|
{
|
|
|
|
struct hlsl_type *type;
|
|
|
|
const char *name;
|
2021-04-27 10:14:19 -07:00
|
|
|
struct hlsl_semantic semantic;
|
2021-05-31 19:41:14 -07:00
|
|
|
struct hlsl_reg_reservation reg_reservation;
|
2021-02-04 14:33:49 -08:00
|
|
|
unsigned int modifiers;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct parse_colon_attribute
|
|
|
|
{
|
2021-04-27 10:14:19 -07:00
|
|
|
struct hlsl_semantic semantic;
|
2021-05-31 19:41:14 -07:00
|
|
|
struct hlsl_reg_reservation reg_reservation;
|
2021-02-04 14:33:49 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct parse_initializer
|
|
|
|
{
|
|
|
|
struct hlsl_ir_node **args;
|
|
|
|
unsigned int args_count;
|
|
|
|
struct list *instrs;
|
2022-03-30 14:38:28 -07:00
|
|
|
bool braces;
|
2021-02-04 14:33:49 -08:00
|
|
|
};
|
|
|
|
|
2021-03-04 15:33:27 -08:00
|
|
|
struct parse_array_sizes
|
|
|
|
{
|
|
|
|
uint32_t *sizes; /* innermost first */
|
|
|
|
unsigned int count;
|
|
|
|
};
|
|
|
|
|
2021-02-04 14:33:49 -08:00
|
|
|
struct parse_variable_def
|
|
|
|
{
|
|
|
|
struct list entry;
|
2021-02-12 08:48:55 -08:00
|
|
|
struct vkd3d_shader_location loc;
|
2021-02-04 14:33:49 -08:00
|
|
|
|
|
|
|
char *name;
|
2021-03-04 15:33:27 -08:00
|
|
|
struct parse_array_sizes arrays;
|
2021-04-27 10:14:19 -07:00
|
|
|
struct hlsl_semantic semantic;
|
2021-05-31 19:41:14 -07:00
|
|
|
struct hlsl_reg_reservation reg_reservation;
|
2021-02-04 14:33:49 -08:00
|
|
|
struct parse_initializer initializer;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct parse_function
|
|
|
|
{
|
|
|
|
char *name;
|
|
|
|
struct hlsl_ir_function_decl *decl;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct parse_if_body
|
|
|
|
{
|
|
|
|
struct list *then_instrs;
|
|
|
|
struct list *else_instrs;
|
|
|
|
};
|
|
|
|
|
|
|
|
enum parse_assign_op
|
|
|
|
{
|
|
|
|
ASSIGN_OP_ASSIGN,
|
|
|
|
ASSIGN_OP_ADD,
|
|
|
|
ASSIGN_OP_SUB,
|
|
|
|
ASSIGN_OP_MUL,
|
|
|
|
ASSIGN_OP_DIV,
|
|
|
|
ASSIGN_OP_MOD,
|
|
|
|
ASSIGN_OP_LSHIFT,
|
|
|
|
ASSIGN_OP_RSHIFT,
|
|
|
|
ASSIGN_OP_AND,
|
|
|
|
ASSIGN_OP_OR,
|
|
|
|
ASSIGN_OP_XOR,
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
%code provides
|
2021-02-04 14:33:49 -08:00
|
|
|
{
|
|
|
|
|
2021-02-12 08:48:53 -08:00
|
|
|
int yylex(HLSL_YYSTYPE *yylval_param, HLSL_YYLTYPE *yylloc_param, void *yyscanner);
|
2021-02-04 14:33:52 -08:00
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
}
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
%code
|
|
|
|
{
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
#define YYLLOC_DEFAULT(cur, rhs, n) (cur) = YYRHSLOC(rhs, !!n)
|
|
|
|
|
|
|
|
static void yyerror(YYLTYPE *loc, void *scanner, struct hlsl_ctx *ctx, const char *s)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "%s", s);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct hlsl_ir_node *node_from_list(struct list *list)
|
|
|
|
{
|
|
|
|
return LIST_ENTRY(list_tail(list), struct hlsl_ir_node, entry);
|
|
|
|
}
|
|
|
|
|
2021-05-20 22:32:20 -07:00
|
|
|
static struct list *make_empty_list(struct hlsl_ctx *ctx)
|
2021-02-27 16:03:12 -08:00
|
|
|
{
|
|
|
|
struct list *list;
|
|
|
|
|
2021-05-20 22:32:20 -07:00
|
|
|
if ((list = hlsl_alloc(ctx, sizeof(*list))))
|
2021-02-27 16:03:12 -08:00
|
|
|
list_init(list);
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2021-08-19 08:29:06 -07:00
|
|
|
static void destroy_instr_list(struct list *list)
|
|
|
|
{
|
|
|
|
hlsl_free_instr_list(list);
|
|
|
|
vkd3d_free(list);
|
|
|
|
}
|
|
|
|
|
2021-02-12 08:48:55 -08:00
|
|
|
static void check_invalid_matrix_modifiers(struct hlsl_ctx *ctx, DWORD modifiers, struct vkd3d_shader_location loc)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
if (modifiers & HLSL_MODIFIERS_MAJORITY_MASK)
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER,
|
2021-02-21 20:04:36 -08:00
|
|
|
"'row_major' and 'column_major' modifiers are only allowed for matrices.");
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:17 -08:00
|
|
|
static bool convertible_data_type(struct hlsl_type *type)
|
2021-01-30 11:51:34 -08:00
|
|
|
{
|
|
|
|
return type->type != HLSL_CLASS_OBJECT;
|
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:17 -08:00
|
|
|
static bool compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2)
|
2021-01-30 11:51:36 -08:00
|
|
|
{
|
|
|
|
if (!convertible_data_type(t1) || !convertible_data_type(t2))
|
2021-02-02 14:11:17 -08:00
|
|
|
return false;
|
2021-01-30 11:51:36 -08:00
|
|
|
|
|
|
|
if (t1->type <= HLSL_CLASS_LAST_NUMERIC)
|
|
|
|
{
|
|
|
|
/* Scalar vars can be cast to pretty much everything */
|
|
|
|
if (t1->dimx == 1 && t1->dimy == 1)
|
2021-02-02 14:11:17 -08:00
|
|
|
return true;
|
2021-01-30 11:51:36 -08:00
|
|
|
|
|
|
|
if (t1->type == HLSL_CLASS_VECTOR && t2->type == HLSL_CLASS_VECTOR)
|
|
|
|
return t1->dimx >= t2->dimx;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The other way around is true too i.e. whatever to scalar */
|
|
|
|
if (t2->type <= HLSL_CLASS_LAST_NUMERIC && t2->dimx == 1 && t2->dimy == 1)
|
2021-02-02 14:11:17 -08:00
|
|
|
return true;
|
2021-01-30 11:51:36 -08:00
|
|
|
|
|
|
|
if (t1->type == HLSL_CLASS_ARRAY)
|
|
|
|
{
|
2021-03-17 22:22:19 -07:00
|
|
|
if (hlsl_types_are_equal(t1->e.array.type, t2))
|
2021-01-30 11:51:36 -08:00
|
|
|
/* e.g. float4[3] to float4 is allowed */
|
2021-02-02 14:11:17 -08:00
|
|
|
return true;
|
2021-01-30 11:51:36 -08:00
|
|
|
|
|
|
|
if (t2->type == HLSL_CLASS_ARRAY || t2->type == HLSL_CLASS_STRUCT)
|
2021-02-02 14:11:14 -08:00
|
|
|
return hlsl_type_component_count(t1) >= hlsl_type_component_count(t2);
|
2021-01-30 11:51:36 -08:00
|
|
|
else
|
2021-02-02 14:11:14 -08:00
|
|
|
return hlsl_type_component_count(t1) == hlsl_type_component_count(t2);
|
2021-01-30 11:51:36 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (t1->type == HLSL_CLASS_STRUCT)
|
2021-02-02 14:11:14 -08:00
|
|
|
return hlsl_type_component_count(t1) >= hlsl_type_component_count(t2);
|
2021-01-30 11:51:36 -08:00
|
|
|
|
|
|
|
if (t2->type == HLSL_CLASS_ARRAY || t2->type == HLSL_CLASS_STRUCT)
|
2021-02-02 14:11:14 -08:00
|
|
|
return hlsl_type_component_count(t1) == hlsl_type_component_count(t2);
|
2021-01-30 11:51:36 -08:00
|
|
|
|
|
|
|
if (t1->type == HLSL_CLASS_MATRIX || t2->type == HLSL_CLASS_MATRIX)
|
|
|
|
{
|
|
|
|
if (t1->type == HLSL_CLASS_MATRIX && t2->type == HLSL_CLASS_MATRIX && t1->dimx >= t2->dimx && t1->dimy >= t2->dimy)
|
2021-02-02 14:11:17 -08:00
|
|
|
return true;
|
2021-01-30 11:51:36 -08:00
|
|
|
|
|
|
|
/* Matrix-vector conversion is apparently allowed if they have the same components count */
|
|
|
|
if ((t1->type == HLSL_CLASS_VECTOR || t2->type == HLSL_CLASS_VECTOR)
|
2021-02-02 14:11:14 -08:00
|
|
|
&& hlsl_type_component_count(t1) == hlsl_type_component_count(t2))
|
2021-02-02 14:11:17 -08:00
|
|
|
return true;
|
|
|
|
return false;
|
2021-01-30 11:51:36 -08:00
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:14 -08:00
|
|
|
if (hlsl_type_component_count(t1) >= hlsl_type_component_count(t2))
|
2021-02-02 14:11:17 -08:00
|
|
|
return true;
|
|
|
|
return false;
|
2021-01-30 11:51:36 -08:00
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:17 -08:00
|
|
|
static bool implicit_compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2)
|
2021-01-30 11:51:34 -08:00
|
|
|
{
|
|
|
|
if (!convertible_data_type(t1) || !convertible_data_type(t2))
|
2021-02-02 14:11:17 -08:00
|
|
|
return false;
|
2021-01-30 11:51:34 -08:00
|
|
|
|
|
|
|
if (t1->type <= HLSL_CLASS_LAST_NUMERIC)
|
|
|
|
{
|
|
|
|
/* Scalar vars can be converted to any other numeric data type */
|
|
|
|
if (t1->dimx == 1 && t1->dimy == 1 && t2->type <= HLSL_CLASS_LAST_NUMERIC)
|
2021-02-02 14:11:17 -08:00
|
|
|
return true;
|
2021-01-30 11:51:34 -08:00
|
|
|
/* The other way around is true too */
|
|
|
|
if (t2->dimx == 1 && t2->dimy == 1 && t2->type <= HLSL_CLASS_LAST_NUMERIC)
|
2021-02-02 14:11:17 -08:00
|
|
|
return true;
|
2021-01-30 11:51:34 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (t1->type == HLSL_CLASS_ARRAY && t2->type == HLSL_CLASS_ARRAY)
|
|
|
|
{
|
2021-02-02 14:11:14 -08:00
|
|
|
return hlsl_type_component_count(t1) == hlsl_type_component_count(t2);
|
2021-01-30 11:51:34 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((t1->type == HLSL_CLASS_ARRAY && t2->type <= HLSL_CLASS_LAST_NUMERIC)
|
|
|
|
|| (t1->type <= HLSL_CLASS_LAST_NUMERIC && t2->type == HLSL_CLASS_ARRAY))
|
|
|
|
{
|
|
|
|
/* e.g. float4[3] to float4 is allowed */
|
2021-03-17 22:22:19 -07:00
|
|
|
if (t1->type == HLSL_CLASS_ARRAY && hlsl_types_are_equal(t1->e.array.type, t2))
|
2021-02-02 14:11:17 -08:00
|
|
|
return true;
|
2021-02-02 14:11:14 -08:00
|
|
|
if (hlsl_type_component_count(t1) == hlsl_type_component_count(t2))
|
2021-02-02 14:11:17 -08:00
|
|
|
return true;
|
|
|
|
return false;
|
2021-01-30 11:51:34 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (t1->type <= HLSL_CLASS_VECTOR && t2->type <= HLSL_CLASS_VECTOR)
|
|
|
|
{
|
|
|
|
if (t1->dimx >= t2->dimx)
|
2021-02-02 14:11:17 -08:00
|
|
|
return true;
|
|
|
|
return false;
|
2021-01-30 11:51:34 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (t1->type == HLSL_CLASS_MATRIX || t2->type == HLSL_CLASS_MATRIX)
|
|
|
|
{
|
2021-10-25 00:06:30 -07:00
|
|
|
if (t1->type == HLSL_CLASS_MATRIX && t2->type == HLSL_CLASS_MATRIX)
|
|
|
|
return t1->dimx >= t2->dimx && t1->dimy >= t2->dimy;
|
|
|
|
|
|
|
|
/* Matrix-vector conversion is apparently allowed if they have
|
|
|
|
* the same components count, or if the matrix is 1xN or Nx1
|
|
|
|
* and we are reducing the component count */
|
|
|
|
if (t1->type == HLSL_CLASS_VECTOR || t2->type == HLSL_CLASS_VECTOR)
|
|
|
|
{
|
|
|
|
if (hlsl_type_component_count(t1) == hlsl_type_component_count(t2))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if ((t1->type == HLSL_CLASS_VECTOR || t1->dimx == 1 || t1->dimy == 1) &&
|
|
|
|
(t2->type == HLSL_CLASS_VECTOR || t2->dimx == 1 || t2->dimy == 1))
|
|
|
|
return hlsl_type_component_count(t1) >= hlsl_type_component_count(t2);
|
|
|
|
}
|
2021-01-30 11:51:34 -08:00
|
|
|
|
2021-02-02 14:11:17 -08:00
|
|
|
return false;
|
2021-01-30 11:51:34 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (t1->type == HLSL_CLASS_STRUCT && t2->type == HLSL_CLASS_STRUCT)
|
2021-03-17 22:22:19 -07:00
|
|
|
return hlsl_types_are_equal(t1, t2);
|
2021-01-30 11:51:34 -08:00
|
|
|
|
2021-02-02 14:11:17 -08:00
|
|
|
return false;
|
2021-01-30 11:51:34 -08:00
|
|
|
}
|
|
|
|
|
2022-06-29 15:29:42 -07:00
|
|
|
static struct hlsl_ir_load *add_load_component(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *var_instr,
|
|
|
|
unsigned int comp, const struct vkd3d_shader_location *loc);
|
2022-06-08 16:18:41 -07:00
|
|
|
|
2022-06-07 14:29:19 -07:00
|
|
|
static struct hlsl_ir_node *add_cast(struct hlsl_ctx *ctx, struct list *instrs,
|
2021-10-07 19:58:57 -07:00
|
|
|
struct hlsl_ir_node *node, struct hlsl_type *dst_type, const struct vkd3d_shader_location *loc)
|
2021-01-30 11:51:34 -08:00
|
|
|
{
|
|
|
|
struct hlsl_type *src_type = node->data_type;
|
|
|
|
struct hlsl_ir_expr *cast;
|
|
|
|
|
2021-03-17 22:22:19 -07:00
|
|
|
if (hlsl_types_are_equal(src_type, dst_type))
|
2021-01-30 11:51:34 -08:00
|
|
|
return node;
|
|
|
|
|
2022-06-08 16:18:41 -07:00
|
|
|
if ((src_type->type == HLSL_CLASS_MATRIX || dst_type->type == HLSL_CLASS_MATRIX)
|
|
|
|
&& src_type->type <= HLSL_CLASS_LAST_NUMERIC && dst_type->type <= HLSL_CLASS_LAST_NUMERIC)
|
|
|
|
{
|
|
|
|
struct vkd3d_string_buffer *name;
|
|
|
|
static unsigned int counter = 0;
|
|
|
|
struct hlsl_ir_load *load;
|
|
|
|
struct hlsl_ir_var *var;
|
|
|
|
unsigned int dst_idx;
|
|
|
|
bool broadcast;
|
|
|
|
|
|
|
|
broadcast = src_type->dimx == 1 && src_type->dimy == 1;
|
|
|
|
assert(dst_type->dimx * dst_type->dimy <= src_type->dimx * src_type->dimy || broadcast);
|
|
|
|
if (src_type->type == HLSL_CLASS_MATRIX && dst_type->type == HLSL_CLASS_MATRIX && !broadcast)
|
|
|
|
{
|
|
|
|
assert(dst_type->dimx <= src_type->dimx);
|
|
|
|
assert(dst_type->dimy <= src_type->dimy);
|
|
|
|
}
|
|
|
|
|
|
|
|
name = vkd3d_string_buffer_get(&ctx->string_buffers);
|
|
|
|
vkd3d_string_buffer_printf(name, "<cast-%u>", counter++);
|
|
|
|
var = hlsl_new_synthetic_var(ctx, name->buffer, dst_type, *loc);
|
|
|
|
vkd3d_string_buffer_release(&ctx->string_buffers, name);
|
|
|
|
if (!var)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (dst_idx = 0; dst_idx < dst_type->dimx * dst_type->dimy; ++dst_idx)
|
|
|
|
{
|
2022-06-29 15:29:42 -07:00
|
|
|
struct hlsl_type *dst_scalar_type;
|
|
|
|
unsigned int src_idx, dst_offset;
|
2022-06-08 16:18:41 -07:00
|
|
|
struct hlsl_ir_store *store;
|
|
|
|
struct hlsl_ir_constant *c;
|
|
|
|
|
|
|
|
if (broadcast)
|
|
|
|
{
|
|
|
|
src_idx = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (src_type->type == HLSL_CLASS_MATRIX && dst_type->type == HLSL_CLASS_MATRIX)
|
|
|
|
{
|
|
|
|
unsigned int x = dst_idx % dst_type->dimx, y = dst_idx / dst_type->dimx;
|
|
|
|
|
|
|
|
src_idx = y * src_type->dimx + x;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src_idx = dst_idx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dst_offset = hlsl_compute_component_offset(ctx, dst_type, dst_idx, &dst_scalar_type);
|
|
|
|
|
2022-06-29 15:29:42 -07:00
|
|
|
if (!(load = add_load_component(ctx, instrs, node, src_idx, loc)))
|
2022-06-08 16:18:41 -07:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!(cast = hlsl_new_cast(ctx, &load->node, dst_scalar_type, loc)))
|
|
|
|
return NULL;
|
|
|
|
list_add_tail(instrs, &cast->node.entry);
|
|
|
|
|
|
|
|
if (!(c = hlsl_new_uint_constant(ctx, dst_offset, loc)))
|
|
|
|
return NULL;
|
|
|
|
list_add_tail(instrs, &c->node.entry);
|
|
|
|
|
|
|
|
if (!(store = hlsl_new_store(ctx, var, &c->node, &cast->node, 0, *loc)))
|
|
|
|
return NULL;
|
|
|
|
list_add_tail(instrs, &store->node.entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(load = hlsl_new_load(ctx, var, NULL, dst_type, *loc)))
|
|
|
|
return NULL;
|
|
|
|
list_add_tail(instrs, &load->node.entry);
|
|
|
|
|
|
|
|
return &load->node;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!(cast = hlsl_new_cast(ctx, node, dst_type, loc)))
|
|
|
|
return NULL;
|
|
|
|
list_add_tail(instrs, &cast->node.entry);
|
|
|
|
return &cast->node;
|
|
|
|
}
|
2022-06-07 14:29:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct hlsl_ir_node *add_implicit_conversion(struct hlsl_ctx *ctx, struct list *instrs,
|
|
|
|
struct hlsl_ir_node *node, struct hlsl_type *dst_type, const struct vkd3d_shader_location *loc)
|
|
|
|
{
|
|
|
|
struct hlsl_type *src_type = node->data_type;
|
|
|
|
|
2021-01-30 11:51:34 -08:00
|
|
|
if (!implicit_compatible_data_types(src_type, dst_type))
|
|
|
|
{
|
2021-02-27 16:03:09 -08:00
|
|
|
struct vkd3d_string_buffer *src_string, *dst_string;
|
2021-02-12 12:38:50 -08:00
|
|
|
|
2021-05-20 22:32:22 -07:00
|
|
|
src_string = hlsl_type_to_string(ctx, src_type);
|
|
|
|
dst_string = hlsl_type_to_string(ctx, dst_type);
|
2021-02-12 12:38:50 -08:00
|
|
|
if (src_string && dst_string)
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
|
2021-02-27 16:03:09 -08:00
|
|
|
"Can't implicitly convert from %s to %s.", src_string->buffer, dst_string->buffer);
|
2021-05-20 22:32:22 -07:00
|
|
|
hlsl_release_string_buffer(ctx, src_string);
|
|
|
|
hlsl_release_string_buffer(ctx, dst_string);
|
2021-01-30 11:51:34 -08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dst_type->dimx * dst_type->dimy < src_type->dimx * src_type->dimy)
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_warning(ctx, loc, VKD3D_SHADER_WARNING_HLSL_IMPLICIT_TRUNCATION, "Implicit truncation of %s type.",
|
2021-02-21 20:04:36 -08:00
|
|
|
src_type->type == HLSL_CLASS_VECTOR ? "vector" : "matrix");
|
2021-01-30 11:51:34 -08:00
|
|
|
|
2022-06-07 14:29:19 -07:00
|
|
|
return add_cast(ctx, instrs, node, dst_type, loc);
|
2021-01-30 11:51:34 -08:00
|
|
|
}
|
|
|
|
|
2021-02-12 08:48:55 -08:00
|
|
|
static DWORD add_modifiers(struct hlsl_ctx *ctx, DWORD modifiers, DWORD mod, const struct vkd3d_shader_location loc)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
if (modifiers & mod)
|
|
|
|
{
|
2021-02-27 16:03:10 -08:00
|
|
|
struct vkd3d_string_buffer *string;
|
2021-02-12 12:38:49 -08:00
|
|
|
|
2021-05-20 22:32:22 -07:00
|
|
|
if ((string = hlsl_modifiers_to_string(ctx, mod)))
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER,
|
2021-02-27 16:03:10 -08:00
|
|
|
"Modifier '%s' was already specified.", string->buffer);
|
2021-05-20 22:32:22 -07:00
|
|
|
hlsl_release_string_buffer(ctx, string);
|
2021-01-27 08:29:44 -08:00
|
|
|
return modifiers;
|
|
|
|
}
|
|
|
|
if ((mod & HLSL_MODIFIERS_MAJORITY_MASK) && (modifiers & HLSL_MODIFIERS_MAJORITY_MASK))
|
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER,
|
2021-02-21 20:04:36 -08:00
|
|
|
"'row_major' and 'column_major' modifiers are mutually exclusive.");
|
2021-01-27 08:29:44 -08:00
|
|
|
return modifiers;
|
|
|
|
}
|
|
|
|
return modifiers | mod;
|
|
|
|
}
|
|
|
|
|
2021-05-20 22:32:20 -07:00
|
|
|
static bool append_conditional_break(struct hlsl_ctx *ctx, struct list *cond_list)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
struct hlsl_ir_node *condition, *not;
|
|
|
|
struct hlsl_ir_jump *jump;
|
|
|
|
struct hlsl_ir_if *iff;
|
|
|
|
|
|
|
|
/* E.g. "for (i = 0; ; ++i)". */
|
2022-01-19 03:51:59 -08:00
|
|
|
if (list_empty(cond_list))
|
2021-02-02 14:11:17 -08:00
|
|
|
return true;
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
condition = node_from_list(cond_list);
|
2021-08-12 17:36:13 -07:00
|
|
|
if (!(not = hlsl_new_unary_expr(ctx, HLSL_OP1_LOGIC_NOT, condition, condition->loc)))
|
2021-02-02 14:11:17 -08:00
|
|
|
return false;
|
2021-01-27 08:29:44 -08:00
|
|
|
list_add_tail(cond_list, ¬->entry);
|
|
|
|
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!(iff = hlsl_new_if(ctx, not, condition->loc)))
|
2021-02-02 14:11:17 -08:00
|
|
|
return false;
|
2021-01-27 08:29:44 -08:00
|
|
|
list_add_tail(cond_list, &iff->node.entry);
|
|
|
|
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!(jump = hlsl_new_jump(ctx, HLSL_IR_JUMP_BREAK, condition->loc)))
|
2021-02-02 14:11:17 -08:00
|
|
|
return false;
|
2021-10-15 14:54:10 -07:00
|
|
|
list_add_head(&iff->then_instrs.instrs, &jump->node.entry);
|
2021-02-02 14:11:17 -08:00
|
|
|
return true;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
enum loop_type
|
|
|
|
{
|
|
|
|
LOOP_FOR,
|
|
|
|
LOOP_WHILE,
|
|
|
|
LOOP_DO_WHILE
|
|
|
|
};
|
|
|
|
|
2021-05-20 22:32:20 -07:00
|
|
|
static struct list *create_loop(struct hlsl_ctx *ctx, enum loop_type type, struct list *init, struct list *cond,
|
2021-02-12 08:48:55 -08:00
|
|
|
struct list *iter, struct list *body, struct vkd3d_shader_location loc)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
struct list *list = NULL;
|
|
|
|
struct hlsl_ir_loop *loop = NULL;
|
|
|
|
struct hlsl_ir_if *cond_jump = NULL;
|
|
|
|
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!(list = make_empty_list(ctx)))
|
2021-01-27 08:29:44 -08:00
|
|
|
goto oom;
|
|
|
|
|
|
|
|
if (init)
|
|
|
|
list_move_head(list, init);
|
|
|
|
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!(loop = hlsl_new_loop(ctx, loc)))
|
2021-01-27 08:29:44 -08:00
|
|
|
goto oom;
|
|
|
|
list_add_tail(list, &loop->node.entry);
|
|
|
|
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!append_conditional_break(ctx, cond))
|
2021-01-27 08:29:44 -08:00
|
|
|
goto oom;
|
|
|
|
|
|
|
|
if (type != LOOP_DO_WHILE)
|
2021-10-15 14:54:10 -07:00
|
|
|
list_move_tail(&loop->body.instrs, cond);
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2021-10-15 14:54:10 -07:00
|
|
|
list_move_tail(&loop->body.instrs, body);
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
if (iter)
|
2021-10-15 14:54:10 -07:00
|
|
|
list_move_tail(&loop->body.instrs, iter);
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
if (type == LOOP_DO_WHILE)
|
2021-10-15 14:54:10 -07:00
|
|
|
list_move_tail(&loop->body.instrs, cond);
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
vkd3d_free(init);
|
|
|
|
vkd3d_free(cond);
|
|
|
|
vkd3d_free(body);
|
|
|
|
return list;
|
|
|
|
|
|
|
|
oom:
|
|
|
|
vkd3d_free(loop);
|
|
|
|
vkd3d_free(cond_jump);
|
|
|
|
vkd3d_free(list);
|
2021-08-19 08:29:06 -07:00
|
|
|
destroy_instr_list(init);
|
|
|
|
destroy_instr_list(cond);
|
|
|
|
destroy_instr_list(iter);
|
|
|
|
destroy_instr_list(body);
|
2021-01-27 08:29:44 -08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int initializer_size(const struct parse_initializer *initializer)
|
|
|
|
{
|
|
|
|
unsigned int count = 0, i;
|
|
|
|
|
|
|
|
for (i = 0; i < initializer->args_count; ++i)
|
|
|
|
{
|
2021-02-02 14:11:14 -08:00
|
|
|
count += hlsl_type_component_count(initializer->args[i]->data_type);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void free_parse_initializer(struct parse_initializer *initializer)
|
|
|
|
{
|
2021-08-19 08:29:06 -07:00
|
|
|
destroy_instr_list(initializer->instrs);
|
2021-01-27 08:29:44 -08:00
|
|
|
vkd3d_free(initializer->args);
|
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
static struct hlsl_ir_swizzle *get_swizzle(struct hlsl_ctx *ctx, struct hlsl_ir_node *value, const char *swizzle,
|
2021-02-12 08:48:55 -08:00
|
|
|
struct vkd3d_shader_location *loc)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
unsigned int len = strlen(swizzle), component = 0;
|
|
|
|
unsigned int i, set, swiz = 0;
|
2021-02-02 14:11:17 -08:00
|
|
|
bool valid;
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
if (value->data_type->type == HLSL_CLASS_MATRIX)
|
|
|
|
{
|
|
|
|
/* Matrix swizzle */
|
2021-02-02 14:11:17 -08:00
|
|
|
bool m_swizzle;
|
2021-01-27 08:29:44 -08:00
|
|
|
unsigned int inc, x, y;
|
|
|
|
|
|
|
|
if (len < 3 || swizzle[0] != '_')
|
|
|
|
return NULL;
|
|
|
|
m_swizzle = swizzle[1] == 'm';
|
|
|
|
inc = m_swizzle ? 4 : 3;
|
|
|
|
|
|
|
|
if (len % inc || len > inc * 4)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (i = 0; i < len; i += inc)
|
|
|
|
{
|
|
|
|
if (swizzle[i] != '_')
|
|
|
|
return NULL;
|
|
|
|
if (m_swizzle)
|
|
|
|
{
|
|
|
|
if (swizzle[i + 1] != 'm')
|
|
|
|
return NULL;
|
|
|
|
y = swizzle[i + 2] - '0';
|
|
|
|
x = swizzle[i + 3] - '0';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
y = swizzle[i + 1] - '1';
|
|
|
|
x = swizzle[i + 2] - '1';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (x >= value->data_type->dimx || y >= value->data_type->dimy)
|
|
|
|
return NULL;
|
|
|
|
swiz |= (y << 4 | x) << component * 8;
|
|
|
|
component++;
|
|
|
|
}
|
2021-02-04 14:33:53 -08:00
|
|
|
return hlsl_new_swizzle(ctx, swiz, component, value, loc);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Vector swizzle */
|
|
|
|
if (len > 4)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (set = 0; set < 2; ++set)
|
|
|
|
{
|
2021-02-02 14:11:17 -08:00
|
|
|
valid = true;
|
2021-01-27 08:29:44 -08:00
|
|
|
component = 0;
|
|
|
|
for (i = 0; i < len; ++i)
|
|
|
|
{
|
|
|
|
char c[2][4] = {{'x', 'y', 'z', 'w'}, {'r', 'g', 'b', 'a'}};
|
|
|
|
unsigned int s = 0;
|
|
|
|
|
|
|
|
for (s = 0; s < 4; ++s)
|
|
|
|
{
|
|
|
|
if (swizzle[i] == c[set][s])
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (s == 4)
|
|
|
|
{
|
2021-02-02 14:11:17 -08:00
|
|
|
valid = false;
|
2021-01-27 08:29:44 -08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s >= value->data_type->dimx)
|
|
|
|
return NULL;
|
|
|
|
swiz |= s << component * 2;
|
|
|
|
component++;
|
|
|
|
}
|
|
|
|
if (valid)
|
2021-02-04 14:33:53 -08:00
|
|
|
return hlsl_new_swizzle(ctx, swiz, component, value, loc);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
static struct hlsl_ir_jump *add_return(struct hlsl_ctx *ctx, struct list *instrs,
|
2021-02-12 08:48:55 -08:00
|
|
|
struct hlsl_ir_node *return_value, struct vkd3d_shader_location loc)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
struct hlsl_type *return_type = ctx->cur_function->return_type;
|
2021-01-27 08:29:44 -08:00
|
|
|
struct hlsl_ir_jump *jump;
|
|
|
|
|
|
|
|
if (return_value)
|
|
|
|
{
|
2021-04-08 21:38:22 -07:00
|
|
|
struct hlsl_ir_store *store;
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
if (!(return_value = add_implicit_conversion(ctx, instrs, return_value, return_type, &loc)))
|
2021-01-27 08:29:44 -08:00
|
|
|
return NULL;
|
|
|
|
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!(store = hlsl_new_simple_store(ctx, ctx->cur_function->return_var, return_value)))
|
2021-01-27 08:29:44 -08:00
|
|
|
return NULL;
|
2021-04-08 21:38:22 -07:00
|
|
|
list_add_after(&return_value->entry, &store->node.entry);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
2021-10-03 17:19:06 -07:00
|
|
|
else if (ctx->cur_function->return_var)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RETURN, "Non-void function must return a value.");
|
2021-01-27 08:29:44 -08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!(jump = hlsl_new_jump(ctx, HLSL_IR_JUMP_RETURN, loc)))
|
2021-01-27 08:29:44 -08:00
|
|
|
return NULL;
|
|
|
|
list_add_tail(instrs, &jump->node.entry);
|
|
|
|
|
|
|
|
return jump;
|
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
static struct hlsl_ir_load *add_load(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *var_node,
|
2021-02-12 08:48:55 -08:00
|
|
|
struct hlsl_ir_node *offset, struct hlsl_type *data_type, const struct vkd3d_shader_location loc)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
struct hlsl_ir_node *add = NULL;
|
|
|
|
struct hlsl_ir_load *load;
|
|
|
|
struct hlsl_ir_var *var;
|
|
|
|
|
|
|
|
if (var_node->type == HLSL_IR_LOAD)
|
|
|
|
{
|
2021-02-02 14:11:14 -08:00
|
|
|
const struct hlsl_deref *src = &hlsl_ir_load(var_node)->src;
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
var = src->var;
|
|
|
|
if (src->offset.node)
|
|
|
|
{
|
2021-08-12 17:36:13 -07:00
|
|
|
if (!(add = hlsl_new_binary_expr(ctx, HLSL_OP2_ADD, src->offset.node, offset)))
|
2021-01-27 08:29:44 -08:00
|
|
|
return NULL;
|
|
|
|
list_add_tail(instrs, &add->entry);
|
|
|
|
offset = add;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-04-08 21:38:22 -07:00
|
|
|
struct hlsl_ir_store *store;
|
2021-01-27 08:29:44 -08:00
|
|
|
char name[27];
|
|
|
|
|
|
|
|
sprintf(name, "<deref-%p>", var_node);
|
2021-02-04 14:33:53 -08:00
|
|
|
if (!(var = hlsl_new_synthetic_var(ctx, name, var_node->data_type, var_node->loc)))
|
2021-01-27 08:29:44 -08:00
|
|
|
return NULL;
|
|
|
|
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!(store = hlsl_new_simple_store(ctx, var, var_node)))
|
2021-01-27 08:29:44 -08:00
|
|
|
return NULL;
|
|
|
|
|
2021-04-08 21:38:22 -07:00
|
|
|
list_add_tail(instrs, &store->node.entry);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!(load = hlsl_new_load(ctx, var, offset, data_type, loc)))
|
2021-01-27 08:29:44 -08:00
|
|
|
return NULL;
|
|
|
|
list_add_tail(instrs, &load->node.entry);
|
|
|
|
return load;
|
|
|
|
}
|
|
|
|
|
2022-06-29 15:29:42 -07:00
|
|
|
static struct hlsl_ir_load *add_load_component(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *var_instr,
|
|
|
|
unsigned int comp, const struct vkd3d_shader_location *loc)
|
|
|
|
{
|
|
|
|
struct hlsl_type *comp_type;
|
|
|
|
struct hlsl_ir_node *offset;
|
|
|
|
struct hlsl_ir_constant *c;
|
|
|
|
struct hlsl_ir_load *load;
|
|
|
|
unsigned int comp_offset;
|
|
|
|
struct hlsl_ir_var *var;
|
|
|
|
|
|
|
|
comp_offset = hlsl_compute_component_offset(ctx, var_instr->data_type, comp, &comp_type);
|
|
|
|
|
|
|
|
if (!(c = hlsl_new_uint_constant(ctx, comp_offset, loc)))
|
|
|
|
return NULL;
|
|
|
|
list_add_tail(instrs, &c->node.entry);
|
|
|
|
|
|
|
|
offset = &c->node;
|
|
|
|
|
|
|
|
if (var_instr->type == HLSL_IR_LOAD)
|
|
|
|
{
|
|
|
|
const struct hlsl_deref *src = &hlsl_ir_load(var_instr)->src;
|
|
|
|
struct hlsl_ir_node *add;
|
|
|
|
|
|
|
|
var = src->var;
|
|
|
|
if (src->offset.node)
|
|
|
|
{
|
|
|
|
if (!(add = hlsl_new_binary_expr(ctx, HLSL_OP2_ADD, src->offset.node, &c->node)))
|
|
|
|
return NULL;
|
|
|
|
list_add_tail(instrs, &add->entry);
|
|
|
|
offset = add;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
struct vkd3d_string_buffer *name;
|
|
|
|
struct hlsl_ir_store *store;
|
|
|
|
|
|
|
|
if (!(name = hlsl_get_string_buffer(ctx)))
|
|
|
|
return NULL;
|
|
|
|
vkd3d_string_buffer_printf(name, "<deref-%p>", var_instr);
|
|
|
|
var = hlsl_new_synthetic_var(ctx, name->buffer, var_instr->data_type, var_instr->loc);
|
|
|
|
hlsl_release_string_buffer(ctx, name);
|
|
|
|
if (!var)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!(store = hlsl_new_simple_store(ctx, var, var_instr)))
|
|
|
|
return NULL;
|
|
|
|
list_add_tail(instrs, &store->node.entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(load = hlsl_new_load(ctx, var, offset, comp_type, *loc)))
|
|
|
|
return NULL;
|
|
|
|
list_add_tail(instrs, &load->node.entry);
|
|
|
|
|
|
|
|
return load;
|
|
|
|
}
|
|
|
|
|
2022-04-17 23:34:00 -07:00
|
|
|
static bool add_record_load(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *record,
|
2022-07-14 18:23:45 -07:00
|
|
|
unsigned int idx, const struct vkd3d_shader_location loc)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2022-07-14 18:23:45 -07:00
|
|
|
const struct hlsl_struct_field *field;
|
2021-01-27 08:29:44 -08:00
|
|
|
struct hlsl_ir_constant *c;
|
|
|
|
|
2022-07-14 18:23:45 -07:00
|
|
|
assert(idx < record->data_type->e.record.field_count);
|
|
|
|
field = &record->data_type->e.record.fields[idx];
|
|
|
|
|
2022-04-05 03:33:10 -07:00
|
|
|
if (!(c = hlsl_new_uint_constant(ctx, field->reg_offset, &loc)))
|
2022-04-17 23:34:00 -07:00
|
|
|
return false;
|
2021-01-27 08:29:44 -08:00
|
|
|
list_add_tail(instrs, &c->node.entry);
|
|
|
|
|
2022-04-17 23:34:00 -07:00
|
|
|
return !!add_load(ctx, instrs, record, &c->node, field->type, loc);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
2022-06-07 14:29:21 -07:00
|
|
|
static struct hlsl_ir_node *add_binary_arithmetic_expr(struct hlsl_ctx *ctx, struct list *instrs,
|
2022-04-27 01:56:25 -07:00
|
|
|
enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg1, struct hlsl_ir_node *arg2,
|
|
|
|
const struct vkd3d_shader_location *loc);
|
|
|
|
|
|
|
|
static struct hlsl_ir_node *add_matrix_scalar_load(struct hlsl_ctx *ctx, struct list *instrs,
|
|
|
|
struct hlsl_ir_node *matrix, struct hlsl_ir_node *x, struct hlsl_ir_node *y,
|
|
|
|
const struct vkd3d_shader_location *loc)
|
|
|
|
{
|
2022-06-07 14:29:21 -07:00
|
|
|
struct hlsl_ir_node *major, *minor, *mul, *add;
|
2022-04-27 01:56:25 -07:00
|
|
|
struct hlsl_ir_constant *four;
|
|
|
|
struct hlsl_ir_load *load;
|
|
|
|
struct hlsl_type *type = matrix->data_type, *scalar_type;
|
|
|
|
|
|
|
|
scalar_type = hlsl_get_scalar_type(ctx, type->base_type);
|
|
|
|
|
|
|
|
if (type->modifiers & HLSL_MODIFIER_ROW_MAJOR)
|
|
|
|
{
|
|
|
|
minor = x;
|
|
|
|
major = y;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
minor = y;
|
|
|
|
major = x;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(four = hlsl_new_uint_constant(ctx, 4, loc)))
|
|
|
|
return NULL;
|
|
|
|
list_add_tail(instrs, &four->node.entry);
|
|
|
|
|
|
|
|
if (!(mul = add_binary_arithmetic_expr(ctx, instrs, HLSL_OP2_MUL, &four->node, major, loc)))
|
|
|
|
return NULL;
|
|
|
|
|
2022-06-07 14:29:21 -07:00
|
|
|
if (!(add = add_binary_arithmetic_expr(ctx, instrs, HLSL_OP2_ADD, mul, minor, loc)))
|
2022-04-27 01:56:25 -07:00
|
|
|
return NULL;
|
|
|
|
|
2022-06-07 14:29:21 -07:00
|
|
|
if (!(load = add_load(ctx, instrs, matrix, add, scalar_type, *loc)))
|
2022-04-27 01:56:25 -07:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return &load->node;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool add_matrix_index(struct hlsl_ctx *ctx, struct list *instrs,
|
|
|
|
struct hlsl_ir_node *matrix, struct hlsl_ir_node *index, const struct vkd3d_shader_location *loc)
|
|
|
|
{
|
|
|
|
struct hlsl_type *mat_type = matrix->data_type, *ret_type;
|
|
|
|
struct vkd3d_string_buffer *name;
|
|
|
|
static unsigned int counter = 0;
|
|
|
|
struct hlsl_ir_load *load;
|
|
|
|
struct hlsl_ir_var *var;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
ret_type = hlsl_get_vector_type(ctx, mat_type->base_type, mat_type->dimx);
|
|
|
|
|
|
|
|
name = vkd3d_string_buffer_get(&ctx->string_buffers);
|
|
|
|
vkd3d_string_buffer_printf(name, "<index-%u>", counter++);
|
|
|
|
var = hlsl_new_synthetic_var(ctx, name->buffer, ret_type, *loc);
|
|
|
|
vkd3d_string_buffer_release(&ctx->string_buffers, name);
|
|
|
|
if (!var)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (i = 0; i < mat_type->dimx; ++i)
|
|
|
|
{
|
|
|
|
struct hlsl_ir_store *store;
|
|
|
|
struct hlsl_ir_node *value;
|
|
|
|
struct hlsl_ir_constant *c;
|
|
|
|
|
|
|
|
if (!(c = hlsl_new_uint_constant(ctx, i, loc)))
|
|
|
|
return false;
|
|
|
|
list_add_tail(instrs, &c->node.entry);
|
|
|
|
|
|
|
|
if (!(value = add_matrix_scalar_load(ctx, instrs, matrix, &c->node, index, loc)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!(store = hlsl_new_store(ctx, var, &c->node, value, 0, *loc)))
|
|
|
|
return false;
|
|
|
|
list_add_tail(instrs, &store->node.entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(load = hlsl_new_var_load(ctx, var, *loc)))
|
|
|
|
return false;
|
|
|
|
list_add_tail(instrs, &load->node.entry);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-04-17 23:34:00 -07:00
|
|
|
static bool add_array_load(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *array,
|
2021-02-12 08:48:55 -08:00
|
|
|
struct hlsl_ir_node *index, const struct vkd3d_shader_location loc)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
const struct hlsl_type *expr_type = array->data_type;
|
|
|
|
struct hlsl_type *data_type;
|
|
|
|
struct hlsl_ir_constant *c;
|
|
|
|
|
|
|
|
if (expr_type->type == HLSL_CLASS_ARRAY)
|
|
|
|
{
|
|
|
|
data_type = expr_type->e.array.type;
|
2022-04-27 01:56:23 -07:00
|
|
|
|
2022-04-17 23:34:01 -07:00
|
|
|
if (!(c = hlsl_new_uint_constant(ctx, hlsl_type_get_array_element_reg_size(data_type), &loc)))
|
|
|
|
return false;
|
2022-04-27 01:56:23 -07:00
|
|
|
list_add_tail(instrs, &c->node.entry);
|
|
|
|
|
|
|
|
if (!(index = hlsl_new_binary_expr(ctx, HLSL_OP2_MUL, index, &c->node)))
|
|
|
|
return false;
|
|
|
|
list_add_tail(instrs, &index->entry);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
2022-04-17 23:34:01 -07:00
|
|
|
else if (expr_type->type == HLSL_CLASS_MATRIX)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2022-04-27 01:56:25 -07:00
|
|
|
return add_matrix_index(ctx, instrs, array, index, &loc);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
2022-04-17 23:34:01 -07:00
|
|
|
else if (expr_type->type == HLSL_CLASS_VECTOR)
|
|
|
|
{
|
|
|
|
data_type = hlsl_get_scalar_type(ctx, expr_type->base_type);
|
|
|
|
}
|
2021-01-27 08:29:44 -08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (expr_type->type == HLSL_CLASS_SCALAR)
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &loc, VKD3D_SHADER_ERROR_HLSL_INVALID_INDEX, "Scalar expressions cannot be array-indexed.");
|
2021-01-27 08:29:44 -08:00
|
|
|
else
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &loc, VKD3D_SHADER_ERROR_HLSL_INVALID_INDEX, "Expression cannot be array-indexed.");
|
2022-04-17 23:34:00 -07:00
|
|
|
return false;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
2022-04-17 23:34:00 -07:00
|
|
|
return !!add_load(ctx, instrs, array, index, data_type, loc);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
2022-07-14 18:23:43 -07:00
|
|
|
static const struct hlsl_struct_field *get_struct_field(const struct hlsl_struct_field *fields,
|
|
|
|
size_t count, const char *name)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2022-07-14 18:23:43 -07:00
|
|
|
size_t i;
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2022-07-14 18:23:43 -07:00
|
|
|
for (i = 0; i < count; ++i)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2022-07-14 18:23:43 -07:00
|
|
|
if (!strcmp(fields[i].name, name))
|
|
|
|
return &fields[i];
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
2021-03-02 13:34:43 -08:00
|
|
|
return NULL;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
static struct hlsl_type *apply_type_modifiers(struct hlsl_ctx *ctx, struct hlsl_type *type,
|
2021-02-12 08:48:55 -08:00
|
|
|
unsigned int *modifiers, struct vkd3d_shader_location loc)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
unsigned int default_majority = 0;
|
|
|
|
struct hlsl_type *new_type;
|
|
|
|
|
|
|
|
/* This function is only used for declarations (i.e. variables and struct
|
|
|
|
* fields), which should inherit the matrix majority. We only explicitly set
|
|
|
|
* the default majority for declarations—typedefs depend on this—but we
|
|
|
|
* want to always set it, so that an hlsl_type object is never used to
|
|
|
|
* represent two different majorities (and thus can be used to store its
|
|
|
|
* register size, etc.) */
|
|
|
|
if (!(*modifiers & HLSL_MODIFIERS_MAJORITY_MASK)
|
|
|
|
&& !(type->modifiers & HLSL_MODIFIERS_MAJORITY_MASK)
|
|
|
|
&& type->type == HLSL_CLASS_MATRIX)
|
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
if (ctx->matrix_majority == HLSL_COLUMN_MAJOR)
|
2021-01-27 08:29:44 -08:00
|
|
|
default_majority = HLSL_MODIFIER_COLUMN_MAJOR;
|
|
|
|
else
|
|
|
|
default_majority = HLSL_MODIFIER_ROW_MAJOR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!default_majority && !(*modifiers & HLSL_TYPE_MODIFIERS_MASK))
|
|
|
|
return type;
|
|
|
|
|
2021-06-23 21:57:32 -07:00
|
|
|
if (!(new_type = hlsl_type_clone(ctx, type, default_majority, *modifiers & HLSL_TYPE_MODIFIERS_MASK)))
|
2021-01-27 08:29:44 -08:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
*modifiers &= ~HLSL_TYPE_MODIFIERS_MASK;
|
|
|
|
|
2021-06-23 21:57:31 -07:00
|
|
|
if ((new_type->modifiers & HLSL_MODIFIER_ROW_MAJOR) && (new_type->modifiers & HLSL_MODIFIER_COLUMN_MAJOR))
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER,
|
2021-06-23 21:57:31 -07:00
|
|
|
"'row_major' and 'column_major' modifiers are mutually exclusive.");
|
|
|
|
|
2021-01-27 08:29:44 -08:00
|
|
|
return new_type;
|
|
|
|
}
|
|
|
|
|
2022-03-30 14:38:29 -07:00
|
|
|
static void free_parse_variable_def(struct parse_variable_def *v)
|
|
|
|
{
|
|
|
|
free_parse_initializer(&v->initializer);
|
|
|
|
vkd3d_free(v->arrays.sizes);
|
|
|
|
vkd3d_free(v->name);
|
|
|
|
vkd3d_free((void *)v->semantic.name);
|
|
|
|
vkd3d_free(v);
|
|
|
|
}
|
|
|
|
|
2022-07-14 18:23:43 -07:00
|
|
|
static bool gen_struct_fields(struct hlsl_ctx *ctx, struct parse_fields *fields,
|
|
|
|
struct hlsl_type *type, unsigned int modifiers, struct list *defs)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
struct parse_variable_def *v, *v_next;
|
2022-07-14 18:23:43 -07:00
|
|
|
size_t i = 0;
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
if (type->type == HLSL_CLASS_MATRIX)
|
|
|
|
assert(type->modifiers & HLSL_MODIFIERS_MAJORITY_MASK);
|
|
|
|
|
2022-07-14 18:23:43 -07:00
|
|
|
memset(fields, 0, sizeof(*fields));
|
|
|
|
fields->count = list_count(defs);
|
|
|
|
if (!hlsl_array_reserve(ctx, (void **)&fields->fields, &fields->capacity, fields->count, sizeof(*fields->fields)))
|
|
|
|
return false;
|
2021-03-04 15:33:27 -08:00
|
|
|
|
2022-07-14 18:23:43 -07:00
|
|
|
LIST_FOR_EACH_ENTRY_SAFE(v, v_next, defs, struct parse_variable_def, entry)
|
|
|
|
{
|
|
|
|
struct hlsl_struct_field *field = &fields->fields[i++];
|
|
|
|
unsigned int j;
|
2021-03-04 15:33:27 -08:00
|
|
|
|
|
|
|
field->type = type;
|
2022-07-14 18:23:43 -07:00
|
|
|
for (j = 0; j < v->arrays.count; ++j)
|
|
|
|
field->type = hlsl_new_array_type(ctx, field->type, v->arrays.sizes[j]);
|
2022-03-30 14:38:29 -07:00
|
|
|
vkd3d_free(v->arrays.sizes);
|
2021-03-02 13:34:43 -08:00
|
|
|
field->loc = v->loc;
|
2021-01-27 08:29:44 -08:00
|
|
|
field->name = v->name;
|
|
|
|
field->semantic = v->semantic;
|
2022-04-05 03:33:04 -07:00
|
|
|
field->modifiers = modifiers;
|
2021-01-27 08:29:44 -08:00
|
|
|
if (v->initializer.args_count)
|
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "Illegal initializer on a struct field.");
|
2021-01-27 08:29:44 -08:00
|
|
|
free_parse_initializer(&v->initializer);
|
|
|
|
}
|
|
|
|
vkd3d_free(v);
|
|
|
|
}
|
2022-07-14 18:23:43 -07:00
|
|
|
vkd3d_free(defs);
|
|
|
|
return true;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
static bool add_typedef(struct hlsl_ctx *ctx, DWORD modifiers, struct hlsl_type *orig_type, struct list *list)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
struct parse_variable_def *v, *v_next;
|
|
|
|
struct hlsl_type *type;
|
2021-03-04 15:33:27 -08:00
|
|
|
unsigned int i;
|
2021-02-02 14:11:17 -08:00
|
|
|
bool ret;
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY_SAFE(v, v_next, list, struct parse_variable_def, entry)
|
|
|
|
{
|
2021-03-04 15:33:27 -08:00
|
|
|
if (!v->arrays.count)
|
|
|
|
{
|
2021-06-23 21:57:32 -07:00
|
|
|
if (!(type = hlsl_type_clone(ctx, orig_type, 0, modifiers)))
|
2022-03-30 14:38:29 -07:00
|
|
|
{
|
|
|
|
free_parse_variable_def(v);
|
|
|
|
continue;
|
|
|
|
}
|
2021-03-04 15:33:27 -08:00
|
|
|
}
|
2021-01-27 08:29:44 -08:00
|
|
|
else
|
2021-03-04 15:33:27 -08:00
|
|
|
{
|
|
|
|
type = orig_type;
|
|
|
|
}
|
|
|
|
|
2022-03-30 14:38:29 -07:00
|
|
|
ret = true;
|
2021-03-04 15:33:27 -08:00
|
|
|
for (i = 0; i < v->arrays.count; ++i)
|
|
|
|
{
|
|
|
|
if (!(type = hlsl_new_array_type(ctx, type, v->arrays.sizes[i])))
|
2022-03-30 14:38:29 -07:00
|
|
|
{
|
|
|
|
free_parse_variable_def(v);
|
|
|
|
ret = false;
|
|
|
|
break;
|
|
|
|
}
|
2021-03-04 15:33:27 -08:00
|
|
|
}
|
2022-03-30 14:38:29 -07:00
|
|
|
if (!ret)
|
|
|
|
continue;
|
|
|
|
vkd3d_free(v->arrays.sizes);
|
2021-03-04 15:33:27 -08:00
|
|
|
|
2021-01-27 08:29:44 -08:00
|
|
|
vkd3d_free((void *)type->name);
|
|
|
|
type->name = v->name;
|
|
|
|
|
|
|
|
if (type->type != HLSL_CLASS_MATRIX)
|
2021-02-04 14:33:53 -08:00
|
|
|
check_invalid_matrix_modifiers(ctx, type->modifiers, v->loc);
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
if ((type->modifiers & HLSL_MODIFIER_COLUMN_MAJOR)
|
|
|
|
&& (type->modifiers & HLSL_MODIFIER_ROW_MAJOR))
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER,
|
2021-02-21 20:04:36 -08:00
|
|
|
"'row_major' and 'column_major' modifiers are mutually exclusive.");
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
ret = hlsl_scope_add_type(ctx->cur_scope, type);
|
2021-01-27 08:29:44 -08:00
|
|
|
if (!ret)
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED,
|
2021-02-21 20:04:36 -08:00
|
|
|
"Type '%s' is already defined.", v->name);
|
2022-03-30 14:38:29 -07:00
|
|
|
free_parse_initializer(&v->initializer);
|
2021-01-27 08:29:44 -08:00
|
|
|
vkd3d_free(v);
|
|
|
|
}
|
|
|
|
vkd3d_free(list);
|
2021-02-02 14:11:17 -08:00
|
|
|
return true;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
static bool add_func_parameter(struct hlsl_ctx *ctx, struct list *list,
|
2021-02-12 08:48:55 -08:00
|
|
|
struct parse_parameter *param, const struct vkd3d_shader_location loc)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
struct hlsl_ir_var *var;
|
|
|
|
|
|
|
|
if (param->type->type == HLSL_CLASS_MATRIX)
|
|
|
|
assert(param->type->modifiers & HLSL_MODIFIERS_MAJORITY_MASK);
|
|
|
|
|
2021-05-10 21:36:04 -07:00
|
|
|
if ((param->modifiers & HLSL_STORAGE_OUT) && (param->modifiers & HLSL_STORAGE_UNIFORM))
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER,
|
2021-05-10 21:36:04 -07:00
|
|
|
"Parameter '%s' is declared as both \"out\" and \"uniform\".", param->name);
|
|
|
|
|
2021-05-31 19:41:14 -07:00
|
|
|
if (!(var = hlsl_new_var(ctx, param->name, param->type, loc, ¶m->semantic, param->modifiers, ¶m->reg_reservation)))
|
2021-02-02 14:11:17 -08:00
|
|
|
return false;
|
2021-04-15 17:03:46 -07:00
|
|
|
var->is_param = 1;
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
if (!hlsl_add_var(ctx, var, false))
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-02-02 14:11:14 -08:00
|
|
|
hlsl_free_var(var);
|
2021-02-02 14:11:17 -08:00
|
|
|
return false;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
list_add_tail(list, &var->param_entry);
|
2021-02-02 14:11:17 -08:00
|
|
|
return true;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
2021-05-31 19:41:14 -07:00
|
|
|
static struct hlsl_reg_reservation parse_reg_reservation(const char *reg_string)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-05-31 19:41:14 -07:00
|
|
|
struct hlsl_reg_reservation reservation = {0};
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2021-06-21 21:37:07 -07:00
|
|
|
if (!sscanf(reg_string + 1, "%u", &reservation.index))
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
FIXME("Unsupported register reservation syntax.\n");
|
2021-05-31 19:41:14 -07:00
|
|
|
return reservation;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
2021-05-31 19:41:14 -07:00
|
|
|
reservation.type = reg_string[0];
|
|
|
|
return reservation;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
2021-09-01 15:20:53 -07:00
|
|
|
static const struct hlsl_ir_function_decl *get_func_decl(struct rb_tree *funcs, char *name, struct list *params)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
struct hlsl_ir_function *func;
|
|
|
|
struct rb_entry *entry;
|
|
|
|
|
2021-09-01 15:20:53 -07:00
|
|
|
if ((entry = rb_get(funcs, name)))
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
func = RB_ENTRY_VALUE(entry, struct hlsl_ir_function, entry);
|
|
|
|
|
2021-09-01 15:20:53 -07:00
|
|
|
if ((entry = rb_get(&func->overloads, params)))
|
|
|
|
return RB_ENTRY_VALUE(entry, struct hlsl_ir_function_decl, entry);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2021-05-20 22:32:20 -07:00
|
|
|
static struct list *make_list(struct hlsl_ctx *ctx, struct hlsl_ir_node *node)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
struct list *list;
|
|
|
|
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!(list = make_empty_list(ctx)))
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-02-02 14:11:14 -08:00
|
|
|
hlsl_free_instr(node);
|
2021-01-27 08:29:44 -08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
list_add_tail(list, &node->entry);
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int evaluate_array_dimension(struct hlsl_ir_node *node)
|
|
|
|
{
|
|
|
|
if (node->data_type->type != HLSL_CLASS_SCALAR)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
switch (node->type)
|
|
|
|
{
|
|
|
|
case HLSL_IR_CONSTANT:
|
|
|
|
{
|
2021-02-02 14:11:14 -08:00
|
|
|
struct hlsl_ir_constant *constant = hlsl_ir_constant(node);
|
2021-09-20 14:40:10 -07:00
|
|
|
const union hlsl_constant_value *value = &constant->value[0];
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
switch (constant->node.data_type->base_type)
|
|
|
|
{
|
|
|
|
case HLSL_TYPE_UINT:
|
2021-09-20 14:40:10 -07:00
|
|
|
return value->u;
|
2021-01-27 08:29:44 -08:00
|
|
|
case HLSL_TYPE_INT:
|
2021-09-20 14:40:10 -07:00
|
|
|
return value->i;
|
2021-01-27 08:29:44 -08:00
|
|
|
case HLSL_TYPE_FLOAT:
|
2021-02-16 21:52:05 -08:00
|
|
|
case HLSL_TYPE_HALF:
|
2021-09-20 14:40:10 -07:00
|
|
|
return value->f;
|
2021-01-27 08:29:44 -08:00
|
|
|
case HLSL_TYPE_DOUBLE:
|
2021-09-20 14:40:10 -07:00
|
|
|
return value->d;
|
2021-01-27 08:29:44 -08:00
|
|
|
case HLSL_TYPE_BOOL:
|
2022-04-05 03:33:12 -07:00
|
|
|
return !!value->u;
|
2021-01-27 08:29:44 -08:00
|
|
|
default:
|
2021-02-16 21:52:05 -08:00
|
|
|
assert(0);
|
2021-01-27 08:29:44 -08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
case HLSL_IR_EXPR:
|
|
|
|
case HLSL_IR_LOAD:
|
2021-10-07 19:58:57 -07:00
|
|
|
case HLSL_IR_RESOURCE_LOAD:
|
2021-01-27 08:29:44 -08:00
|
|
|
case HLSL_IR_SWIZZLE:
|
2021-02-02 14:11:14 -08:00
|
|
|
FIXME("Unhandled type %s.\n", hlsl_node_type_to_string(node->type));
|
2021-01-27 08:29:44 -08:00
|
|
|
return 0;
|
|
|
|
|
2021-10-07 19:58:57 -07:00
|
|
|
case HLSL_IR_IF:
|
|
|
|
case HLSL_IR_JUMP:
|
|
|
|
case HLSL_IR_LOOP:
|
2021-04-08 21:38:22 -07:00
|
|
|
case HLSL_IR_STORE:
|
2021-02-02 14:11:14 -08:00
|
|
|
WARN("Invalid node type %s.\n", hlsl_node_type_to_string(node->type));
|
2021-01-27 08:29:44 -08:00
|
|
|
return 0;
|
|
|
|
}
|
2021-10-07 19:58:57 -07:00
|
|
|
|
|
|
|
assert(0);
|
|
|
|
return 0;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:17 -08:00
|
|
|
static bool expr_compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2)
|
2021-01-30 11:51:35 -08:00
|
|
|
{
|
|
|
|
if (t1->base_type > HLSL_TYPE_LAST_SCALAR || t2->base_type > HLSL_TYPE_LAST_SCALAR)
|
2021-02-02 14:11:17 -08:00
|
|
|
return false;
|
2021-01-30 11:51:35 -08:00
|
|
|
|
|
|
|
/* Scalar vars can be converted to pretty much everything */
|
|
|
|
if ((t1->dimx == 1 && t1->dimy == 1) || (t2->dimx == 1 && t2->dimy == 1))
|
2021-02-02 14:11:17 -08:00
|
|
|
return true;
|
2021-01-30 11:51:35 -08:00
|
|
|
|
|
|
|
if (t1->type == HLSL_CLASS_VECTOR && t2->type == HLSL_CLASS_VECTOR)
|
2021-02-02 14:11:17 -08:00
|
|
|
return true;
|
2021-01-30 11:51:35 -08:00
|
|
|
|
|
|
|
if (t1->type == HLSL_CLASS_MATRIX || t2->type == HLSL_CLASS_MATRIX)
|
|
|
|
{
|
|
|
|
/* Matrix-vector conversion is apparently allowed if either they have the same components
|
|
|
|
count or the matrix is nx1 or 1xn */
|
|
|
|
if (t1->type == HLSL_CLASS_VECTOR || t2->type == HLSL_CLASS_VECTOR)
|
|
|
|
{
|
2021-02-02 14:11:14 -08:00
|
|
|
if (hlsl_type_component_count(t1) == hlsl_type_component_count(t2))
|
2021-02-02 14:11:17 -08:00
|
|
|
return true;
|
2021-01-30 11:51:35 -08:00
|
|
|
|
|
|
|
return (t1->type == HLSL_CLASS_MATRIX && (t1->dimx == 1 || t1->dimy == 1))
|
|
|
|
|| (t2->type == HLSL_CLASS_MATRIX && (t2->dimx == 1 || t2->dimy == 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Both matrices */
|
|
|
|
if ((t1->dimx >= t2->dimx && t1->dimy >= t2->dimy)
|
|
|
|
|| (t1->dimx <= t2->dimx && t1->dimy <= t2->dimy))
|
2021-02-02 14:11:17 -08:00
|
|
|
return true;
|
2021-01-30 11:51:35 -08:00
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:17 -08:00
|
|
|
return false;
|
2021-01-30 11:51:35 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static enum hlsl_base_type expr_common_base_type(enum hlsl_base_type t1, enum hlsl_base_type t2)
|
|
|
|
{
|
2021-08-27 03:05:13 -07:00
|
|
|
if (t1 > HLSL_TYPE_LAST_SCALAR || t2 > HLSL_TYPE_LAST_SCALAR) {
|
2021-01-30 11:51:35 -08:00
|
|
|
FIXME("Unexpected base type.\n");
|
|
|
|
return HLSL_TYPE_FLOAT;
|
|
|
|
}
|
2021-08-27 03:05:13 -07:00
|
|
|
if (t1 == t2)
|
|
|
|
return t1 == HLSL_TYPE_BOOL ? HLSL_TYPE_INT : t1;
|
|
|
|
if (t1 == HLSL_TYPE_DOUBLE || t2 == HLSL_TYPE_DOUBLE)
|
|
|
|
return HLSL_TYPE_DOUBLE;
|
|
|
|
if (t1 == HLSL_TYPE_FLOAT || t2 == HLSL_TYPE_FLOAT
|
|
|
|
|| t1 == HLSL_TYPE_HALF || t2 == HLSL_TYPE_HALF)
|
|
|
|
return HLSL_TYPE_FLOAT;
|
|
|
|
if (t1 == HLSL_TYPE_UINT || t2 == HLSL_TYPE_UINT)
|
|
|
|
return HLSL_TYPE_UINT;
|
|
|
|
return HLSL_TYPE_INT;
|
2021-01-30 11:51:35 -08:00
|
|
|
}
|
|
|
|
|
2021-10-25 00:06:26 -07:00
|
|
|
static bool expr_common_shape(struct hlsl_ctx *ctx, struct hlsl_type *t1, struct hlsl_type *t2,
|
2021-12-01 08:14:58 -08:00
|
|
|
const struct vkd3d_shader_location *loc, enum hlsl_type_class *type, unsigned int *dimx, unsigned int *dimy)
|
2021-01-30 11:51:35 -08:00
|
|
|
{
|
2021-03-04 02:25:08 -08:00
|
|
|
if (t1->type > HLSL_CLASS_LAST_NUMERIC)
|
2021-01-30 11:51:35 -08:00
|
|
|
{
|
2021-03-04 02:25:08 -08:00
|
|
|
struct vkd3d_string_buffer *string;
|
|
|
|
|
2021-05-20 22:32:22 -07:00
|
|
|
if ((string = hlsl_type_to_string(ctx, t1)))
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
|
2021-03-04 02:25:08 -08:00
|
|
|
"Expression of type \"%s\" cannot be used in a numeric expression.", string->buffer);
|
2021-05-20 22:32:22 -07:00
|
|
|
hlsl_release_string_buffer(ctx, string);
|
2021-10-25 00:06:26 -07:00
|
|
|
return false;
|
2021-03-04 02:25:08 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (t2->type > HLSL_CLASS_LAST_NUMERIC)
|
|
|
|
{
|
|
|
|
struct vkd3d_string_buffer *string;
|
|
|
|
|
2021-05-20 22:32:22 -07:00
|
|
|
if ((string = hlsl_type_to_string(ctx, t2)))
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
|
2021-03-04 02:25:08 -08:00
|
|
|
"Expression of type \"%s\" cannot be used in a numeric expression.", string->buffer);
|
2021-05-20 22:32:22 -07:00
|
|
|
hlsl_release_string_buffer(ctx, string);
|
2021-10-25 00:06:26 -07:00
|
|
|
return false;
|
2021-01-30 11:51:35 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!expr_compatible_data_types(t1, t2))
|
|
|
|
{
|
2021-05-20 22:32:22 -07:00
|
|
|
struct vkd3d_string_buffer *t1_string = hlsl_type_to_string(ctx, t1);
|
|
|
|
struct vkd3d_string_buffer *t2_string = hlsl_type_to_string(ctx, t2);
|
2021-03-04 02:25:08 -08:00
|
|
|
|
|
|
|
if (t1_string && t2_string)
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
|
2021-03-04 02:25:08 -08:00
|
|
|
"Expression data types \"%s\" and \"%s\" are incompatible.",
|
|
|
|
t1_string->buffer, t2_string->buffer);
|
2021-05-20 22:32:22 -07:00
|
|
|
hlsl_release_string_buffer(ctx, t1_string);
|
|
|
|
hlsl_release_string_buffer(ctx, t2_string);
|
2021-10-25 00:06:26 -07:00
|
|
|
return false;
|
2021-01-30 11:51:35 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (t1->dimx == 1 && t1->dimy == 1)
|
|
|
|
{
|
2021-10-25 00:06:26 -07:00
|
|
|
*type = t2->type;
|
|
|
|
*dimx = t2->dimx;
|
|
|
|
*dimy = t2->dimy;
|
2021-01-30 11:51:35 -08:00
|
|
|
}
|
|
|
|
else if (t2->dimx == 1 && t2->dimy == 1)
|
|
|
|
{
|
2021-10-25 00:06:26 -07:00
|
|
|
*type = t1->type;
|
|
|
|
*dimx = t1->dimx;
|
|
|
|
*dimy = t1->dimy;
|
2021-01-30 11:51:35 -08:00
|
|
|
}
|
|
|
|
else if (t1->type == HLSL_CLASS_MATRIX && t2->type == HLSL_CLASS_MATRIX)
|
|
|
|
{
|
2021-10-25 00:06:26 -07:00
|
|
|
*type = HLSL_CLASS_MATRIX;
|
|
|
|
*dimx = min(t1->dimx, t2->dimx);
|
|
|
|
*dimy = min(t1->dimy, t2->dimy);
|
2021-01-30 11:51:35 -08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-10-25 00:06:28 -07:00
|
|
|
if (t1->dimx * t1->dimy <= t2->dimx * t2->dimy)
|
2021-01-30 11:51:35 -08:00
|
|
|
{
|
2021-10-25 00:06:26 -07:00
|
|
|
*type = t1->type;
|
2021-10-25 00:06:27 -07:00
|
|
|
*dimx = t1->dimx;
|
|
|
|
*dimy = t1->dimy;
|
2021-01-30 11:51:35 -08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-10-25 00:06:26 -07:00
|
|
|
*type = t2->type;
|
2021-10-25 00:06:27 -07:00
|
|
|
*dimx = t2->dimx;
|
|
|
|
*dimy = t2->dimy;
|
2021-01-30 11:51:35 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-25 00:06:26 -07:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-06-08 16:18:42 -07:00
|
|
|
static unsigned int minor_size(const struct hlsl_type *type)
|
|
|
|
{
|
|
|
|
if (type->modifiers & HLSL_MODIFIER_ROW_MAJOR)
|
|
|
|
return type->dimx;
|
|
|
|
else
|
|
|
|
return type->dimy;
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int major_size(const struct hlsl_type *type)
|
|
|
|
{
|
|
|
|
if (type->modifiers & HLSL_MODIFIER_ROW_MAJOR)
|
|
|
|
return type->dimy;
|
|
|
|
else
|
|
|
|
return type->dimx;
|
|
|
|
}
|
|
|
|
|
2022-06-07 14:29:21 -07:00
|
|
|
static struct hlsl_ir_node *add_expr(struct hlsl_ctx *ctx, struct list *instrs,
|
2021-12-01 08:14:58 -08:00
|
|
|
enum hlsl_ir_expr_op op, struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS],
|
|
|
|
struct hlsl_type *type, const struct vkd3d_shader_location *loc)
|
2021-01-30 11:51:35 -08:00
|
|
|
{
|
|
|
|
struct hlsl_ir_expr *expr;
|
|
|
|
unsigned int i;
|
|
|
|
|
2022-06-08 16:18:42 -07:00
|
|
|
if (type->type == HLSL_CLASS_MATRIX)
|
|
|
|
{
|
|
|
|
struct vkd3d_string_buffer *name;
|
|
|
|
static unsigned int counter = 0;
|
|
|
|
struct hlsl_type *vector_type;
|
|
|
|
struct hlsl_ir_load *load;
|
|
|
|
struct hlsl_ir_var *var;
|
|
|
|
|
|
|
|
vector_type = hlsl_get_vector_type(ctx, type->base_type, minor_size(type));
|
|
|
|
|
|
|
|
name = vkd3d_string_buffer_get(&ctx->string_buffers);
|
|
|
|
vkd3d_string_buffer_printf(name, "<split_op-%u>", counter++);
|
|
|
|
var = hlsl_new_synthetic_var(ctx, name->buffer, type, *loc);
|
|
|
|
vkd3d_string_buffer_release(&ctx->string_buffers, name);
|
|
|
|
if (!var)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (i = 0; i < major_size(type); i++)
|
|
|
|
{
|
|
|
|
struct hlsl_ir_node *value, *vector_operands[HLSL_MAX_OPERANDS] = { NULL };
|
|
|
|
struct hlsl_ir_store *store;
|
|
|
|
struct hlsl_ir_constant *c;
|
|
|
|
unsigned int j;
|
|
|
|
|
|
|
|
if (!(c = hlsl_new_uint_constant(ctx, 4 * i, loc)))
|
|
|
|
return NULL;
|
|
|
|
list_add_tail(instrs, &c->node.entry);
|
|
|
|
|
|
|
|
for (j = 0; j < HLSL_MAX_OPERANDS; j++)
|
|
|
|
{
|
|
|
|
if (operands[j])
|
|
|
|
{
|
|
|
|
struct hlsl_type *vector_arg_type;
|
|
|
|
struct hlsl_ir_load *load;
|
|
|
|
|
|
|
|
vector_arg_type = hlsl_get_vector_type(ctx, operands[j]->data_type->base_type, minor_size(type));
|
|
|
|
|
|
|
|
if (!(load = add_load(ctx, instrs, operands[j], &c->node, vector_arg_type, *loc)))
|
|
|
|
return NULL;
|
|
|
|
vector_operands[j] = &load->node;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(value = add_expr(ctx, instrs, op, vector_operands, vector_type, loc)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!(store = hlsl_new_store(ctx, var, &c->node, value, 0, *loc)))
|
|
|
|
return NULL;
|
|
|
|
list_add_tail(instrs, &store->node.entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(load = hlsl_new_load(ctx, var, NULL, type, *loc)))
|
|
|
|
return NULL;
|
|
|
|
list_add_tail(instrs, &load->node.entry);
|
|
|
|
|
|
|
|
return &load->node;
|
|
|
|
}
|
|
|
|
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!(expr = hlsl_alloc(ctx, sizeof(*expr))))
|
2021-01-30 11:51:35 -08:00
|
|
|
return NULL;
|
|
|
|
init_node(&expr->node, HLSL_IR_EXPR, type, *loc);
|
|
|
|
expr->op = op;
|
2021-09-27 18:51:44 -07:00
|
|
|
for (i = 0; i < HLSL_MAX_OPERANDS; ++i)
|
2021-01-30 11:51:35 -08:00
|
|
|
hlsl_src_from_node(&expr->operands[i], operands[i]);
|
|
|
|
list_add_tail(instrs, &expr->node.entry);
|
|
|
|
|
2022-06-07 14:29:21 -07:00
|
|
|
return &expr->node;
|
2021-01-30 11:51:35 -08:00
|
|
|
}
|
|
|
|
|
2022-02-24 10:45:15 -08:00
|
|
|
static void check_integer_type(struct hlsl_ctx *ctx, const struct hlsl_ir_node *instr)
|
|
|
|
{
|
|
|
|
const struct hlsl_type *type = instr->data_type;
|
|
|
|
struct vkd3d_string_buffer *string;
|
|
|
|
|
|
|
|
switch (type->base_type)
|
|
|
|
{
|
|
|
|
case HLSL_TYPE_BOOL:
|
|
|
|
case HLSL_TYPE_INT:
|
|
|
|
case HLSL_TYPE_UINT:
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
if ((string = hlsl_type_to_string(ctx, type)))
|
|
|
|
hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
|
|
|
|
"Expression type '%s' is not integer.", string->buffer);
|
|
|
|
hlsl_release_string_buffer(ctx, string);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-07 14:29:21 -07:00
|
|
|
static struct hlsl_ir_node *add_unary_arithmetic_expr(struct hlsl_ctx *ctx, struct list *instrs,
|
2021-12-01 08:14:58 -08:00
|
|
|
enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg, const struct vkd3d_shader_location *loc)
|
2021-09-23 14:47:03 -07:00
|
|
|
{
|
2021-10-15 01:37:02 -07:00
|
|
|
struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = {arg};
|
2021-09-23 14:47:03 -07:00
|
|
|
|
2021-10-15 01:37:03 -07:00
|
|
|
return add_expr(ctx, instrs, op, args, arg->data_type, loc);
|
2021-09-23 14:47:03 -07:00
|
|
|
}
|
|
|
|
|
2022-06-07 14:29:21 -07:00
|
|
|
static struct hlsl_ir_node *add_unary_bitwise_expr(struct hlsl_ctx *ctx, struct list *instrs,
|
2022-02-24 10:45:20 -08:00
|
|
|
enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg, const struct vkd3d_shader_location *loc)
|
|
|
|
{
|
|
|
|
check_integer_type(ctx, arg);
|
|
|
|
|
|
|
|
return add_unary_arithmetic_expr(ctx, instrs, op, arg, loc);
|
|
|
|
}
|
|
|
|
|
2022-06-07 14:29:21 -07:00
|
|
|
static struct hlsl_ir_node *add_unary_logical_expr(struct hlsl_ctx *ctx, struct list *instrs,
|
2022-02-24 10:45:21 -08:00
|
|
|
enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg, const struct vkd3d_shader_location *loc)
|
|
|
|
{
|
|
|
|
struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = {0};
|
|
|
|
struct hlsl_type *bool_type;
|
|
|
|
|
|
|
|
bool_type = hlsl_get_numeric_type(ctx, arg->data_type->type, HLSL_TYPE_BOOL,
|
|
|
|
arg->data_type->dimx, arg->data_type->dimy);
|
|
|
|
|
|
|
|
if (!(args[0] = add_implicit_conversion(ctx, instrs, arg, bool_type, loc)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return add_expr(ctx, instrs, op, args, bool_type, loc);
|
|
|
|
}
|
|
|
|
|
2022-06-07 14:29:21 -07:00
|
|
|
static struct hlsl_ir_node *add_binary_arithmetic_expr(struct hlsl_ctx *ctx, struct list *instrs,
|
2021-10-15 01:37:01 -07:00
|
|
|
enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg1, struct hlsl_ir_node *arg2,
|
2021-12-01 08:14:58 -08:00
|
|
|
const struct vkd3d_shader_location *loc)
|
2021-10-15 01:37:01 -07:00
|
|
|
{
|
|
|
|
struct hlsl_type *common_type;
|
|
|
|
enum hlsl_base_type base = expr_common_base_type(arg1->data_type->base_type, arg2->data_type->base_type);
|
|
|
|
enum hlsl_type_class type;
|
|
|
|
unsigned int dimx, dimy;
|
|
|
|
struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = {0};
|
|
|
|
|
|
|
|
if (!expr_common_shape(ctx, arg1->data_type, arg2->data_type, loc, &type, &dimx, &dimy))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
common_type = hlsl_get_numeric_type(ctx, type, base, dimx, dimy);
|
|
|
|
|
|
|
|
if (!(args[0] = add_implicit_conversion(ctx, instrs, arg1, common_type, loc)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!(args[1] = add_implicit_conversion(ctx, instrs, arg2, common_type, loc)))
|
|
|
|
return NULL;
|
|
|
|
|
2021-10-15 01:37:03 -07:00
|
|
|
return add_expr(ctx, instrs, op, args, common_type, loc);
|
2021-10-15 01:37:01 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct list *add_binary_arithmetic_expr_merge(struct hlsl_ctx *ctx, struct list *list1, struct list *list2,
|
2021-02-12 08:48:55 -08:00
|
|
|
enum hlsl_ir_expr_op op, struct vkd3d_shader_location loc)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-10-15 01:37:01 -07:00
|
|
|
struct hlsl_ir_node *arg1 = node_from_list(list1), *arg2 = node_from_list(list2);
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
list_move_tail(list1, list2);
|
|
|
|
vkd3d_free(list2);
|
2021-10-15 01:37:01 -07:00
|
|
|
add_binary_arithmetic_expr(ctx, list1, op, arg1, arg2, &loc);
|
2021-01-27 08:29:44 -08:00
|
|
|
return list1;
|
|
|
|
}
|
|
|
|
|
2022-06-07 14:29:21 -07:00
|
|
|
static struct hlsl_ir_node *add_binary_bitwise_expr(struct hlsl_ctx *ctx, struct list *instrs,
|
2022-02-11 12:04:07 -08:00
|
|
|
enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg1, struct hlsl_ir_node *arg2,
|
|
|
|
const struct vkd3d_shader_location *loc)
|
|
|
|
{
|
2022-02-24 10:45:15 -08:00
|
|
|
check_integer_type(ctx, arg1);
|
|
|
|
check_integer_type(ctx, arg2);
|
2022-02-11 12:04:07 -08:00
|
|
|
|
|
|
|
return add_binary_arithmetic_expr(ctx, instrs, op, arg1, arg2, loc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct list *add_binary_bitwise_expr_merge(struct hlsl_ctx *ctx, struct list *list1, struct list *list2,
|
|
|
|
enum hlsl_ir_expr_op op, const struct vkd3d_shader_location *loc)
|
|
|
|
{
|
|
|
|
struct hlsl_ir_node *arg1 = node_from_list(list1), *arg2 = node_from_list(list2);
|
|
|
|
|
|
|
|
list_move_tail(list1, list2);
|
|
|
|
vkd3d_free(list2);
|
|
|
|
add_binary_bitwise_expr(ctx, list1, op, arg1, arg2, loc);
|
|
|
|
|
|
|
|
return list1;
|
|
|
|
}
|
|
|
|
|
2022-06-07 14:29:21 -07:00
|
|
|
static struct hlsl_ir_node *add_binary_comparison_expr(struct hlsl_ctx *ctx, struct list *instrs,
|
2021-10-15 01:37:04 -07:00
|
|
|
enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg1, struct hlsl_ir_node *arg2,
|
|
|
|
struct vkd3d_shader_location *loc)
|
|
|
|
{
|
|
|
|
struct hlsl_type *common_type, *return_type;
|
|
|
|
enum hlsl_base_type base = expr_common_base_type(arg1->data_type->base_type, arg2->data_type->base_type);
|
|
|
|
enum hlsl_type_class type;
|
|
|
|
unsigned int dimx, dimy;
|
|
|
|
struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = {0};
|
|
|
|
|
|
|
|
if (!expr_common_shape(ctx, arg1->data_type, arg2->data_type, loc, &type, &dimx, &dimy))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
common_type = hlsl_get_numeric_type(ctx, type, base, dimx, dimy);
|
|
|
|
return_type = hlsl_get_numeric_type(ctx, type, HLSL_TYPE_BOOL, dimx, dimy);
|
|
|
|
|
|
|
|
if (!(args[0] = add_implicit_conversion(ctx, instrs, arg1, common_type, loc)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!(args[1] = add_implicit_conversion(ctx, instrs, arg2, common_type, loc)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return add_expr(ctx, instrs, op, args, return_type, loc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct list *add_binary_comparison_expr_merge(struct hlsl_ctx *ctx, struct list *list1, struct list *list2,
|
|
|
|
enum hlsl_ir_expr_op op, struct vkd3d_shader_location loc)
|
|
|
|
{
|
|
|
|
struct hlsl_ir_node *arg1 = node_from_list(list1), *arg2 = node_from_list(list2);
|
|
|
|
|
|
|
|
list_move_tail(list1, list2);
|
|
|
|
vkd3d_free(list2);
|
|
|
|
add_binary_comparison_expr(ctx, list1, op, arg1, arg2, &loc);
|
|
|
|
return list1;
|
|
|
|
}
|
|
|
|
|
2022-06-07 14:29:21 -07:00
|
|
|
static struct hlsl_ir_node *add_binary_logical_expr(struct hlsl_ctx *ctx, struct list *instrs,
|
2022-02-24 10:45:16 -08:00
|
|
|
enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg1, struct hlsl_ir_node *arg2,
|
|
|
|
const struct vkd3d_shader_location *loc)
|
|
|
|
{
|
|
|
|
struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = {0};
|
|
|
|
struct hlsl_type *common_type;
|
|
|
|
enum hlsl_type_class type;
|
|
|
|
unsigned int dimx, dimy;
|
|
|
|
|
|
|
|
if (!expr_common_shape(ctx, arg1->data_type, arg2->data_type, loc, &type, &dimx, &dimy))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
common_type = hlsl_get_numeric_type(ctx, type, HLSL_TYPE_BOOL, dimx, dimy);
|
|
|
|
|
|
|
|
if (!(args[0] = add_implicit_conversion(ctx, instrs, arg1, common_type, loc)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!(args[1] = add_implicit_conversion(ctx, instrs, arg2, common_type, loc)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return add_expr(ctx, instrs, op, args, common_type, loc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct list *add_binary_logical_expr_merge(struct hlsl_ctx *ctx, struct list *list1, struct list *list2,
|
|
|
|
enum hlsl_ir_expr_op op, const struct vkd3d_shader_location *loc)
|
|
|
|
{
|
|
|
|
struct hlsl_ir_node *arg1 = node_from_list(list1), *arg2 = node_from_list(list2);
|
|
|
|
|
|
|
|
list_move_tail(list1, list2);
|
|
|
|
vkd3d_free(list2);
|
|
|
|
add_binary_logical_expr(ctx, list1, op, arg1, arg2, loc);
|
|
|
|
|
|
|
|
return list1;
|
|
|
|
}
|
|
|
|
|
2022-06-07 14:29:21 -07:00
|
|
|
static struct hlsl_ir_node *add_binary_shift_expr(struct hlsl_ctx *ctx, struct list *instrs,
|
2022-02-24 10:45:18 -08:00
|
|
|
enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg1, struct hlsl_ir_node *arg2,
|
|
|
|
const struct vkd3d_shader_location *loc)
|
|
|
|
{
|
|
|
|
enum hlsl_base_type base = arg1->data_type->base_type;
|
|
|
|
struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = {0};
|
|
|
|
struct hlsl_type *return_type, *integer_type;
|
|
|
|
enum hlsl_type_class type;
|
|
|
|
unsigned int dimx, dimy;
|
|
|
|
|
|
|
|
check_integer_type(ctx, arg1);
|
|
|
|
check_integer_type(ctx, arg2);
|
|
|
|
|
|
|
|
if (base == HLSL_TYPE_BOOL)
|
|
|
|
base = HLSL_TYPE_INT;
|
|
|
|
|
|
|
|
if (!expr_common_shape(ctx, arg1->data_type, arg2->data_type, loc, &type, &dimx, &dimy))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return_type = hlsl_get_numeric_type(ctx, type, base, dimx, dimy);
|
|
|
|
integer_type = hlsl_get_numeric_type(ctx, type, HLSL_TYPE_INT, dimx, dimy);
|
|
|
|
|
|
|
|
if (!(args[0] = add_implicit_conversion(ctx, instrs, arg1, return_type, loc)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!(args[1] = add_implicit_conversion(ctx, instrs, arg2, integer_type, loc)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return add_expr(ctx, instrs, op, args, return_type, loc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct list *add_binary_shift_expr_merge(struct hlsl_ctx *ctx, struct list *list1, struct list *list2,
|
|
|
|
enum hlsl_ir_expr_op op, const struct vkd3d_shader_location *loc)
|
|
|
|
{
|
|
|
|
struct hlsl_ir_node *arg1 = node_from_list(list1), *arg2 = node_from_list(list2);
|
|
|
|
|
|
|
|
list_move_tail(list1, list2);
|
|
|
|
vkd3d_free(list2);
|
|
|
|
add_binary_shift_expr(ctx, list1, op, arg1, arg2, loc);
|
|
|
|
|
|
|
|
return list1;
|
|
|
|
}
|
|
|
|
|
2022-06-24 00:41:27 -07:00
|
|
|
static struct hlsl_ir_node *add_binary_dot_expr(struct hlsl_ctx *ctx, struct list *instrs,
|
|
|
|
struct hlsl_ir_node *arg1, struct hlsl_ir_node *arg2, const struct vkd3d_shader_location *loc)
|
|
|
|
{
|
|
|
|
enum hlsl_base_type base = expr_common_base_type(arg1->data_type->base_type, arg2->data_type->base_type);
|
|
|
|
struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = {0};
|
|
|
|
struct hlsl_type *common_type, *ret_type;
|
|
|
|
enum hlsl_ir_expr_op op;
|
|
|
|
unsigned dim;
|
|
|
|
|
|
|
|
if (arg1->data_type->type == HLSL_CLASS_MATRIX)
|
|
|
|
{
|
|
|
|
struct vkd3d_string_buffer *string;
|
|
|
|
|
|
|
|
if ((string = hlsl_type_to_string(ctx, arg1->data_type)))
|
|
|
|
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
|
|
|
|
"Invalid type %s.\n", string->buffer);
|
|
|
|
hlsl_release_string_buffer(ctx, string);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (arg2->data_type->type == HLSL_CLASS_MATRIX)
|
|
|
|
{
|
|
|
|
struct vkd3d_string_buffer *string;
|
|
|
|
|
|
|
|
if ((string = hlsl_type_to_string(ctx, arg2->data_type)))
|
|
|
|
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
|
|
|
|
"Invalid type %s.\n", string->buffer);
|
|
|
|
hlsl_release_string_buffer(ctx, string);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (arg1->data_type->type == HLSL_CLASS_SCALAR)
|
|
|
|
dim = arg2->data_type->dimx;
|
|
|
|
else if (arg1->data_type->type == HLSL_CLASS_SCALAR)
|
|
|
|
dim = arg1->data_type->dimx;
|
|
|
|
else
|
|
|
|
dim = min(arg1->data_type->dimx, arg2->data_type->dimx);
|
|
|
|
|
|
|
|
if (dim == 1)
|
|
|
|
op = HLSL_OP2_MUL;
|
|
|
|
else
|
|
|
|
op = HLSL_OP2_DOT;
|
|
|
|
|
|
|
|
common_type = hlsl_get_vector_type(ctx, base, dim);
|
|
|
|
ret_type = hlsl_get_scalar_type(ctx, base);
|
|
|
|
|
|
|
|
if (!(args[0] = add_implicit_conversion(ctx, instrs, arg1, common_type, loc)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!(args[1] = add_implicit_conversion(ctx, instrs, arg2, common_type, loc)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return add_expr(ctx, instrs, op, args, ret_type, loc);
|
|
|
|
}
|
|
|
|
|
2021-01-30 11:51:33 -08:00
|
|
|
static enum hlsl_ir_expr_op op_from_assignment(enum parse_assign_op op)
|
|
|
|
{
|
|
|
|
static const enum hlsl_ir_expr_op ops[] =
|
|
|
|
{
|
|
|
|
0,
|
2021-08-12 17:36:13 -07:00
|
|
|
HLSL_OP2_ADD,
|
2021-08-09 19:56:19 -07:00
|
|
|
0,
|
2021-08-12 17:36:13 -07:00
|
|
|
HLSL_OP2_MUL,
|
|
|
|
HLSL_OP2_DIV,
|
|
|
|
HLSL_OP2_MOD,
|
|
|
|
HLSL_OP2_LSHIFT,
|
|
|
|
HLSL_OP2_RSHIFT,
|
|
|
|
HLSL_OP2_BIT_AND,
|
|
|
|
HLSL_OP2_BIT_OR,
|
|
|
|
HLSL_OP2_BIT_XOR,
|
2021-01-30 11:51:33 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
return ops[op];
|
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:17 -08:00
|
|
|
static bool invert_swizzle(unsigned int *swizzle, unsigned int *writemask, unsigned int *ret_width)
|
2021-01-30 11:51:33 -08:00
|
|
|
{
|
|
|
|
unsigned int i, j, bit = 0, inverted = 0, width, new_writemask = 0, new_swizzle = 0;
|
|
|
|
|
|
|
|
/* Apply the writemask to the swizzle to get a new writemask and swizzle. */
|
|
|
|
for (i = 0; i < 4; ++i)
|
|
|
|
{
|
|
|
|
if (*writemask & (1 << i))
|
|
|
|
{
|
|
|
|
unsigned int s = (*swizzle >> (i * 2)) & 3;
|
|
|
|
new_swizzle |= s << (bit++ * 2);
|
|
|
|
if (new_writemask & (1 << s))
|
2021-02-02 14:11:17 -08:00
|
|
|
return false;
|
2021-01-30 11:51:33 -08:00
|
|
|
new_writemask |= 1 << s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
width = bit;
|
|
|
|
|
|
|
|
/* Invert the swizzle. */
|
|
|
|
bit = 0;
|
|
|
|
for (i = 0; i < 4; ++i)
|
|
|
|
{
|
|
|
|
for (j = 0; j < width; ++j)
|
|
|
|
{
|
|
|
|
unsigned int s = (new_swizzle >> (j * 2)) & 3;
|
|
|
|
if (s == i)
|
|
|
|
inverted |= j << (bit++ * 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*swizzle = inverted;
|
|
|
|
*writemask = new_writemask;
|
|
|
|
*ret_width = width;
|
2021-02-02 14:11:17 -08:00
|
|
|
return true;
|
2021-01-30 11:51:33 -08:00
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *lhs,
|
2021-01-30 11:51:33 -08:00
|
|
|
enum parse_assign_op assign_op, struct hlsl_ir_node *rhs)
|
|
|
|
{
|
2021-03-09 17:42:49 -08:00
|
|
|
struct hlsl_type *lhs_type = lhs->data_type;
|
2021-04-08 21:38:22 -07:00
|
|
|
struct hlsl_ir_store *store;
|
2021-03-09 17:42:46 -08:00
|
|
|
struct hlsl_ir_expr *copy;
|
2022-01-31 02:51:34 -08:00
|
|
|
unsigned int writemask = 0;
|
2021-01-30 11:51:33 -08:00
|
|
|
|
2021-08-09 19:56:19 -07:00
|
|
|
if (assign_op == ASSIGN_OP_SUB)
|
|
|
|
{
|
2022-06-07 14:29:21 -07:00
|
|
|
if (!(rhs = add_unary_arithmetic_expr(ctx, instrs, HLSL_OP1_NEG, rhs, &rhs->loc)))
|
2021-08-09 19:56:19 -07:00
|
|
|
return NULL;
|
|
|
|
assign_op = ASSIGN_OP_ADD;
|
|
|
|
}
|
2021-03-09 17:42:49 -08:00
|
|
|
if (assign_op != ASSIGN_OP_ASSIGN)
|
|
|
|
{
|
|
|
|
enum hlsl_ir_expr_op op = op_from_assignment(assign_op);
|
|
|
|
|
2021-08-09 19:56:19 -07:00
|
|
|
assert(op);
|
2022-06-07 14:29:21 -07:00
|
|
|
if (!(rhs = add_binary_arithmetic_expr(ctx, instrs, op, lhs, rhs, &rhs->loc)))
|
2021-03-09 17:42:49 -08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2021-01-30 11:51:33 -08:00
|
|
|
if (lhs_type->type <= HLSL_CLASS_LAST_NUMERIC)
|
|
|
|
{
|
|
|
|
writemask = (1 << lhs_type->dimx) - 1;
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
if (!(rhs = add_implicit_conversion(ctx, instrs, rhs, lhs_type, &rhs->loc)))
|
2021-01-30 11:51:33 -08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!(store = hlsl_alloc(ctx, sizeof(*store))))
|
2021-01-30 11:51:33 -08:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
while (lhs->type != HLSL_IR_LOAD)
|
|
|
|
{
|
2021-08-12 17:36:13 -07:00
|
|
|
if (lhs->type == HLSL_IR_EXPR && hlsl_ir_expr(lhs)->op == HLSL_OP1_CAST)
|
2021-01-30 11:51:33 -08:00
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_fixme(ctx, &lhs->loc, "Cast on the LHS.");
|
2021-04-08 21:38:22 -07:00
|
|
|
vkd3d_free(store);
|
2021-01-30 11:51:33 -08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
else if (lhs->type == HLSL_IR_SWIZZLE)
|
|
|
|
{
|
2021-03-09 17:42:49 -08:00
|
|
|
struct hlsl_ir_swizzle *swizzle = hlsl_ir_swizzle(lhs), *new_swizzle;
|
|
|
|
unsigned int width, s = swizzle->swizzle;
|
2021-01-30 11:51:33 -08:00
|
|
|
|
|
|
|
if (lhs->data_type->type == HLSL_CLASS_MATRIX)
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_fixme(ctx, &lhs->loc, "Matrix assignment with a writemask.");
|
2021-01-30 11:51:33 -08:00
|
|
|
|
2021-03-09 17:42:49 -08:00
|
|
|
if (!invert_swizzle(&s, &writemask, &width))
|
2021-01-30 11:51:33 -08:00
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &lhs->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_WRITEMASK, "Invalid writemask.");
|
2021-04-08 21:38:22 -07:00
|
|
|
vkd3d_free(store);
|
2021-01-30 11:51:33 -08:00
|
|
|
return NULL;
|
|
|
|
}
|
2021-03-09 17:42:49 -08:00
|
|
|
|
|
|
|
if (!(new_swizzle = hlsl_new_swizzle(ctx, s, width, rhs, &swizzle->node.loc)))
|
|
|
|
{
|
2021-04-08 21:38:22 -07:00
|
|
|
vkd3d_free(store);
|
2021-03-09 17:42:49 -08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
list_add_tail(instrs, &new_swizzle->node.entry);
|
|
|
|
|
|
|
|
lhs = swizzle->val.node;
|
|
|
|
rhs = &new_swizzle->node;
|
2021-01-30 11:51:33 -08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &lhs->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_LVALUE, "Invalid lvalue.");
|
2021-04-08 21:38:22 -07:00
|
|
|
vkd3d_free(store);
|
2021-01-30 11:51:33 -08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-08 21:38:22 -07:00
|
|
|
init_node(&store->node, HLSL_IR_STORE, NULL, lhs->loc);
|
|
|
|
store->writemask = writemask;
|
|
|
|
store->lhs.var = hlsl_ir_load(lhs)->src.var;
|
|
|
|
hlsl_src_from_node(&store->lhs.offset, hlsl_ir_load(lhs)->src.offset.node);
|
|
|
|
hlsl_src_from_node(&store->rhs, rhs);
|
|
|
|
list_add_tail(instrs, &store->node.entry);
|
2021-01-30 11:51:33 -08:00
|
|
|
|
2021-03-09 17:42:46 -08:00
|
|
|
/* Don't use the instruction itself as a source, as this makes structure
|
|
|
|
* splitting easier. Instead copy it here. Since we retrieve sources from
|
2021-03-16 14:31:52 -07:00
|
|
|
* the last instruction in the list, we do need to copy. */
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!(copy = hlsl_new_copy(ctx, rhs)))
|
2021-03-09 17:42:46 -08:00
|
|
|
return NULL;
|
|
|
|
list_add_tail(instrs, ©->node.entry);
|
|
|
|
return ©->node;
|
2021-01-30 11:51:33 -08:00
|
|
|
}
|
|
|
|
|
2021-03-09 17:42:48 -08:00
|
|
|
static bool add_increment(struct hlsl_ctx *ctx, struct list *instrs, bool decrement, bool post,
|
|
|
|
struct vkd3d_shader_location loc)
|
2021-03-09 17:42:47 -08:00
|
|
|
{
|
|
|
|
struct hlsl_ir_node *lhs = node_from_list(instrs);
|
|
|
|
struct hlsl_ir_constant *one;
|
|
|
|
|
|
|
|
if (lhs->data_type->modifiers & HLSL_MODIFIER_CONST)
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &loc, VKD3D_SHADER_ERROR_HLSL_MODIFIES_CONST,
|
2021-03-09 17:42:48 -08:00
|
|
|
"Argument to %s%screment operator is const.", post ? "post" : "pre", decrement ? "de" : "in");
|
2021-03-09 17:42:47 -08:00
|
|
|
|
2022-04-05 03:33:10 -07:00
|
|
|
if (!(one = hlsl_new_int_constant(ctx, 1, &loc)))
|
2021-03-09 17:42:47 -08:00
|
|
|
return false;
|
|
|
|
list_add_tail(instrs, &one->node.entry);
|
|
|
|
|
2021-03-09 17:42:48 -08:00
|
|
|
if (!add_assignment(ctx, instrs, lhs, decrement ? ASSIGN_OP_SUB : ASSIGN_OP_ADD, &one->node))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (post)
|
|
|
|
{
|
|
|
|
struct hlsl_ir_expr *copy;
|
|
|
|
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!(copy = hlsl_new_copy(ctx, lhs)))
|
2021-03-09 17:42:48 -08:00
|
|
|
return false;
|
|
|
|
list_add_tail(instrs, ©->node.entry);
|
|
|
|
|
|
|
|
/* Post increment/decrement expressions are considered const. */
|
2021-06-23 21:57:32 -07:00
|
|
|
if (!(copy->node.data_type = hlsl_type_clone(ctx, copy->node.data_type, 0, HLSL_MODIFIER_CONST)))
|
2021-03-09 17:42:48 -08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2021-03-09 17:42:47 -08:00
|
|
|
}
|
|
|
|
|
2022-04-27 01:56:24 -07:00
|
|
|
static void initialize_var_components(struct hlsl_ctx *ctx, struct list *instrs,
|
2022-05-03 02:57:17 -07:00
|
|
|
struct hlsl_ir_var *dst, unsigned int *store_index, struct hlsl_ir_node *src)
|
2022-04-14 03:52:38 -07:00
|
|
|
{
|
2022-04-27 01:56:24 -07:00
|
|
|
unsigned int src_comp_count = hlsl_type_component_count(src->data_type);
|
|
|
|
unsigned int k;
|
2022-04-14 03:52:38 -07:00
|
|
|
|
2022-04-27 01:56:24 -07:00
|
|
|
for (k = 0; k < src_comp_count; ++k)
|
2022-04-14 03:52:38 -07:00
|
|
|
{
|
2022-06-29 15:29:42 -07:00
|
|
|
struct hlsl_type *dst_comp_type;
|
|
|
|
unsigned int dst_reg_offset;
|
2022-04-14 03:52:38 -07:00
|
|
|
struct hlsl_ir_store *store;
|
|
|
|
struct hlsl_ir_constant *c;
|
2022-04-27 01:56:24 -07:00
|
|
|
struct hlsl_ir_load *load;
|
|
|
|
struct hlsl_ir_node *conv;
|
2022-04-14 03:52:38 -07:00
|
|
|
|
2022-06-29 15:29:42 -07:00
|
|
|
if (!(load = add_load_component(ctx, instrs, src, k, &src->loc)))
|
2022-04-14 03:52:38 -07:00
|
|
|
return;
|
|
|
|
|
2022-06-29 15:29:42 -07:00
|
|
|
dst_reg_offset = hlsl_compute_component_offset(ctx, dst->data_type, *store_index, &dst_comp_type);
|
2022-04-14 03:52:38 -07:00
|
|
|
|
2022-05-03 02:57:17 -07:00
|
|
|
if (!(conv = add_implicit_conversion(ctx, instrs, &load->node, dst_comp_type, &src->loc)))
|
2022-04-14 03:52:38 -07:00
|
|
|
return;
|
|
|
|
|
2022-05-03 02:57:17 -07:00
|
|
|
if (!(c = hlsl_new_uint_constant(ctx, dst_reg_offset, &src->loc)))
|
2022-04-27 01:56:24 -07:00
|
|
|
return;
|
|
|
|
list_add_tail(instrs, &c->node.entry);
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2022-05-03 02:57:17 -07:00
|
|
|
if (!(store = hlsl_new_store(ctx, dst, &c->node, conv, 0, src->loc)))
|
2022-04-27 01:56:24 -07:00
|
|
|
return;
|
|
|
|
list_add_tail(instrs, &store->node.entry);
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2022-04-27 01:56:24 -07:00
|
|
|
++*store_index;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_type,
|
|
|
|
DWORD modifiers, struct list *var_list)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
struct parse_variable_def *v, *v_next;
|
2021-03-22 15:02:36 -07:00
|
|
|
struct hlsl_ir_function_decl *func;
|
2021-01-27 08:29:44 -08:00
|
|
|
struct list *statements_list;
|
|
|
|
struct hlsl_ir_var *var;
|
|
|
|
struct hlsl_type *type;
|
2021-03-22 15:02:36 -07:00
|
|
|
bool local = true;
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
if (basic_type->type == HLSL_CLASS_MATRIX)
|
|
|
|
assert(basic_type->modifiers & HLSL_MODIFIERS_MAJORITY_MASK);
|
|
|
|
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!(statements_list = make_empty_list(ctx)))
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
LIST_FOR_EACH_ENTRY_SAFE(v, v_next, var_list, struct parse_variable_def, entry)
|
|
|
|
free_parse_variable_def(v);
|
|
|
|
vkd3d_free(var_list);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!var_list)
|
|
|
|
return statements_list;
|
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY_SAFE(v, v_next, var_list, struct parse_variable_def, entry)
|
|
|
|
{
|
2021-03-04 15:33:27 -08:00
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
type = basic_type;
|
|
|
|
for (i = 0; i < v->arrays.count; ++i)
|
|
|
|
type = hlsl_new_array_type(ctx, type, v->arrays.sizes[i]);
|
2022-03-30 14:38:29 -07:00
|
|
|
vkd3d_free(v->arrays.sizes);
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2021-03-22 15:02:37 -07:00
|
|
|
if (type->type != HLSL_CLASS_MATRIX)
|
|
|
|
check_invalid_matrix_modifiers(ctx, modifiers, v->loc);
|
|
|
|
|
2022-03-22 14:59:10 -07:00
|
|
|
if (modifiers & (HLSL_STORAGE_IN | HLSL_STORAGE_OUT))
|
|
|
|
{
|
|
|
|
struct vkd3d_string_buffer *string;
|
|
|
|
|
|
|
|
if ((string = hlsl_modifiers_to_string(ctx, modifiers & (HLSL_STORAGE_IN | HLSL_STORAGE_OUT))))
|
|
|
|
hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER,
|
|
|
|
"Modifiers '%s' are not allowed on non-parameter variables.", string->buffer);
|
|
|
|
hlsl_release_string_buffer(ctx, string);
|
|
|
|
}
|
|
|
|
|
2021-05-31 19:41:14 -07:00
|
|
|
if (!(var = hlsl_new_var(ctx, v->name, type, v->loc, &v->semantic, modifiers, &v->reg_reservation)))
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
free_parse_variable_def(v);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-06-21 21:37:10 -07:00
|
|
|
var->buffer = ctx->cur_buffer;
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
if (ctx->cur_scope == ctx->globals)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-02-02 14:11:17 -08:00
|
|
|
local = false;
|
2021-03-22 15:02:36 -07:00
|
|
|
|
2021-05-10 21:36:05 -07:00
|
|
|
if ((modifiers & HLSL_STORAGE_UNIFORM) && (modifiers & HLSL_STORAGE_STATIC))
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER,
|
2021-05-10 21:36:05 -07:00
|
|
|
"Variable '%s' is declared as both \"uniform\" and \"static\".", var->name);
|
|
|
|
|
2021-05-16 10:47:50 -07:00
|
|
|
/* Mark it as uniform. We need to do this here since synthetic
|
|
|
|
* variables also get put in the global scope, but shouldn't be
|
|
|
|
* considered uniforms, and we have no way of telling otherwise. */
|
|
|
|
if (!(modifiers & HLSL_STORAGE_STATIC))
|
|
|
|
var->modifiers |= HLSL_STORAGE_UNIFORM;
|
|
|
|
|
2021-03-22 15:02:36 -07:00
|
|
|
if ((func = hlsl_get_func_decl(ctx, var->name)))
|
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED,
|
2021-03-22 15:02:36 -07:00
|
|
|
"'%s' is already defined as a function.", var->name);
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_note(ctx, &func->loc, VKD3D_SHADER_LOG_ERROR,
|
2021-03-22 15:02:36 -07:00
|
|
|
"'%s' was previously defined here.", var->name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
static const unsigned int invalid = HLSL_STORAGE_EXTERN | HLSL_STORAGE_SHARED
|
|
|
|
| HLSL_STORAGE_GROUPSHARED | HLSL_STORAGE_UNIFORM;
|
|
|
|
|
2021-03-22 15:02:37 -07:00
|
|
|
if (modifiers & invalid)
|
2021-03-22 15:02:36 -07:00
|
|
|
{
|
|
|
|
struct vkd3d_string_buffer *string;
|
|
|
|
|
2021-05-20 22:32:22 -07:00
|
|
|
if ((string = hlsl_modifiers_to_string(ctx, modifiers & invalid)))
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER,
|
2021-03-22 15:02:36 -07:00
|
|
|
"Modifiers '%s' are not allowed on local variables.", string->buffer);
|
2021-05-20 22:32:22 -07:00
|
|
|
hlsl_release_string_buffer(ctx, string);
|
2021-03-22 15:02:36 -07:00
|
|
|
}
|
2021-04-27 10:14:19 -07:00
|
|
|
if (var->semantic.name)
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SEMANTIC,
|
2021-03-22 15:02:36 -07:00
|
|
|
"Semantics are not allowed on local variables.");
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
2021-03-17 22:22:23 -07:00
|
|
|
if ((type->modifiers & HLSL_MODIFIER_CONST) && !v->initializer.args_count
|
2021-03-22 15:02:37 -07:00
|
|
|
&& !(modifiers & (HLSL_STORAGE_STATIC | HLSL_STORAGE_UNIFORM)))
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_INITIALIZER,
|
2021-02-21 20:04:36 -08:00
|
|
|
"Const variable \"%s\" is missing an initializer.", var->name);
|
2021-02-02 14:11:14 -08:00
|
|
|
hlsl_free_var(var);
|
2022-03-30 14:38:29 -07:00
|
|
|
free_parse_initializer(&v->initializer);
|
2021-01-27 08:29:44 -08:00
|
|
|
vkd3d_free(v);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-03-22 15:02:36 -07:00
|
|
|
if (!hlsl_add_var(ctx, var, local))
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-03-22 15:02:36 -07:00
|
|
|
struct hlsl_ir_var *old = hlsl_get_var(ctx->cur_scope, var->name);
|
|
|
|
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED,
|
2021-03-22 15:02:36 -07:00
|
|
|
"Variable \"%s\" was already declared in this scope.", var->name);
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_note(ctx, &old->loc, VKD3D_SHADER_LOG_ERROR, "\"%s\" was previously declared here.", old->name);
|
2021-02-02 14:11:14 -08:00
|
|
|
hlsl_free_var(var);
|
2022-03-30 14:38:29 -07:00
|
|
|
free_parse_initializer(&v->initializer);
|
2021-01-27 08:29:44 -08:00
|
|
|
vkd3d_free(v);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (v->initializer.args_count)
|
|
|
|
{
|
2022-03-30 14:38:31 -07:00
|
|
|
if (v->initializer.braces)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2022-03-30 14:38:31 -07:00
|
|
|
unsigned int size = initializer_size(&v->initializer);
|
2022-04-27 01:56:24 -07:00
|
|
|
unsigned int store_index = 0;
|
|
|
|
unsigned int k;
|
2022-03-30 14:38:31 -07:00
|
|
|
|
2022-04-27 01:56:24 -07:00
|
|
|
if (hlsl_type_component_count(type) != size)
|
2022-03-30 14:38:31 -07:00
|
|
|
{
|
|
|
|
hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT,
|
2022-04-27 01:56:24 -07:00
|
|
|
"Expected %u components in initializer, but got %u.",
|
|
|
|
hlsl_type_component_count(type), size);
|
2022-03-30 14:38:31 -07:00
|
|
|
free_parse_initializer(&v->initializer);
|
|
|
|
vkd3d_free(v);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-04-27 01:56:24 -07:00
|
|
|
for (k = 0; k < v->initializer.args_count; ++k)
|
2022-03-30 14:38:31 -07:00
|
|
|
{
|
2022-04-27 01:56:24 -07:00
|
|
|
initialize_var_components(ctx, v->initializer.instrs, var,
|
2022-05-03 02:57:17 -07:00
|
|
|
&store_index, v->initializer.args[k]);
|
2022-03-30 14:38:31 -07:00
|
|
|
}
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
2022-03-30 14:38:31 -07:00
|
|
|
else
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2022-03-30 14:38:31 -07:00
|
|
|
struct hlsl_ir_load *load = hlsl_new_var_load(ctx, var, var->loc);
|
2022-03-10 07:14:11 -08:00
|
|
|
|
2022-03-30 14:38:31 -07:00
|
|
|
assert(v->initializer.args_count == 1);
|
|
|
|
list_add_tail(v->initializer.instrs, &load->node.entry);
|
|
|
|
add_assignment(ctx, v->initializer.instrs, &load->node, ASSIGN_OP_ASSIGN, v->initializer.args[0]);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (modifiers & HLSL_STORAGE_STATIC)
|
2021-02-04 14:33:53 -08:00
|
|
|
list_move_tail(&ctx->static_initializers, v->initializer.instrs);
|
2021-01-27 08:29:44 -08:00
|
|
|
else
|
|
|
|
list_move_tail(statements_list, v->initializer.instrs);
|
2022-03-30 14:38:31 -07:00
|
|
|
vkd3d_free(v->initializer.args);
|
2021-01-27 08:29:44 -08:00
|
|
|
vkd3d_free(v->initializer.instrs);
|
|
|
|
}
|
|
|
|
vkd3d_free(v);
|
|
|
|
}
|
|
|
|
vkd3d_free(var_list);
|
|
|
|
return statements_list;
|
|
|
|
}
|
|
|
|
|
2021-09-01 15:20:52 -07:00
|
|
|
struct find_function_call_args
|
|
|
|
{
|
|
|
|
const struct parse_initializer *params;
|
|
|
|
const struct hlsl_ir_function_decl *decl;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void find_function_call_exact(struct rb_entry *entry, void *context)
|
|
|
|
{
|
|
|
|
const struct hlsl_ir_function_decl *decl = RB_ENTRY_VALUE(entry, const struct hlsl_ir_function_decl, entry);
|
|
|
|
struct find_function_call_args *args = context;
|
|
|
|
const struct hlsl_ir_var *param;
|
|
|
|
unsigned int i = 0;
|
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY(param, decl->parameters, struct hlsl_ir_var, param_entry)
|
|
|
|
{
|
|
|
|
if (i >= args->params->args_count
|
|
|
|
|| !hlsl_types_are_equal(param->data_type, args->params->args[i++]->data_type))
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (i == args->params->args_count)
|
|
|
|
args->decl = decl;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct hlsl_ir_function_decl *find_function_call(struct hlsl_ctx *ctx,
|
|
|
|
const char *name, const struct parse_initializer *params)
|
|
|
|
{
|
|
|
|
struct find_function_call_args args = {.params = params};
|
|
|
|
struct hlsl_ir_function *func;
|
|
|
|
struct rb_entry *entry;
|
|
|
|
|
|
|
|
if (!(entry = rb_get(&ctx->functions, name)))
|
|
|
|
return NULL;
|
|
|
|
func = RB_ENTRY_VALUE(entry, struct hlsl_ir_function, entry);
|
|
|
|
|
|
|
|
rb_for_each_entry(&func->overloads, find_function_call_exact, &args);
|
|
|
|
if (!args.decl)
|
|
|
|
FIXME("Search for compatible overloads.\n");
|
|
|
|
return args.decl;
|
|
|
|
}
|
|
|
|
|
2022-02-02 04:46:13 -08:00
|
|
|
static struct hlsl_ir_node *intrinsic_float_convert_arg(struct hlsl_ctx *ctx,
|
|
|
|
const struct parse_initializer *params, struct hlsl_ir_node *arg, const struct vkd3d_shader_location *loc)
|
|
|
|
{
|
|
|
|
struct hlsl_type *type = arg->data_type;
|
|
|
|
|
|
|
|
if (type->base_type == HLSL_TYPE_FLOAT || type->base_type == HLSL_TYPE_HALF)
|
|
|
|
return arg;
|
|
|
|
|
|
|
|
type = hlsl_get_numeric_type(ctx, type->type, HLSL_TYPE_FLOAT, type->dimx, type->dimy);
|
|
|
|
return add_implicit_conversion(ctx, params->instrs, arg, type, loc);
|
|
|
|
}
|
|
|
|
|
2021-09-17 14:06:37 -07:00
|
|
|
static bool intrinsic_abs(struct hlsl_ctx *ctx,
|
2021-12-01 08:14:58 -08:00
|
|
|
const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
|
2021-09-17 14:06:37 -07:00
|
|
|
{
|
2021-12-01 08:14:58 -08:00
|
|
|
return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_ABS, params->args[0], loc);
|
2021-09-17 14:06:37 -07:00
|
|
|
}
|
|
|
|
|
2021-09-01 15:20:55 -07:00
|
|
|
static bool intrinsic_clamp(struct hlsl_ctx *ctx,
|
2021-12-01 08:14:58 -08:00
|
|
|
const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
|
2021-09-01 15:20:55 -07:00
|
|
|
{
|
2022-06-07 14:29:21 -07:00
|
|
|
struct hlsl_ir_node *max;
|
2021-09-01 15:20:55 -07:00
|
|
|
|
2021-12-01 08:14:58 -08:00
|
|
|
if (!(max = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MAX, params->args[0], params->args[1], loc)))
|
2021-09-01 15:20:55 -07:00
|
|
|
return false;
|
|
|
|
|
2022-06-07 14:29:21 -07:00
|
|
|
return !!add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MIN, max, params->args[2], loc);
|
2021-09-01 15:20:55 -07:00
|
|
|
}
|
|
|
|
|
2021-11-19 09:33:53 -08:00
|
|
|
static bool intrinsic_cross(struct hlsl_ctx *ctx,
|
2021-12-01 08:14:58 -08:00
|
|
|
const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
|
2021-11-19 09:33:53 -08:00
|
|
|
{
|
|
|
|
struct hlsl_ir_swizzle *arg1_swzl1, *arg1_swzl2, *arg2_swzl1, *arg2_swzl2;
|
|
|
|
struct hlsl_ir_node *arg1 = params->args[0], *arg2 = params->args[1];
|
2022-06-07 14:29:21 -07:00
|
|
|
struct hlsl_ir_node *arg1_cast, *arg2_cast, *mul1_neg, *mul1, *mul2;
|
2021-11-19 09:33:53 -08:00
|
|
|
struct hlsl_type *cast_type;
|
|
|
|
enum hlsl_base_type base;
|
|
|
|
|
|
|
|
if (arg1->data_type->base_type == HLSL_TYPE_HALF && arg2->data_type->base_type == HLSL_TYPE_HALF)
|
|
|
|
base = HLSL_TYPE_HALF;
|
|
|
|
else
|
|
|
|
base = HLSL_TYPE_FLOAT;
|
|
|
|
|
|
|
|
cast_type = hlsl_get_vector_type(ctx, base, 3);
|
|
|
|
|
2021-12-01 08:14:58 -08:00
|
|
|
if (!(arg1_cast = add_implicit_conversion(ctx, params->instrs, arg1, cast_type, loc)))
|
2021-11-19 09:33:53 -08:00
|
|
|
return false;
|
|
|
|
|
2021-12-01 08:14:58 -08:00
|
|
|
if (!(arg2_cast = add_implicit_conversion(ctx, params->instrs, arg2, cast_type, loc)))
|
2021-11-19 09:33:53 -08:00
|
|
|
return false;
|
|
|
|
|
2021-12-01 08:14:58 -08:00
|
|
|
if (!(arg1_swzl1 = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(Z, X, Y, Z), 3, arg1_cast, loc)))
|
2021-11-19 09:33:53 -08:00
|
|
|
return false;
|
|
|
|
list_add_tail(params->instrs, &arg1_swzl1->node.entry);
|
|
|
|
|
2021-12-01 08:14:58 -08:00
|
|
|
if (!(arg2_swzl1 = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(Y, Z, X, Y), 3, arg2_cast, loc)))
|
2021-11-19 09:33:53 -08:00
|
|
|
return false;
|
|
|
|
list_add_tail(params->instrs, &arg2_swzl1->node.entry);
|
|
|
|
|
|
|
|
if (!(mul1 = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MUL,
|
2021-12-01 08:14:58 -08:00
|
|
|
&arg1_swzl1->node, &arg2_swzl1->node, loc)))
|
2021-11-19 09:33:53 -08:00
|
|
|
return false;
|
|
|
|
|
2022-06-07 14:29:21 -07:00
|
|
|
if (!(mul1_neg = hlsl_new_unary_expr(ctx, HLSL_OP1_NEG, mul1, *loc)))
|
2021-11-19 09:33:53 -08:00
|
|
|
return false;
|
|
|
|
list_add_tail(params->instrs, &mul1_neg->entry);
|
|
|
|
|
2021-12-01 08:14:58 -08:00
|
|
|
if (!(arg1_swzl2 = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(Y, Z, X, Y), 3, arg1_cast, loc)))
|
2021-11-19 09:33:53 -08:00
|
|
|
return false;
|
|
|
|
list_add_tail(params->instrs, &arg1_swzl2->node.entry);
|
|
|
|
|
2021-12-01 08:14:58 -08:00
|
|
|
if (!(arg2_swzl2 = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(Z, X, Y, Z), 3, arg2_cast, loc)))
|
2021-11-19 09:33:53 -08:00
|
|
|
return false;
|
|
|
|
list_add_tail(params->instrs, &arg2_swzl2->node.entry);
|
|
|
|
|
|
|
|
if (!(mul2 = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MUL,
|
2021-12-01 08:14:58 -08:00
|
|
|
&arg1_swzl2->node, &arg2_swzl2->node, loc)))
|
2021-11-19 09:33:53 -08:00
|
|
|
return false;
|
|
|
|
|
2022-06-07 14:29:21 -07:00
|
|
|
return !!add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_ADD, mul2, mul1_neg, loc);
|
2021-11-19 09:33:53 -08:00
|
|
|
}
|
|
|
|
|
2022-06-24 00:41:27 -07:00
|
|
|
static bool intrinsic_dot(struct hlsl_ctx *ctx,
|
|
|
|
const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
|
|
|
|
{
|
|
|
|
return !!add_binary_dot_expr(ctx, params->instrs, params->args[0], params->args[1], loc);
|
|
|
|
}
|
|
|
|
|
2022-02-02 04:46:15 -08:00
|
|
|
static bool intrinsic_floor(struct hlsl_ctx *ctx,
|
|
|
|
const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
|
|
|
|
{
|
|
|
|
struct hlsl_ir_node *arg;
|
|
|
|
|
|
|
|
if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_FLOOR, arg, loc);
|
|
|
|
}
|
|
|
|
|
2022-06-24 00:41:29 -07:00
|
|
|
static bool intrinsic_ldexp(struct hlsl_ctx *ctx,
|
|
|
|
const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
|
|
|
|
{
|
|
|
|
struct hlsl_ir_node *arg;
|
|
|
|
|
|
|
|
if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[1], loc)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!(arg = add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_EXP2, arg, loc)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return !!add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MUL, params->args[0], arg, loc);
|
|
|
|
}
|
|
|
|
|
2022-06-24 00:41:30 -07:00
|
|
|
static bool intrinsic_lerp(struct hlsl_ctx *ctx,
|
|
|
|
const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
|
|
|
|
{
|
|
|
|
struct hlsl_ir_node *arg, *neg, *add, *mul;
|
|
|
|
|
|
|
|
if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!(neg = add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_NEG, arg, loc)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!(add = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_ADD, params->args[1], neg, loc)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!(mul = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MUL, params->args[2], add, loc)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return !!add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_ADD, arg, mul, loc);
|
|
|
|
}
|
|
|
|
|
2021-09-01 15:20:54 -07:00
|
|
|
static bool intrinsic_max(struct hlsl_ctx *ctx,
|
2021-12-01 08:14:58 -08:00
|
|
|
const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
|
2021-09-01 15:20:54 -07:00
|
|
|
{
|
2021-12-01 08:14:58 -08:00
|
|
|
return !!add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MAX, params->args[0], params->args[1], loc);
|
2021-09-01 15:20:54 -07:00
|
|
|
}
|
|
|
|
|
2021-12-01 08:15:01 -08:00
|
|
|
static bool intrinsic_min(struct hlsl_ctx *ctx,
|
|
|
|
const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
|
|
|
|
{
|
|
|
|
return !!add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MIN, params->args[0], params->args[1], loc);
|
|
|
|
}
|
|
|
|
|
2022-06-08 16:18:43 -07:00
|
|
|
static bool intrinsic_mul(struct hlsl_ctx *ctx,
|
|
|
|
const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
|
|
|
|
{
|
|
|
|
struct hlsl_ir_node *arg1 = params->args[0], *arg2 = params->args[1], *cast1, *cast2;
|
|
|
|
enum hlsl_base_type base = expr_common_base_type(arg1->data_type->base_type, arg2->data_type->base_type);
|
|
|
|
struct hlsl_type *cast_type1 = arg1->data_type, *cast_type2 = arg2->data_type, *matrix_type, *ret_type;
|
|
|
|
unsigned int i, j, k, vect_count = 0;
|
|
|
|
struct vkd3d_string_buffer *name;
|
|
|
|
static unsigned int counter = 0;
|
|
|
|
struct hlsl_ir_load *load;
|
|
|
|
struct hlsl_ir_var *var;
|
|
|
|
|
|
|
|
if (arg1->data_type->type == HLSL_CLASS_SCALAR || arg2->data_type->type == HLSL_CLASS_SCALAR)
|
|
|
|
return !!add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MUL, arg1, arg2, loc);
|
|
|
|
|
|
|
|
if (arg1->data_type->type == HLSL_CLASS_VECTOR)
|
|
|
|
{
|
|
|
|
vect_count++;
|
|
|
|
cast_type1 = hlsl_get_matrix_type(ctx, base, arg1->data_type->dimx, 1);
|
|
|
|
}
|
|
|
|
if (arg2->data_type->type == HLSL_CLASS_VECTOR)
|
|
|
|
{
|
|
|
|
vect_count++;
|
|
|
|
cast_type2 = hlsl_get_matrix_type(ctx, base, 1, arg2->data_type->dimx);
|
|
|
|
}
|
|
|
|
|
|
|
|
matrix_type = hlsl_get_matrix_type(ctx, base, cast_type2->dimx, cast_type1->dimy);
|
|
|
|
|
|
|
|
if (vect_count == 0)
|
|
|
|
{
|
|
|
|
ret_type = matrix_type;
|
|
|
|
}
|
|
|
|
else if (vect_count == 1)
|
|
|
|
{
|
|
|
|
assert(matrix_type->dimx == 1 || matrix_type->dimy == 1);
|
|
|
|
ret_type = hlsl_get_vector_type(ctx, base, matrix_type->dimx * matrix_type->dimy);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
assert(matrix_type->dimx == 1 && matrix_type->dimy == 1);
|
|
|
|
ret_type = hlsl_get_scalar_type(ctx, base);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(cast1 = add_implicit_conversion(ctx, params->instrs, arg1, cast_type1, loc)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!(cast2 = add_implicit_conversion(ctx, params->instrs, arg2, cast_type2, loc)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
name = vkd3d_string_buffer_get(&ctx->string_buffers);
|
|
|
|
vkd3d_string_buffer_printf(name, "<mul-%u>", counter++);
|
|
|
|
var = hlsl_new_synthetic_var(ctx, name->buffer, matrix_type, *loc);
|
|
|
|
vkd3d_string_buffer_release(&ctx->string_buffers, name);
|
|
|
|
if (!var)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (i = 0; i < matrix_type->dimx; ++i)
|
|
|
|
for (j = 0; j < matrix_type->dimy; ++j)
|
|
|
|
{
|
|
|
|
struct hlsl_ir_node *node = NULL;
|
|
|
|
struct hlsl_type *scalar_type;
|
|
|
|
struct hlsl_ir_store *store;
|
|
|
|
struct hlsl_ir_constant *c;
|
|
|
|
unsigned int offset;
|
|
|
|
|
|
|
|
for (k = 0; k < cast_type1->dimx && k < cast_type2->dimy; ++k)
|
|
|
|
{
|
|
|
|
struct hlsl_ir_load *value1, *value2;
|
|
|
|
struct hlsl_ir_node *mul;
|
|
|
|
|
2022-06-29 15:29:42 -07:00
|
|
|
if (!(value1 = add_load_component(ctx, params->instrs, cast1, j * cast1->data_type->dimx + k, loc)))
|
2022-06-08 16:18:43 -07:00
|
|
|
return false;
|
|
|
|
|
2022-06-29 15:29:42 -07:00
|
|
|
if (!(value2 = add_load_component(ctx, params->instrs, cast2, k * cast2->data_type->dimx + i, loc)))
|
2022-06-08 16:18:43 -07:00
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!(mul = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MUL, &value1->node, &value2->node, loc)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (node)
|
|
|
|
{
|
|
|
|
if (!(node = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_ADD, node, mul, loc)))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
node = mul;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
offset = hlsl_compute_component_offset(ctx, matrix_type, j * matrix_type->dimx + i, &scalar_type);
|
|
|
|
if (!(c = hlsl_new_uint_constant(ctx, offset, loc)))
|
|
|
|
return false;
|
|
|
|
list_add_tail(params->instrs, &c->node.entry);
|
|
|
|
|
|
|
|
if (!(store = hlsl_new_store(ctx, var, &c->node, node, 0, *loc)))
|
|
|
|
return false;
|
|
|
|
list_add_tail(params->instrs, &store->node.entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(load = hlsl_new_load(ctx, var, NULL, matrix_type, *loc)))
|
|
|
|
return false;
|
|
|
|
list_add_tail(params->instrs, &load->node.entry);
|
|
|
|
|
|
|
|
return !!add_implicit_conversion(ctx, params->instrs, &load->node, ret_type, loc);
|
|
|
|
}
|
|
|
|
|
2021-09-20 05:20:56 -07:00
|
|
|
static bool intrinsic_pow(struct hlsl_ctx *ctx,
|
2021-12-01 08:14:58 -08:00
|
|
|
const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
|
2021-09-20 05:20:56 -07:00
|
|
|
{
|
2022-06-07 14:29:21 -07:00
|
|
|
struct hlsl_ir_node *log, *exp, *arg, *mul;
|
2021-09-20 05:20:56 -07:00
|
|
|
|
2022-03-08 15:58:13 -08:00
|
|
|
if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!(log = hlsl_new_unary_expr(ctx, HLSL_OP1_LOG2, arg, *loc)))
|
2021-09-20 05:20:56 -07:00
|
|
|
return false;
|
|
|
|
list_add_tail(params->instrs, &log->entry);
|
|
|
|
|
2021-12-01 08:14:58 -08:00
|
|
|
if (!(mul = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MUL, params->args[1], log, loc)))
|
2021-09-20 05:20:56 -07:00
|
|
|
return false;
|
|
|
|
|
2022-06-07 14:29:21 -07:00
|
|
|
if (!(exp = hlsl_new_unary_expr(ctx, HLSL_OP1_EXP2, mul, *loc)))
|
2021-09-20 05:20:56 -07:00
|
|
|
return false;
|
|
|
|
list_add_tail(params->instrs, &exp->entry);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-11-19 06:38:41 -08:00
|
|
|
static bool intrinsic_round(struct hlsl_ctx *ctx,
|
2021-12-01 08:14:58 -08:00
|
|
|
const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
|
2021-11-19 06:38:41 -08:00
|
|
|
{
|
2022-02-02 04:46:13 -08:00
|
|
|
struct hlsl_ir_node *arg;
|
|
|
|
|
|
|
|
if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_ROUND, arg, loc);
|
2021-11-19 06:38:41 -08:00
|
|
|
}
|
|
|
|
|
2021-09-16 11:55:56 -07:00
|
|
|
static bool intrinsic_saturate(struct hlsl_ctx *ctx,
|
2021-12-01 08:14:58 -08:00
|
|
|
const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
|
2021-09-16 11:55:56 -07:00
|
|
|
{
|
2022-02-02 04:46:14 -08:00
|
|
|
struct hlsl_ir_node *arg;
|
|
|
|
|
|
|
|
if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_SAT, arg, loc);
|
2021-09-16 11:55:56 -07:00
|
|
|
}
|
|
|
|
|
2021-09-01 15:20:54 -07:00
|
|
|
static const struct intrinsic_function
|
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
int param_count;
|
|
|
|
bool check_numeric;
|
2021-12-01 08:14:58 -08:00
|
|
|
bool (*handler)(struct hlsl_ctx *ctx, const struct parse_initializer *params,
|
|
|
|
const struct vkd3d_shader_location *loc);
|
2021-09-01 15:20:54 -07:00
|
|
|
}
|
|
|
|
intrinsic_functions[] =
|
|
|
|
{
|
2021-11-19 06:38:41 -08:00
|
|
|
/* Note: these entries should be kept in alphabetical order. */
|
2021-09-17 14:06:37 -07:00
|
|
|
{"abs", 1, true, intrinsic_abs},
|
2021-09-01 15:20:55 -07:00
|
|
|
{"clamp", 3, true, intrinsic_clamp},
|
2021-11-19 09:33:53 -08:00
|
|
|
{"cross", 2, true, intrinsic_cross},
|
2022-06-24 00:41:27 -07:00
|
|
|
{"dot", 2, true, intrinsic_dot},
|
2022-02-02 04:46:15 -08:00
|
|
|
{"floor", 1, true, intrinsic_floor},
|
2022-06-24 00:41:29 -07:00
|
|
|
{"ldexp", 2, true, intrinsic_ldexp},
|
2022-06-24 00:41:30 -07:00
|
|
|
{"lerp", 3, true, intrinsic_lerp},
|
2021-09-01 15:20:54 -07:00
|
|
|
{"max", 2, true, intrinsic_max},
|
2021-12-01 08:15:01 -08:00
|
|
|
{"min", 2, true, intrinsic_min},
|
2022-06-08 16:18:43 -07:00
|
|
|
{"mul", 2, true, intrinsic_mul},
|
2021-09-20 05:20:56 -07:00
|
|
|
{"pow", 2, true, intrinsic_pow},
|
2021-11-19 06:38:41 -08:00
|
|
|
{"round", 1, true, intrinsic_round},
|
2021-09-16 11:55:56 -07:00
|
|
|
{"saturate", 1, true, intrinsic_saturate},
|
2021-09-01 15:20:54 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
static int intrinsic_function_name_compare(const void *a, const void *b)
|
|
|
|
{
|
|
|
|
const struct intrinsic_function *func = b;
|
|
|
|
|
|
|
|
return strcmp(a, func->name);
|
|
|
|
}
|
|
|
|
|
2021-09-01 15:20:52 -07:00
|
|
|
static struct list *add_call(struct hlsl_ctx *ctx, const char *name,
|
|
|
|
struct parse_initializer *params, struct vkd3d_shader_location loc)
|
|
|
|
{
|
|
|
|
const struct hlsl_ir_function_decl *decl;
|
2021-09-01 15:20:54 -07:00
|
|
|
struct intrinsic_function *intrinsic;
|
2021-09-01 15:20:52 -07:00
|
|
|
|
|
|
|
if ((decl = find_function_call(ctx, name, params)))
|
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_fixme(ctx, &loc, "Call to user-defined function \"%s\".", name);
|
2021-09-01 15:20:52 -07:00
|
|
|
free_parse_initializer(params);
|
|
|
|
return NULL;
|
|
|
|
}
|
2021-09-01 15:20:54 -07:00
|
|
|
else if ((intrinsic = bsearch(name, intrinsic_functions, ARRAY_SIZE(intrinsic_functions),
|
|
|
|
sizeof(*intrinsic_functions), intrinsic_function_name_compare)))
|
|
|
|
{
|
|
|
|
if (intrinsic->param_count >= 0 && params->args_count != intrinsic->param_count)
|
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT,
|
2022-04-06 01:53:29 -07:00
|
|
|
"Wrong number of arguments to function '%s': expected %u, but got %u.",
|
2021-09-01 15:20:54 -07:00
|
|
|
name, intrinsic->param_count, params->args_count);
|
|
|
|
free_parse_initializer(params);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (intrinsic->check_numeric)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < params->args_count; ++i)
|
|
|
|
{
|
|
|
|
if (params->args[i]->data_type->type > HLSL_CLASS_LAST_NUMERIC)
|
|
|
|
{
|
|
|
|
struct vkd3d_string_buffer *string;
|
|
|
|
|
|
|
|
if ((string = hlsl_type_to_string(ctx, params->args[i]->data_type)))
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
|
2022-04-06 01:53:29 -07:00
|
|
|
"Wrong type for argument %u of '%s': expected a numeric type, but got '%s'.",
|
2021-09-01 15:20:54 -07:00
|
|
|
i + 1, name, string->buffer);
|
|
|
|
hlsl_release_string_buffer(ctx, string);
|
|
|
|
free_parse_initializer(params);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-01 08:14:58 -08:00
|
|
|
if (!intrinsic->handler(ctx, params, &loc))
|
2021-09-01 15:20:54 -07:00
|
|
|
{
|
|
|
|
free_parse_initializer(params);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
2021-09-01 15:20:52 -07:00
|
|
|
else
|
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &loc, VKD3D_SHADER_ERROR_HLSL_NOT_DEFINED, "Function \"%s\" is not defined.", name);
|
2021-09-01 15:20:52 -07:00
|
|
|
free_parse_initializer(params);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
vkd3d_free(params->args);
|
|
|
|
return params->instrs;
|
|
|
|
}
|
|
|
|
|
2021-09-20 14:40:14 -07:00
|
|
|
static struct list *add_constructor(struct hlsl_ctx *ctx, struct hlsl_type *type,
|
|
|
|
struct parse_initializer *params, struct vkd3d_shader_location loc)
|
|
|
|
{
|
|
|
|
static unsigned int counter;
|
|
|
|
struct hlsl_ir_load *load;
|
|
|
|
struct hlsl_ir_var *var;
|
2022-04-27 01:56:26 -07:00
|
|
|
unsigned int i, idx = 0;
|
2021-09-20 14:40:14 -07:00
|
|
|
char name[23];
|
|
|
|
|
|
|
|
sprintf(name, "<constructor-%x>", counter++);
|
|
|
|
if (!(var = hlsl_new_synthetic_var(ctx, name, type, loc)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (i = 0; i < params->args_count; ++i)
|
|
|
|
{
|
|
|
|
struct hlsl_ir_node *arg = params->args[i];
|
|
|
|
|
|
|
|
if (arg->data_type->type == HLSL_CLASS_OBJECT)
|
|
|
|
{
|
|
|
|
struct vkd3d_string_buffer *string;
|
|
|
|
|
|
|
|
if ((string = hlsl_type_to_string(ctx, arg->data_type)))
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &arg->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
|
2021-09-20 14:40:14 -07:00
|
|
|
"Invalid type %s for constructor argument.", string->buffer);
|
|
|
|
hlsl_release_string_buffer(ctx, string);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-05-03 02:57:17 -07:00
|
|
|
initialize_var_components(ctx, params->instrs, var, &idx, arg);
|
2021-09-20 14:40:14 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!(load = hlsl_new_var_load(ctx, var, loc)))
|
|
|
|
return NULL;
|
|
|
|
list_add_tail(params->instrs, &load->node.entry);
|
|
|
|
|
|
|
|
vkd3d_free(params->args);
|
|
|
|
return params->instrs;
|
|
|
|
}
|
|
|
|
|
2021-10-07 19:58:57 -07:00
|
|
|
static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *object,
|
|
|
|
const char *name, const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
|
|
|
|
{
|
|
|
|
const struct hlsl_type *object_type = object->data_type;
|
|
|
|
struct hlsl_ir_load *object_load;
|
|
|
|
|
|
|
|
if (object_type->type != HLSL_CLASS_OBJECT || object_type->base_type != HLSL_TYPE_TEXTURE
|
|
|
|
|| object_type->sampler_dim == HLSL_SAMPLER_DIM_GENERIC)
|
|
|
|
{
|
|
|
|
struct vkd3d_string_buffer *string;
|
|
|
|
|
|
|
|
if ((string = hlsl_type_to_string(ctx, object_type)))
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
|
2021-10-07 19:58:57 -07:00
|
|
|
"Type '%s' does not have methods.", string->buffer);
|
|
|
|
hlsl_release_string_buffer(ctx, string);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Only HLSL_IR_LOAD can return an object. */
|
|
|
|
object_load = hlsl_ir_load(object);
|
|
|
|
|
2022-01-27 10:31:24 -08:00
|
|
|
if (!strcmp(name, "Load")
|
|
|
|
&& object_type->sampler_dim != HLSL_SAMPLER_DIM_CUBE
|
|
|
|
&& object_type->sampler_dim != HLSL_SAMPLER_DIM_CUBEARRAY)
|
2021-10-07 19:58:57 -07:00
|
|
|
{
|
2022-01-27 10:31:22 -08:00
|
|
|
const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim);
|
2021-10-07 19:58:57 -07:00
|
|
|
struct hlsl_ir_resource_load *load;
|
|
|
|
struct hlsl_ir_node *coords;
|
|
|
|
|
2022-01-27 10:31:24 -08:00
|
|
|
if (object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMS
|
|
|
|
|| object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMSARRAY)
|
|
|
|
{
|
|
|
|
FIXME("'Load' method for multi-sample textures.\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-10-07 19:58:57 -07:00
|
|
|
if (params->args_count < 1 || params->args_count > 3)
|
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT,
|
2021-10-07 19:58:57 -07:00
|
|
|
"Wrong number of arguments to method 'Load': expected 1, 2, or 3, but got %u.", params->args_count);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (params->args_count >= 2)
|
2022-01-27 10:31:24 -08:00
|
|
|
hlsl_fixme(ctx, loc, "Offset parameter.");
|
|
|
|
if (params->args_count == 3)
|
|
|
|
hlsl_fixme(ctx, loc, "Tiled resource status argument.");
|
2021-10-07 19:58:57 -07:00
|
|
|
|
2021-10-25 00:06:25 -07:00
|
|
|
/* +1 for the mipmap level */
|
2021-10-07 19:58:57 -07:00
|
|
|
if (!(coords = add_implicit_conversion(ctx, instrs, params->args[0],
|
2021-10-25 00:06:25 -07:00
|
|
|
hlsl_get_vector_type(ctx, HLSL_TYPE_INT, sampler_dim + 1), loc)))
|
2021-10-07 19:58:57 -07:00
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!(load = hlsl_new_resource_load(ctx, object_type->e.resource_format, HLSL_RESOURCE_LOAD,
|
2022-01-26 06:35:29 -08:00
|
|
|
object_load->src.var, object_load->src.offset.node, NULL, NULL, coords, NULL, loc)))
|
2021-11-05 11:35:52 -07:00
|
|
|
return false;
|
|
|
|
list_add_tail(instrs, &load->node.entry);
|
|
|
|
return true;
|
|
|
|
}
|
2022-01-27 10:31:24 -08:00
|
|
|
else if (!strcmp(name, "Sample")
|
|
|
|
&& object_type->sampler_dim != HLSL_SAMPLER_DIM_2DMS
|
|
|
|
&& object_type->sampler_dim != HLSL_SAMPLER_DIM_2DMSARRAY)
|
2021-11-05 11:35:52 -07:00
|
|
|
{
|
2022-01-27 10:31:22 -08:00
|
|
|
const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim);
|
2021-11-05 11:35:52 -07:00
|
|
|
const struct hlsl_type *sampler_type;
|
|
|
|
struct hlsl_ir_resource_load *load;
|
2022-01-26 06:35:29 -08:00
|
|
|
struct hlsl_ir_node *offset = NULL;
|
2021-11-05 11:35:52 -07:00
|
|
|
struct hlsl_ir_load *sampler_load;
|
|
|
|
struct hlsl_ir_node *coords;
|
|
|
|
|
|
|
|
if (params->args_count != 2 && params->args_count != 3)
|
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT,
|
2021-11-05 11:35:52 -07:00
|
|
|
"Wrong number of arguments to method 'Sample': expected 2 or 3, but got %u.", params->args_count);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
sampler_type = params->args[0]->data_type;
|
|
|
|
if (sampler_type->type != HLSL_CLASS_OBJECT || sampler_type->base_type != HLSL_TYPE_SAMPLER
|
|
|
|
|| sampler_type->sampler_dim != HLSL_SAMPLER_DIM_GENERIC)
|
|
|
|
{
|
|
|
|
struct vkd3d_string_buffer *string;
|
|
|
|
|
|
|
|
if ((string = hlsl_type_to_string(ctx, sampler_type)))
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
|
2021-11-05 11:35:52 -07:00
|
|
|
"Wrong type for argument 0 of Sample(): expected 'sampler', but got '%s'.", string->buffer);
|
|
|
|
hlsl_release_string_buffer(ctx, string);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Only HLSL_IR_LOAD can return an object. */
|
|
|
|
sampler_load = hlsl_ir_load(params->args[0]);
|
|
|
|
|
|
|
|
if (!(coords = add_implicit_conversion(ctx, instrs, params->args[1],
|
|
|
|
hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc)))
|
2022-01-26 06:35:29 -08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
if (params->args_count == 3)
|
|
|
|
{
|
|
|
|
if (!(offset = add_implicit_conversion(ctx, instrs, params->args[2],
|
|
|
|
hlsl_get_vector_type(ctx, HLSL_TYPE_INT, sampler_dim), loc)))
|
|
|
|
return false;
|
|
|
|
}
|
2021-11-05 11:35:52 -07:00
|
|
|
|
|
|
|
if (!(load = hlsl_new_resource_load(ctx, object_type->e.resource_format,
|
|
|
|
HLSL_RESOURCE_SAMPLE, object_load->src.var, object_load->src.offset.node,
|
2022-01-26 06:35:32 -08:00
|
|
|
sampler_load->src.var, sampler_load->src.offset.node, coords, offset, loc)))
|
|
|
|
return false;
|
|
|
|
list_add_tail(instrs, &load->node.entry);
|
|
|
|
return true;
|
|
|
|
}
|
2022-01-27 10:31:24 -08:00
|
|
|
else if ((!strcmp(name, "Gather") || !strcmp(name, "GatherRed") || !strcmp(name, "GatherBlue")
|
2022-01-26 06:35:32 -08:00
|
|
|
|| !strcmp(name, "GatherGreen") || !strcmp(name, "GatherAlpha"))
|
2022-01-27 10:31:24 -08:00
|
|
|
&& (object_type->sampler_dim == HLSL_SAMPLER_DIM_2D
|
|
|
|
|| object_type->sampler_dim == HLSL_SAMPLER_DIM_2DARRAY
|
|
|
|
|| object_type->sampler_dim == HLSL_SAMPLER_DIM_CUBE
|
|
|
|
|| object_type->sampler_dim == HLSL_SAMPLER_DIM_CUBEARRAY))
|
2022-01-26 06:35:32 -08:00
|
|
|
{
|
2022-01-27 10:31:22 -08:00
|
|
|
const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim);
|
2022-01-26 06:35:32 -08:00
|
|
|
enum hlsl_resource_load_type load_type;
|
|
|
|
const struct hlsl_type *sampler_type;
|
|
|
|
struct hlsl_ir_resource_load *load;
|
|
|
|
struct hlsl_ir_node *offset = NULL;
|
|
|
|
struct hlsl_ir_load *sampler_load;
|
|
|
|
struct hlsl_type *result_type;
|
|
|
|
struct hlsl_ir_node *coords;
|
|
|
|
unsigned int read_channel;
|
|
|
|
|
|
|
|
if (!strcmp(name, "GatherGreen"))
|
|
|
|
{
|
|
|
|
load_type = HLSL_RESOURCE_GATHER_GREEN;
|
|
|
|
read_channel = 1;
|
|
|
|
}
|
|
|
|
else if (!strcmp(name, "GatherBlue"))
|
|
|
|
{
|
|
|
|
load_type = HLSL_RESOURCE_GATHER_BLUE;
|
|
|
|
read_channel = 2;
|
|
|
|
}
|
|
|
|
else if (!strcmp(name, "GatherAlpha"))
|
|
|
|
{
|
|
|
|
load_type = HLSL_RESOURCE_GATHER_ALPHA;
|
|
|
|
read_channel = 3;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
load_type = HLSL_RESOURCE_GATHER_RED;
|
|
|
|
read_channel = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(name, "Gather"))
|
|
|
|
{
|
|
|
|
if (params->args_count != 2 && params->args_count != 3)
|
|
|
|
{
|
|
|
|
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT,
|
|
|
|
"Wrong number of arguments to method 'Gather': expected 2 or 3, but got %u.", params->args_count);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (params->args_count < 2 || params->args_count == 5 || params->args_count > 7)
|
|
|
|
{
|
|
|
|
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT,
|
|
|
|
"Wrong number of arguments to method '%s': expected 2, 3, 4, 6 or 7, but got %u.",
|
|
|
|
name, params->args_count);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (params->args_count == 4 || params->args_count == 7)
|
|
|
|
hlsl_fixme(ctx, loc, "Tiled resource status argument.");
|
|
|
|
|
|
|
|
if (params->args_count == 6 || params->args_count == 7)
|
|
|
|
hlsl_fixme(ctx, loc, "Multiple Gather() offset parameters.");
|
|
|
|
|
|
|
|
if (params->args_count == 3 || params->args_count == 4)
|
|
|
|
{
|
|
|
|
if (!(offset = add_implicit_conversion(ctx, instrs, params->args[2],
|
|
|
|
hlsl_get_vector_type(ctx, HLSL_TYPE_INT, sampler_dim), loc)))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
sampler_type = params->args[0]->data_type;
|
|
|
|
if (sampler_type->type != HLSL_CLASS_OBJECT || sampler_type->base_type != HLSL_TYPE_SAMPLER
|
|
|
|
|| sampler_type->sampler_dim != HLSL_SAMPLER_DIM_GENERIC)
|
|
|
|
{
|
|
|
|
struct vkd3d_string_buffer *string;
|
|
|
|
|
|
|
|
if ((string = hlsl_type_to_string(ctx, sampler_type)))
|
|
|
|
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
|
|
|
|
"Wrong type for argument 1 of %s(): expected 'sampler', but got '%s'.", name, string->buffer);
|
|
|
|
hlsl_release_string_buffer(ctx, string);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (read_channel >= object_type->e.resource_format->dimx)
|
|
|
|
{
|
|
|
|
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
|
|
|
|
"Method %s() requires at least %u channels.", name, read_channel + 1);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
result_type = hlsl_get_vector_type(ctx, object_type->e.resource_format->base_type, 4);
|
|
|
|
|
|
|
|
/* Only HLSL_IR_LOAD can return an object. */
|
|
|
|
sampler_load = hlsl_ir_load(params->args[0]);
|
|
|
|
|
|
|
|
if (!(coords = add_implicit_conversion(ctx, instrs, params->args[1],
|
|
|
|
hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!(load = hlsl_new_resource_load(ctx, result_type,
|
|
|
|
load_type, object_load->src.var, object_load->src.offset.node,
|
2022-01-26 06:35:29 -08:00
|
|
|
sampler_load->src.var, sampler_load->src.offset.node, coords, offset, loc)))
|
2021-10-07 19:58:57 -07:00
|
|
|
return false;
|
|
|
|
list_add_tail(instrs, &load->node.entry);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
struct vkd3d_string_buffer *string;
|
|
|
|
|
|
|
|
if ((string = hlsl_type_to_string(ctx, object_type)))
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_NOT_DEFINED,
|
2021-10-07 19:58:57 -07:00
|
|
|
"Method '%s' is not defined on type '%s'.", name, string->buffer);
|
|
|
|
hlsl_release_string_buffer(ctx, string);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:49 -08:00
|
|
|
}
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
%locations
|
|
|
|
%define parse.error verbose
|
2021-02-12 08:48:53 -08:00
|
|
|
%define api.prefix {hlsl_yy}
|
2021-02-04 14:33:53 -08:00
|
|
|
%define api.pure full
|
2021-01-27 08:29:44 -08:00
|
|
|
%expect 1
|
2021-02-04 14:33:53 -08:00
|
|
|
%lex-param {yyscan_t scanner}
|
|
|
|
%parse-param {void *scanner}
|
|
|
|
%parse-param {struct hlsl_ctx *ctx}
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
%union
|
|
|
|
{
|
|
|
|
struct hlsl_type *type;
|
|
|
|
INT intval;
|
|
|
|
FLOAT floatval;
|
|
|
|
BOOL boolval;
|
|
|
|
char *name;
|
|
|
|
DWORD modifiers;
|
|
|
|
struct hlsl_ir_node *instr;
|
|
|
|
struct list *list;
|
2022-07-14 18:23:43 -07:00
|
|
|
struct parse_fields fields;
|
2021-01-27 08:29:44 -08:00
|
|
|
struct parse_function function;
|
|
|
|
struct parse_parameter parameter;
|
|
|
|
struct parse_initializer initializer;
|
2021-03-04 15:33:27 -08:00
|
|
|
struct parse_array_sizes arrays;
|
2021-01-27 08:29:44 -08:00
|
|
|
struct parse_variable_def *variable_def;
|
|
|
|
struct parse_if_body if_body;
|
|
|
|
enum parse_assign_op assign_op;
|
2021-05-31 19:41:14 -07:00
|
|
|
struct hlsl_reg_reservation reg_reservation;
|
2021-01-27 08:29:44 -08:00
|
|
|
struct parse_colon_attribute colon_attribute;
|
2021-04-27 10:14:19 -07:00
|
|
|
struct hlsl_semantic semantic;
|
2021-06-21 21:37:09 -07:00
|
|
|
enum hlsl_buffer_type buffer_type;
|
2021-10-07 19:58:55 -07:00
|
|
|
enum hlsl_sampler_dim sampler_dim;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
%token KW_BLENDSTATE
|
|
|
|
%token KW_BREAK
|
|
|
|
%token KW_BUFFER
|
|
|
|
%token KW_CBUFFER
|
|
|
|
%token KW_COLUMN_MAJOR
|
|
|
|
%token KW_COMPILE
|
|
|
|
%token KW_CONST
|
|
|
|
%token KW_CONTINUE
|
|
|
|
%token KW_DEPTHSTENCILSTATE
|
|
|
|
%token KW_DEPTHSTENCILVIEW
|
|
|
|
%token KW_DISCARD
|
|
|
|
%token KW_DO
|
|
|
|
%token KW_DOUBLE
|
|
|
|
%token KW_ELSE
|
|
|
|
%token KW_EXTERN
|
|
|
|
%token KW_FALSE
|
|
|
|
%token KW_FOR
|
|
|
|
%token KW_GEOMETRYSHADER
|
|
|
|
%token KW_GROUPSHARED
|
|
|
|
%token KW_IF
|
|
|
|
%token KW_IN
|
|
|
|
%token KW_INLINE
|
|
|
|
%token KW_INOUT
|
|
|
|
%token KW_MATRIX
|
|
|
|
%token KW_NAMESPACE
|
|
|
|
%token KW_NOINTERPOLATION
|
|
|
|
%token KW_OUT
|
|
|
|
%token KW_PASS
|
|
|
|
%token KW_PIXELSHADER
|
|
|
|
%token KW_PRECISE
|
|
|
|
%token KW_RASTERIZERSTATE
|
|
|
|
%token KW_RENDERTARGETVIEW
|
|
|
|
%token KW_RETURN
|
|
|
|
%token KW_REGISTER
|
|
|
|
%token KW_ROW_MAJOR
|
|
|
|
%token KW_SAMPLER
|
|
|
|
%token KW_SAMPLER1D
|
|
|
|
%token KW_SAMPLER2D
|
|
|
|
%token KW_SAMPLER3D
|
|
|
|
%token KW_SAMPLERCUBE
|
|
|
|
%token KW_SAMPLER_STATE
|
|
|
|
%token KW_SAMPLERCOMPARISONSTATE
|
|
|
|
%token KW_SHARED
|
|
|
|
%token KW_STATEBLOCK
|
|
|
|
%token KW_STATEBLOCK_STATE
|
|
|
|
%token KW_STATIC
|
|
|
|
%token KW_STRING
|
|
|
|
%token KW_STRUCT
|
|
|
|
%token KW_SWITCH
|
|
|
|
%token KW_TBUFFER
|
|
|
|
%token KW_TECHNIQUE
|
|
|
|
%token KW_TECHNIQUE10
|
|
|
|
%token KW_TEXTURE
|
|
|
|
%token KW_TEXTURE1D
|
|
|
|
%token KW_TEXTURE1DARRAY
|
|
|
|
%token KW_TEXTURE2D
|
|
|
|
%token KW_TEXTURE2DARRAY
|
|
|
|
%token KW_TEXTURE2DMS
|
|
|
|
%token KW_TEXTURE2DMSARRAY
|
|
|
|
%token KW_TEXTURE3D
|
|
|
|
%token KW_TEXTURECUBE
|
2022-01-27 10:31:26 -08:00
|
|
|
%token KW_TEXTURECUBEARRAY
|
2021-01-27 08:29:44 -08:00
|
|
|
%token KW_TRUE
|
|
|
|
%token KW_TYPEDEF
|
|
|
|
%token KW_UNIFORM
|
|
|
|
%token KW_VECTOR
|
|
|
|
%token KW_VERTEXSHADER
|
|
|
|
%token KW_VOID
|
|
|
|
%token KW_VOLATILE
|
|
|
|
%token KW_WHILE
|
|
|
|
|
|
|
|
%token OP_INC
|
|
|
|
%token OP_DEC
|
|
|
|
%token OP_AND
|
|
|
|
%token OP_OR
|
|
|
|
%token OP_EQ
|
|
|
|
%token OP_LEFTSHIFT
|
|
|
|
%token OP_LEFTSHIFTASSIGN
|
|
|
|
%token OP_RIGHTSHIFT
|
|
|
|
%token OP_RIGHTSHIFTASSIGN
|
|
|
|
%token OP_ELLIPSIS
|
|
|
|
%token OP_LE
|
|
|
|
%token OP_GE
|
|
|
|
%token OP_NE
|
|
|
|
%token OP_ADDASSIGN
|
|
|
|
%token OP_SUBASSIGN
|
|
|
|
%token OP_MULASSIGN
|
|
|
|
%token OP_DIVASSIGN
|
|
|
|
%token OP_MODASSIGN
|
|
|
|
%token OP_ANDASSIGN
|
|
|
|
%token OP_ORASSIGN
|
|
|
|
%token OP_XORASSIGN
|
|
|
|
%token OP_UNKNOWN1
|
|
|
|
%token OP_UNKNOWN2
|
|
|
|
%token OP_UNKNOWN3
|
|
|
|
%token OP_UNKNOWN4
|
|
|
|
|
|
|
|
%token <floatval> C_FLOAT
|
|
|
|
|
|
|
|
%token <intval> C_INTEGER
|
|
|
|
%token <intval> PRE_LINE
|
|
|
|
|
|
|
|
%type <list> add_expr
|
|
|
|
%type <list> assignment_expr
|
|
|
|
%type <list> bitand_expr
|
|
|
|
%type <list> bitor_expr
|
|
|
|
%type <list> bitxor_expr
|
|
|
|
%type <list> compound_statement
|
|
|
|
%type <list> conditional_expr
|
|
|
|
%type <list> declaration
|
|
|
|
%type <list> declaration_statement
|
|
|
|
%type <list> equality_expr
|
|
|
|
%type <list> expr
|
|
|
|
%type <list> expr_statement
|
|
|
|
%type <list> initializer_expr
|
|
|
|
%type <list> jump_statement
|
|
|
|
%type <list> logicand_expr
|
|
|
|
%type <list> logicor_expr
|
|
|
|
%type <list> loop_statement
|
|
|
|
%type <list> mul_expr
|
|
|
|
%type <list> param_list
|
|
|
|
%type <list> parameters
|
|
|
|
%type <list> postfix_expr
|
|
|
|
%type <list> primary_expr
|
|
|
|
%type <list> relational_expr
|
|
|
|
%type <list> selection_statement
|
|
|
|
%type <list> shift_expr
|
|
|
|
%type <list> statement
|
|
|
|
%type <list> statement_list
|
|
|
|
%type <list> struct_declaration
|
|
|
|
%type <list> type_specs
|
|
|
|
%type <list> unary_expr
|
|
|
|
%type <list> variables_def
|
|
|
|
%type <list> variables_def_optional
|
|
|
|
|
|
|
|
%token <name> VAR_IDENTIFIER
|
|
|
|
%token <name> NEW_IDENTIFIER
|
|
|
|
%token <name> STRING
|
|
|
|
%token <name> TYPE_IDENTIFIER
|
|
|
|
|
2021-03-04 15:33:27 -08:00
|
|
|
%type <arrays> arrays
|
|
|
|
|
2021-01-27 08:29:44 -08:00
|
|
|
%type <assign_op> assign_op
|
|
|
|
|
|
|
|
%type <boolval> boolean
|
|
|
|
|
2021-06-21 21:37:09 -07:00
|
|
|
%type <buffer_type> buffer_type
|
|
|
|
|
2021-01-27 08:29:44 -08:00
|
|
|
%type <colon_attribute> colon_attribute
|
|
|
|
|
2022-07-14 18:23:43 -07:00
|
|
|
%type <fields> field
|
|
|
|
%type <fields> fields_list
|
|
|
|
|
2021-01-27 08:29:44 -08:00
|
|
|
%type <function> func_declaration
|
|
|
|
%type <function> func_prototype
|
|
|
|
|
|
|
|
%type <initializer> complex_initializer
|
2022-03-30 14:38:27 -07:00
|
|
|
%type <initializer> complex_initializer_list
|
2021-09-01 15:20:52 -07:00
|
|
|
%type <initializer> func_arguments
|
2021-01-27 08:29:44 -08:00
|
|
|
%type <initializer> initializer_expr_list
|
|
|
|
|
|
|
|
%type <if_body> if_body
|
|
|
|
|
|
|
|
%type <modifiers> var_modifiers
|
|
|
|
|
|
|
|
%type <name> any_identifier
|
|
|
|
%type <name> var_identifier
|
|
|
|
|
|
|
|
%type <parameter> parameter
|
|
|
|
|
|
|
|
%type <reg_reservation> register_opt
|
|
|
|
|
2021-10-07 19:58:55 -07:00
|
|
|
%type <sampler_dim> texture_type
|
|
|
|
|
2021-04-27 10:14:19 -07:00
|
|
|
%type <semantic> semantic
|
|
|
|
|
2021-01-27 08:29:44 -08:00
|
|
|
%type <type> field_type
|
|
|
|
%type <type> named_struct_spec
|
|
|
|
%type <type> unnamed_struct_spec
|
|
|
|
%type <type> struct_spec
|
|
|
|
%type <type> type
|
|
|
|
%type <type> typedef_type
|
|
|
|
|
|
|
|
%type <variable_def> type_spec
|
2021-09-23 14:47:06 -07:00
|
|
|
%type <variable_def> variable_decl
|
2021-01-27 08:29:44 -08:00
|
|
|
%type <variable_def> variable_def
|
|
|
|
|
|
|
|
%%
|
|
|
|
|
|
|
|
hlsl_prog:
|
2021-03-02 13:34:42 -08:00
|
|
|
%empty
|
2021-01-27 08:29:44 -08:00
|
|
|
| hlsl_prog func_declaration
|
|
|
|
{
|
|
|
|
const struct hlsl_ir_function_decl *decl;
|
|
|
|
|
2021-09-01 15:20:53 -07:00
|
|
|
decl = get_func_decl(&ctx->functions, $2.name, $2.decl->parameters);
|
2021-01-27 08:29:44 -08:00
|
|
|
if (decl && !decl->func->intrinsic)
|
|
|
|
{
|
2021-10-15 14:54:09 -07:00
|
|
|
if (decl->has_body && $2.decl->has_body)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &$2.decl->loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED,
|
2021-02-21 20:04:36 -08:00
|
|
|
"Function \"%s\" is already defined.", $2.name);
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_note(ctx, &decl->loc, VKD3D_SHADER_LOG_ERROR, "\"%s\" was previously defined here.", $2.name);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
2021-03-17 22:22:19 -07:00
|
|
|
else if (!hlsl_types_are_equal(decl->return_type, $2.decl->return_type))
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &$2.decl->loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED,
|
2021-02-21 20:04:36 -08:00
|
|
|
"Function \"%s\" was already declared with a different return type.", $2.name);
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_note(ctx, &decl->loc, VKD3D_SHADER_LOG_ERROR, "\"%s\" was previously declared here.", $2.name);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-20 22:32:20 -07:00
|
|
|
hlsl_add_function(ctx, $2.name, $2.decl, false);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
2021-06-21 21:37:10 -07:00
|
|
|
| hlsl_prog buffer_declaration buffer_body
|
2021-01-27 08:29:44 -08:00
|
|
|
| hlsl_prog declaration_statement
|
|
|
|
{
|
|
|
|
if (!list_empty($2))
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_fixme(ctx, &@2, "Uniform initializer.");
|
2021-08-19 08:29:06 -07:00
|
|
|
destroy_instr_list($2);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| hlsl_prog preproc_directive
|
|
|
|
| hlsl_prog ';'
|
|
|
|
|
2021-06-21 21:37:09 -07:00
|
|
|
buffer_declaration:
|
2021-06-21 21:37:10 -07:00
|
|
|
buffer_type any_identifier colon_attribute
|
2021-06-21 21:37:09 -07:00
|
|
|
{
|
|
|
|
if ($3.semantic.name)
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_SEMANTIC, "Semantics are not allowed on buffers.");
|
2021-06-21 21:37:09 -07:00
|
|
|
|
2021-06-21 21:37:10 -07:00
|
|
|
if (!(ctx->cur_buffer = hlsl_new_buffer(ctx, $1, $2, &$3.reg_reservation, @2)))
|
2021-06-21 21:37:09 -07:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
|
2021-06-21 21:37:10 -07:00
|
|
|
buffer_body:
|
|
|
|
'{' declaration_statement_list '}'
|
|
|
|
{
|
|
|
|
ctx->cur_buffer = ctx->globals_buffer;
|
|
|
|
}
|
|
|
|
|
2021-06-21 21:37:09 -07:00
|
|
|
buffer_type:
|
|
|
|
KW_CBUFFER
|
|
|
|
{
|
|
|
|
$$ = HLSL_BUFFER_CONSTANT;
|
|
|
|
}
|
|
|
|
| KW_TBUFFER
|
|
|
|
{
|
|
|
|
$$ = HLSL_BUFFER_TEXTURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
declaration_statement_list:
|
|
|
|
declaration_statement
|
|
|
|
| declaration_statement_list declaration_statement
|
|
|
|
|
2021-01-27 08:29:44 -08:00
|
|
|
preproc_directive:
|
|
|
|
PRE_LINE STRING
|
|
|
|
{
|
|
|
|
const char **new_array = NULL;
|
|
|
|
|
2021-02-12 08:48:56 -08:00
|
|
|
ctx->location.line = $1;
|
|
|
|
if (strcmp($2, ctx->location.source_name))
|
2021-09-20 14:40:11 -07:00
|
|
|
new_array = hlsl_realloc(ctx, ctx->source_files,
|
2021-02-04 14:33:53 -08:00
|
|
|
sizeof(*ctx->source_files) * (ctx->source_files_count + 1));
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
if (new_array)
|
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
ctx->source_files = new_array;
|
|
|
|
ctx->source_files[ctx->source_files_count++] = $2;
|
2021-02-12 08:48:56 -08:00
|
|
|
ctx->location.source_name = $2;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
vkd3d_free($2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct_declaration:
|
|
|
|
var_modifiers struct_spec variables_def_optional ';'
|
|
|
|
{
|
|
|
|
struct hlsl_type *type;
|
2022-01-31 02:51:34 -08:00
|
|
|
unsigned int modifiers = $1;
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
if (!$3)
|
|
|
|
{
|
|
|
|
if (!$2->name)
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@2, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX,
|
2021-02-21 20:04:36 -08:00
|
|
|
"Anonymous struct type must declare a variable.");
|
2021-01-27 08:29:44 -08:00
|
|
|
if (modifiers)
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER,
|
2021-11-05 11:35:57 -07:00
|
|
|
"Modifiers are not allowed on struct type declarations.");
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
if (!(type = apply_type_modifiers(ctx, $2, &modifiers, @1)))
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
2021-02-04 14:33:53 -08:00
|
|
|
$$ = declare_vars(ctx, type, modifiers, $3);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
struct_spec:
|
|
|
|
named_struct_spec
|
|
|
|
| unnamed_struct_spec
|
|
|
|
|
|
|
|
named_struct_spec:
|
|
|
|
KW_STRUCT any_identifier '{' fields_list '}'
|
|
|
|
{
|
2021-02-02 14:11:17 -08:00
|
|
|
bool ret;
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2022-07-14 18:23:43 -07:00
|
|
|
$$ = hlsl_new_struct_type(ctx, $2, $4.fields, $4.count);
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
if (hlsl_get_var(ctx->cur_scope, $2))
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@2, VKD3D_SHADER_ERROR_HLSL_REDEFINED, "\"%s\" is already declared as a variable.", $2);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
ret = hlsl_scope_add_type(ctx->cur_scope, $$);
|
2021-01-27 08:29:44 -08:00
|
|
|
if (!ret)
|
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@2, VKD3D_SHADER_ERROR_HLSL_REDEFINED, "Struct \"%s\" is already defined.", $2);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unnamed_struct_spec:
|
|
|
|
KW_STRUCT '{' fields_list '}'
|
|
|
|
{
|
2022-07-14 18:23:43 -07:00
|
|
|
$$ = hlsl_new_struct_type(ctx, NULL, $3.fields, $3.count);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
any_identifier:
|
|
|
|
VAR_IDENTIFIER
|
|
|
|
| TYPE_IDENTIFIER
|
|
|
|
| NEW_IDENTIFIER
|
|
|
|
|
|
|
|
fields_list:
|
2021-03-02 13:34:42 -08:00
|
|
|
%empty
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2022-07-14 18:23:43 -07:00
|
|
|
$$.fields = NULL;
|
|
|
|
$$.count = 0;
|
|
|
|
$$.capacity = 0;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| fields_list field
|
|
|
|
{
|
2022-07-14 18:23:43 -07:00
|
|
|
size_t i;
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2022-07-14 18:23:43 -07:00
|
|
|
for (i = 0; i < $2.count; ++i)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2022-07-14 18:23:43 -07:00
|
|
|
const struct hlsl_struct_field *field = &$2.fields[i];
|
|
|
|
const struct hlsl_struct_field *existing;
|
|
|
|
|
|
|
|
if ((existing = get_struct_field($1.fields, $1.count, field->name)))
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2022-07-14 18:23:43 -07:00
|
|
|
hlsl_error(ctx, &field->loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED,
|
2021-02-21 20:04:36 -08:00
|
|
|
"Field \"%s\" is already defined.", field->name);
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_note(ctx, &existing->loc, VKD3D_SHADER_LOG_ERROR,
|
2021-03-02 13:34:43 -08:00
|
|
|
"'%s' was previously defined here.", field->name);
|
|
|
|
}
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
2022-07-14 18:23:43 -07:00
|
|
|
|
|
|
|
if (!hlsl_array_reserve(ctx, (void **)&$1.fields, &$1.capacity, $1.count + $2.count, sizeof(*$1.fields)))
|
|
|
|
YYABORT;
|
|
|
|
memcpy($1.fields + $1.count, $2.fields, $2.count * sizeof(*$2.fields));
|
|
|
|
$1.count += $2.count;
|
|
|
|
vkd3d_free($2.fields);
|
|
|
|
|
|
|
|
$$ = $1;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
field_type:
|
|
|
|
type
|
|
|
|
| unnamed_struct_spec
|
|
|
|
|
|
|
|
field:
|
|
|
|
var_modifiers field_type variables_def ';'
|
|
|
|
{
|
|
|
|
struct hlsl_type *type;
|
2022-01-31 02:51:34 -08:00
|
|
|
unsigned int modifiers = $1;
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
if (!(type = apply_type_modifiers(ctx, $2, &modifiers, @1)))
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
2022-04-05 03:33:04 -07:00
|
|
|
if (modifiers & ~HLSL_STORAGE_NOINTERPOLATION)
|
2021-03-22 15:02:35 -07:00
|
|
|
{
|
|
|
|
struct vkd3d_string_buffer *string;
|
|
|
|
|
2021-05-20 22:32:22 -07:00
|
|
|
if ((string = hlsl_modifiers_to_string(ctx, modifiers)))
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER,
|
2021-03-22 15:02:35 -07:00
|
|
|
"Modifiers '%s' are not allowed on struct fields.", string->buffer);
|
2021-05-20 22:32:22 -07:00
|
|
|
hlsl_release_string_buffer(ctx, string);
|
2021-03-22 15:02:35 -07:00
|
|
|
}
|
2022-07-14 18:23:43 -07:00
|
|
|
if (!gen_struct_fields(ctx, &$$, type, modifiers, $3))
|
|
|
|
YYABORT;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
func_declaration:
|
|
|
|
func_prototype compound_statement
|
|
|
|
{
|
|
|
|
$$ = $1;
|
2021-10-15 14:54:09 -07:00
|
|
|
$$.decl->has_body = true;
|
2021-10-15 14:54:10 -07:00
|
|
|
list_move_tail(&$$.decl->body.instrs, $2);
|
2021-10-15 14:54:09 -07:00
|
|
|
vkd3d_free($2);
|
2021-02-04 14:33:53 -08:00
|
|
|
hlsl_pop_scope(ctx);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| func_prototype ';'
|
|
|
|
{
|
|
|
|
$$ = $1;
|
2021-02-04 14:33:53 -08:00
|
|
|
hlsl_pop_scope(ctx);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
func_prototype:
|
|
|
|
/* var_modifiers is necessary to avoid shift/reduce conflicts. */
|
|
|
|
var_modifiers type var_identifier '(' parameters ')' colon_attribute
|
|
|
|
{
|
2022-05-10 06:08:37 -07:00
|
|
|
unsigned int modifiers = $1;
|
2021-03-02 13:34:43 -08:00
|
|
|
struct hlsl_ir_var *var;
|
2022-05-10 06:08:37 -07:00
|
|
|
struct hlsl_type *type;
|
2021-03-02 13:34:43 -08:00
|
|
|
|
2022-05-10 06:08:37 -07:00
|
|
|
if (modifiers & ~HLSL_MODIFIERS_MAJORITY_MASK)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER,
|
2022-05-10 06:08:37 -07:00
|
|
|
"Only majority modifiers are allowed on functions.");
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
2022-05-10 06:08:37 -07:00
|
|
|
if (!(type = apply_type_modifiers(ctx, $2, &modifiers, @1)))
|
|
|
|
YYABORT;
|
2021-03-02 13:34:43 -08:00
|
|
|
if ((var = hlsl_get_var(ctx->globals, $3)))
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_REDEFINED,
|
2021-03-02 13:34:43 -08:00
|
|
|
"\"%s\" is already declared as a variable.", $3);
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_note(ctx, &var->loc, VKD3D_SHADER_LOG_ERROR,
|
2021-03-02 13:34:43 -08:00
|
|
|
"\"%s\" was previously declared here.", $3);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
2022-05-10 06:08:37 -07:00
|
|
|
if (hlsl_types_are_equal(type, ctx->builtin_types.Void) && $7.semantic.name)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@7, VKD3D_SHADER_ERROR_HLSL_INVALID_SEMANTIC,
|
2021-02-21 20:04:36 -08:00
|
|
|
"Semantics are not allowed on void functions.");
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
2021-05-31 19:41:14 -07:00
|
|
|
if ($7.reg_reservation.type)
|
2021-01-27 08:29:44 -08:00
|
|
|
FIXME("Unexpected register reservation for a function.\n");
|
2021-05-31 19:41:14 -07:00
|
|
|
|
2022-05-10 06:08:37 -07:00
|
|
|
if (!($$.decl = hlsl_new_func_decl(ctx, type, $5, &$7.semantic, @3)))
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
$$.name = $3;
|
2021-02-04 14:33:53 -08:00
|
|
|
ctx->cur_function = $$.decl;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
compound_statement:
|
|
|
|
'{' '}'
|
|
|
|
{
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!($$ = make_empty_list(ctx)))
|
2021-02-27 16:03:12 -08:00
|
|
|
YYABORT;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| '{' scope_start statement_list '}'
|
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
hlsl_pop_scope(ctx);
|
2021-01-27 08:29:44 -08:00
|
|
|
$$ = $3;
|
|
|
|
}
|
|
|
|
|
|
|
|
scope_start:
|
2021-03-02 13:34:42 -08:00
|
|
|
%empty
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
hlsl_push_scope(ctx);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
var_identifier:
|
|
|
|
VAR_IDENTIFIER
|
|
|
|
| NEW_IDENTIFIER
|
|
|
|
|
|
|
|
colon_attribute:
|
2021-03-02 13:34:42 -08:00
|
|
|
%empty
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-04-27 10:14:19 -07:00
|
|
|
$$.semantic.name = NULL;
|
2021-05-31 19:41:14 -07:00
|
|
|
$$.reg_reservation.type = 0;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| semantic
|
|
|
|
{
|
|
|
|
$$.semantic = $1;
|
2021-05-31 19:41:14 -07:00
|
|
|
$$.reg_reservation.type = 0;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| register_opt
|
|
|
|
{
|
2021-04-27 10:14:19 -07:00
|
|
|
$$.semantic.name = NULL;
|
2021-01-27 08:29:44 -08:00
|
|
|
$$.reg_reservation = $1;
|
|
|
|
}
|
|
|
|
|
|
|
|
semantic:
|
|
|
|
':' any_identifier
|
|
|
|
{
|
2021-04-27 10:14:19 -07:00
|
|
|
char *p;
|
|
|
|
|
|
|
|
for (p = $2 + strlen($2); p > $2 && isdigit(p[-1]); --p)
|
|
|
|
;
|
|
|
|
$$.name = $2;
|
|
|
|
$$.index = atoi(p);
|
|
|
|
*p = 0;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: Writemasks */
|
|
|
|
register_opt:
|
|
|
|
':' KW_REGISTER '(' any_identifier ')'
|
|
|
|
{
|
2021-05-31 19:41:14 -07:00
|
|
|
$$ = parse_reg_reservation($4);
|
2021-01-27 08:29:44 -08:00
|
|
|
vkd3d_free($4);
|
|
|
|
}
|
|
|
|
| ':' KW_REGISTER '(' any_identifier ',' any_identifier ')'
|
|
|
|
{
|
|
|
|
FIXME("Ignoring shader target %s in a register reservation.\n", debugstr_a($4));
|
|
|
|
vkd3d_free($4);
|
|
|
|
|
2021-05-31 19:41:14 -07:00
|
|
|
$$ = parse_reg_reservation($6);
|
2021-01-27 08:29:44 -08:00
|
|
|
vkd3d_free($6);
|
|
|
|
}
|
|
|
|
|
|
|
|
parameters:
|
|
|
|
scope_start
|
|
|
|
{
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!($$ = make_empty_list(ctx)))
|
2021-02-27 16:03:12 -08:00
|
|
|
YYABORT;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| scope_start param_list
|
|
|
|
{
|
|
|
|
$$ = $2;
|
|
|
|
}
|
|
|
|
|
|
|
|
param_list:
|
|
|
|
parameter
|
|
|
|
{
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!($$ = make_empty_list(ctx)))
|
2021-02-27 16:03:12 -08:00
|
|
|
YYABORT;
|
2021-02-04 14:33:53 -08:00
|
|
|
if (!add_func_parameter(ctx, $$, &$1, @1))
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
ERR("Error adding function parameter %s.\n", $1.name);
|
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
| param_list ',' parameter
|
|
|
|
{
|
|
|
|
$$ = $1;
|
2021-02-04 14:33:53 -08:00
|
|
|
if (!add_func_parameter(ctx, $$, &$3, @3))
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_REDEFINED,
|
2021-02-21 20:04:36 -08:00
|
|
|
"Parameter \"%s\" is already declared.", $3.name);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
parameter:
|
2022-03-22 14:59:10 -07:00
|
|
|
var_modifiers type any_identifier colon_attribute
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
struct hlsl_type *type;
|
2022-03-22 14:59:10 -07:00
|
|
|
unsigned int modifiers = $1;
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2022-03-22 14:59:10 -07:00
|
|
|
if (!(type = apply_type_modifiers(ctx, $2, &modifiers, @1)))
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
|
2022-03-22 14:59:10 -07:00
|
|
|
$$.modifiers = modifiers;
|
|
|
|
if (!($$.modifiers & (HLSL_STORAGE_IN | HLSL_STORAGE_OUT)))
|
|
|
|
$$.modifiers |= HLSL_STORAGE_IN;
|
2021-01-27 08:29:44 -08:00
|
|
|
$$.type = type;
|
2022-03-22 14:59:10 -07:00
|
|
|
$$.name = $3;
|
|
|
|
$$.semantic = $4.semantic;
|
|
|
|
$$.reg_reservation = $4.reg_reservation;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
2021-10-07 19:58:55 -07:00
|
|
|
texture_type:
|
|
|
|
KW_TEXTURE1D
|
|
|
|
{
|
|
|
|
$$ = HLSL_SAMPLER_DIM_1D;
|
|
|
|
}
|
|
|
|
| KW_TEXTURE2D
|
|
|
|
{
|
|
|
|
$$ = HLSL_SAMPLER_DIM_2D;
|
|
|
|
}
|
|
|
|
| KW_TEXTURE3D
|
|
|
|
{
|
|
|
|
$$ = HLSL_SAMPLER_DIM_3D;
|
|
|
|
}
|
|
|
|
| KW_TEXTURECUBE
|
|
|
|
{
|
|
|
|
$$ = HLSL_SAMPLER_DIM_CUBE;
|
|
|
|
}
|
2022-01-27 10:31:26 -08:00
|
|
|
| KW_TEXTURE1DARRAY
|
|
|
|
{
|
|
|
|
$$ = HLSL_SAMPLER_DIM_1DARRAY;
|
|
|
|
}
|
|
|
|
| KW_TEXTURE2DARRAY
|
|
|
|
{
|
|
|
|
$$ = HLSL_SAMPLER_DIM_2DARRAY;
|
|
|
|
}
|
|
|
|
| KW_TEXTURECUBEARRAY
|
|
|
|
{
|
|
|
|
$$ = HLSL_SAMPLER_DIM_CUBEARRAY;
|
|
|
|
}
|
2021-10-07 19:58:55 -07:00
|
|
|
|
2021-01-27 08:29:44 -08:00
|
|
|
type:
|
2021-08-30 10:21:25 -07:00
|
|
|
KW_VECTOR '<' type ',' C_INTEGER '>'
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
if ($3->type != HLSL_CLASS_SCALAR)
|
|
|
|
{
|
2021-03-04 02:25:08 -08:00
|
|
|
struct vkd3d_string_buffer *string;
|
|
|
|
|
2021-05-20 22:32:22 -07:00
|
|
|
string = hlsl_type_to_string(ctx, $3);
|
2021-03-04 02:25:08 -08:00
|
|
|
if (string)
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
|
2021-03-04 02:25:08 -08:00
|
|
|
"Vector base type %s is not scalar.", string->buffer);
|
2021-05-20 22:32:22 -07:00
|
|
|
hlsl_release_string_buffer(ctx, string);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
if ($5 < 1 || $5 > 4)
|
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@5, VKD3D_SHADER_ERROR_HLSL_INVALID_SIZE,
|
2021-03-04 02:25:08 -08:00
|
|
|
"Vector size %d is not between 1 and 4.", $5);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
|
2021-10-25 00:06:25 -07:00
|
|
|
$$ = hlsl_get_vector_type(ctx, $3->base_type, $5);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
2021-11-16 10:55:00 -08:00
|
|
|
| KW_VECTOR
|
|
|
|
{
|
|
|
|
$$ = hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, 4);
|
|
|
|
}
|
2021-08-30 10:21:25 -07:00
|
|
|
| KW_MATRIX '<' type ',' C_INTEGER ',' C_INTEGER '>'
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
if ($3->type != HLSL_CLASS_SCALAR)
|
|
|
|
{
|
2021-03-04 02:25:08 -08:00
|
|
|
struct vkd3d_string_buffer *string;
|
|
|
|
|
2021-05-20 22:32:22 -07:00
|
|
|
string = hlsl_type_to_string(ctx, $3);
|
2021-03-04 02:25:08 -08:00
|
|
|
if (string)
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
|
2021-03-04 02:25:08 -08:00
|
|
|
"Matrix base type %s is not scalar.", string->buffer);
|
2021-05-20 22:32:22 -07:00
|
|
|
hlsl_release_string_buffer(ctx, string);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
if ($5 < 1 || $5 > 4)
|
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@5, VKD3D_SHADER_ERROR_HLSL_INVALID_SIZE,
|
2021-03-04 02:25:08 -08:00
|
|
|
"Matrix row count %d is not between 1 and 4.", $5);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
if ($7 < 1 || $7 > 4)
|
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@7, VKD3D_SHADER_ERROR_HLSL_INVALID_SIZE,
|
2021-03-04 02:25:08 -08:00
|
|
|
"Matrix column count %d is not between 1 and 4.", $7);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
|
2021-10-25 00:06:25 -07:00
|
|
|
$$ = hlsl_get_matrix_type(ctx, $3->base_type, $7, $5);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
2021-11-16 10:55:00 -08:00
|
|
|
| KW_MATRIX
|
|
|
|
{
|
|
|
|
$$ = hlsl_get_matrix_type(ctx, HLSL_TYPE_FLOAT, 4, 4);
|
|
|
|
}
|
2021-08-30 10:21:25 -07:00
|
|
|
| KW_VOID
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
$$ = ctx->builtin_types.Void;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| KW_SAMPLER
|
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
$$ = ctx->builtin_types.sampler[HLSL_SAMPLER_DIM_GENERIC];
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| KW_SAMPLER1D
|
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
$$ = ctx->builtin_types.sampler[HLSL_SAMPLER_DIM_1D];
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| KW_SAMPLER2D
|
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
$$ = ctx->builtin_types.sampler[HLSL_SAMPLER_DIM_2D];
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| KW_SAMPLER3D
|
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
$$ = ctx->builtin_types.sampler[HLSL_SAMPLER_DIM_3D];
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| KW_SAMPLERCUBE
|
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
$$ = ctx->builtin_types.sampler[HLSL_SAMPLER_DIM_3D];
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
2021-10-07 19:58:53 -07:00
|
|
|
| KW_TEXTURE
|
|
|
|
{
|
2021-10-07 19:58:55 -07:00
|
|
|
$$ = hlsl_new_texture_type(ctx, HLSL_SAMPLER_DIM_GENERIC, NULL);
|
2021-10-07 19:58:53 -07:00
|
|
|
}
|
2021-10-07 19:58:55 -07:00
|
|
|
| texture_type
|
2021-10-07 19:58:53 -07:00
|
|
|
{
|
2021-10-25 00:06:25 -07:00
|
|
|
$$ = hlsl_new_texture_type(ctx, $1, hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, 4));
|
2021-10-07 19:58:53 -07:00
|
|
|
}
|
2021-10-07 19:58:55 -07:00
|
|
|
| texture_type '<' type '>'
|
2021-10-07 19:58:53 -07:00
|
|
|
{
|
2021-10-07 19:58:55 -07:00
|
|
|
if ($3->type > HLSL_CLASS_VECTOR)
|
|
|
|
{
|
|
|
|
struct vkd3d_string_buffer *string;
|
|
|
|
|
|
|
|
string = hlsl_type_to_string(ctx, $3);
|
|
|
|
if (string)
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
|
2022-04-06 01:53:29 -07:00
|
|
|
"Texture data type %s is not scalar or vector.", string->buffer);
|
2021-10-07 19:58:55 -07:00
|
|
|
hlsl_release_string_buffer(ctx, string);
|
|
|
|
}
|
|
|
|
$$ = hlsl_new_texture_type(ctx, $1, $3);
|
2021-10-07 19:58:53 -07:00
|
|
|
}
|
2021-01-27 08:29:44 -08:00
|
|
|
| TYPE_IDENTIFIER
|
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
$$ = hlsl_get_type(ctx->cur_scope, $1, true);
|
2021-01-27 08:29:44 -08:00
|
|
|
vkd3d_free($1);
|
|
|
|
}
|
|
|
|
| KW_STRUCT TYPE_IDENTIFIER
|
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
$$ = hlsl_get_type(ctx->cur_scope, $2, true);
|
2021-01-27 08:29:44 -08:00
|
|
|
if ($$->type != HLSL_CLASS_STRUCT)
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_REDEFINED, "\"%s\" redefined as a structure.", $2);
|
2021-01-27 08:29:44 -08:00
|
|
|
vkd3d_free($2);
|
|
|
|
}
|
|
|
|
|
|
|
|
declaration_statement:
|
|
|
|
declaration
|
|
|
|
| struct_declaration
|
|
|
|
| typedef
|
|
|
|
{
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!($$ = make_empty_list(ctx)))
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef_type:
|
|
|
|
type
|
|
|
|
| struct_spec
|
|
|
|
|
|
|
|
typedef:
|
|
|
|
KW_TYPEDEF var_modifiers typedef_type type_specs ';'
|
|
|
|
{
|
|
|
|
if ($2 & ~HLSL_TYPE_MODIFIERS_MASK)
|
|
|
|
{
|
|
|
|
struct parse_variable_def *v, *v_next;
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER,
|
2021-02-21 20:04:36 -08:00
|
|
|
"Storage modifiers are not allowed on typedefs.");
|
2021-01-27 08:29:44 -08:00
|
|
|
LIST_FOR_EACH_ENTRY_SAFE(v, v_next, $4, struct parse_variable_def, entry)
|
|
|
|
vkd3d_free(v);
|
|
|
|
vkd3d_free($4);
|
|
|
|
YYABORT;
|
|
|
|
}
|
2021-02-04 14:33:53 -08:00
|
|
|
if (!add_typedef(ctx, $2, $3, $4))
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
|
|
|
|
type_specs:
|
|
|
|
type_spec
|
|
|
|
{
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!($$ = make_empty_list(ctx)))
|
2021-02-27 16:03:12 -08:00
|
|
|
YYABORT;
|
2021-01-27 08:29:44 -08:00
|
|
|
list_add_head($$, &$1->entry);
|
|
|
|
}
|
|
|
|
| type_specs ',' type_spec
|
|
|
|
{
|
|
|
|
$$ = $1;
|
|
|
|
list_add_tail($$, &$3->entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
type_spec:
|
2021-03-04 15:33:27 -08:00
|
|
|
any_identifier arrays
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-05-20 22:32:20 -07:00
|
|
|
$$ = hlsl_alloc(ctx, sizeof(*$$));
|
2021-02-04 14:33:52 -08:00
|
|
|
$$->loc = @1;
|
2021-01-27 08:29:44 -08:00
|
|
|
$$->name = $1;
|
2021-03-04 15:33:27 -08:00
|
|
|
$$->arrays = $2;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
declaration:
|
|
|
|
var_modifiers type variables_def ';'
|
|
|
|
{
|
|
|
|
struct hlsl_type *type;
|
2022-01-31 02:51:34 -08:00
|
|
|
unsigned int modifiers = $1;
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
if (!(type = apply_type_modifiers(ctx, $2, &modifiers, @1)))
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
2021-02-04 14:33:53 -08:00
|
|
|
$$ = declare_vars(ctx, type, modifiers, $3);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
variables_def_optional:
|
2021-03-02 13:34:42 -08:00
|
|
|
%empty
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
$$ = NULL;
|
|
|
|
}
|
|
|
|
| variables_def
|
|
|
|
|
|
|
|
variables_def:
|
|
|
|
variable_def
|
|
|
|
{
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!($$ = make_empty_list(ctx)))
|
2021-02-27 16:03:12 -08:00
|
|
|
YYABORT;
|
2021-01-27 08:29:44 -08:00
|
|
|
list_add_head($$, &$1->entry);
|
|
|
|
}
|
|
|
|
| variables_def ',' variable_def
|
|
|
|
{
|
|
|
|
$$ = $1;
|
|
|
|
list_add_tail($$, &$3->entry);
|
|
|
|
}
|
|
|
|
|
2021-09-23 14:47:06 -07:00
|
|
|
variable_decl:
|
2021-03-04 15:33:27 -08:00
|
|
|
any_identifier arrays colon_attribute
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-05-20 22:32:20 -07:00
|
|
|
$$ = hlsl_alloc(ctx, sizeof(*$$));
|
2021-02-04 14:33:52 -08:00
|
|
|
$$->loc = @1;
|
2021-01-27 08:29:44 -08:00
|
|
|
$$->name = $1;
|
2021-03-04 15:33:27 -08:00
|
|
|
$$->arrays = $2;
|
2021-01-27 08:29:44 -08:00
|
|
|
$$->semantic = $3.semantic;
|
|
|
|
$$->reg_reservation = $3.reg_reservation;
|
|
|
|
}
|
2021-09-23 14:47:06 -07:00
|
|
|
|
2021-09-27 18:51:42 -07:00
|
|
|
state:
|
|
|
|
any_identifier '=' expr ';'
|
|
|
|
{
|
|
|
|
vkd3d_free($1);
|
|
|
|
hlsl_free_instr_list($3);
|
|
|
|
}
|
|
|
|
|
|
|
|
state_block_start:
|
|
|
|
%empty
|
|
|
|
{
|
|
|
|
ctx->in_state_block = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
state_block:
|
|
|
|
%empty
|
|
|
|
| state_block state
|
|
|
|
|
2021-09-23 14:47:06 -07:00
|
|
|
variable_def:
|
|
|
|
variable_decl
|
|
|
|
| variable_decl '=' complex_initializer
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-09-23 14:47:06 -07:00
|
|
|
$$ = $1;
|
|
|
|
$$->initializer = $3;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
2021-09-27 18:51:42 -07:00
|
|
|
| variable_decl '{' state_block_start state_block '}'
|
|
|
|
{
|
|
|
|
$$ = $1;
|
|
|
|
ctx->in_state_block = 0;
|
|
|
|
}
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2021-03-04 15:33:27 -08:00
|
|
|
arrays:
|
2021-03-02 13:34:42 -08:00
|
|
|
%empty
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-03-04 15:33:27 -08:00
|
|
|
$$.sizes = NULL;
|
|
|
|
$$.count = 0;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
2021-03-04 15:33:27 -08:00
|
|
|
| '[' expr ']' arrays
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
unsigned int size = evaluate_array_dimension(node_from_list($2));
|
2021-03-04 15:33:27 -08:00
|
|
|
uint32_t *new_array;
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2021-08-19 08:29:06 -07:00
|
|
|
destroy_instr_list($2);
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2021-03-04 15:33:27 -08:00
|
|
|
$$ = $4;
|
|
|
|
|
2021-01-27 08:29:44 -08:00
|
|
|
if (!size)
|
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@2, VKD3D_SHADER_ERROR_HLSL_INVALID_SIZE,
|
2021-02-21 20:04:36 -08:00
|
|
|
"Array size is not a positive integer constant.");
|
2021-03-04 15:33:27 -08:00
|
|
|
vkd3d_free($$.sizes);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (size > 65536)
|
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@2, VKD3D_SHADER_ERROR_HLSL_INVALID_SIZE,
|
2021-03-04 02:25:08 -08:00
|
|
|
"Array size %u is not between 1 and 65536.", size);
|
2021-03-04 15:33:27 -08:00
|
|
|
vkd3d_free($$.sizes);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
2021-03-04 15:33:27 -08:00
|
|
|
|
2021-09-20 14:40:11 -07:00
|
|
|
if (!(new_array = hlsl_realloc(ctx, $$.sizes, ($$.count + 1) * sizeof(*new_array))))
|
2021-03-04 15:33:27 -08:00
|
|
|
{
|
|
|
|
vkd3d_free($$.sizes);
|
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
$$.sizes = new_array;
|
|
|
|
$$.sizes[$$.count++] = size;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
var_modifiers:
|
2021-03-02 13:34:42 -08:00
|
|
|
%empty
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
$$ = 0;
|
|
|
|
}
|
|
|
|
| KW_EXTERN var_modifiers
|
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
$$ = add_modifiers(ctx, $2, HLSL_STORAGE_EXTERN, @1);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| KW_NOINTERPOLATION var_modifiers
|
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
$$ = add_modifiers(ctx, $2, HLSL_STORAGE_NOINTERPOLATION, @1);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| KW_PRECISE var_modifiers
|
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
$$ = add_modifiers(ctx, $2, HLSL_MODIFIER_PRECISE, @1);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| KW_SHARED var_modifiers
|
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
$$ = add_modifiers(ctx, $2, HLSL_STORAGE_SHARED, @1);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| KW_GROUPSHARED var_modifiers
|
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
$$ = add_modifiers(ctx, $2, HLSL_STORAGE_GROUPSHARED, @1);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| KW_STATIC var_modifiers
|
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
$$ = add_modifiers(ctx, $2, HLSL_STORAGE_STATIC, @1);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| KW_UNIFORM var_modifiers
|
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
$$ = add_modifiers(ctx, $2, HLSL_STORAGE_UNIFORM, @1);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| KW_VOLATILE var_modifiers
|
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
$$ = add_modifiers(ctx, $2, HLSL_STORAGE_VOLATILE, @1);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| KW_CONST var_modifiers
|
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
$$ = add_modifiers(ctx, $2, HLSL_MODIFIER_CONST, @1);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| KW_ROW_MAJOR var_modifiers
|
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
$$ = add_modifiers(ctx, $2, HLSL_MODIFIER_ROW_MAJOR, @1);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| KW_COLUMN_MAJOR var_modifiers
|
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
$$ = add_modifiers(ctx, $2, HLSL_MODIFIER_COLUMN_MAJOR, @1);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
2022-03-22 14:59:10 -07:00
|
|
|
| KW_IN var_modifiers
|
|
|
|
{
|
|
|
|
$$ = add_modifiers(ctx, $2, HLSL_STORAGE_IN, @1);
|
|
|
|
}
|
|
|
|
| KW_OUT var_modifiers
|
|
|
|
{
|
|
|
|
$$ = add_modifiers(ctx, $2, HLSL_STORAGE_OUT, @1);
|
|
|
|
}
|
|
|
|
| KW_INOUT var_modifiers
|
|
|
|
{
|
|
|
|
$$ = add_modifiers(ctx, $2, HLSL_STORAGE_IN | HLSL_STORAGE_OUT, @1);
|
|
|
|
}
|
|
|
|
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
complex_initializer:
|
|
|
|
initializer_expr
|
|
|
|
{
|
|
|
|
$$.args_count = 1;
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!($$.args = hlsl_alloc(ctx, sizeof(*$$.args))))
|
2022-03-30 14:38:26 -07:00
|
|
|
{
|
|
|
|
destroy_instr_list($1);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
2022-03-30 14:38:26 -07:00
|
|
|
}
|
2021-01-27 08:29:44 -08:00
|
|
|
$$.args[0] = node_from_list($1);
|
|
|
|
$$.instrs = $1;
|
2022-03-30 14:38:28 -07:00
|
|
|
$$.braces = false;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
2022-03-30 14:38:27 -07:00
|
|
|
| '{' complex_initializer_list '}'
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
$$ = $2;
|
2022-03-30 14:38:28 -07:00
|
|
|
$$.braces = true;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
2022-03-30 14:38:27 -07:00
|
|
|
| '{' complex_initializer_list ',' '}'
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
$$ = $2;
|
2022-03-30 14:38:28 -07:00
|
|
|
$$.braces = true;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
2022-03-30 14:38:27 -07:00
|
|
|
complex_initializer_list:
|
|
|
|
complex_initializer
|
|
|
|
| complex_initializer_list ',' complex_initializer
|
|
|
|
{
|
|
|
|
struct hlsl_ir_node **new_args;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
$$ = $1;
|
|
|
|
if (!(new_args = hlsl_realloc(ctx, $$.args, ($$.args_count + $3.args_count) * sizeof(*$$.args))))
|
|
|
|
{
|
|
|
|
free_parse_initializer(&$$);
|
|
|
|
free_parse_initializer(&$3);
|
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
$$.args = new_args;
|
|
|
|
for (i = 0; i < $3.args_count; ++i)
|
|
|
|
$$.args[$$.args_count++] = $3.args[i];
|
|
|
|
list_move_tail($$.instrs, $3.instrs);
|
|
|
|
free_parse_initializer(&$3);
|
|
|
|
}
|
|
|
|
|
2021-01-27 08:29:44 -08:00
|
|
|
initializer_expr:
|
|
|
|
assignment_expr
|
|
|
|
|
|
|
|
initializer_expr_list:
|
|
|
|
initializer_expr
|
|
|
|
{
|
|
|
|
$$.args_count = 1;
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!($$.args = hlsl_alloc(ctx, sizeof(*$$.args))))
|
2022-03-30 14:38:26 -07:00
|
|
|
{
|
|
|
|
destroy_instr_list($1);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
2022-03-30 14:38:26 -07:00
|
|
|
}
|
2021-01-27 08:29:44 -08:00
|
|
|
$$.args[0] = node_from_list($1);
|
|
|
|
$$.instrs = $1;
|
2022-03-30 14:38:28 -07:00
|
|
|
$$.braces = false;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| initializer_expr_list ',' initializer_expr
|
|
|
|
{
|
2022-03-30 14:38:26 -07:00
|
|
|
struct hlsl_ir_node **new_args;
|
|
|
|
|
2021-01-27 08:29:44 -08:00
|
|
|
$$ = $1;
|
2022-03-30 14:38:26 -07:00
|
|
|
if (!(new_args = hlsl_realloc(ctx, $$.args, ($$.args_count + 1) * sizeof(*$$.args))))
|
|
|
|
{
|
|
|
|
free_parse_initializer(&$$);
|
|
|
|
destroy_instr_list($3);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
2022-03-30 14:38:26 -07:00
|
|
|
}
|
|
|
|
$$.args = new_args;
|
2021-01-27 08:29:44 -08:00
|
|
|
$$.args[$$.args_count++] = node_from_list($3);
|
|
|
|
list_move_tail($$.instrs, $3);
|
|
|
|
vkd3d_free($3);
|
|
|
|
}
|
|
|
|
|
|
|
|
boolean:
|
|
|
|
KW_TRUE
|
|
|
|
{
|
|
|
|
$$ = TRUE;
|
|
|
|
}
|
|
|
|
| KW_FALSE
|
|
|
|
{
|
|
|
|
$$ = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
statement_list:
|
|
|
|
statement
|
|
|
|
| statement_list statement
|
|
|
|
{
|
|
|
|
$$ = $1;
|
|
|
|
list_move_tail($$, $2);
|
|
|
|
vkd3d_free($2);
|
|
|
|
}
|
|
|
|
|
|
|
|
statement:
|
|
|
|
declaration_statement
|
|
|
|
| expr_statement
|
|
|
|
| compound_statement
|
|
|
|
| jump_statement
|
|
|
|
| selection_statement
|
|
|
|
| loop_statement
|
|
|
|
|
|
|
|
jump_statement:
|
|
|
|
KW_RETURN expr ';'
|
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
if (!add_return(ctx, $2, node_from_list($2), @1))
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
$$ = $2;
|
|
|
|
}
|
|
|
|
| KW_RETURN ';'
|
|
|
|
{
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!($$ = make_empty_list(ctx)))
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
2021-02-04 14:33:53 -08:00
|
|
|
if (!add_return(ctx, $$, NULL, @1))
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
|
|
|
|
selection_statement:
|
|
|
|
KW_IF '(' expr ')' if_body
|
|
|
|
{
|
|
|
|
struct hlsl_ir_node *condition = node_from_list($3);
|
|
|
|
struct hlsl_ir_if *instr;
|
|
|
|
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!(instr = hlsl_new_if(ctx, condition, @1)))
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
2021-10-15 14:54:10 -07:00
|
|
|
list_move_tail(&instr->then_instrs.instrs, $5.then_instrs);
|
2021-09-20 14:40:12 -07:00
|
|
|
if ($5.else_instrs)
|
2021-10-15 14:54:10 -07:00
|
|
|
list_move_tail(&instr->else_instrs.instrs, $5.else_instrs);
|
2021-01-27 08:29:44 -08:00
|
|
|
vkd3d_free($5.then_instrs);
|
|
|
|
vkd3d_free($5.else_instrs);
|
|
|
|
if (condition->data_type->dimx > 1 || condition->data_type->dimy > 1)
|
2021-03-04 02:25:08 -08:00
|
|
|
{
|
|
|
|
struct vkd3d_string_buffer *string;
|
|
|
|
|
2021-05-20 22:32:22 -07:00
|
|
|
if ((string = hlsl_type_to_string(ctx, condition->data_type)))
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &instr->node.loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
|
2021-03-04 02:25:08 -08:00
|
|
|
"if condition type %s is not scalar.", string->buffer);
|
2021-05-20 22:32:22 -07:00
|
|
|
hlsl_release_string_buffer(ctx, string);
|
2021-03-04 02:25:08 -08:00
|
|
|
}
|
2021-01-27 08:29:44 -08:00
|
|
|
$$ = $3;
|
|
|
|
list_add_tail($$, &instr->node.entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
if_body:
|
|
|
|
statement
|
|
|
|
{
|
|
|
|
$$.then_instrs = $1;
|
|
|
|
$$.else_instrs = NULL;
|
|
|
|
}
|
|
|
|
| statement KW_ELSE statement
|
|
|
|
{
|
|
|
|
$$.then_instrs = $1;
|
|
|
|
$$.else_instrs = $3;
|
|
|
|
}
|
|
|
|
|
|
|
|
loop_statement:
|
|
|
|
KW_WHILE '(' expr ')' statement
|
|
|
|
{
|
2021-05-20 22:32:20 -07:00
|
|
|
$$ = create_loop(ctx, LOOP_WHILE, NULL, $3, NULL, $5, @1);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| KW_DO statement KW_WHILE '(' expr ')' ';'
|
|
|
|
{
|
2021-05-20 22:32:20 -07:00
|
|
|
$$ = create_loop(ctx, LOOP_DO_WHILE, NULL, $5, NULL, $2, @1);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| KW_FOR '(' scope_start expr_statement expr_statement expr ')' statement
|
|
|
|
{
|
2021-05-20 22:32:20 -07:00
|
|
|
$$ = create_loop(ctx, LOOP_FOR, $4, $5, $6, $8, @1);
|
2021-02-04 14:33:53 -08:00
|
|
|
hlsl_pop_scope(ctx);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| KW_FOR '(' scope_start declaration expr_statement expr ')' statement
|
|
|
|
{
|
2021-05-20 22:32:20 -07:00
|
|
|
$$ = create_loop(ctx, LOOP_FOR, $4, $5, $6, $8, @1);
|
2021-02-04 14:33:53 -08:00
|
|
|
hlsl_pop_scope(ctx);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
expr_statement:
|
|
|
|
';'
|
|
|
|
{
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!($$ = make_empty_list(ctx)))
|
2021-02-27 16:03:12 -08:00
|
|
|
YYABORT;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| expr ';'
|
|
|
|
{
|
|
|
|
$$ = $1;
|
|
|
|
}
|
|
|
|
|
2021-09-01 15:20:52 -07:00
|
|
|
func_arguments:
|
|
|
|
%empty
|
|
|
|
{
|
|
|
|
$$.args = NULL;
|
|
|
|
$$.args_count = 0;
|
|
|
|
if (!($$.instrs = make_empty_list(ctx)))
|
|
|
|
YYABORT;
|
2022-03-30 14:38:28 -07:00
|
|
|
$$.braces = false;
|
2021-09-01 15:20:52 -07:00
|
|
|
}
|
|
|
|
| initializer_expr_list
|
|
|
|
|
2021-01-27 08:29:44 -08:00
|
|
|
primary_expr:
|
|
|
|
C_FLOAT
|
|
|
|
{
|
|
|
|
struct hlsl_ir_constant *c;
|
|
|
|
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!(c = hlsl_alloc(ctx, sizeof(*c))))
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
2021-10-25 00:06:25 -07:00
|
|
|
init_node(&c->node, HLSL_IR_CONSTANT, hlsl_get_scalar_type(ctx, HLSL_TYPE_FLOAT), @1);
|
2021-09-20 14:40:10 -07:00
|
|
|
c->value[0].f = $1;
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!($$ = make_list(ctx, &c->node)))
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
| C_INTEGER
|
|
|
|
{
|
|
|
|
struct hlsl_ir_constant *c;
|
|
|
|
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!(c = hlsl_alloc(ctx, sizeof(*c))))
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
2021-10-25 00:06:25 -07:00
|
|
|
init_node(&c->node, HLSL_IR_CONSTANT, hlsl_get_scalar_type(ctx, HLSL_TYPE_INT), @1);
|
2021-09-20 14:40:10 -07:00
|
|
|
c->value[0].i = $1;
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!($$ = make_list(ctx, &c->node)))
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
| boolean
|
|
|
|
{
|
|
|
|
struct hlsl_ir_constant *c;
|
|
|
|
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!(c = hlsl_alloc(ctx, sizeof(*c))))
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
2021-10-25 00:06:25 -07:00
|
|
|
init_node(&c->node, HLSL_IR_CONSTANT, hlsl_get_scalar_type(ctx, HLSL_TYPE_BOOL), @1);
|
2022-04-05 03:33:12 -07:00
|
|
|
c->value[0].u = $1 ? ~0u : 0;
|
2021-05-20 22:32:20 -07:00
|
|
|
if (!($$ = make_list(ctx, &c->node)))
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
| VAR_IDENTIFIER
|
|
|
|
{
|
|
|
|
struct hlsl_ir_load *load;
|
|
|
|
struct hlsl_ir_var *var;
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
if (!(var = hlsl_get_var(ctx->cur_scope, $1)))
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_NOT_DEFINED, "Variable \"%s\" is not defined.", $1);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
2021-09-27 18:51:42 -07:00
|
|
|
if (!(load = hlsl_new_var_load(ctx, var, @1)))
|
|
|
|
YYABORT;
|
|
|
|
if (!($$ = make_list(ctx, &load->node)))
|
|
|
|
YYABORT;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| '(' expr ')'
|
|
|
|
{
|
|
|
|
$$ = $2;
|
|
|
|
}
|
2021-09-01 15:20:52 -07:00
|
|
|
| var_identifier '(' func_arguments ')'
|
|
|
|
{
|
|
|
|
if (!($$ = add_call(ctx, $1, &$3, @1)))
|
|
|
|
YYABORT;
|
|
|
|
}
|
2021-09-27 18:51:42 -07:00
|
|
|
| NEW_IDENTIFIER
|
|
|
|
{
|
|
|
|
if (ctx->in_state_block)
|
|
|
|
{
|
|
|
|
struct hlsl_ir_load *load;
|
|
|
|
struct hlsl_ir_var *var;
|
|
|
|
|
|
|
|
if (!(var = hlsl_new_synthetic_var(ctx, "<state-block-expr>",
|
2021-10-25 00:06:25 -07:00
|
|
|
hlsl_get_scalar_type(ctx, HLSL_TYPE_INT), @1)))
|
2021-09-27 18:51:42 -07:00
|
|
|
YYABORT;
|
|
|
|
if (!(load = hlsl_new_var_load(ctx, var, @1)))
|
|
|
|
YYABORT;
|
|
|
|
if (!($$ = make_list(ctx, &load->node)))
|
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-04-06 01:53:29 -07:00
|
|
|
hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_NOT_DEFINED, "Identifier \"%s\" is not declared.", $1);
|
2021-09-27 18:51:42 -07:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
}
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
postfix_expr:
|
|
|
|
primary_expr
|
|
|
|
| postfix_expr OP_INC
|
|
|
|
{
|
2021-03-09 17:42:48 -08:00
|
|
|
if (!add_increment(ctx, $1, false, true, @2))
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-08-19 08:29:06 -07:00
|
|
|
destroy_instr_list($1);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
2021-03-09 17:42:48 -08:00
|
|
|
$$ = $1;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| postfix_expr OP_DEC
|
|
|
|
{
|
2021-03-09 17:42:48 -08:00
|
|
|
if (!add_increment(ctx, $1, true, true, @2))
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-08-19 08:29:06 -07:00
|
|
|
destroy_instr_list($1);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
2021-03-09 17:42:48 -08:00
|
|
|
$$ = $1;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| postfix_expr '.' any_identifier
|
|
|
|
{
|
|
|
|
struct hlsl_ir_node *node = node_from_list($1);
|
|
|
|
|
|
|
|
if (node->data_type->type == HLSL_CLASS_STRUCT)
|
|
|
|
{
|
|
|
|
struct hlsl_type *type = node->data_type;
|
2022-07-14 18:23:43 -07:00
|
|
|
const struct hlsl_struct_field *field;
|
2022-07-14 18:23:45 -07:00
|
|
|
unsigned int field_idx = 0;
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2022-07-14 18:23:43 -07:00
|
|
|
if (!(field = get_struct_field(type->e.record.fields, type->e.record.field_count, $3)))
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_NOT_DEFINED, "Field \"%s\" is not defined.", $3);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
2021-03-02 13:34:43 -08:00
|
|
|
|
2022-07-14 18:23:45 -07:00
|
|
|
field_idx = field - type->e.record.fields;
|
|
|
|
if (!add_record_load(ctx, $1, node, field_idx, @2))
|
2021-03-02 13:34:43 -08:00
|
|
|
YYABORT;
|
|
|
|
$$ = $1;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
else if (node->data_type->type <= HLSL_CLASS_LAST_NUMERIC)
|
|
|
|
{
|
|
|
|
struct hlsl_ir_swizzle *swizzle;
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
if (!(swizzle = get_swizzle(ctx, node, $3, &@3)))
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "Invalid swizzle \"%s\".", $3);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
2021-09-23 14:47:05 -07:00
|
|
|
list_add_tail($1, &swizzle->node.entry);
|
|
|
|
$$ = $1;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "Invalid subscript \"%s\".", $3);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
| postfix_expr '[' expr ']'
|
|
|
|
{
|
|
|
|
struct hlsl_ir_node *array = node_from_list($1), *index = node_from_list($3);
|
2021-03-04 15:33:27 -08:00
|
|
|
struct hlsl_ir_expr *cast;
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
list_move_tail($1, $3);
|
|
|
|
vkd3d_free($3);
|
|
|
|
|
|
|
|
if (index->data_type->type != HLSL_CLASS_SCALAR)
|
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, "Array index is not scalar.");
|
2021-08-19 08:29:06 -07:00
|
|
|
destroy_instr_list($1);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
|
2021-10-25 00:06:25 -07:00
|
|
|
if (!(cast = hlsl_new_cast(ctx, index, hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), &index->loc)))
|
2021-03-04 15:33:27 -08:00
|
|
|
{
|
2021-08-19 08:29:06 -07:00
|
|
|
destroy_instr_list($1);
|
2021-03-04 15:33:27 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
list_add_tail($1, &cast->node.entry);
|
|
|
|
|
|
|
|
if (!add_array_load(ctx, $1, array, &cast->node, @2))
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-08-19 08:29:06 -07:00
|
|
|
destroy_instr_list($1);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
$$ = $1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* var_modifiers is necessary to avoid shift/reduce conflicts. */
|
|
|
|
| var_modifiers type '(' initializer_expr_list ')'
|
|
|
|
{
|
|
|
|
if ($1)
|
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER,
|
2021-02-21 20:04:36 -08:00
|
|
|
"Modifiers are not allowed on constructors.");
|
2021-09-27 05:41:32 -07:00
|
|
|
free_parse_initializer(&$4);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
if ($2->type > HLSL_CLASS_LAST_NUMERIC)
|
|
|
|
{
|
2021-03-04 02:25:08 -08:00
|
|
|
struct vkd3d_string_buffer *string;
|
|
|
|
|
2021-05-20 22:32:22 -07:00
|
|
|
if ((string = hlsl_type_to_string(ctx, $2)))
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@2, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
|
2021-03-04 02:25:08 -08:00
|
|
|
"Constructor data type %s is not numeric.", string->buffer);
|
2021-05-20 22:32:22 -07:00
|
|
|
hlsl_release_string_buffer(ctx, string);
|
2021-09-27 05:41:32 -07:00
|
|
|
free_parse_initializer(&$4);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
if ($2->dimx * $2->dimy != initializer_size(&$4))
|
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@4, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT,
|
2021-02-21 20:04:36 -08:00
|
|
|
"Expected %u components in constructor, but got %u.",
|
2021-01-27 08:29:44 -08:00
|
|
|
$2->dimx * $2->dimy, initializer_size(&$4));
|
2021-09-27 05:41:32 -07:00
|
|
|
free_parse_initializer(&$4);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
|
2021-09-20 14:40:14 -07:00
|
|
|
if (!($$ = add_constructor(ctx, $2, &$4, @2)))
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-09-20 14:40:14 -07:00
|
|
|
free_parse_initializer(&$4);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
2021-09-20 14:40:14 -07:00
|
|
|
}
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
2021-10-07 19:58:57 -07:00
|
|
|
| postfix_expr '.' any_identifier '(' func_arguments ')'
|
|
|
|
{
|
|
|
|
struct hlsl_ir_node *object = node_from_list($1);
|
|
|
|
|
|
|
|
list_move_tail($1, $5.instrs);
|
|
|
|
vkd3d_free($5.instrs);
|
|
|
|
|
|
|
|
if (!add_method_call(ctx, $1, object, $3, &$5, &@3))
|
|
|
|
{
|
|
|
|
hlsl_free_instr_list($1);
|
|
|
|
vkd3d_free($5.args);
|
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
vkd3d_free($5.args);
|
|
|
|
$$ = $1;
|
|
|
|
}
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
unary_expr:
|
|
|
|
postfix_expr
|
|
|
|
| OP_INC unary_expr
|
|
|
|
{
|
2021-03-09 17:42:48 -08:00
|
|
|
if (!add_increment(ctx, $2, false, false, @1))
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-08-19 08:29:06 -07:00
|
|
|
destroy_instr_list($2);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
2021-03-09 17:42:47 -08:00
|
|
|
$$ = $2;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| OP_DEC unary_expr
|
|
|
|
{
|
2021-03-09 17:42:48 -08:00
|
|
|
if (!add_increment(ctx, $2, true, false, @1))
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-08-19 08:29:06 -07:00
|
|
|
destroy_instr_list($2);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
2021-03-09 17:42:47 -08:00
|
|
|
$$ = $2;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
2021-09-23 14:47:04 -07:00
|
|
|
| '+' unary_expr
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-09-23 14:47:04 -07:00
|
|
|
$$ = $2;
|
|
|
|
}
|
|
|
|
| '-' unary_expr
|
|
|
|
{
|
2021-10-15 01:37:02 -07:00
|
|
|
add_unary_arithmetic_expr(ctx, $2, HLSL_OP1_NEG, node_from_list($2), &@1);
|
|
|
|
$$ = $2;
|
2021-09-23 14:47:04 -07:00
|
|
|
}
|
|
|
|
| '~' unary_expr
|
|
|
|
{
|
2022-02-24 10:45:20 -08:00
|
|
|
add_unary_bitwise_expr(ctx, $2, HLSL_OP1_BIT_NOT, node_from_list($2), &@1);
|
2021-10-15 01:37:02 -07:00
|
|
|
$$ = $2;
|
2021-09-23 14:47:04 -07:00
|
|
|
}
|
|
|
|
| '!' unary_expr
|
|
|
|
{
|
2022-02-24 10:45:21 -08:00
|
|
|
add_unary_logical_expr(ctx, $2, HLSL_OP1_LOGIC_NOT, node_from_list($2), &@1);
|
2021-10-15 01:37:02 -07:00
|
|
|
$$ = $2;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
/* var_modifiers is necessary to avoid shift/reduce conflicts. */
|
2021-03-04 15:33:27 -08:00
|
|
|
| '(' var_modifiers type arrays ')' unary_expr
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
struct hlsl_type *src_type = node_from_list($6)->data_type;
|
|
|
|
struct hlsl_type *dst_type;
|
2021-03-04 15:33:27 -08:00
|
|
|
unsigned int i;
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
if ($2)
|
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@2, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER,
|
2021-02-21 20:04:36 -08:00
|
|
|
"Modifiers are not allowed on casts.");
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
|
2021-03-04 15:33:27 -08:00
|
|
|
dst_type = $3;
|
|
|
|
for (i = 0; i < $4.count; ++i)
|
|
|
|
dst_type = hlsl_new_array_type(ctx, dst_type, $4.sizes[i]);
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
if (!compatible_data_types(src_type, dst_type))
|
|
|
|
{
|
2021-02-27 16:03:09 -08:00
|
|
|
struct vkd3d_string_buffer *src_string, *dst_string;
|
2021-02-12 12:38:50 -08:00
|
|
|
|
2021-05-20 22:32:22 -07:00
|
|
|
src_string = hlsl_type_to_string(ctx, src_type);
|
|
|
|
dst_string = hlsl_type_to_string(ctx, dst_type);
|
2021-02-12 12:38:50 -08:00
|
|
|
if (src_string && dst_string)
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, "Can't cast from %s to %s.",
|
2021-02-27 16:03:09 -08:00
|
|
|
src_string->buffer, dst_string->buffer);
|
2021-05-20 22:32:22 -07:00
|
|
|
hlsl_release_string_buffer(ctx, src_string);
|
|
|
|
hlsl_release_string_buffer(ctx, dst_string);
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
|
2022-06-07 14:29:19 -07:00
|
|
|
if (!add_cast(ctx, $6, node_from_list($6), dst_type, &@3))
|
2021-09-23 14:47:05 -07:00
|
|
|
{
|
|
|
|
hlsl_free_instr_list($6);
|
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
$$ = $6;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
mul_expr:
|
|
|
|
unary_expr
|
|
|
|
| mul_expr '*' unary_expr
|
|
|
|
{
|
2021-10-15 01:37:01 -07:00
|
|
|
$$ = add_binary_arithmetic_expr_merge(ctx, $1, $3, HLSL_OP2_MUL, @2);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| mul_expr '/' unary_expr
|
|
|
|
{
|
2021-10-15 01:37:01 -07:00
|
|
|
$$ = add_binary_arithmetic_expr_merge(ctx, $1, $3, HLSL_OP2_DIV, @2);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| mul_expr '%' unary_expr
|
|
|
|
{
|
2021-10-15 01:37:01 -07:00
|
|
|
$$ = add_binary_arithmetic_expr_merge(ctx, $1, $3, HLSL_OP2_MOD, @2);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
add_expr:
|
|
|
|
mul_expr
|
|
|
|
| add_expr '+' mul_expr
|
|
|
|
{
|
2021-10-15 01:37:01 -07:00
|
|
|
$$ = add_binary_arithmetic_expr_merge(ctx, $1, $3, HLSL_OP2_ADD, @2);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| add_expr '-' mul_expr
|
|
|
|
{
|
2021-08-09 19:56:19 -07:00
|
|
|
struct hlsl_ir_node *neg;
|
|
|
|
|
2021-08-12 17:36:13 -07:00
|
|
|
if (!(neg = hlsl_new_unary_expr(ctx, HLSL_OP1_NEG, node_from_list($3), @2)))
|
2021-08-09 19:56:19 -07:00
|
|
|
YYABORT;
|
|
|
|
list_add_tail($3, &neg->entry);
|
2021-10-15 01:37:01 -07:00
|
|
|
$$ = add_binary_arithmetic_expr_merge(ctx, $1, $3, HLSL_OP2_ADD, @2);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
shift_expr:
|
|
|
|
add_expr
|
|
|
|
| shift_expr OP_LEFTSHIFT add_expr
|
|
|
|
{
|
2022-02-24 10:45:18 -08:00
|
|
|
$$ = add_binary_shift_expr_merge(ctx, $1, $3, HLSL_OP2_LSHIFT, &@2);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| shift_expr OP_RIGHTSHIFT add_expr
|
|
|
|
{
|
2022-02-24 10:45:19 -08:00
|
|
|
$$ = add_binary_shift_expr_merge(ctx, $1, $3, HLSL_OP2_RSHIFT, &@2);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
relational_expr:
|
|
|
|
shift_expr
|
|
|
|
| relational_expr '<' shift_expr
|
|
|
|
{
|
2021-10-15 01:37:04 -07:00
|
|
|
$$ = add_binary_comparison_expr_merge(ctx, $1, $3, HLSL_OP2_LESS, @2);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| relational_expr '>' shift_expr
|
|
|
|
{
|
2022-01-19 03:52:06 -08:00
|
|
|
$$ = add_binary_comparison_expr_merge(ctx, $3, $1, HLSL_OP2_LESS, @2);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| relational_expr OP_LE shift_expr
|
|
|
|
{
|
2022-01-19 03:52:06 -08:00
|
|
|
$$ = add_binary_comparison_expr_merge(ctx, $3, $1, HLSL_OP2_GEQUAL, @2);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| relational_expr OP_GE shift_expr
|
|
|
|
{
|
2021-10-15 01:37:04 -07:00
|
|
|
$$ = add_binary_comparison_expr_merge(ctx, $1, $3, HLSL_OP2_GEQUAL, @2);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
equality_expr:
|
|
|
|
relational_expr
|
|
|
|
| equality_expr OP_EQ relational_expr
|
|
|
|
{
|
2021-10-15 01:37:04 -07:00
|
|
|
$$ = add_binary_comparison_expr_merge(ctx, $1, $3, HLSL_OP2_EQUAL, @2);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
| equality_expr OP_NE relational_expr
|
|
|
|
{
|
2021-10-15 01:37:04 -07:00
|
|
|
$$ = add_binary_comparison_expr_merge(ctx, $1, $3, HLSL_OP2_NEQUAL, @2);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
bitand_expr:
|
|
|
|
equality_expr
|
|
|
|
| bitand_expr '&' equality_expr
|
|
|
|
{
|
2022-02-11 12:04:07 -08:00
|
|
|
$$ = add_binary_bitwise_expr_merge(ctx, $1, $3, HLSL_OP2_BIT_AND, &@2);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
bitxor_expr:
|
|
|
|
bitand_expr
|
|
|
|
| bitxor_expr '^' bitand_expr
|
|
|
|
{
|
2022-02-11 12:04:08 -08:00
|
|
|
$$ = add_binary_bitwise_expr_merge(ctx, $1, $3, HLSL_OP2_BIT_XOR, &@2);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
bitor_expr:
|
|
|
|
bitxor_expr
|
|
|
|
| bitor_expr '|' bitxor_expr
|
|
|
|
{
|
2022-02-11 12:04:09 -08:00
|
|
|
$$ = add_binary_bitwise_expr_merge(ctx, $1, $3, HLSL_OP2_BIT_OR, &@2);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
logicand_expr:
|
|
|
|
bitor_expr
|
|
|
|
| logicand_expr OP_AND bitor_expr
|
|
|
|
{
|
2022-02-24 10:45:16 -08:00
|
|
|
$$ = add_binary_logical_expr_merge(ctx, $1, $3, HLSL_OP2_LOGIC_AND, &@2);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
logicor_expr:
|
|
|
|
logicand_expr
|
|
|
|
| logicor_expr OP_OR logicand_expr
|
|
|
|
{
|
2022-02-24 10:45:17 -08:00
|
|
|
$$ = add_binary_logical_expr_merge(ctx, $1, $3, HLSL_OP2_LOGIC_OR, &@2);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
conditional_expr:
|
|
|
|
logicor_expr
|
|
|
|
| logicor_expr '?' expr ':' assignment_expr
|
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_fixme(ctx, &@$, "Ternary operator.");
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
assignment_expr:
|
|
|
|
|
|
|
|
conditional_expr
|
|
|
|
| unary_expr assign_op assignment_expr
|
|
|
|
{
|
|
|
|
struct hlsl_ir_node *lhs = node_from_list($1), *rhs = node_from_list($3);
|
|
|
|
|
|
|
|
if (lhs->data_type->modifiers & HLSL_MODIFIER_CONST)
|
|
|
|
{
|
2021-12-01 08:14:57 -08:00
|
|
|
hlsl_error(ctx, &@2, VKD3D_SHADER_ERROR_HLSL_MODIFIES_CONST, "Statement modifies a const expression.");
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
}
|
|
|
|
list_move_tail($3, $1);
|
|
|
|
vkd3d_free($1);
|
2021-02-04 14:33:53 -08:00
|
|
|
if (!add_assignment(ctx, $3, lhs, $2, rhs))
|
2021-01-27 08:29:44 -08:00
|
|
|
YYABORT;
|
|
|
|
$$ = $3;
|
|
|
|
}
|
|
|
|
|
|
|
|
assign_op:
|
|
|
|
'='
|
|
|
|
{
|
|
|
|
$$ = ASSIGN_OP_ASSIGN;
|
|
|
|
}
|
|
|
|
| OP_ADDASSIGN
|
|
|
|
{
|
|
|
|
$$ = ASSIGN_OP_ADD;
|
|
|
|
}
|
|
|
|
| OP_SUBASSIGN
|
|
|
|
{
|
|
|
|
$$ = ASSIGN_OP_SUB;
|
|
|
|
}
|
|
|
|
| OP_MULASSIGN
|
|
|
|
{
|
|
|
|
$$ = ASSIGN_OP_MUL;
|
|
|
|
}
|
|
|
|
| OP_DIVASSIGN
|
|
|
|
{
|
|
|
|
$$ = ASSIGN_OP_DIV;
|
|
|
|
}
|
|
|
|
| OP_MODASSIGN
|
|
|
|
{
|
|
|
|
$$ = ASSIGN_OP_MOD;
|
|
|
|
}
|
|
|
|
| OP_LEFTSHIFTASSIGN
|
|
|
|
{
|
|
|
|
$$ = ASSIGN_OP_LSHIFT;
|
|
|
|
}
|
|
|
|
| OP_RIGHTSHIFTASSIGN
|
|
|
|
{
|
|
|
|
$$ = ASSIGN_OP_RSHIFT;
|
|
|
|
}
|
|
|
|
| OP_ANDASSIGN
|
|
|
|
{
|
|
|
|
$$ = ASSIGN_OP_AND;
|
|
|
|
}
|
|
|
|
| OP_ORASSIGN
|
|
|
|
{
|
|
|
|
$$ = ASSIGN_OP_OR;
|
|
|
|
}
|
|
|
|
| OP_XORASSIGN
|
|
|
|
{
|
|
|
|
$$ = ASSIGN_OP_XOR;
|
|
|
|
}
|
|
|
|
|
|
|
|
expr:
|
|
|
|
assignment_expr
|
|
|
|
| expr ',' assignment_expr
|
|
|
|
{
|
|
|
|
$$ = $1;
|
|
|
|
list_move_tail($$, $3);
|
|
|
|
vkd3d_free($3);
|
|
|
|
}
|