Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- v2: Rebase.
libs/vkd3d-shader/hlsl.c | 27 ++++++++------- libs/vkd3d-shader/hlsl.h | 15 ++++++--- libs/vkd3d-shader/hlsl.y | 34 +++++++++++-------- libs/vkd3d-shader/hlsl_codegen.c | 56 +++++++++++++++++++++----------- 4 files changed, 85 insertions(+), 47 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 5804c8e5..e81efa2d 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -93,7 +93,7 @@ struct hlsl_ir_var *hlsl_get_var(struct hlsl_scope *scope, const char *name) void hlsl_free_var(struct hlsl_ir_var *decl) { vkd3d_free((void *)decl->name); - vkd3d_free((void *)decl->semantic); + vkd3d_free((void *)decl->semantic.name); vkd3d_free((void *)decl->reg_reservation); vkd3d_free(decl); } @@ -326,7 +326,7 @@ struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old, u { 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->semantic.name); vkd3d_free((void *)field->name); vkd3d_free(field); } @@ -338,8 +338,11 @@ struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old, u field->loc = old_field->loc; field->type = hlsl_type_clone(ctx, old_field->type, default_majority); field->name = vkd3d_strdup(old_field->name); - if (old_field->semantic) - field->semantic = vkd3d_strdup(old_field->semantic); + if (old_field->semantic.name) + { + field->semantic.name = vkd3d_strdup(old_field->semantic.name); + field->semantic.index = old_field->semantic.index; + } field->reg_offset = reg_size; reg_size += field->type->reg_size; list_add_tail(type->e.elements, &field->entry); @@ -387,8 +390,9 @@ struct hlsl_ir_expr *hlsl_new_copy(struct hlsl_ir_node *node) return hlsl_new_cast(node, node->data_type, &node->loc); }
-struct hlsl_ir_var *hlsl_new_var(const char *name, struct hlsl_type *type, const struct vkd3d_shader_location loc, - const char *semantic, unsigned int modifiers, const struct hlsl_reg_reservation *reg_reservation) +struct hlsl_ir_var *hlsl_new_var(const char *name, struct hlsl_type *type, + const struct vkd3d_shader_location loc, const struct hlsl_semantic *semantic, unsigned int modifiers, + const struct hlsl_reg_reservation *reg_reservation) { struct hlsl_ir_var *var;
@@ -398,7 +402,8 @@ struct hlsl_ir_var *hlsl_new_var(const char *name, struct hlsl_type *type, const var->name = name; var->data_type = type; var->loc = loc; - var->semantic = semantic; + if (semantic) + var->semantic = *semantic; var->modifiers = modifiers; var->reg_reservation = reg_reservation; return var; @@ -556,7 +561,7 @@ bool hlsl_type_is_void(const struct hlsl_type *type) }
struct hlsl_ir_function_decl *hlsl_new_func_decl(struct hlsl_ctx *ctx, struct hlsl_type *return_type, - struct list *parameters, const char *semantic, struct vkd3d_shader_location loc) + struct list *parameters, const struct hlsl_semantic *semantic, struct vkd3d_shader_location loc) { struct hlsl_ir_function_decl *decl;
@@ -881,8 +886,8 @@ static void dump_ir_var(struct vkd3d_string_buffer *buffer, const struct hlsl_ir vkd3d_string_buffer_cache_cleanup(&string_buffers); } 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); + if (var->semantic.name) + vkd3d_string_buffer_printf(buffer, " : %s%u", var->semantic.name, var->semantic.index); }
static void dump_deref(struct vkd3d_string_buffer *buffer, const struct hlsl_deref *deref) @@ -1184,7 +1189,7 @@ void hlsl_free_type(struct hlsl_type *type) 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((void *)field->semantic.name); vkd3d_free(field); } } diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 1c5f63aa..c698983a 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -129,13 +129,19 @@ struct hlsl_type unsigned int bytecode_offset; };
+struct hlsl_semantic +{ + const char *name; + uint32_t index; +}; + struct hlsl_struct_field { struct list entry; struct vkd3d_shader_location loc; struct hlsl_type *type; const char *name; - const char *semantic; + struct hlsl_semantic semantic; unsigned int reg_offset;
unsigned int name_bytecode_offset; @@ -215,7 +221,7 @@ struct hlsl_ir_var struct hlsl_type *data_type; struct vkd3d_shader_location loc; const char *name; - const char *semantic; + struct hlsl_semantic semantic; unsigned int modifiers; const struct hlsl_reg_reservation *reg_reservation; struct list scope_entry, param_entry, extern_entry; @@ -569,7 +575,8 @@ struct hlsl_ir_expr *hlsl_new_cast(struct hlsl_ir_node *node, struct hlsl_type * struct vkd3d_shader_location *loc) DECLSPEC_HIDDEN; struct hlsl_ir_expr *hlsl_new_copy(struct hlsl_ir_node *node) DECLSPEC_HIDDEN; struct hlsl_ir_function_decl *hlsl_new_func_decl(struct hlsl_ctx *ctx, struct hlsl_type *return_type, - struct list *parameters, const char *semantic, struct vkd3d_shader_location loc) DECLSPEC_HIDDEN; + struct list *parameters, const struct hlsl_semantic *semantic, + struct vkd3d_shader_location loc) DECLSPEC_HIDDEN; struct hlsl_ir_if *hlsl_new_if(struct hlsl_ir_node *condition, struct vkd3d_shader_location loc) DECLSPEC_HIDDEN; struct hlsl_ir_jump *hlsl_new_jump(enum hlsl_ir_jump_type type, struct vkd3d_shader_location loc) DECLSPEC_HIDDEN; struct hlsl_ir_load *hlsl_new_load(struct hlsl_ir_var *var, struct hlsl_ir_node *offset, struct hlsl_type *type, @@ -591,7 +598,7 @@ struct hlsl_ir_constant *hlsl_new_uint_constant(struct hlsl_ctx *ctx, unsigned i struct hlsl_ir_node *hlsl_new_unary_expr(enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg, struct vkd3d_shader_location loc) DECLSPEC_HIDDEN; struct hlsl_ir_var *hlsl_new_var(const char *name, struct hlsl_type *type, - const struct vkd3d_shader_location loc, const char *semantic, unsigned int modifiers, + const struct vkd3d_shader_location loc, const struct hlsl_semantic *semantic, unsigned int modifiers, const struct hlsl_reg_reservation *reg_reservation) DECLSPEC_HIDDEN; struct hlsl_ir_load *hlsl_new_var_load(struct hlsl_ir_var *var, const struct vkd3d_shader_location loc) DECLSPEC_HIDDEN;
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index bc4e1b8d..4e17e806 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -32,14 +32,14 @@ struct parse_parameter { struct hlsl_type *type; const char *name; - const char *semantic; + struct hlsl_semantic semantic; const struct hlsl_reg_reservation *reg_reservation; unsigned int modifiers; };
struct parse_colon_attribute { - const char *semantic; + struct hlsl_semantic semantic; struct hlsl_reg_reservation *reg_reservation; };
@@ -63,7 +63,7 @@ struct parse_variable_def
char *name; struct parse_array_sizes arrays; - const char *semantic; + struct hlsl_semantic semantic; struct hlsl_reg_reservation *reg_reservation; struct parse_initializer initializer; }; @@ -763,7 +763,7 @@ static bool add_func_parameter(struct hlsl_ctx *ctx, struct list *list, if (param->type->type == HLSL_CLASS_MATRIX) assert(param->type->modifiers & HLSL_MODIFIERS_MAJORITY_MASK);
- if (!(var = hlsl_new_var(param->name, param->type, loc, param->semantic, param->modifiers, param->reg_reservation))) + if (!(var = hlsl_new_var(param->name, param->type, loc, ¶m->semantic, param->modifiers, param->reg_reservation))) return false; var->is_param = 1;
@@ -1369,7 +1369,7 @@ 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); + vkd3d_free((void *)v->semantic.name); vkd3d_free(v->reg_reservation); vkd3d_free(v); } @@ -1409,7 +1409,7 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t if (type->type != HLSL_CLASS_MATRIX) check_invalid_matrix_modifiers(ctx, modifiers, v->loc);
- if (!(var = hlsl_new_var(v->name, type, v->loc, v->semantic, modifiers, v->reg_reservation))) + if (!(var = hlsl_new_var(v->name, type, v->loc, &v->semantic, modifiers, v->reg_reservation))) { free_parse_variable_def(v); continue; @@ -1441,7 +1441,7 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t "Modifiers '%s' are not allowed on local variables.", string->buffer); vkd3d_string_buffer_release(&ctx->string_buffers, string); } - if (var->semantic) + if (var->semantic.name) hlsl_error(ctx, var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SEMANTIC, "Semantics are not allowed on local variables."); } @@ -1572,6 +1572,7 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t enum parse_assign_op assign_op; struct hlsl_reg_reservation *reg_reservation; struct parse_colon_attribute colon_attribute; + struct hlsl_semantic semantic; }
%token KW_BLENDSTATE @@ -1737,13 +1738,14 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t %type <modifiers> var_modifiers
%type <name> any_identifier -%type <name> semantic %type <name> var_identifier
%type <parameter> parameter
%type <reg_reservation> register_opt
+%type <semantic> semantic + %type <type> base_type %type <type> field_type %type <type> named_struct_spec @@ -1960,7 +1962,7 @@ func_prototype: ""%s" was previously declared here.", $3); YYABORT; } - if (hlsl_type_is_void($2) && $7.semantic) + if (hlsl_type_is_void($2) && $7.semantic.name) { hlsl_error(ctx, @7, VKD3D_SHADER_ERROR_HLSL_INVALID_SEMANTIC, "Semantics are not allowed on void functions."); @@ -1971,7 +1973,7 @@ func_prototype: FIXME("Unexpected register reservation for a function.\n"); vkd3d_free($7.reg_reservation); } - if (!($$.decl = hlsl_new_func_decl(ctx, $2, $5, $7.semantic, @3))) + if (!($$.decl = hlsl_new_func_decl(ctx, $2, $5, &$7.semantic, @3))) YYABORT; $$.name = $3; ctx->cur_function = $$.decl; @@ -2002,7 +2004,7 @@ var_identifier: colon_attribute: %empty { - $$.semantic = NULL; + $$.semantic.name = NULL; $$.reg_reservation = NULL; } | semantic @@ -2012,14 +2014,20 @@ colon_attribute: } | register_opt { - $$.semantic = NULL; + $$.semantic.name = NULL; $$.reg_reservation = $1; }
semantic: ':' any_identifier { - $$ = $2; + char *p; + + for (p = $2 + strlen($2); p > $2 && isdigit(p[-1]); --p) + ; + $$.name = $2; + $$.index = atoi(p); + *p = 0; }
/* FIXME: Writemasks */ diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 3fadc288..180259f6 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -70,9 +70,10 @@ static void prepend_uniform_copy(struct hlsl_ctx *ctx, struct list *instrs, stru }
static void prepend_input_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_var *var, - struct hlsl_type *type, unsigned int field_offset, const char *semantic) + struct hlsl_type *type, unsigned int field_offset, const struct hlsl_semantic *semantic) { struct vkd3d_string_buffer *name; + struct hlsl_semantic new_semantic; struct hlsl_ir_constant *offset; struct hlsl_ir_store *store; struct hlsl_ir_var *varying; @@ -83,13 +84,21 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct list *instrs, struct ctx->failed = true; return; } - vkd3d_string_buffer_printf(name, "<input-%s>", semantic); - if (!(varying = hlsl_new_var(vkd3d_strdup(name->buffer), type, var->loc, vkd3d_strdup(semantic), 0, NULL))) + vkd3d_string_buffer_printf(name, "<input-%s%u>", semantic->name, semantic->index); + if (!(new_semantic.name = vkd3d_strdup(semantic->name))) { vkd3d_string_buffer_release(&ctx->string_buffers, name); ctx->failed = true; return; } + new_semantic.index = semantic->index; + if (!(varying = hlsl_new_var(vkd3d_strdup(name->buffer), type, var->loc, &new_semantic, 0, NULL))) + { + vkd3d_string_buffer_release(&ctx->string_buffers, name); + vkd3d_free((void *)new_semantic.name); + ctx->failed = true; + return; + } vkd3d_string_buffer_release(&ctx->string_buffers, name); varying->is_input_varying = 1; varying->is_param = var->is_param; @@ -127,8 +136,8 @@ static void prepend_input_struct_copy(struct hlsl_ctx *ctx, struct list *instrs, { if (field->type->type == HLSL_CLASS_STRUCT) prepend_input_struct_copy(ctx, instrs, var, field->type, field_offset + field->reg_offset); - else if (field->semantic) - prepend_input_copy(ctx, instrs, var, field->type, field_offset + field->reg_offset, field->semantic); + else if (field->semantic.name) + prepend_input_copy(ctx, instrs, var, field->type, field_offset + field->reg_offset, &field->semantic); else hlsl_error(ctx, field->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_SEMANTIC, "Field '%s' is missing a semantic.", field->name); @@ -142,14 +151,15 @@ static void prepend_input_var_copy(struct hlsl_ctx *ctx, struct list *instrs, st { if (var->data_type->type == HLSL_CLASS_STRUCT) prepend_input_struct_copy(ctx, instrs, var, var->data_type, 0); - else if (var->semantic) - prepend_input_copy(ctx, instrs, var, var->data_type, 0, var->semantic); + else if (var->semantic.name) + prepend_input_copy(ctx, instrs, var, var->data_type, 0, &var->semantic); }
static void append_output_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_var *var, - struct hlsl_type *type, unsigned int field_offset, const char *semantic) + struct hlsl_type *type, unsigned int field_offset, const struct hlsl_semantic *semantic) { struct vkd3d_string_buffer *name; + struct hlsl_semantic new_semantic; struct hlsl_ir_constant *offset; struct hlsl_ir_store *store; struct hlsl_ir_var *varying; @@ -160,9 +170,17 @@ static void append_output_copy(struct hlsl_ctx *ctx, struct list *instrs, struct ctx->failed = true; return; } - vkd3d_string_buffer_printf(name, "<output-%s>", semantic); - if (!(varying = hlsl_new_var(vkd3d_strdup(name->buffer), type, var->loc, vkd3d_strdup(semantic), 0, NULL))) + vkd3d_string_buffer_printf(name, "<output-%s%u>", semantic->name, semantic->index); + if (!(new_semantic.name = vkd3d_strdup(semantic->name))) + { + vkd3d_string_buffer_release(&ctx->string_buffers, name); + ctx->failed = true; + return; + } + new_semantic.index = semantic->index; + if (!(varying = hlsl_new_var(vkd3d_strdup(name->buffer), type, var->loc, &new_semantic, 0, NULL))) { + vkd3d_free((void *)new_semantic.name); vkd3d_string_buffer_release(&ctx->string_buffers, name); ctx->failed = true; return; @@ -204,8 +222,8 @@ static void append_output_struct_copy(struct hlsl_ctx *ctx, struct list *instrs, { if (field->type->type == HLSL_CLASS_STRUCT) append_output_struct_copy(ctx, instrs, var, field->type, field_offset + field->reg_offset); - else if (field->semantic) - append_output_copy(ctx, instrs, var, field->type, field_offset + field->reg_offset, field->semantic); + else if (field->semantic.name) + append_output_copy(ctx, instrs, var, field->type, field_offset + field->reg_offset, &field->semantic); else hlsl_error(ctx, field->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_SEMANTIC, "Field '%s' is missing a semantic.", field->name); @@ -219,8 +237,8 @@ static void append_output_var_copy(struct hlsl_ctx *ctx, struct list *instrs, st { if (var->data_type->type == HLSL_CLASS_STRUCT) append_output_struct_copy(ctx, instrs, var, var->data_type, 0); - else if (var->semantic) - append_output_copy(ctx, instrs, var, var->data_type, 0, var->semantic); + else if (var->semantic.name) + append_output_copy(ctx, instrs, var, var->data_type, 0, &var->semantic); }
static bool transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx, struct hlsl_ir_node *, void *), @@ -1180,7 +1198,7 @@ static void write_sm1_uniforms(struct hlsl_ctx *ctx, struct bytecode_buffer *buf
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) { - if (!var->semantic && var->reg.allocated) + if (!var->semantic.name && var->reg.allocated) { ++uniform_count;
@@ -1218,7 +1236,7 @@ static void write_sm1_uniforms(struct hlsl_ctx *ctx, struct bytecode_buffer *buf
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) { - if (!var->semantic && var->reg.allocated) + if (!var->semantic.name && var->reg.allocated) { put_dword(buffer, 0); /* name */ put_dword(buffer, D3DXRS_FLOAT4 | (var->reg.id << 16)); @@ -1232,7 +1250,7 @@ static void write_sm1_uniforms(struct hlsl_ctx *ctx, struct bytecode_buffer *buf
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) { - if (!var->semantic && var->reg.allocated) + if (!var->semantic.name && var->reg.allocated) { set_dword(buffer, vars_start + (uniform_count * 5), (buffer->count - ctab_start) * sizeof(*buffer->data)); put_string(buffer, var->name); @@ -1328,7 +1346,7 @@ int hlsl_emit_dxbc(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_fun } else { - if (var->data_type->type != HLSL_CLASS_STRUCT && !var->semantic) + if (var->data_type->type != HLSL_CLASS_STRUCT && !var->semantic.name) hlsl_error(ctx, var->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_SEMANTIC, "Parameter "%s" is missing a semantic.", var->name);
@@ -1341,7 +1359,7 @@ int hlsl_emit_dxbc(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_fun } if (entry_func->return_var) { - if (entry_func->return_var->data_type->type != HLSL_CLASS_STRUCT && !entry_func->return_var->semantic) + if (entry_func->return_var->data_type->type != HLSL_CLASS_STRUCT && !entry_func->return_var->semantic.name) hlsl_error(ctx, entry_func->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_SEMANTIC, "Entry point "%s" is missing a return value semantic.", entry_func->func->name);