2021-01-27 08:29:44 -08:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "hlsl.h"
|
2021-01-30 11:51:32 -08:00
|
|
|
#include <stdio.h>
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2021-02-12 08:48:55 -08:00
|
|
|
void hlsl_note(struct hlsl_ctx *ctx, const struct vkd3d_shader_location loc,
|
2021-02-12 08:48:54 -08:00
|
|
|
enum vkd3d_shader_log_level level, const char *fmt, ...)
|
|
|
|
{
|
2021-02-21 20:04:38 -08:00
|
|
|
va_list args;
|
|
|
|
|
|
|
|
va_start(args, fmt);
|
|
|
|
vkd3d_shader_vnote(ctx->message_context, &loc, level, fmt, args);
|
|
|
|
va_end(args);
|
2021-02-12 08:48:54 -08:00
|
|
|
}
|
|
|
|
|
2021-02-21 20:04:36 -08:00
|
|
|
void hlsl_error(struct hlsl_ctx *ctx, const struct vkd3d_shader_location loc,
|
|
|
|
enum vkd3d_shader_error error, const char *fmt, ...)
|
2021-02-12 08:48:54 -08:00
|
|
|
{
|
2021-02-21 20:04:36 -08:00
|
|
|
va_list args;
|
|
|
|
|
|
|
|
va_start(args, fmt);
|
|
|
|
vkd3d_shader_verror(ctx->message_context, &loc, error, fmt, args);
|
|
|
|
va_end(args);
|
2021-02-12 08:48:54 -08:00
|
|
|
|
2021-02-12 12:38:46 -08:00
|
|
|
ctx->failed = true;
|
2021-02-12 08:48:54 -08:00
|
|
|
}
|
|
|
|
|
2021-02-21 20:04:36 -08:00
|
|
|
void hlsl_warning(struct hlsl_ctx *ctx, const struct vkd3d_shader_location loc,
|
|
|
|
enum vkd3d_shader_error error, const char *fmt, ...)
|
2021-02-02 14:11:13 -08:00
|
|
|
{
|
2021-02-21 20:04:36 -08:00
|
|
|
va_list args;
|
|
|
|
|
|
|
|
va_start(args, fmt);
|
|
|
|
vkd3d_shader_vwarning(ctx->message_context, &loc, error, fmt, args);
|
|
|
|
va_end(args);
|
2021-02-02 14:11:13 -08:00
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
bool hlsl_add_var(struct hlsl_ctx *ctx, struct hlsl_ir_var *decl, bool local_var)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
struct hlsl_scope *scope = ctx->cur_scope;
|
2021-01-27 08:29:44 -08:00
|
|
|
struct hlsl_ir_var *var;
|
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry)
|
|
|
|
{
|
|
|
|
if (!strcmp(decl->name, var->name))
|
2021-02-02 14:11:17 -08:00
|
|
|
return false;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
2021-02-04 14:33:53 -08:00
|
|
|
if (local_var && scope->upper->upper == ctx->globals)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
/* Check whether the variable redefines a function parameter. */
|
|
|
|
LIST_FOR_EACH_ENTRY(var, &scope->upper->vars, struct hlsl_ir_var, scope_entry)
|
|
|
|
{
|
|
|
|
if (!strcmp(decl->name, var->name))
|
2021-02-02 14:11:17 -08:00
|
|
|
return false;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
list_add_tail(&scope->vars, &decl->scope_entry);
|
2021-02-02 14:11:17 -08:00
|
|
|
return true;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:14 -08:00
|
|
|
struct hlsl_ir_var *hlsl_get_var(struct hlsl_scope *scope, const char *name)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
struct hlsl_ir_var *var;
|
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry)
|
|
|
|
{
|
|
|
|
if (!strcmp(name, var->name))
|
|
|
|
return var;
|
|
|
|
}
|
|
|
|
if (!scope->upper)
|
|
|
|
return NULL;
|
2021-02-02 14:11:14 -08:00
|
|
|
return hlsl_get_var(scope->upper, name);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:14 -08:00
|
|
|
void hlsl_free_var(struct hlsl_ir_var *decl)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
vkd3d_free((void *)decl->name);
|
|
|
|
vkd3d_free((void *)decl->semantic);
|
|
|
|
vkd3d_free((void *)decl->reg_reservation);
|
|
|
|
vkd3d_free(decl);
|
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
struct hlsl_type *hlsl_new_type(struct hlsl_ctx *ctx, const char *name, enum hlsl_type_class type_class,
|
2021-01-27 08:29:44 -08:00
|
|
|
enum hlsl_base_type base_type, unsigned dimx, unsigned dimy)
|
|
|
|
{
|
|
|
|
struct hlsl_type *type;
|
|
|
|
|
|
|
|
if (!(type = vkd3d_calloc(1, sizeof(*type))))
|
|
|
|
return NULL;
|
|
|
|
type->name = name;
|
|
|
|
type->type = type_class;
|
|
|
|
type->base_type = base_type;
|
|
|
|
type->dimx = dimx;
|
|
|
|
type->dimy = dimy;
|
|
|
|
if (type_class == HLSL_CLASS_MATRIX)
|
2021-02-02 14:11:14 -08:00
|
|
|
type->reg_size = hlsl_type_is_row_major(type) ? dimy : dimx;
|
2021-01-27 08:29:44 -08:00
|
|
|
else
|
|
|
|
type->reg_size = 1;
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
list_add_tail(&ctx->types, &type->entry);
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
struct hlsl_type *hlsl_new_array_type(struct hlsl_ctx *ctx, struct hlsl_type *basic_type, unsigned int array_size)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
struct hlsl_type *type = hlsl_new_type(ctx, NULL, HLSL_CLASS_ARRAY, HLSL_TYPE_FLOAT, 1, 1);
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
if (!type)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
type->modifiers = basic_type->modifiers;
|
|
|
|
type->e.array.elements_count = array_size;
|
|
|
|
type->e.array.type = basic_type;
|
|
|
|
type->reg_size = basic_type->reg_size * array_size;
|
|
|
|
type->dimx = basic_type->dimx;
|
|
|
|
type->dimy = basic_type->dimy;
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
2021-01-30 11:51:32 -08:00
|
|
|
static DWORD get_array_size(const struct hlsl_type *type)
|
|
|
|
{
|
|
|
|
if (type->type == HLSL_CLASS_ARRAY)
|
|
|
|
return get_array_size(type->e.array.type) * type->e.array.elements_count;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
struct hlsl_type *hlsl_new_struct_type(struct hlsl_ctx *ctx, const char *name, struct list *fields)
|
2021-01-30 11:51:32 -08:00
|
|
|
{
|
|
|
|
struct hlsl_struct_field *field;
|
|
|
|
unsigned int reg_size = 0;
|
|
|
|
struct hlsl_type *type;
|
|
|
|
|
|
|
|
if (!(type = vkd3d_calloc(1, sizeof(*type))))
|
|
|
|
return NULL;
|
|
|
|
type->type = HLSL_CLASS_STRUCT;
|
|
|
|
type->base_type = HLSL_TYPE_VOID;
|
|
|
|
type->name = name;
|
|
|
|
type->dimx = 0;
|
|
|
|
type->dimy = 1;
|
|
|
|
type->e.elements = fields;
|
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY(field, fields, struct hlsl_struct_field, entry)
|
|
|
|
{
|
|
|
|
field->reg_offset = reg_size;
|
|
|
|
reg_size += field->type->reg_size;
|
|
|
|
type->dimx += field->type->dimx * field->type->dimy * get_array_size(field->type);
|
|
|
|
}
|
|
|
|
type->reg_size = reg_size;
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
list_add_tail(&ctx->types, &type->entry);
|
2021-01-30 11:51:32 -08:00
|
|
|
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:17 -08:00
|
|
|
struct hlsl_type *hlsl_get_type(struct hlsl_scope *scope, const char *name, bool recursive)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
struct rb_entry *entry = rb_get(&scope->types, name);
|
|
|
|
|
|
|
|
if (entry)
|
|
|
|
return RB_ENTRY_VALUE(entry, struct hlsl_type, scope_entry);
|
|
|
|
|
|
|
|
if (recursive && scope->upper)
|
2021-02-02 14:11:14 -08:00
|
|
|
return hlsl_get_type(scope->upper, name, recursive);
|
2021-01-27 08:29:44 -08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
bool hlsl_get_function(struct hlsl_ctx *ctx, const char *name)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
return rb_get(&ctx->functions, name) != NULL;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
2021-03-04 15:33:24 -08:00
|
|
|
struct hlsl_ir_function_decl *hlsl_get_func_decl(struct hlsl_ctx *ctx, const char *name)
|
|
|
|
{
|
|
|
|
struct hlsl_ir_function_decl *decl;
|
|
|
|
struct hlsl_ir_function *func;
|
|
|
|
struct rb_entry *entry;
|
|
|
|
|
|
|
|
if ((entry = rb_get(&ctx->functions, name)))
|
|
|
|
{
|
|
|
|
func = RB_ENTRY_VALUE(entry, struct hlsl_ir_function, entry);
|
|
|
|
RB_FOR_EACH_ENTRY(decl, &func->overloads, struct hlsl_ir_function_decl, entry)
|
|
|
|
return decl;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:14 -08:00
|
|
|
unsigned int hlsl_type_component_count(struct hlsl_type *type)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
struct hlsl_struct_field *field;
|
|
|
|
unsigned int count = 0;
|
|
|
|
|
|
|
|
if (type->type <= HLSL_CLASS_LAST_NUMERIC)
|
|
|
|
{
|
|
|
|
return type->dimx * type->dimy;
|
|
|
|
}
|
|
|
|
if (type->type == HLSL_CLASS_ARRAY)
|
|
|
|
{
|
2021-02-02 14:11:14 -08:00
|
|
|
return hlsl_type_component_count(type->e.array.type) * type->e.array.elements_count;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
if (type->type != HLSL_CLASS_STRUCT)
|
|
|
|
{
|
|
|
|
ERR("Unexpected data type %s.\n", debug_hlsl_type(type));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY(field, type->e.elements, struct hlsl_struct_field, entry)
|
|
|
|
{
|
2021-02-02 14:11:14 -08:00
|
|
|
count += hlsl_type_component_count(field->type);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2021-03-17 22:22:19 -07:00
|
|
|
bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
if (t1 == t2)
|
2021-02-02 14:11:17 -08:00
|
|
|
return true;
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
if (t1->type != t2->type)
|
2021-02-02 14:11:17 -08:00
|
|
|
return false;
|
2021-01-27 08:29:44 -08:00
|
|
|
if (t1->base_type != t2->base_type)
|
2021-02-02 14:11:17 -08:00
|
|
|
return false;
|
2021-01-27 08:29:44 -08:00
|
|
|
if (t1->base_type == HLSL_TYPE_SAMPLER && t1->sampler_dim != t2->sampler_dim)
|
2021-02-02 14:11:17 -08:00
|
|
|
return false;
|
2021-01-27 08:29:44 -08:00
|
|
|
if ((t1->modifiers & HLSL_MODIFIERS_MAJORITY_MASK)
|
|
|
|
!= (t2->modifiers & HLSL_MODIFIERS_MAJORITY_MASK))
|
2021-02-02 14:11:17 -08:00
|
|
|
return false;
|
2021-01-27 08:29:44 -08:00
|
|
|
if (t1->dimx != t2->dimx)
|
2021-02-02 14:11:17 -08:00
|
|
|
return false;
|
2021-01-27 08:29:44 -08:00
|
|
|
if (t1->dimy != t2->dimy)
|
2021-02-02 14:11:17 -08:00
|
|
|
return false;
|
2021-01-27 08:29:44 -08:00
|
|
|
if (t1->type == HLSL_CLASS_STRUCT)
|
|
|
|
{
|
|
|
|
struct list *t1cur, *t2cur;
|
|
|
|
struct hlsl_struct_field *t1field, *t2field;
|
|
|
|
|
|
|
|
t1cur = list_head(t1->e.elements);
|
|
|
|
t2cur = list_head(t2->e.elements);
|
|
|
|
while (t1cur && t2cur)
|
|
|
|
{
|
|
|
|
t1field = LIST_ENTRY(t1cur, struct hlsl_struct_field, entry);
|
|
|
|
t2field = LIST_ENTRY(t2cur, struct hlsl_struct_field, entry);
|
2021-03-17 22:22:19 -07:00
|
|
|
if (!hlsl_types_are_equal(t1field->type, t2field->type))
|
2021-02-02 14:11:17 -08:00
|
|
|
return false;
|
2021-01-27 08:29:44 -08:00
|
|
|
if (strcmp(t1field->name, t2field->name))
|
2021-02-02 14:11:17 -08:00
|
|
|
return false;
|
2021-01-27 08:29:44 -08:00
|
|
|
t1cur = list_next(t1->e.elements, t1cur);
|
|
|
|
t2cur = list_next(t2->e.elements, t2cur);
|
|
|
|
}
|
|
|
|
if (t1cur != t2cur)
|
2021-02-02 14:11:17 -08:00
|
|
|
return false;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
if (t1->type == HLSL_CLASS_ARRAY)
|
|
|
|
return t1->e.array.elements_count == t2->e.array.elements_count
|
2021-03-17 22:22:19 -07:00
|
|
|
&& hlsl_types_are_equal(t1->e.array.type, t2->e.array.type);
|
2021-01-27 08:29:44 -08:00
|
|
|
|
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
|
|
|
struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old, unsigned int default_majority)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
struct hlsl_struct_field *old_field, *field;
|
|
|
|
struct hlsl_type *type;
|
|
|
|
|
|
|
|
if (!(type = vkd3d_calloc(1, sizeof(*type))))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (old->name)
|
|
|
|
{
|
|
|
|
type->name = vkd3d_strdup(old->name);
|
|
|
|
if (!type->name)
|
|
|
|
{
|
|
|
|
vkd3d_free(type);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
type->type = old->type;
|
|
|
|
type->base_type = old->base_type;
|
|
|
|
type->dimx = old->dimx;
|
|
|
|
type->dimy = old->dimy;
|
|
|
|
type->modifiers = old->modifiers;
|
|
|
|
if (!(type->modifiers & HLSL_MODIFIERS_MAJORITY_MASK))
|
|
|
|
type->modifiers |= default_majority;
|
|
|
|
type->sampler_dim = old->sampler_dim;
|
|
|
|
switch (old->type)
|
|
|
|
{
|
|
|
|
case HLSL_CLASS_ARRAY:
|
2021-02-04 14:33:53 -08:00
|
|
|
type->e.array.type = hlsl_type_clone(ctx, old->e.array.type, default_majority);
|
2021-01-27 08:29:44 -08:00
|
|
|
type->e.array.elements_count = old->e.array.elements_count;
|
|
|
|
type->reg_size = type->e.array.elements_count * type->e.array.type->reg_size;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case HLSL_CLASS_STRUCT:
|
|
|
|
{
|
|
|
|
unsigned int reg_size = 0;
|
|
|
|
|
|
|
|
if (!(type->e.elements = vkd3d_malloc(sizeof(*type->e.elements))))
|
|
|
|
{
|
|
|
|
vkd3d_free((void *)type->name);
|
|
|
|
vkd3d_free(type);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
list_init(type->e.elements);
|
|
|
|
LIST_FOR_EACH_ENTRY(old_field, old->e.elements, struct hlsl_struct_field, entry)
|
|
|
|
{
|
|
|
|
if (!(field = vkd3d_calloc(1, sizeof(*field))))
|
|
|
|
{
|
|
|
|
LIST_FOR_EACH_ENTRY_SAFE(field, old_field, type->e.elements, struct hlsl_struct_field, entry)
|
|
|
|
{
|
|
|
|
vkd3d_free((void *)field->semantic);
|
|
|
|
vkd3d_free((void *)field->name);
|
|
|
|
vkd3d_free(field);
|
|
|
|
}
|
|
|
|
vkd3d_free(type->e.elements);
|
|
|
|
vkd3d_free((void *)type->name);
|
|
|
|
vkd3d_free(type);
|
|
|
|
return NULL;
|
|
|
|
}
|
2021-03-02 13:34:43 -08:00
|
|
|
field->loc = old_field->loc;
|
2021-02-04 14:33:53 -08:00
|
|
|
field->type = hlsl_type_clone(ctx, old_field->type, default_majority);
|
2021-01-27 08:29:44 -08:00
|
|
|
field->name = vkd3d_strdup(old_field->name);
|
|
|
|
if (old_field->semantic)
|
|
|
|
field->semantic = vkd3d_strdup(old_field->semantic);
|
|
|
|
field->reg_offset = reg_size;
|
|
|
|
reg_size += field->type->reg_size;
|
|
|
|
list_add_tail(type->e.elements, &field->entry);
|
|
|
|
}
|
|
|
|
type->reg_size = reg_size;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case HLSL_CLASS_MATRIX:
|
2021-02-02 14:11:14 -08:00
|
|
|
type->reg_size = hlsl_type_is_row_major(type) ? type->dimy : type->dimx;
|
2021-01-27 08:29:44 -08:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
type->reg_size = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
list_add_tail(&ctx->types, &type->entry);
|
2021-01-27 08:29:44 -08:00
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:50 -08:00
|
|
|
bool hlsl_scope_add_type(struct hlsl_scope *scope, struct hlsl_type *type)
|
|
|
|
{
|
|
|
|
if (hlsl_get_type(scope, type->name, false))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
rb_put(&scope->types, type->name, &type->scope_entry);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:14 -08:00
|
|
|
struct hlsl_ir_expr *hlsl_new_cast(struct hlsl_ir_node *node, struct hlsl_type *type,
|
2021-02-12 08:48:55 -08:00
|
|
|
struct vkd3d_shader_location *loc)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
struct hlsl_ir_node *cast;
|
|
|
|
|
2021-02-02 14:11:14 -08:00
|
|
|
cast = hlsl_new_unary_expr(HLSL_IR_UNOP_CAST, node, *loc);
|
2021-01-27 08:29:44 -08:00
|
|
|
if (cast)
|
|
|
|
cast->data_type = type;
|
2021-02-02 14:11:14 -08:00
|
|
|
return hlsl_ir_expr(cast);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
2021-03-16 14:31:52 -07:00
|
|
|
struct hlsl_ir_expr *hlsl_new_copy(struct hlsl_ir_node *node)
|
|
|
|
{
|
|
|
|
/* Use a cast to the same type as a makeshift identity expression. */
|
|
|
|
return hlsl_new_cast(node, node->data_type, &node->loc);
|
|
|
|
}
|
|
|
|
|
2021-02-12 08:48:55 -08:00
|
|
|
struct hlsl_ir_var *hlsl_new_var(const char *name, struct hlsl_type *type, const struct vkd3d_shader_location loc,
|
2021-03-22 15:02:37 -07:00
|
|
|
const char *semantic, const struct hlsl_reg_reservation *reg_reservation)
|
2021-01-30 11:51:32 -08:00
|
|
|
{
|
|
|
|
struct hlsl_ir_var *var;
|
|
|
|
|
|
|
|
if (!(var = vkd3d_calloc(1, sizeof(*var))))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
var->name = name;
|
|
|
|
var->data_type = type;
|
|
|
|
var->loc = loc;
|
|
|
|
var->semantic = semantic;
|
|
|
|
var->reg_reservation = reg_reservation;
|
|
|
|
return var;
|
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
struct hlsl_ir_var *hlsl_new_synthetic_var(struct hlsl_ctx *ctx, const char *name, struct hlsl_type *type,
|
2021-02-12 08:48:55 -08:00
|
|
|
const struct vkd3d_shader_location loc)
|
2021-01-30 11:51:32 -08:00
|
|
|
{
|
2021-03-22 15:02:37 -07:00
|
|
|
struct hlsl_ir_var *var = hlsl_new_var(vkd3d_strdup(name), type, loc, NULL, NULL);
|
2021-01-30 11:51:32 -08:00
|
|
|
|
|
|
|
if (var)
|
2021-02-04 14:33:53 -08:00
|
|
|
list_add_tail(&ctx->globals->vars, &var->scope_entry);
|
2021-01-30 11:51:32 -08:00
|
|
|
return var;
|
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:17 -08:00
|
|
|
static bool type_is_single_reg(const struct hlsl_type *type)
|
2021-01-30 11:51:32 -08:00
|
|
|
{
|
|
|
|
return type->type == HLSL_CLASS_SCALAR || type->type == HLSL_CLASS_VECTOR;
|
|
|
|
}
|
|
|
|
|
2021-04-08 21:38:22 -07:00
|
|
|
struct hlsl_ir_store *hlsl_new_store(struct hlsl_ir_var *var, struct hlsl_ir_node *offset,
|
2021-02-12 08:48:55 -08:00
|
|
|
struct hlsl_ir_node *rhs, unsigned int writemask, struct vkd3d_shader_location loc)
|
2021-01-30 11:51:32 -08:00
|
|
|
{
|
2021-04-08 21:38:22 -07:00
|
|
|
struct hlsl_ir_store *store;
|
2021-01-30 11:51:32 -08:00
|
|
|
|
|
|
|
if (!writemask && type_is_single_reg(rhs->data_type))
|
|
|
|
writemask = (1 << rhs->data_type->dimx) - 1;
|
|
|
|
|
2021-04-08 21:38:22 -07:00
|
|
|
if (!(store = vkd3d_malloc(sizeof(*store))))
|
2021-01-30 11:51:32 -08:00
|
|
|
return NULL;
|
|
|
|
|
2021-04-08 21:38:22 -07:00
|
|
|
init_node(&store->node, HLSL_IR_STORE, NULL, loc);
|
|
|
|
store->lhs.var = var;
|
|
|
|
hlsl_src_from_node(&store->lhs.offset, offset);
|
|
|
|
hlsl_src_from_node(&store->rhs, rhs);
|
|
|
|
store->writemask = writemask;
|
|
|
|
return store;
|
2021-01-30 11:51:32 -08:00
|
|
|
}
|
|
|
|
|
2021-04-08 21:38:22 -07:00
|
|
|
struct hlsl_ir_store *hlsl_new_simple_store(struct hlsl_ir_var *lhs, struct hlsl_ir_node *rhs)
|
2021-01-30 11:51:32 -08:00
|
|
|
{
|
2021-04-08 21:38:22 -07:00
|
|
|
return hlsl_new_store(lhs, NULL, rhs, 0, rhs->loc);
|
2021-01-30 11:51:32 -08:00
|
|
|
}
|
|
|
|
|
2021-02-12 08:48:55 -08:00
|
|
|
struct hlsl_ir_constant *hlsl_new_uint_constant(struct hlsl_ctx *ctx, unsigned int n,
|
|
|
|
const struct vkd3d_shader_location loc)
|
2021-01-30 11:51:32 -08:00
|
|
|
{
|
|
|
|
struct hlsl_ir_constant *c;
|
|
|
|
|
|
|
|
if (!(c = vkd3d_malloc(sizeof(*c))))
|
|
|
|
return NULL;
|
2021-02-04 14:33:53 -08:00
|
|
|
init_node(&c->node, HLSL_IR_CONSTANT, ctx->builtin_types.scalar[HLSL_TYPE_UINT], loc);
|
2021-01-30 11:51:32 -08:00
|
|
|
c->value.u[0] = n;
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2021-02-12 08:48:55 -08:00
|
|
|
struct hlsl_ir_node *hlsl_new_unary_expr(enum hlsl_ir_expr_op op,
|
|
|
|
struct hlsl_ir_node *arg, struct vkd3d_shader_location loc)
|
2021-01-30 11:51:32 -08:00
|
|
|
{
|
|
|
|
struct hlsl_ir_expr *expr;
|
|
|
|
|
|
|
|
if (!(expr = vkd3d_calloc(1, sizeof(*expr))))
|
|
|
|
return NULL;
|
|
|
|
init_node(&expr->node, HLSL_IR_EXPR, arg->data_type, loc);
|
|
|
|
expr->op = op;
|
|
|
|
hlsl_src_from_node(&expr->operands[0], arg);
|
|
|
|
return &expr->node;
|
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:14 -08:00
|
|
|
struct hlsl_ir_node *hlsl_new_binary_expr(enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg1, struct hlsl_ir_node *arg2)
|
2021-01-30 11:51:32 -08:00
|
|
|
{
|
|
|
|
struct hlsl_ir_expr *expr;
|
|
|
|
|
2021-03-17 22:22:19 -07:00
|
|
|
assert(hlsl_types_are_equal(arg1->data_type, arg2->data_type));
|
2021-01-30 11:51:32 -08:00
|
|
|
|
|
|
|
if (!(expr = vkd3d_calloc(1, sizeof(*expr))))
|
|
|
|
return NULL;
|
|
|
|
init_node(&expr->node, HLSL_IR_EXPR, arg1->data_type, arg1->loc);
|
|
|
|
expr->op = op;
|
|
|
|
hlsl_src_from_node(&expr->operands[0], arg1);
|
|
|
|
hlsl_src_from_node(&expr->operands[1], arg2);
|
|
|
|
return &expr->node;
|
|
|
|
}
|
|
|
|
|
2021-02-12 08:48:55 -08:00
|
|
|
struct hlsl_ir_if *hlsl_new_if(struct hlsl_ir_node *condition, struct vkd3d_shader_location loc)
|
2021-01-30 11:51:32 -08:00
|
|
|
{
|
|
|
|
struct hlsl_ir_if *iff;
|
|
|
|
|
|
|
|
if (!(iff = vkd3d_malloc(sizeof(*iff))))
|
|
|
|
return NULL;
|
|
|
|
init_node(&iff->node, HLSL_IR_IF, NULL, loc);
|
|
|
|
hlsl_src_from_node(&iff->condition, condition);
|
|
|
|
list_init(&iff->then_instrs);
|
|
|
|
list_init(&iff->else_instrs);
|
|
|
|
return iff;
|
|
|
|
}
|
|
|
|
|
2021-03-17 22:22:20 -07:00
|
|
|
struct hlsl_ir_load *hlsl_new_load(struct hlsl_ir_var *var, struct hlsl_ir_node *offset,
|
|
|
|
struct hlsl_type *type, const struct vkd3d_shader_location loc)
|
2021-01-30 11:51:32 -08:00
|
|
|
{
|
|
|
|
struct hlsl_ir_load *load;
|
|
|
|
|
|
|
|
if (!(load = vkd3d_calloc(1, sizeof(*load))))
|
|
|
|
return NULL;
|
2021-03-17 22:22:20 -07:00
|
|
|
init_node(&load->node, HLSL_IR_LOAD, type, loc);
|
2021-01-30 11:51:32 -08:00
|
|
|
load->src.var = var;
|
2021-03-17 22:22:20 -07:00
|
|
|
hlsl_src_from_node(&load->src.offset, offset);
|
2021-01-30 11:51:32 -08:00
|
|
|
return load;
|
|
|
|
}
|
|
|
|
|
2021-03-17 22:22:20 -07:00
|
|
|
struct hlsl_ir_load *hlsl_new_var_load(struct hlsl_ir_var *var, const struct vkd3d_shader_location loc)
|
|
|
|
{
|
|
|
|
return hlsl_new_load(var, NULL, var->data_type, loc);
|
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
struct hlsl_ir_swizzle *hlsl_new_swizzle(struct hlsl_ctx *ctx, DWORD s, unsigned int components,
|
2021-02-12 08:48:55 -08:00
|
|
|
struct hlsl_ir_node *val, struct vkd3d_shader_location *loc)
|
2021-01-30 11:51:32 -08:00
|
|
|
{
|
|
|
|
struct hlsl_ir_swizzle *swizzle;
|
|
|
|
|
|
|
|
if (!(swizzle = vkd3d_malloc(sizeof(*swizzle))))
|
|
|
|
return NULL;
|
|
|
|
init_node(&swizzle->node, HLSL_IR_SWIZZLE,
|
2021-02-04 14:33:53 -08:00
|
|
|
hlsl_new_type(ctx, NULL, HLSL_CLASS_VECTOR, val->data_type->base_type, components, 1), *loc);
|
2021-01-30 11:51:32 -08:00
|
|
|
hlsl_src_from_node(&swizzle->val, val);
|
|
|
|
swizzle->swizzle = s;
|
|
|
|
return swizzle;
|
|
|
|
}
|
|
|
|
|
2021-02-27 16:03:13 -08:00
|
|
|
struct hlsl_ir_jump *hlsl_new_jump(enum hlsl_ir_jump_type type, struct vkd3d_shader_location loc)
|
|
|
|
{
|
|
|
|
struct hlsl_ir_jump *jump;
|
|
|
|
|
|
|
|
if (!(jump = vkd3d_malloc(sizeof(*jump))))
|
|
|
|
return NULL;
|
|
|
|
init_node(&jump->node, HLSL_IR_JUMP, NULL, loc);
|
|
|
|
jump->type = type;
|
|
|
|
return jump;
|
|
|
|
}
|
|
|
|
|
2021-02-27 16:03:14 -08:00
|
|
|
struct hlsl_ir_loop *hlsl_new_loop(struct vkd3d_shader_location loc)
|
|
|
|
{
|
|
|
|
struct hlsl_ir_loop *loop;
|
|
|
|
|
|
|
|
if (!(loop = vkd3d_calloc(1, sizeof(*loop))))
|
|
|
|
return NULL;
|
|
|
|
init_node(&loop->node, HLSL_IR_LOOP, NULL, loc);
|
|
|
|
list_init(&loop->body);
|
|
|
|
return loop;
|
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:17 -08:00
|
|
|
bool hlsl_type_is_void(const struct hlsl_type *type)
|
2021-01-30 11:51:32 -08:00
|
|
|
{
|
|
|
|
return type->type == HLSL_CLASS_OBJECT && type->base_type == HLSL_TYPE_VOID;
|
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
struct hlsl_ir_function_decl *hlsl_new_func_decl(struct hlsl_ctx *ctx, struct hlsl_type *return_type,
|
2021-02-12 08:48:55 -08:00
|
|
|
struct list *parameters, const char *semantic, struct vkd3d_shader_location loc)
|
2021-01-30 11:51:32 -08:00
|
|
|
{
|
|
|
|
struct hlsl_ir_function_decl *decl;
|
|
|
|
|
|
|
|
if (!(decl = vkd3d_calloc(1, sizeof(*decl))))
|
|
|
|
return NULL;
|
|
|
|
decl->return_type = return_type;
|
|
|
|
decl->parameters = parameters;
|
|
|
|
decl->loc = loc;
|
|
|
|
|
2021-02-02 14:11:14 -08:00
|
|
|
if (!hlsl_type_is_void(return_type))
|
2021-01-30 11:51:32 -08:00
|
|
|
{
|
|
|
|
struct hlsl_ir_var *return_var;
|
|
|
|
char name[28];
|
|
|
|
|
|
|
|
sprintf(name, "<retval-%p>", decl);
|
2021-03-28 12:46:58 -07:00
|
|
|
if (!(return_var = hlsl_new_var(vkd3d_strdup(name), return_type, loc, semantic, NULL)))
|
2021-01-30 11:51:32 -08:00
|
|
|
{
|
|
|
|
vkd3d_free(decl);
|
|
|
|
return NULL;
|
|
|
|
}
|
2021-03-28 12:46:58 -07:00
|
|
|
list_add_tail(&ctx->globals->vars, &return_var->scope_entry);
|
2021-01-30 11:51:32 -08:00
|
|
|
decl->return_var = return_var;
|
|
|
|
}
|
|
|
|
|
|
|
|
return decl;
|
|
|
|
}
|
|
|
|
|
2021-01-27 08:29:44 -08:00
|
|
|
static int compare_hlsl_types_rb(const void *key, const struct rb_entry *entry)
|
|
|
|
{
|
|
|
|
const struct hlsl_type *type = RB_ENTRY_VALUE(entry, const struct hlsl_type, scope_entry);
|
|
|
|
const char *name = key;
|
|
|
|
|
|
|
|
if (name == type->name)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!name || !type->name)
|
|
|
|
{
|
|
|
|
ERR("hlsl_type without a name in a scope?\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return strcmp(name, type->name);
|
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
void hlsl_push_scope(struct hlsl_ctx *ctx)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
struct hlsl_scope *new_scope;
|
|
|
|
|
|
|
|
if (!(new_scope = vkd3d_malloc(sizeof(*new_scope))))
|
|
|
|
return;
|
|
|
|
TRACE("Pushing a new scope.\n");
|
|
|
|
list_init(&new_scope->vars);
|
|
|
|
rb_init(&new_scope->types, compare_hlsl_types_rb);
|
|
|
|
new_scope->upper = ctx->cur_scope;
|
|
|
|
ctx->cur_scope = new_scope;
|
|
|
|
list_add_tail(&ctx->scopes, &new_scope->entry);
|
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
void hlsl_pop_scope(struct hlsl_ctx *ctx)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
struct hlsl_scope *prev_scope = ctx->cur_scope->upper;
|
|
|
|
|
2021-02-02 14:11:16 -08:00
|
|
|
assert(prev_scope);
|
2021-01-27 08:29:44 -08:00
|
|
|
TRACE("Popping current scope.\n");
|
|
|
|
ctx->cur_scope = prev_scope;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int compare_param_hlsl_types(const struct hlsl_type *t1, const struct hlsl_type *t2)
|
|
|
|
{
|
|
|
|
if (t1->type != t2->type)
|
|
|
|
{
|
|
|
|
if (!((t1->type == HLSL_CLASS_SCALAR && t2->type == HLSL_CLASS_VECTOR)
|
|
|
|
|| (t1->type == HLSL_CLASS_VECTOR && t2->type == HLSL_CLASS_SCALAR)))
|
|
|
|
return t1->type - t2->type;
|
|
|
|
}
|
|
|
|
if (t1->base_type != t2->base_type)
|
|
|
|
return t1->base_type - t2->base_type;
|
|
|
|
if (t1->base_type == HLSL_TYPE_SAMPLER && t1->sampler_dim != t2->sampler_dim)
|
|
|
|
return t1->sampler_dim - t2->sampler_dim;
|
|
|
|
if (t1->dimx != t2->dimx)
|
|
|
|
return t1->dimx - t2->dimx;
|
|
|
|
if (t1->dimy != t2->dimy)
|
|
|
|
return t1->dimx - t2->dimx;
|
|
|
|
if (t1->type == HLSL_CLASS_STRUCT)
|
|
|
|
{
|
|
|
|
struct list *t1cur, *t2cur;
|
|
|
|
struct hlsl_struct_field *t1field, *t2field;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
t1cur = list_head(t1->e.elements);
|
|
|
|
t2cur = list_head(t2->e.elements);
|
|
|
|
while (t1cur && t2cur)
|
|
|
|
{
|
|
|
|
t1field = LIST_ENTRY(t1cur, struct hlsl_struct_field, entry);
|
|
|
|
t2field = LIST_ENTRY(t2cur, struct hlsl_struct_field, entry);
|
|
|
|
if ((r = compare_param_hlsl_types(t1field->type, t2field->type)))
|
|
|
|
return r;
|
|
|
|
if ((r = strcmp(t1field->name, t2field->name)))
|
|
|
|
return r;
|
|
|
|
t1cur = list_next(t1->e.elements, t1cur);
|
|
|
|
t2cur = list_next(t2->e.elements, t2cur);
|
|
|
|
}
|
|
|
|
if (t1cur != t2cur)
|
|
|
|
return t1cur ? 1 : -1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (t1->type == HLSL_CLASS_ARRAY)
|
|
|
|
{
|
|
|
|
if (t1->e.array.elements_count != t2->e.array.elements_count)
|
|
|
|
return t1->e.array.elements_count - t2->e.array.elements_count;
|
|
|
|
return compare_param_hlsl_types(t1->e.array.type, t2->e.array.type);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int compare_function_decl_rb(const void *key, const struct rb_entry *entry)
|
|
|
|
{
|
|
|
|
const struct list *params = key;
|
|
|
|
const struct hlsl_ir_function_decl *decl = RB_ENTRY_VALUE(entry, const struct hlsl_ir_function_decl, entry);
|
|
|
|
int decl_params_count = decl->parameters ? list_count(decl->parameters) : 0;
|
|
|
|
int params_count = params ? list_count(params) : 0;
|
|
|
|
struct list *p1cur, *p2cur;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
if (params_count != decl_params_count)
|
|
|
|
return params_count - decl_params_count;
|
|
|
|
|
|
|
|
p1cur = params ? list_head(params) : NULL;
|
|
|
|
p2cur = decl->parameters ? list_head(decl->parameters) : NULL;
|
|
|
|
while (p1cur && p2cur)
|
|
|
|
{
|
|
|
|
struct hlsl_ir_var *p1, *p2;
|
|
|
|
p1 = LIST_ENTRY(p1cur, struct hlsl_ir_var, param_entry);
|
|
|
|
p2 = LIST_ENTRY(p2cur, struct hlsl_ir_var, param_entry);
|
|
|
|
if ((r = compare_param_hlsl_types(p1->data_type, p2->data_type)))
|
|
|
|
return r;
|
|
|
|
p1cur = list_next(params, p1cur);
|
|
|
|
p2cur = list_next(decl->parameters, p2cur);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-02-27 16:03:09 -08:00
|
|
|
struct vkd3d_string_buffer *hlsl_type_to_string(struct vkd3d_string_buffer_cache *string_buffers,
|
|
|
|
const struct hlsl_type *type)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-02-27 16:03:09 -08:00
|
|
|
struct vkd3d_string_buffer *string;
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2021-02-16 21:52:05 -08:00
|
|
|
static const char base_types[HLSL_TYPE_LAST_SCALAR + 1][7] =
|
|
|
|
{
|
|
|
|
"float",
|
|
|
|
"half",
|
|
|
|
"double",
|
|
|
|
"int",
|
|
|
|
"uint",
|
|
|
|
"bool",
|
|
|
|
};
|
|
|
|
|
2021-02-27 16:03:09 -08:00
|
|
|
if (!(string = vkd3d_string_buffer_get(string_buffers)))
|
|
|
|
return NULL;
|
|
|
|
|
2021-01-27 08:29:44 -08:00
|
|
|
if (type->name)
|
2021-02-27 16:03:09 -08:00
|
|
|
{
|
|
|
|
vkd3d_string_buffer_printf(string, "%s", type->name);
|
|
|
|
return string;
|
|
|
|
}
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2021-02-12 12:38:50 -08:00
|
|
|
switch (type->type)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-02-12 12:38:50 -08:00
|
|
|
case HLSL_CLASS_SCALAR:
|
2021-02-27 16:03:11 -08:00
|
|
|
assert(type->base_type < ARRAY_SIZE(base_types));
|
2021-02-27 16:03:09 -08:00
|
|
|
vkd3d_string_buffer_printf(string, "%s", base_types[type->base_type]);
|
|
|
|
return string;
|
2021-02-12 12:38:50 -08:00
|
|
|
|
|
|
|
case HLSL_CLASS_VECTOR:
|
2021-02-27 16:03:11 -08:00
|
|
|
assert(type->base_type < ARRAY_SIZE(base_types));
|
2021-02-27 16:03:09 -08:00
|
|
|
vkd3d_string_buffer_printf(string, "%s%u", base_types[type->base_type], type->dimx);
|
2021-02-12 12:38:50 -08:00
|
|
|
return string;
|
|
|
|
|
|
|
|
case HLSL_CLASS_MATRIX:
|
2021-02-27 16:03:11 -08:00
|
|
|
assert(type->base_type < ARRAY_SIZE(base_types));
|
2021-02-27 16:03:09 -08:00
|
|
|
vkd3d_string_buffer_printf(string, "%s%ux%u", base_types[type->base_type], type->dimx, type->dimy);
|
2021-02-12 12:38:50 -08:00
|
|
|
return string;
|
|
|
|
|
|
|
|
case HLSL_CLASS_ARRAY:
|
2021-02-16 21:52:04 -08:00
|
|
|
{
|
2021-02-27 16:03:09 -08:00
|
|
|
struct vkd3d_string_buffer *inner_string;
|
2021-02-16 21:52:04 -08:00
|
|
|
const struct hlsl_type *t;
|
|
|
|
|
|
|
|
for (t = type; t->type == HLSL_CLASS_ARRAY; t = t->e.array.type)
|
2021-02-27 16:03:09 -08:00
|
|
|
;
|
2021-02-16 21:52:04 -08:00
|
|
|
|
2021-02-27 16:03:09 -08:00
|
|
|
if ((inner_string = hlsl_type_to_string(string_buffers, t)))
|
2021-02-16 21:52:04 -08:00
|
|
|
{
|
2021-02-27 16:03:09 -08:00
|
|
|
vkd3d_string_buffer_printf(string, "%s", inner_string->buffer);
|
|
|
|
vkd3d_string_buffer_release(string_buffers, inner_string);
|
2021-02-16 21:52:04 -08:00
|
|
|
}
|
|
|
|
|
2021-02-27 16:03:09 -08:00
|
|
|
for (t = type; t->type == HLSL_CLASS_ARRAY; t = t->e.array.type)
|
|
|
|
vkd3d_string_buffer_printf(string, "[%u]", t->e.array.elements_count);
|
2021-02-12 12:38:50 -08:00
|
|
|
return string;
|
2021-02-16 21:52:04 -08:00
|
|
|
}
|
2021-02-12 12:38:50 -08:00
|
|
|
|
|
|
|
case HLSL_CLASS_STRUCT:
|
2021-02-27 16:03:09 -08:00
|
|
|
vkd3d_string_buffer_printf(string, "<anonymous struct>");
|
|
|
|
return string;
|
2021-02-12 12:38:50 -08:00
|
|
|
|
|
|
|
default:
|
2021-02-27 16:03:09 -08:00
|
|
|
vkd3d_string_buffer_printf(string, "<unexpected type>");
|
|
|
|
return string;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
2021-02-12 12:38:50 -08:00
|
|
|
}
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2021-02-12 12:38:50 -08:00
|
|
|
const char *debug_hlsl_type(const struct hlsl_type *type)
|
|
|
|
{
|
2021-02-27 16:03:09 -08:00
|
|
|
struct vkd3d_string_buffer_cache string_buffers;
|
|
|
|
struct vkd3d_string_buffer *string;
|
2021-02-12 12:38:50 -08:00
|
|
|
const char *ret;
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2021-02-27 16:03:09 -08:00
|
|
|
vkd3d_string_buffer_cache_init(&string_buffers);
|
|
|
|
if (!(string = hlsl_type_to_string(&string_buffers, type)))
|
2021-02-12 12:38:50 -08:00
|
|
|
return NULL;
|
2021-02-27 16:03:09 -08:00
|
|
|
ret = vkd3d_dbg_sprintf("%s", string->buffer);
|
|
|
|
vkd3d_string_buffer_release(&string_buffers, string);
|
|
|
|
vkd3d_string_buffer_cache_cleanup(&string_buffers);
|
2021-02-12 12:38:50 -08:00
|
|
|
return ret;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
2021-02-27 16:03:10 -08:00
|
|
|
struct vkd3d_string_buffer *hlsl_modifiers_to_string(struct vkd3d_string_buffer_cache *string_buffers,
|
|
|
|
unsigned int modifiers)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-02-27 16:03:10 -08:00
|
|
|
struct vkd3d_string_buffer *string;
|
2021-02-12 12:38:49 -08:00
|
|
|
|
2021-02-27 16:03:10 -08:00
|
|
|
if (!(string = vkd3d_string_buffer_get(string_buffers)))
|
2021-02-12 12:38:49 -08:00
|
|
|
return NULL;
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
if (modifiers & HLSL_STORAGE_EXTERN)
|
2021-02-27 16:03:10 -08:00
|
|
|
vkd3d_string_buffer_printf(string, "extern ");
|
2021-01-27 08:29:44 -08:00
|
|
|
if (modifiers & HLSL_STORAGE_NOINTERPOLATION)
|
2021-02-27 16:03:10 -08:00
|
|
|
vkd3d_string_buffer_printf(string, "nointerpolation ");
|
2021-01-27 08:29:44 -08:00
|
|
|
if (modifiers & HLSL_MODIFIER_PRECISE)
|
2021-02-27 16:03:10 -08:00
|
|
|
vkd3d_string_buffer_printf(string, "precise ");
|
2021-01-27 08:29:44 -08:00
|
|
|
if (modifiers & HLSL_STORAGE_SHARED)
|
2021-02-27 16:03:10 -08:00
|
|
|
vkd3d_string_buffer_printf(string, "shared ");
|
2021-01-27 08:29:44 -08:00
|
|
|
if (modifiers & HLSL_STORAGE_GROUPSHARED)
|
2021-02-27 16:03:10 -08:00
|
|
|
vkd3d_string_buffer_printf(string, "groupshared ");
|
2021-01-27 08:29:44 -08:00
|
|
|
if (modifiers & HLSL_STORAGE_STATIC)
|
2021-02-27 16:03:10 -08:00
|
|
|
vkd3d_string_buffer_printf(string, "static ");
|
2021-01-27 08:29:44 -08:00
|
|
|
if (modifiers & HLSL_STORAGE_UNIFORM)
|
2021-02-27 16:03:10 -08:00
|
|
|
vkd3d_string_buffer_printf(string, "uniform ");
|
2021-01-27 08:29:44 -08:00
|
|
|
if (modifiers & HLSL_STORAGE_VOLATILE)
|
2021-02-27 16:03:10 -08:00
|
|
|
vkd3d_string_buffer_printf(string, "volatile ");
|
2021-01-27 08:29:44 -08:00
|
|
|
if (modifiers & HLSL_MODIFIER_CONST)
|
2021-02-27 16:03:10 -08:00
|
|
|
vkd3d_string_buffer_printf(string, "const ");
|
2021-01-27 08:29:44 -08:00
|
|
|
if (modifiers & HLSL_MODIFIER_ROW_MAJOR)
|
2021-02-27 16:03:10 -08:00
|
|
|
vkd3d_string_buffer_printf(string, "row_major ");
|
2021-01-27 08:29:44 -08:00
|
|
|
if (modifiers & HLSL_MODIFIER_COLUMN_MAJOR)
|
2021-02-27 16:03:10 -08:00
|
|
|
vkd3d_string_buffer_printf(string, "column_major ");
|
2021-01-27 08:29:44 -08:00
|
|
|
if ((modifiers & (HLSL_STORAGE_IN | HLSL_STORAGE_OUT)) == (HLSL_STORAGE_IN | HLSL_STORAGE_OUT))
|
2021-02-27 16:03:10 -08:00
|
|
|
vkd3d_string_buffer_printf(string, "inout ");
|
2021-01-27 08:29:44 -08:00
|
|
|
else if (modifiers & HLSL_STORAGE_IN)
|
2021-02-27 16:03:10 -08:00
|
|
|
vkd3d_string_buffer_printf(string, "in ");
|
2021-01-27 08:29:44 -08:00
|
|
|
else if (modifiers & HLSL_STORAGE_OUT)
|
2021-02-27 16:03:10 -08:00
|
|
|
vkd3d_string_buffer_printf(string, "out ");
|
2021-02-12 12:38:49 -08:00
|
|
|
|
2021-02-27 16:03:10 -08:00
|
|
|
if (string->content_size)
|
|
|
|
string->buffer[--string->content_size] = 0;
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2021-02-12 12:38:49 -08:00
|
|
|
return string;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:14 -08:00
|
|
|
const char *hlsl_node_type_to_string(enum hlsl_ir_node_type type)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
static const char * const names[] =
|
|
|
|
{
|
|
|
|
"HLSL_IR_CONSTANT",
|
|
|
|
"HLSL_IR_EXPR",
|
|
|
|
"HLSL_IR_IF",
|
|
|
|
"HLSL_IR_LOAD",
|
|
|
|
"HLSL_IR_LOOP",
|
|
|
|
"HLSL_IR_JUMP",
|
2021-04-08 21:38:22 -07:00
|
|
|
"HLSL_IR_STORE",
|
2021-01-27 08:29:44 -08:00
|
|
|
"HLSL_IR_SWIZZLE",
|
|
|
|
};
|
|
|
|
|
|
|
|
if (type >= ARRAY_SIZE(names))
|
|
|
|
return "Unexpected node type";
|
|
|
|
return names[type];
|
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:15 -08:00
|
|
|
static void dump_instr(struct vkd3d_string_buffer *buffer, const struct hlsl_ir_node *instr);
|
2021-01-27 08:29:44 -08:00
|
|
|
|
2021-02-02 14:11:15 -08:00
|
|
|
static void dump_instr_list(struct vkd3d_string_buffer *buffer, const struct list *list)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
struct hlsl_ir_node *instr;
|
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY(instr, list, struct hlsl_ir_node, entry)
|
|
|
|
{
|
2021-02-02 14:11:15 -08:00
|
|
|
dump_instr(buffer, instr);
|
2021-01-27 08:29:44 -08:00
|
|
|
vkd3d_string_buffer_printf(buffer, "\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:15 -08:00
|
|
|
static void dump_src(struct vkd3d_string_buffer *buffer, const struct hlsl_src *src)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
if (src->node->index)
|
|
|
|
vkd3d_string_buffer_printf(buffer, "@%u", src->node->index);
|
|
|
|
else
|
|
|
|
vkd3d_string_buffer_printf(buffer, "%p", src->node);
|
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:15 -08:00
|
|
|
static void dump_ir_var(struct vkd3d_string_buffer *buffer, const struct hlsl_ir_var *var)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-03-22 15:02:37 -07:00
|
|
|
if (var->is_input_varying)
|
|
|
|
vkd3d_string_buffer_printf(buffer, "in ");
|
|
|
|
if (var->is_output_varying)
|
|
|
|
vkd3d_string_buffer_printf(buffer, "out ");
|
|
|
|
if (var->is_uniform)
|
|
|
|
vkd3d_string_buffer_printf(buffer, "uniform ");
|
2021-01-27 08:29:44 -08:00
|
|
|
vkd3d_string_buffer_printf(buffer, "%s %s", debug_hlsl_type(var->data_type), var->name);
|
|
|
|
if (var->semantic)
|
|
|
|
vkd3d_string_buffer_printf(buffer, " : %s", var->semantic);
|
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:15 -08:00
|
|
|
static void dump_deref(struct vkd3d_string_buffer *buffer, const struct hlsl_deref *deref)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
2021-02-12 12:38:50 -08:00
|
|
|
vkd3d_string_buffer_printf(buffer, "%s", deref->var->name);
|
2021-01-27 08:29:44 -08:00
|
|
|
if (deref->offset.node)
|
|
|
|
{
|
|
|
|
vkd3d_string_buffer_printf(buffer, "[");
|
2021-02-02 14:11:15 -08:00
|
|
|
dump_src(buffer, &deref->offset);
|
2021-01-27 08:29:44 -08:00
|
|
|
vkd3d_string_buffer_printf(buffer, "]");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-08 21:38:23 -07:00
|
|
|
const char *debug_hlsl_writemask(unsigned int writemask)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
static const char components[] = {'x', 'y', 'z', 'w'};
|
|
|
|
char string[5];
|
|
|
|
unsigned int i = 0, pos = 0;
|
|
|
|
|
|
|
|
assert(!(writemask & ~VKD3DSP_WRITEMASK_ALL));
|
|
|
|
|
|
|
|
while (writemask)
|
|
|
|
{
|
|
|
|
if (writemask & 1)
|
|
|
|
string[pos++] = components[i];
|
|
|
|
writemask >>= 1;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
string[pos] = '\0';
|
|
|
|
return vkd3d_dbg_sprintf(".%s", string);
|
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:15 -08:00
|
|
|
static void dump_ir_constant(struct vkd3d_string_buffer *buffer, const struct hlsl_ir_constant *constant)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
struct hlsl_type *type = constant->node.data_type;
|
|
|
|
unsigned int x;
|
|
|
|
|
|
|
|
if (type->dimx != 1)
|
|
|
|
vkd3d_string_buffer_printf(buffer, "{");
|
|
|
|
for (x = 0; x < type->dimx; ++x)
|
|
|
|
{
|
|
|
|
switch (type->base_type)
|
|
|
|
{
|
|
|
|
case HLSL_TYPE_BOOL:
|
|
|
|
vkd3d_string_buffer_printf(buffer, "%s ", constant->value.b[x] ? "true" : "false");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case HLSL_TYPE_DOUBLE:
|
|
|
|
vkd3d_string_buffer_printf(buffer, "%.16e ", constant->value.d[x]);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case HLSL_TYPE_FLOAT:
|
|
|
|
vkd3d_string_buffer_printf(buffer, "%.8e ", constant->value.f[x]);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case HLSL_TYPE_INT:
|
|
|
|
vkd3d_string_buffer_printf(buffer, "%d ", constant->value.i[x]);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case HLSL_TYPE_UINT:
|
|
|
|
vkd3d_string_buffer_printf(buffer, "%u ", constant->value.u[x]);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2021-02-16 21:52:05 -08:00
|
|
|
assert(0);
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (type->dimx != 1)
|
|
|
|
vkd3d_string_buffer_printf(buffer, "}");
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *debug_expr_op(const struct hlsl_ir_expr *expr)
|
|
|
|
{
|
|
|
|
static const char * const op_names[] =
|
|
|
|
{
|
|
|
|
"~",
|
|
|
|
"!",
|
|
|
|
"-",
|
|
|
|
"abs",
|
|
|
|
"sign",
|
|
|
|
"rcp",
|
|
|
|
"rsq",
|
|
|
|
"sqrt",
|
|
|
|
"nrm",
|
|
|
|
"exp2",
|
|
|
|
"log2",
|
|
|
|
|
|
|
|
"cast",
|
|
|
|
|
|
|
|
"fract",
|
|
|
|
|
|
|
|
"sin",
|
|
|
|
"cos",
|
|
|
|
"sin_reduced",
|
|
|
|
"cos_reduced",
|
|
|
|
|
|
|
|
"dsx",
|
|
|
|
"dsy",
|
|
|
|
|
|
|
|
"sat",
|
|
|
|
|
|
|
|
"+",
|
|
|
|
"-",
|
|
|
|
"*",
|
|
|
|
"/",
|
|
|
|
|
|
|
|
"%",
|
|
|
|
|
|
|
|
"<",
|
|
|
|
">",
|
|
|
|
"<=",
|
|
|
|
">=",
|
|
|
|
"==",
|
|
|
|
"!=",
|
|
|
|
|
|
|
|
"&&",
|
|
|
|
"||",
|
|
|
|
|
|
|
|
"<<",
|
|
|
|
">>",
|
|
|
|
"&",
|
|
|
|
"|",
|
|
|
|
"^",
|
|
|
|
|
|
|
|
"dot",
|
|
|
|
"crs",
|
|
|
|
"min",
|
|
|
|
"max",
|
|
|
|
|
|
|
|
"pow",
|
|
|
|
|
|
|
|
"lerp",
|
|
|
|
|
|
|
|
",",
|
|
|
|
};
|
|
|
|
|
|
|
|
return op_names[expr->op];
|
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:15 -08:00
|
|
|
static void dump_ir_expr(struct vkd3d_string_buffer *buffer, const struct hlsl_ir_expr *expr)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
vkd3d_string_buffer_printf(buffer, "%s (", debug_expr_op(expr));
|
|
|
|
for (i = 0; i < 3 && expr->operands[i].node; ++i)
|
|
|
|
{
|
2021-02-02 14:11:15 -08:00
|
|
|
dump_src(buffer, &expr->operands[i]);
|
2021-01-27 08:29:44 -08:00
|
|
|
vkd3d_string_buffer_printf(buffer, " ");
|
|
|
|
}
|
|
|
|
vkd3d_string_buffer_printf(buffer, ")");
|
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:15 -08:00
|
|
|
static void dump_ir_if(struct vkd3d_string_buffer *buffer, const struct hlsl_ir_if *if_node)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
vkd3d_string_buffer_printf(buffer, "if (");
|
2021-02-02 14:11:15 -08:00
|
|
|
dump_src(buffer, &if_node->condition);
|
2021-01-27 08:29:44 -08:00
|
|
|
vkd3d_string_buffer_printf(buffer, ")\n{\n");
|
2021-02-02 14:11:15 -08:00
|
|
|
dump_instr_list(buffer, &if_node->then_instrs);
|
2021-01-27 08:29:44 -08:00
|
|
|
vkd3d_string_buffer_printf(buffer, "}\nelse\n{\n");
|
2021-02-02 14:11:15 -08:00
|
|
|
dump_instr_list(buffer, &if_node->else_instrs);
|
2021-01-27 08:29:44 -08:00
|
|
|
vkd3d_string_buffer_printf(buffer, "}\n");
|
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:15 -08:00
|
|
|
static void dump_ir_jump(struct vkd3d_string_buffer *buffer, const struct hlsl_ir_jump *jump)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
switch (jump->type)
|
|
|
|
{
|
|
|
|
case HLSL_IR_JUMP_BREAK:
|
|
|
|
vkd3d_string_buffer_printf(buffer, "break");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case HLSL_IR_JUMP_CONTINUE:
|
|
|
|
vkd3d_string_buffer_printf(buffer, "continue");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case HLSL_IR_JUMP_DISCARD:
|
|
|
|
vkd3d_string_buffer_printf(buffer, "discard");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case HLSL_IR_JUMP_RETURN:
|
|
|
|
vkd3d_string_buffer_printf(buffer, "return");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:15 -08:00
|
|
|
static void dump_ir_loop(struct vkd3d_string_buffer *buffer, const struct hlsl_ir_loop *loop)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
vkd3d_string_buffer_printf(buffer, "for (;;)\n{\n");
|
2021-02-02 14:11:15 -08:00
|
|
|
dump_instr_list(buffer, &loop->body);
|
2021-01-27 08:29:44 -08:00
|
|
|
vkd3d_string_buffer_printf(buffer, "}\n");
|
|
|
|
}
|
|
|
|
|
2021-04-08 21:38:22 -07:00
|
|
|
static void dump_ir_store(struct vkd3d_string_buffer *buffer, const struct hlsl_ir_store *store)
|
|
|
|
{
|
|
|
|
vkd3d_string_buffer_printf(buffer, "= (");
|
|
|
|
dump_deref(buffer, &store->lhs);
|
|
|
|
if (store->writemask != VKD3DSP_WRITEMASK_ALL)
|
2021-04-08 21:38:23 -07:00
|
|
|
vkd3d_string_buffer_printf(buffer, "%s", debug_hlsl_writemask(store->writemask));
|
2021-04-08 21:38:22 -07:00
|
|
|
vkd3d_string_buffer_printf(buffer, " ");
|
|
|
|
dump_src(buffer, &store->rhs);
|
|
|
|
vkd3d_string_buffer_printf(buffer, ")");
|
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:15 -08:00
|
|
|
static void dump_ir_swizzle(struct vkd3d_string_buffer *buffer, const struct hlsl_ir_swizzle *swizzle)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
2021-02-02 14:11:15 -08:00
|
|
|
dump_src(buffer, &swizzle->val);
|
2021-01-27 08:29:44 -08:00
|
|
|
vkd3d_string_buffer_printf(buffer, ".");
|
|
|
|
if (swizzle->val.node->data_type->dimy > 1)
|
|
|
|
{
|
|
|
|
for (i = 0; i < swizzle->node.data_type->dimx; ++i)
|
|
|
|
vkd3d_string_buffer_printf(buffer, "_m%u%u", (swizzle->swizzle >> i * 8) & 0xf, (swizzle->swizzle >> (i * 8 + 4)) & 0xf);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
static const char c[] = {'x', 'y', 'z', 'w'};
|
|
|
|
|
|
|
|
for (i = 0; i < swizzle->node.data_type->dimx; ++i)
|
|
|
|
vkd3d_string_buffer_printf(buffer, "%c", c[(swizzle->swizzle >> i * 2) & 0x3]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:15 -08:00
|
|
|
static void dump_instr(struct vkd3d_string_buffer *buffer, const struct hlsl_ir_node *instr)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
if (instr->index)
|
|
|
|
vkd3d_string_buffer_printf(buffer, "%4u: ", instr->index);
|
|
|
|
else
|
|
|
|
vkd3d_string_buffer_printf(buffer, "%p: ", instr);
|
|
|
|
|
|
|
|
vkd3d_string_buffer_printf(buffer, "%10s | ", instr->data_type ? debug_hlsl_type(instr->data_type) : "");
|
|
|
|
|
|
|
|
switch (instr->type)
|
|
|
|
{
|
|
|
|
case HLSL_IR_CONSTANT:
|
2021-02-02 14:11:15 -08:00
|
|
|
dump_ir_constant(buffer, hlsl_ir_constant(instr));
|
2021-01-27 08:29:44 -08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case HLSL_IR_EXPR:
|
2021-02-02 14:11:15 -08:00
|
|
|
dump_ir_expr(buffer, hlsl_ir_expr(instr));
|
2021-01-27 08:29:44 -08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case HLSL_IR_IF:
|
2021-02-02 14:11:15 -08:00
|
|
|
dump_ir_if(buffer, hlsl_ir_if(instr));
|
2021-01-27 08:29:44 -08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case HLSL_IR_JUMP:
|
2021-02-02 14:11:15 -08:00
|
|
|
dump_ir_jump(buffer, hlsl_ir_jump(instr));
|
2021-01-27 08:29:44 -08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case HLSL_IR_LOAD:
|
2021-02-02 14:11:15 -08:00
|
|
|
dump_deref(buffer, &hlsl_ir_load(instr)->src);
|
2021-01-27 08:29:44 -08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case HLSL_IR_LOOP:
|
2021-02-02 14:11:15 -08:00
|
|
|
dump_ir_loop(buffer, hlsl_ir_loop(instr));
|
2021-01-27 08:29:44 -08:00
|
|
|
break;
|
|
|
|
|
2021-04-08 21:38:22 -07:00
|
|
|
case HLSL_IR_STORE:
|
|
|
|
dump_ir_store(buffer, hlsl_ir_store(instr));
|
|
|
|
break;
|
|
|
|
|
2021-01-27 08:29:44 -08:00
|
|
|
case HLSL_IR_SWIZZLE:
|
2021-02-02 14:11:15 -08:00
|
|
|
dump_ir_swizzle(buffer, hlsl_ir_swizzle(instr));
|
2021-01-27 08:29:44 -08:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2021-02-02 14:11:14 -08:00
|
|
|
vkd3d_string_buffer_printf(buffer, "<No dump function for %s>", hlsl_node_type_to_string(instr->type));
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:14 -08:00
|
|
|
void hlsl_dump_function(const struct hlsl_ir_function_decl *func)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
struct vkd3d_string_buffer buffer;
|
|
|
|
struct hlsl_ir_var *param;
|
|
|
|
|
|
|
|
vkd3d_string_buffer_init(&buffer);
|
|
|
|
vkd3d_string_buffer_printf(&buffer, "Dumping function %s.\n", func->func->name);
|
|
|
|
vkd3d_string_buffer_printf(&buffer, "Function parameters:\n");
|
|
|
|
LIST_FOR_EACH_ENTRY(param, func->parameters, struct hlsl_ir_var, param_entry)
|
|
|
|
{
|
2021-02-02 14:11:15 -08:00
|
|
|
dump_ir_var(&buffer, param);
|
2021-01-27 08:29:44 -08:00
|
|
|
vkd3d_string_buffer_printf(&buffer, "\n");
|
|
|
|
}
|
|
|
|
if (func->body)
|
2021-02-02 14:11:15 -08:00
|
|
|
dump_instr_list(&buffer, func->body);
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
vkd3d_string_buffer_trace(&buffer);
|
|
|
|
vkd3d_string_buffer_cleanup(&buffer);
|
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:14 -08:00
|
|
|
void hlsl_free_type(struct hlsl_type *type)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
struct hlsl_struct_field *field, *next_field;
|
|
|
|
|
|
|
|
vkd3d_free((void *)type->name);
|
|
|
|
if (type->type == HLSL_CLASS_STRUCT)
|
|
|
|
{
|
|
|
|
LIST_FOR_EACH_ENTRY_SAFE(field, next_field, type->e.elements, struct hlsl_struct_field, entry)
|
|
|
|
{
|
|
|
|
vkd3d_free((void *)field->name);
|
|
|
|
vkd3d_free((void *)field->semantic);
|
|
|
|
vkd3d_free(field);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
vkd3d_free(type);
|
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:14 -08:00
|
|
|
void hlsl_free_instr_list(struct list *list)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
struct hlsl_ir_node *node, *next_node;
|
|
|
|
|
|
|
|
if (!list)
|
|
|
|
return;
|
|
|
|
/* Iterate in reverse, to avoid use-after-free when unlinking sources from
|
|
|
|
* the "uses" list. */
|
|
|
|
LIST_FOR_EACH_ENTRY_SAFE_REV(node, next_node, list, struct hlsl_ir_node, entry)
|
2021-02-02 14:11:14 -08:00
|
|
|
hlsl_free_instr(node);
|
2021-01-27 08:29:44 -08:00
|
|
|
vkd3d_free(list);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void free_ir_constant(struct hlsl_ir_constant *constant)
|
|
|
|
{
|
|
|
|
vkd3d_free(constant);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void free_ir_expr(struct hlsl_ir_expr *expr)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(expr->operands); ++i)
|
|
|
|
hlsl_src_remove(&expr->operands[i]);
|
|
|
|
vkd3d_free(expr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void free_ir_if(struct hlsl_ir_if *if_node)
|
|
|
|
{
|
|
|
|
struct hlsl_ir_node *node, *next_node;
|
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY_SAFE(node, next_node, &if_node->then_instrs, struct hlsl_ir_node, entry)
|
2021-02-02 14:11:14 -08:00
|
|
|
hlsl_free_instr(node);
|
2021-01-27 08:29:44 -08:00
|
|
|
LIST_FOR_EACH_ENTRY_SAFE(node, next_node, &if_node->else_instrs, struct hlsl_ir_node, entry)
|
2021-02-02 14:11:14 -08:00
|
|
|
hlsl_free_instr(node);
|
2021-01-27 08:29:44 -08:00
|
|
|
hlsl_src_remove(&if_node->condition);
|
|
|
|
vkd3d_free(if_node);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void free_ir_jump(struct hlsl_ir_jump *jump)
|
|
|
|
{
|
|
|
|
vkd3d_free(jump);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void free_ir_load(struct hlsl_ir_load *load)
|
|
|
|
{
|
|
|
|
hlsl_src_remove(&load->src.offset);
|
|
|
|
vkd3d_free(load);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void free_ir_loop(struct hlsl_ir_loop *loop)
|
|
|
|
{
|
|
|
|
struct hlsl_ir_node *node, *next_node;
|
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY_SAFE(node, next_node, &loop->body, struct hlsl_ir_node, entry)
|
2021-02-02 14:11:14 -08:00
|
|
|
hlsl_free_instr(node);
|
2021-01-27 08:29:44 -08:00
|
|
|
vkd3d_free(loop);
|
|
|
|
}
|
|
|
|
|
2021-04-08 21:38:22 -07:00
|
|
|
static void free_ir_store(struct hlsl_ir_store *store)
|
|
|
|
{
|
|
|
|
hlsl_src_remove(&store->rhs);
|
|
|
|
hlsl_src_remove(&store->lhs.offset);
|
|
|
|
vkd3d_free(store);
|
|
|
|
}
|
|
|
|
|
2021-01-27 08:29:44 -08:00
|
|
|
static void free_ir_swizzle(struct hlsl_ir_swizzle *swizzle)
|
|
|
|
{
|
|
|
|
hlsl_src_remove(&swizzle->val);
|
|
|
|
vkd3d_free(swizzle);
|
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:14 -08:00
|
|
|
void hlsl_free_instr(struct hlsl_ir_node *node)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
switch (node->type)
|
|
|
|
{
|
|
|
|
case HLSL_IR_CONSTANT:
|
2021-02-02 14:11:14 -08:00
|
|
|
free_ir_constant(hlsl_ir_constant(node));
|
2021-01-27 08:29:44 -08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case HLSL_IR_EXPR:
|
2021-02-02 14:11:14 -08:00
|
|
|
free_ir_expr(hlsl_ir_expr(node));
|
2021-01-27 08:29:44 -08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case HLSL_IR_IF:
|
2021-02-02 14:11:14 -08:00
|
|
|
free_ir_if(hlsl_ir_if(node));
|
2021-01-27 08:29:44 -08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case HLSL_IR_JUMP:
|
2021-02-02 14:11:14 -08:00
|
|
|
free_ir_jump(hlsl_ir_jump(node));
|
2021-01-27 08:29:44 -08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case HLSL_IR_LOAD:
|
2021-02-02 14:11:14 -08:00
|
|
|
free_ir_load(hlsl_ir_load(node));
|
2021-01-27 08:29:44 -08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case HLSL_IR_LOOP:
|
2021-02-02 14:11:14 -08:00
|
|
|
free_ir_loop(hlsl_ir_loop(node));
|
2021-01-27 08:29:44 -08:00
|
|
|
break;
|
|
|
|
|
2021-04-08 21:38:22 -07:00
|
|
|
case HLSL_IR_STORE:
|
|
|
|
free_ir_store(hlsl_ir_store(node));
|
|
|
|
break;
|
|
|
|
|
2021-01-27 08:29:44 -08:00
|
|
|
case HLSL_IR_SWIZZLE:
|
2021-02-02 14:11:14 -08:00
|
|
|
free_ir_swizzle(hlsl_ir_swizzle(node));
|
2021-01-27 08:29:44 -08:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2021-02-02 14:11:14 -08:00
|
|
|
FIXME("Unsupported node type %s.\n", hlsl_node_type_to_string(node->type));
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void free_function_decl(struct hlsl_ir_function_decl *decl)
|
|
|
|
{
|
|
|
|
vkd3d_free(decl->parameters);
|
2021-02-02 14:11:14 -08:00
|
|
|
hlsl_free_instr_list(decl->body);
|
2021-01-27 08:29:44 -08:00
|
|
|
vkd3d_free(decl);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void free_function_decl_rb(struct rb_entry *entry, void *context)
|
|
|
|
{
|
|
|
|
free_function_decl(RB_ENTRY_VALUE(entry, struct hlsl_ir_function_decl, entry));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void free_function(struct hlsl_ir_function *func)
|
|
|
|
{
|
|
|
|
rb_destroy(&func->overloads, free_function_decl_rb, NULL);
|
|
|
|
vkd3d_free((void *)func->name);
|
|
|
|
vkd3d_free(func);
|
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:50 -08:00
|
|
|
static void free_function_rb(struct rb_entry *entry, void *context)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
free_function(RB_ENTRY_VALUE(entry, struct hlsl_ir_function, entry));
|
|
|
|
}
|
|
|
|
|
2021-02-02 14:11:17 -08:00
|
|
|
void hlsl_add_function(struct rb_tree *funcs, char *name, struct hlsl_ir_function_decl *decl, bool intrinsic)
|
2021-01-27 08:29:44 -08:00
|
|
|
{
|
|
|
|
struct hlsl_ir_function *func;
|
|
|
|
struct rb_entry *func_entry, *old_entry;
|
|
|
|
|
|
|
|
func_entry = rb_get(funcs, name);
|
|
|
|
if (func_entry)
|
|
|
|
{
|
|
|
|
func = RB_ENTRY_VALUE(func_entry, struct hlsl_ir_function, entry);
|
|
|
|
if (intrinsic != func->intrinsic)
|
|
|
|
{
|
|
|
|
if (intrinsic)
|
|
|
|
{
|
|
|
|
ERR("Redeclaring a user defined function as an intrinsic.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
func->intrinsic = intrinsic;
|
|
|
|
rb_destroy(&func->overloads, free_function_decl_rb, NULL);
|
|
|
|
rb_init(&func->overloads, compare_function_decl_rb);
|
|
|
|
}
|
|
|
|
decl->func = func;
|
|
|
|
if ((old_entry = rb_get(&func->overloads, decl->parameters)))
|
|
|
|
{
|
|
|
|
struct hlsl_ir_function_decl *old_decl =
|
|
|
|
RB_ENTRY_VALUE(old_entry, struct hlsl_ir_function_decl, entry);
|
|
|
|
|
|
|
|
if (!decl->body)
|
|
|
|
{
|
|
|
|
free_function_decl(decl);
|
|
|
|
vkd3d_free(name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
rb_remove(&func->overloads, old_entry);
|
|
|
|
free_function_decl(old_decl);
|
|
|
|
}
|
|
|
|
rb_put(&func->overloads, decl->parameters, &decl->entry);
|
|
|
|
vkd3d_free(name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
func = vkd3d_malloc(sizeof(*func));
|
|
|
|
func->name = name;
|
|
|
|
rb_init(&func->overloads, compare_function_decl_rb);
|
|
|
|
decl->func = func;
|
|
|
|
rb_put(&func->overloads, decl->parameters, &decl->entry);
|
|
|
|
func->intrinsic = intrinsic;
|
|
|
|
rb_put(funcs, func->name, &func->entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct hlsl_profile_info *get_target_info(const char *target)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
static const struct hlsl_profile_info profiles[] =
|
|
|
|
{
|
2021-02-02 14:11:17 -08:00
|
|
|
{"cs_4_0", VKD3D_SHADER_TYPE_COMPUTE, 4, 0, 0, 0, false},
|
|
|
|
{"cs_4_1", VKD3D_SHADER_TYPE_COMPUTE, 4, 1, 0, 0, false},
|
|
|
|
{"cs_5_0", VKD3D_SHADER_TYPE_COMPUTE, 5, 0, 0, 0, false},
|
|
|
|
{"ds_5_0", VKD3D_SHADER_TYPE_DOMAIN, 5, 0, 0, 0, false},
|
|
|
|
{"fx_2_0", VKD3D_SHADER_TYPE_EFFECT, 2, 0, 0, 0, false},
|
|
|
|
{"fx_4_0", VKD3D_SHADER_TYPE_EFFECT, 4, 0, 0, 0, false},
|
|
|
|
{"fx_4_1", VKD3D_SHADER_TYPE_EFFECT, 4, 1, 0, 0, false},
|
|
|
|
{"fx_5_0", VKD3D_SHADER_TYPE_EFFECT, 5, 0, 0, 0, false},
|
|
|
|
{"gs_4_0", VKD3D_SHADER_TYPE_GEOMETRY, 4, 0, 0, 0, false},
|
|
|
|
{"gs_4_1", VKD3D_SHADER_TYPE_GEOMETRY, 4, 1, 0, 0, false},
|
|
|
|
{"gs_5_0", VKD3D_SHADER_TYPE_GEOMETRY, 5, 0, 0, 0, false},
|
|
|
|
{"hs_5_0", VKD3D_SHADER_TYPE_HULL, 5, 0, 0, 0, false},
|
|
|
|
{"ps.1.0", VKD3D_SHADER_TYPE_PIXEL, 1, 0, 0, 0, false},
|
|
|
|
{"ps.1.1", VKD3D_SHADER_TYPE_PIXEL, 1, 1, 0, 0, false},
|
|
|
|
{"ps.1.2", VKD3D_SHADER_TYPE_PIXEL, 1, 2, 0, 0, false},
|
|
|
|
{"ps.1.3", VKD3D_SHADER_TYPE_PIXEL, 1, 3, 0, 0, false},
|
|
|
|
{"ps.1.4", VKD3D_SHADER_TYPE_PIXEL, 1, 4, 0, 0, false},
|
|
|
|
{"ps.2.0", VKD3D_SHADER_TYPE_PIXEL, 2, 0, 0, 0, false},
|
|
|
|
{"ps.2.a", VKD3D_SHADER_TYPE_PIXEL, 2, 1, 0, 0, false},
|
|
|
|
{"ps.2.b", VKD3D_SHADER_TYPE_PIXEL, 2, 2, 0, 0, false},
|
|
|
|
{"ps.2.sw", VKD3D_SHADER_TYPE_PIXEL, 2, 0, 0, 0, true},
|
|
|
|
{"ps.3.0", VKD3D_SHADER_TYPE_PIXEL, 3, 0, 0, 0, false},
|
|
|
|
{"ps_1_0", VKD3D_SHADER_TYPE_PIXEL, 1, 0, 0, 0, false},
|
|
|
|
{"ps_1_1", VKD3D_SHADER_TYPE_PIXEL, 1, 1, 0, 0, false},
|
|
|
|
{"ps_1_2", VKD3D_SHADER_TYPE_PIXEL, 1, 2, 0, 0, false},
|
|
|
|
{"ps_1_3", VKD3D_SHADER_TYPE_PIXEL, 1, 3, 0, 0, false},
|
|
|
|
{"ps_1_4", VKD3D_SHADER_TYPE_PIXEL, 1, 4, 0, 0, false},
|
|
|
|
{"ps_2_0", VKD3D_SHADER_TYPE_PIXEL, 2, 0, 0, 0, false},
|
|
|
|
{"ps_2_a", VKD3D_SHADER_TYPE_PIXEL, 2, 1, 0, 0, false},
|
|
|
|
{"ps_2_b", VKD3D_SHADER_TYPE_PIXEL, 2, 2, 0, 0, false},
|
|
|
|
{"ps_2_sw", VKD3D_SHADER_TYPE_PIXEL, 2, 0, 0, 0, true},
|
|
|
|
{"ps_3_0", VKD3D_SHADER_TYPE_PIXEL, 3, 0, 0, 0, false},
|
|
|
|
{"ps_3_sw", VKD3D_SHADER_TYPE_PIXEL, 3, 0, 0, 0, true},
|
|
|
|
{"ps_4_0", VKD3D_SHADER_TYPE_PIXEL, 4, 0, 0, 0, false},
|
|
|
|
{"ps_4_0_level_9_0", VKD3D_SHADER_TYPE_PIXEL, 4, 0, 9, 0, false},
|
|
|
|
{"ps_4_0_level_9_1", VKD3D_SHADER_TYPE_PIXEL, 4, 0, 9, 1, false},
|
|
|
|
{"ps_4_0_level_9_3", VKD3D_SHADER_TYPE_PIXEL, 4, 0, 9, 3, false},
|
|
|
|
{"ps_4_1", VKD3D_SHADER_TYPE_PIXEL, 4, 1, 0, 0, false},
|
|
|
|
{"ps_5_0", VKD3D_SHADER_TYPE_PIXEL, 5, 0, 0, 0, false},
|
|
|
|
{"tx_1_0", VKD3D_SHADER_TYPE_TEXTURE, 1, 0, 0, 0, false},
|
|
|
|
{"vs.1.0", VKD3D_SHADER_TYPE_VERTEX, 1, 0, 0, 0, false},
|
|
|
|
{"vs.1.1", VKD3D_SHADER_TYPE_VERTEX, 1, 1, 0, 0, false},
|
|
|
|
{"vs.2.0", VKD3D_SHADER_TYPE_VERTEX, 2, 0, 0, 0, false},
|
|
|
|
{"vs.2.a", VKD3D_SHADER_TYPE_VERTEX, 2, 1, 0, 0, false},
|
|
|
|
{"vs.2.sw", VKD3D_SHADER_TYPE_VERTEX, 2, 0, 0, 0, true},
|
|
|
|
{"vs.3.0", VKD3D_SHADER_TYPE_VERTEX, 3, 0, 0, 0, false},
|
|
|
|
{"vs.3.sw", VKD3D_SHADER_TYPE_VERTEX, 3, 0, 0, 0, true},
|
|
|
|
{"vs_1_0", VKD3D_SHADER_TYPE_VERTEX, 1, 0, 0, 0, false},
|
|
|
|
{"vs_1_1", VKD3D_SHADER_TYPE_VERTEX, 1, 1, 0, 0, false},
|
|
|
|
{"vs_2_0", VKD3D_SHADER_TYPE_VERTEX, 2, 0, 0, 0, false},
|
|
|
|
{"vs_2_a", VKD3D_SHADER_TYPE_VERTEX, 2, 1, 0, 0, false},
|
|
|
|
{"vs_2_sw", VKD3D_SHADER_TYPE_VERTEX, 2, 0, 0, 0, true},
|
|
|
|
{"vs_3_0", VKD3D_SHADER_TYPE_VERTEX, 3, 0, 0, 0, false},
|
|
|
|
{"vs_3_sw", VKD3D_SHADER_TYPE_VERTEX, 3, 0, 0, 0, true},
|
|
|
|
{"vs_4_0", VKD3D_SHADER_TYPE_VERTEX, 4, 0, 0, 0, false},
|
|
|
|
{"vs_4_0_level_9_0", VKD3D_SHADER_TYPE_VERTEX, 4, 0, 9, 0, false},
|
|
|
|
{"vs_4_0_level_9_1", VKD3D_SHADER_TYPE_VERTEX, 4, 0, 9, 1, false},
|
|
|
|
{"vs_4_0_level_9_3", VKD3D_SHADER_TYPE_VERTEX, 4, 0, 9, 3, false},
|
|
|
|
{"vs_4_1", VKD3D_SHADER_TYPE_VERTEX, 4, 1, 0, 0, false},
|
|
|
|
{"vs_5_0", VKD3D_SHADER_TYPE_VERTEX, 5, 0, 0, 0, false},
|
2021-01-27 08:29:44 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(profiles); ++i)
|
|
|
|
{
|
|
|
|
if (!strcmp(target, profiles[i].name))
|
|
|
|
return &profiles[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:50 -08:00
|
|
|
static int compare_function_rb(const void *key, const struct rb_entry *entry)
|
|
|
|
{
|
|
|
|
const char *name = key;
|
|
|
|
const struct hlsl_ir_function *func = RB_ENTRY_VALUE(entry, const struct hlsl_ir_function,entry);
|
|
|
|
|
|
|
|
return strcmp(name, func->name);
|
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
static void declare_predefined_types(struct hlsl_ctx *ctx)
|
2021-02-04 14:33:50 -08:00
|
|
|
{
|
2021-02-04 14:33:51 -08:00
|
|
|
unsigned int x, y, bt, i;
|
2021-02-04 14:33:50 -08:00
|
|
|
struct hlsl_type *type;
|
2021-02-04 14:33:51 -08:00
|
|
|
|
2021-02-04 14:33:50 -08:00
|
|
|
static const char * const names[] =
|
|
|
|
{
|
|
|
|
"float",
|
|
|
|
"half",
|
|
|
|
"double",
|
|
|
|
"int",
|
|
|
|
"uint",
|
|
|
|
"bool",
|
|
|
|
};
|
|
|
|
char name[10];
|
|
|
|
|
|
|
|
static const char *const sampler_names[] =
|
|
|
|
{
|
|
|
|
"sampler",
|
|
|
|
"sampler1D",
|
|
|
|
"sampler2D",
|
|
|
|
"sampler3D",
|
|
|
|
"samplerCUBE"
|
|
|
|
};
|
|
|
|
|
2021-02-04 14:33:51 -08:00
|
|
|
static const struct
|
|
|
|
{
|
|
|
|
char name[13];
|
|
|
|
enum hlsl_type_class class;
|
|
|
|
enum hlsl_base_type base_type;
|
|
|
|
unsigned int dimx, dimy;
|
|
|
|
}
|
|
|
|
effect_types[] =
|
|
|
|
{
|
|
|
|
{"DWORD", HLSL_CLASS_SCALAR, HLSL_TYPE_INT, 1, 1},
|
|
|
|
{"FLOAT", HLSL_CLASS_SCALAR, HLSL_TYPE_FLOAT, 1, 1},
|
|
|
|
{"VECTOR", HLSL_CLASS_VECTOR, HLSL_TYPE_FLOAT, 4, 1},
|
|
|
|
{"MATRIX", HLSL_CLASS_MATRIX, HLSL_TYPE_FLOAT, 4, 4},
|
|
|
|
{"STRING", HLSL_CLASS_OBJECT, HLSL_TYPE_STRING, 1, 1},
|
|
|
|
{"TEXTURE", HLSL_CLASS_OBJECT, HLSL_TYPE_TEXTURE, 1, 1},
|
|
|
|
{"PIXELSHADER", HLSL_CLASS_OBJECT, HLSL_TYPE_PIXELSHADER, 1, 1},
|
|
|
|
{"VERTEXSHADER", HLSL_CLASS_OBJECT, HLSL_TYPE_VERTEXSHADER, 1, 1},
|
|
|
|
};
|
|
|
|
|
2021-02-04 14:33:50 -08:00
|
|
|
for (bt = 0; bt <= HLSL_TYPE_LAST_SCALAR; ++bt)
|
|
|
|
{
|
|
|
|
for (y = 1; y <= 4; ++y)
|
|
|
|
{
|
|
|
|
for (x = 1; x <= 4; ++x)
|
|
|
|
{
|
|
|
|
sprintf(name, "%s%ux%u", names[bt], y, x);
|
2021-02-04 14:33:53 -08:00
|
|
|
type = hlsl_new_type(ctx, vkd3d_strdup(name), HLSL_CLASS_MATRIX, bt, x, y);
|
|
|
|
hlsl_scope_add_type(ctx->globals, type);
|
2021-02-04 14:33:50 -08:00
|
|
|
|
|
|
|
if (y == 1)
|
|
|
|
{
|
|
|
|
sprintf(name, "%s%u", names[bt], x);
|
2021-02-04 14:33:53 -08:00
|
|
|
type = hlsl_new_type(ctx, vkd3d_strdup(name), HLSL_CLASS_VECTOR, bt, x, y);
|
|
|
|
hlsl_scope_add_type(ctx->globals, type);
|
|
|
|
ctx->builtin_types.vector[bt][x - 1] = type;
|
2021-02-04 14:33:50 -08:00
|
|
|
|
|
|
|
if (x == 1)
|
|
|
|
{
|
|
|
|
sprintf(name, "%s", names[bt]);
|
2021-02-04 14:33:53 -08:00
|
|
|
type = hlsl_new_type(ctx, vkd3d_strdup(name), HLSL_CLASS_SCALAR, bt, x, y);
|
|
|
|
hlsl_scope_add_type(ctx->globals, type);
|
|
|
|
ctx->builtin_types.scalar[bt] = type;
|
2021-02-04 14:33:50 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (bt = 0; bt <= HLSL_SAMPLER_DIM_MAX; ++bt)
|
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
type = hlsl_new_type(ctx, vkd3d_strdup(sampler_names[bt]), HLSL_CLASS_OBJECT, HLSL_TYPE_SAMPLER, 1, 1);
|
2021-02-04 14:33:50 -08:00
|
|
|
type->sampler_dim = bt;
|
2021-02-04 14:33:53 -08:00
|
|
|
ctx->builtin_types.sampler[bt] = type;
|
2021-02-04 14:33:50 -08:00
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
ctx->builtin_types.Void = hlsl_new_type(ctx, vkd3d_strdup("void"), HLSL_CLASS_OBJECT, HLSL_TYPE_VOID, 1, 1);
|
2021-02-04 14:33:50 -08:00
|
|
|
|
2021-02-04 14:33:51 -08:00
|
|
|
for (i = 0; i < ARRAY_SIZE(effect_types); ++i)
|
|
|
|
{
|
2021-02-04 14:33:53 -08:00
|
|
|
type = hlsl_new_type(ctx, vkd3d_strdup(effect_types[i].name), effect_types[i].class,
|
2021-02-04 14:33:51 -08:00
|
|
|
effect_types[i].base_type, effect_types[i].dimx, effect_types[i].dimy);
|
2021-02-04 14:33:53 -08:00
|
|
|
hlsl_scope_add_type(ctx->globals, type);
|
2021-02-04 14:33:51 -08:00
|
|
|
}
|
2021-02-04 14:33:50 -08:00
|
|
|
}
|
|
|
|
|
2021-04-08 21:38:25 -07:00
|
|
|
static bool hlsl_ctx_init(struct hlsl_ctx *ctx, const struct hlsl_profile_info *profile,
|
|
|
|
struct vkd3d_shader_message_context *message_context)
|
2021-02-04 14:33:50 -08:00
|
|
|
{
|
|
|
|
memset(ctx, 0, sizeof(*ctx));
|
|
|
|
|
2021-04-08 21:38:25 -07:00
|
|
|
ctx->profile = profile;
|
|
|
|
|
2021-02-04 14:33:50 -08:00
|
|
|
ctx->message_context = message_context;
|
|
|
|
|
|
|
|
if (!(ctx->source_files = vkd3d_malloc(sizeof(*ctx->source_files))))
|
2021-02-12 08:48:56 -08:00
|
|
|
return false;
|
|
|
|
if (!(ctx->source_files[0] = vkd3d_strdup("")))
|
2021-02-04 14:33:50 -08:00
|
|
|
{
|
2021-02-12 08:48:56 -08:00
|
|
|
vkd3d_free(ctx->source_files);
|
2021-02-04 14:33:50 -08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
ctx->source_files_count = 1;
|
2021-02-12 08:48:56 -08:00
|
|
|
ctx->location.source_name = ctx->source_files[0];
|
|
|
|
ctx->location.line = ctx->location.column = 1;
|
2021-02-27 16:03:09 -08:00
|
|
|
vkd3d_string_buffer_cache_init(&ctx->string_buffers);
|
2021-02-04 14:33:50 -08:00
|
|
|
|
|
|
|
ctx->matrix_majority = HLSL_COLUMN_MAJOR;
|
|
|
|
|
|
|
|
list_init(&ctx->scopes);
|
|
|
|
hlsl_push_scope(ctx);
|
|
|
|
ctx->globals = ctx->cur_scope;
|
|
|
|
|
|
|
|
list_init(&ctx->types);
|
2021-02-04 14:33:53 -08:00
|
|
|
declare_predefined_types(ctx);
|
2021-02-04 14:33:50 -08:00
|
|
|
|
|
|
|
rb_init(&ctx->functions, compare_function_rb);
|
|
|
|
|
|
|
|
list_init(&ctx->static_initializers);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-02-04 14:33:53 -08:00
|
|
|
static void hlsl_ctx_cleanup(struct hlsl_ctx *ctx)
|
2021-02-04 14:33:50 -08:00
|
|
|
{
|
|
|
|
struct hlsl_scope *scope, *next_scope;
|
|
|
|
struct hlsl_ir_var *var, *next_var;
|
|
|
|
struct hlsl_type *type, *next_type;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ctx->source_files_count; ++i)
|
|
|
|
vkd3d_free((void *)ctx->source_files[i]);
|
|
|
|
vkd3d_free(ctx->source_files);
|
2021-02-27 16:03:09 -08:00
|
|
|
vkd3d_string_buffer_cache_cleanup(&ctx->string_buffers);
|
2021-02-04 14:33:50 -08:00
|
|
|
|
|
|
|
rb_destroy(&ctx->functions, free_function_rb, NULL);
|
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY_SAFE(scope, next_scope, &ctx->scopes, struct hlsl_scope, entry)
|
|
|
|
{
|
|
|
|
LIST_FOR_EACH_ENTRY_SAFE(var, next_var, &scope->vars, struct hlsl_ir_var, scope_entry)
|
|
|
|
hlsl_free_var(var);
|
|
|
|
rb_destroy(&scope->types, NULL, NULL);
|
|
|
|
vkd3d_free(scope);
|
|
|
|
}
|
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY_SAFE(type, next_type, &ctx->types, struct hlsl_type, entry)
|
|
|
|
hlsl_free_type(type);
|
|
|
|
}
|
|
|
|
|
2021-03-04 15:33:28 -08:00
|
|
|
int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d_shader_compile_info *compile_info,
|
2021-01-27 08:29:44 -08:00
|
|
|
struct vkd3d_shader_code *dxbc, struct vkd3d_shader_message_context *message_context)
|
|
|
|
{
|
|
|
|
const struct vkd3d_shader_hlsl_source_info *hlsl_source_info;
|
2021-03-04 15:33:24 -08:00
|
|
|
struct hlsl_ir_function_decl *entry_func;
|
2021-01-27 08:29:44 -08:00
|
|
|
const struct hlsl_profile_info *profile;
|
2021-03-04 15:33:24 -08:00
|
|
|
const char *entry_point;
|
2021-03-28 12:46:56 -07:00
|
|
|
struct hlsl_ir_var *var;
|
2021-02-04 14:33:53 -08:00
|
|
|
struct hlsl_ctx ctx;
|
2021-02-04 14:33:50 -08:00
|
|
|
int ret;
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
if (!(hlsl_source_info = vkd3d_find_struct(compile_info->next, HLSL_SOURCE_INFO)))
|
|
|
|
{
|
|
|
|
ERR("No HLSL source info given.\n");
|
|
|
|
return VKD3D_ERROR_INVALID_ARGUMENT;
|
|
|
|
}
|
2021-03-04 15:33:24 -08:00
|
|
|
entry_point = hlsl_source_info->entry_point ? hlsl_source_info->entry_point : "main";
|
2021-01-27 08:29:44 -08:00
|
|
|
|
|
|
|
if (!(profile = get_target_info(hlsl_source_info->profile)))
|
|
|
|
{
|
|
|
|
FIXME("Unknown compilation target %s.\n", debugstr_a(hlsl_source_info->profile));
|
|
|
|
return VKD3D_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
vkd3d_shader_dump_shader(profile->type, &compile_info->source);
|
|
|
|
|
2021-04-08 21:38:25 -07:00
|
|
|
if (!hlsl_ctx_init(&ctx, profile, message_context))
|
2021-02-04 14:33:50 -08:00
|
|
|
return VKD3D_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
2021-03-04 15:33:28 -08:00
|
|
|
if (hlsl_lexer_compile(&ctx, hlsl) == 2)
|
2021-03-04 15:33:25 -08:00
|
|
|
{
|
|
|
|
hlsl_ctx_cleanup(&ctx);
|
|
|
|
return VKD3D_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
2021-02-04 14:33:50 -08:00
|
|
|
|
2021-03-04 15:33:24 -08:00
|
|
|
if (ctx.failed)
|
|
|
|
{
|
|
|
|
hlsl_ctx_cleanup(&ctx);
|
|
|
|
return VKD3D_ERROR_INVALID_SHADER;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(entry_func = hlsl_get_func_decl(&ctx, entry_point)))
|
|
|
|
{
|
|
|
|
const struct vkd3d_shader_location loc = {.source_name = compile_info->source_name};
|
2021-02-04 14:33:50 -08:00
|
|
|
|
2021-03-04 15:33:24 -08:00
|
|
|
hlsl_error(&ctx, loc, VKD3D_SHADER_ERROR_HLSL_NOT_DEFINED,
|
|
|
|
"Entry point \"%s\" is not defined.", entry_point);
|
|
|
|
return VKD3D_ERROR_INVALID_SHADER;
|
|
|
|
}
|
|
|
|
|
2021-03-28 12:46:56 -07:00
|
|
|
LIST_FOR_EACH_ENTRY(var, entry_func->parameters, struct hlsl_ir_var, param_entry)
|
|
|
|
{
|
|
|
|
if (var->data_type->type != HLSL_CLASS_STRUCT && !var->semantic
|
|
|
|
&& (var->is_input_varying || var->is_output_varying))
|
|
|
|
hlsl_error(&ctx, var->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_SEMANTIC,
|
|
|
|
"Parameter \"%s\" is missing a semantic.", var->name);
|
|
|
|
}
|
|
|
|
|
2021-03-04 15:33:24 -08:00
|
|
|
if (!hlsl_type_is_void(entry_func->return_type)
|
2021-03-28 12:46:58 -07:00
|
|
|
&& entry_func->return_type->type != HLSL_CLASS_STRUCT && !entry_func->return_var->semantic)
|
2021-03-04 15:33:24 -08:00
|
|
|
hlsl_error(&ctx, entry_func->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_SEMANTIC,
|
|
|
|
"Entry point \"%s\" is missing a return value semantic.", entry_point);
|
|
|
|
|
|
|
|
ret = hlsl_emit_dxbc(&ctx, entry_func);
|
|
|
|
|
|
|
|
hlsl_ctx_cleanup(&ctx);
|
2021-02-04 14:33:50 -08:00
|
|
|
return ret;
|
2021-01-27 08:29:44 -08:00
|
|
|
}
|