From: Zebediah Figura zfigura@codeweavers.com
--- libs/vkd3d-shader/hlsl.c | 36 +++++++- libs/vkd3d-shader/hlsl.h | 15 +++- libs/vkd3d-shader/hlsl.y | 108 ++++++++++++++++++++++- libs/vkd3d-shader/hlsl_codegen.c | 5 ++ libs/vkd3d-shader/vkd3d_shader_private.h | 1 + tests/hlsl-attributes.shader_test | 22 ++--- tests/hlsl-numthreads.shader_test | 36 ++++---- 7 files changed, 189 insertions(+), 34 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 11cb2e7e..6221a2ff 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -1180,7 +1180,8 @@ struct hlsl_ir_loop *hlsl_new_loop(struct hlsl_ctx *ctx, struct vkd3d_shader_loc }
struct hlsl_ir_function_decl *hlsl_new_func_decl(struct hlsl_ctx *ctx, struct hlsl_type *return_type, - struct list *parameters, const struct hlsl_semantic *semantic, struct vkd3d_shader_location loc) + struct list *parameters, const struct hlsl_semantic *semantic, + unsigned int attr_count, const struct hlsl_attribute *const *attrs, const struct vkd3d_shader_location *loc) { struct hlsl_ir_function_decl *decl;
@@ -1189,11 +1190,13 @@ struct hlsl_ir_function_decl *hlsl_new_func_decl(struct hlsl_ctx *ctx, struct hl list_init(&decl->body.instrs); decl->return_type = return_type; decl->parameters = parameters; - decl->loc = loc; + decl->loc = *loc; + decl->attr_count = attr_count; + decl->attrs = attrs;
if (!hlsl_types_are_equal(return_type, ctx->builtin_types.Void)) { - if (!(decl->return_var = hlsl_new_synthetic_var(ctx, "retval", return_type, &loc))) + if (!(decl->return_var = hlsl_new_synthetic_var(ctx, "retval", return_type, loc))) { vkd3d_free(decl); return NULL; @@ -2086,8 +2089,25 @@ void hlsl_free_instr(struct hlsl_ir_node *node) } }
+void hlsl_free_attribute(struct hlsl_attribute *attr) +{ + unsigned int i; + + for (i = 0; i < attr->args_count; ++i) + hlsl_src_remove(&attr->args[i]); + hlsl_free_instr_list(&attr->instrs); + vkd3d_free((void *)attr->name); + vkd3d_free(attr); +} + static void free_function_decl(struct hlsl_ir_function_decl *decl) { + unsigned int i; + + for (i = 0; i < decl->attr_count; ++i) + hlsl_free_attribute((void *)decl->attrs[i]); + vkd3d_free((void *)decl->attrs); + vkd3d_free(decl->parameters); hlsl_free_instr_list(&decl->body.instrs); vkd3d_free(decl); @@ -2135,6 +2155,7 @@ void hlsl_add_function(struct hlsl_ctx *ctx, char *name, struct hlsl_ir_function { struct hlsl_ir_function_decl *old_decl = RB_ENTRY_VALUE(old_entry, struct hlsl_ir_function_decl, entry); + unsigned int i;
if (!decl->has_body) { @@ -2142,6 +2163,15 @@ void hlsl_add_function(struct hlsl_ctx *ctx, char *name, struct hlsl_ir_function vkd3d_free(name); return; } + + for (i = 0; i < decl->attr_count; ++i) + hlsl_free_attribute((void *)decl->attrs[i]); + vkd3d_free((void *)decl->attrs); + decl->attr_count = old_decl->attr_count; + decl->attrs = old_decl->attrs; + old_decl->attr_count = 0; + old_decl->attrs = NULL; + rb_remove(&func->overloads, old_entry); free_function_decl(old_decl); } diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 26629fcd..9f87db77 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -212,6 +212,15 @@ struct hlsl_src struct list entry; };
+struct hlsl_attribute +{ + const char *name; + struct list instrs; + struct vkd3d_shader_location loc; + unsigned int args_count; + struct hlsl_src args[]; +}; + #define HLSL_STORAGE_EXTERN 0x00000001 #define HLSL_STORAGE_NOINTERPOLATION 0x00000002 #define HLSL_MODIFIER_PRECISE 0x00000004 @@ -279,6 +288,8 @@ struct hlsl_ir_function_decl struct list *parameters; struct hlsl_block body; bool has_body; + unsigned int attr_count; + const struct hlsl_attribute *const *attrs; };
struct hlsl_ir_if @@ -741,6 +752,7 @@ void hlsl_cleanup_deref(struct hlsl_deref *deref);
void hlsl_replace_node(struct hlsl_ir_node *old, struct hlsl_ir_node *new);
+void hlsl_free_attribute(struct hlsl_attribute *attr); void hlsl_free_instr(struct hlsl_ir_node *node); void hlsl_free_instr_list(struct list *list); void hlsl_free_type(struct hlsl_type *type); @@ -771,7 +783,8 @@ struct hlsl_ir_node *hlsl_new_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr_op op struct hlsl_ir_constant *hlsl_new_float_constant(struct hlsl_ctx *ctx, float f, const struct vkd3d_shader_location *loc); struct hlsl_ir_function_decl *hlsl_new_func_decl(struct hlsl_ctx *ctx, struct hlsl_type *return_type, - struct list *parameters, const struct hlsl_semantic *semantic, struct vkd3d_shader_location loc); + struct list *parameters, const struct hlsl_semantic *semantic, + unsigned int attr_count, const struct hlsl_attribute *const *attrs, const struct vkd3d_shader_location *loc); struct hlsl_ir_if *hlsl_new_if(struct hlsl_ctx *ctx, struct hlsl_ir_node *condition, struct vkd3d_shader_location loc); struct hlsl_ir_constant *hlsl_new_int_constant(struct hlsl_ctx *ctx, int n, const struct vkd3d_shader_location *loc); diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 00842195..1ba4adf2 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -102,6 +102,12 @@ enum parse_assign_op ASSIGN_OP_XOR, };
+struct parse_attribute_list +{ + unsigned int count; + const struct hlsl_attribute **attrs; +}; + }
%code provides @@ -3036,6 +3042,8 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl struct hlsl_semantic semantic; enum hlsl_buffer_type buffer_type; enum hlsl_sampler_dim sampler_dim; + struct hlsl_attribute *attr; + struct parse_attribute_list attr_list; }
%token KW_BLENDSTATE @@ -3185,6 +3193,10 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl
%type <assign_op> assign_op
+%type <attr> attribute + +%type <attr_list> attribute_list + %type <boolval> boolean
%type <buffer_type> buffer_type @@ -3435,6 +3447,67 @@ field: YYABORT; }
+attribute: + '[' any_identifier ']' + { + if (!($$ = hlsl_alloc(ctx, offsetof(struct hlsl_attribute, args[0])))) + { + vkd3d_free($2); + YYABORT; + } + $$->name = $2; + list_init(&$$->instrs); + $$->loc = @$; + $$->args_count = 0; + } + | '[' any_identifier '(' initializer_expr_list ')' ']' + { + unsigned int i; + + if (!($$ = hlsl_alloc(ctx, offsetof(struct hlsl_attribute, args[$4.args_count])))) + { + vkd3d_free($2); + free_parse_initializer(&$4); + YYABORT; + } + $$->name = $2; + list_init(&$$->instrs); + list_move_tail(&$$->instrs, $4.instrs); + vkd3d_free($4.instrs); + $$->loc = @$; + $$->args_count = $4.args_count; + for (i = 0; i < $4.args_count; ++i) + hlsl_src_from_node(&$$->args[i], $4.args[i]); + } + +attribute_list: + attribute + { + $$.count = 1; + if (!($$.attrs = hlsl_alloc(ctx, sizeof(*$$.attrs)))) + { + hlsl_free_attribute($1); + YYABORT; + } + $$.attrs[0] = $1; + } + | attribute_list attribute + { + const struct hlsl_attribute **new_array; + + $$ = $1; + if (!(new_array = vkd3d_realloc($$.attrs, ($$.count + 1) * sizeof(*$$.attrs)))) + { + unsigned int i; + + for (i = 0; i < $$.count; ++i) + hlsl_free_attribute((void *)$$.attrs[i]); + vkd3d_free($$.attrs); + YYABORT; + } + $$.attrs[$$.count++] = $2; + } + func_declaration: func_prototype compound_statement { @@ -3483,11 +3556,44 @@ func_prototype: if ($7.reg_reservation.type) FIXME("Unexpected register reservation for a function.\n");
- if (!($$.decl = hlsl_new_func_decl(ctx, type, $5, &$7.semantic, @3))) + if (!($$.decl = hlsl_new_func_decl(ctx, type, $5, &$7.semantic, 0, NULL, &@3))) YYABORT; $$.name = $3; ctx->cur_function = $$.decl; } + /* var_modifiers is necessary to avoid shift/reduce conflicts. */ + | attribute_list var_modifiers type var_identifier '(' parameters ')' colon_attribute + { + struct hlsl_ir_var *var; + + if ($2) + { + hlsl_error(ctx, &@2, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, + "Modifiers are not allowed on functions."); + YYABORT; + } + if ((var = hlsl_get_var(ctx->globals, $4))) + { + hlsl_error(ctx, &@4, VKD3D_SHADER_ERROR_HLSL_REDEFINED, + ""%s" is already declared as a variable.", $4); + hlsl_note(ctx, &var->loc, VKD3D_SHADER_LOG_ERROR, + ""%s" was previously declared here.", $4); + YYABORT; + } + if (hlsl_types_are_equal($3, ctx->builtin_types.Void) && $8.semantic.name) + { + hlsl_error(ctx, &@8, VKD3D_SHADER_ERROR_HLSL_INVALID_SEMANTIC, + "Semantics are not allowed on void functions."); + } + + if ($8.reg_reservation.type) + FIXME("Unexpected register reservation for a function.\n"); + + if (!($$.decl = hlsl_new_func_decl(ctx, $3, $6, &$8.semantic, $1.count, $1.attrs, &@4))) + YYABORT; + $$.name = $4; + ctx->cur_function = $$.decl; + }
compound_statement: '{' '}' diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 6e650db0..0df870cc 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -2539,6 +2539,7 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry { struct hlsl_block *const body = &entry_func->body; struct hlsl_ir_var *var; + unsigned int i; bool progress;
list_move_head(&body->instrs, &ctx->static_initializers); @@ -2576,6 +2577,10 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry append_output_var_copy(ctx, &body->instrs, entry_func->return_var); }
+ for (i = 0; i < entry_func->attr_count; ++i) + hlsl_warning(ctx, &entry_func->attrs[i]->loc, VKD3D_SHADER_WARNING_HLSL_UNKNOWN_ATTRIBUTE, + "Ignoring unknown attribute "%s".", entry_func->attrs[i]->name); + transform_ir(ctx, lower_broadcasts, body, NULL); while (transform_ir(ctx, fold_redundant_casts, body, NULL)); do diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index aca5606b..cd2ff305 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -122,6 +122,7 @@ enum vkd3d_shader_error
VKD3D_SHADER_WARNING_HLSL_IMPLICIT_TRUNCATION = 5300, VKD3D_SHADER_WARNING_HLSL_DIVISION_BY_ZERO = 5301, + VKD3D_SHADER_WARNING_HLSL_UNKNOWN_ATTRIBUTE = 5302,
VKD3D_SHADER_ERROR_GLSL_INTERNAL = 6000,
diff --git a/tests/hlsl-attributes.shader_test b/tests/hlsl-attributes.shader_test index 26bf25dc..400ce7f8 100644 --- a/tests/hlsl-attributes.shader_test +++ b/tests/hlsl-attributes.shader_test @@ -2,17 +2,17 @@ % we need to get the parsing syntax right. Most of the following tests which % succeed print warnings.
-[pixel shader todo] +[pixel shader]
[numthreads] float4 main() : sv_target { return 0; }
-[pixel shader todo] +[pixel shader]
[ numthreads ] float4 main() : sv_target { return 0; }
-[pixel shader todo] +[pixel shader]
[numthreads(1)] float4 main() : sv_target { return 0; } @@ -54,12 +54,12 @@ float4 main() : sv_target { return 0; } [numthreads(float2(1))] float4 main() : sv_target { return 0; }
-[pixel shader todo] +[pixel shader]
[not_a_real_attribute_name] float4 main() : sv_target { return 0; }
-[pixel shader todo] +[pixel shader]
uniform float4 f;
@@ -71,27 +71,27 @@ float4 main() : sv_target { return 0; } [one, two] float4 main() : sv_target { return 0; }
-[pixel shader todo] +[pixel shader]
[one][two] float4 main() : sv_target { return 0; }
-[pixel shader fail] +[pixel shader fail todo]
[one][one] float4 main() : sv_target { return 0; }
-[pixel shader fail] +[pixel shader fail todo]
[one][one(1)] float4 main() : sv_target { return 0; }
-[pixel shader todo] +[pixel shader]
[one][One] float4 main() : sv_target { return 0; }
-[pixel shader todo] +[pixel shader]
[numthreads] float4 main(); @@ -99,7 +99,7 @@ float4 main(); [numthreads] float4 main() : sv_target { return 0; }
-[pixel shader todo] +[pixel shader]
/* Expressions with side effects are forbidden in attributes—see * hlsl-numthreads.shader_test for an example—but not if the attribute is diff --git a/tests/hlsl-numthreads.shader_test b/tests/hlsl-numthreads.shader_test index f0ef5f62..3e3973b3 100644 --- a/tests/hlsl-numthreads.shader_test +++ b/tests/hlsl-numthreads.shader_test @@ -8,52 +8,52 @@ shader model >= 5.0 [numthreads(1, 1, 1)] void main() {}
-[compute shader fail] +[compute shader fail todo]
[numthreads] void main() {}
-[compute shader fail] +[compute shader fail todo]
[numthreads(1, 1)] void main() {}
-[compute shader fail] +[compute shader fail todo]
[numthreads(1, 1, 1, 1)] void main() {}
-[compute shader fail] +[compute shader fail todo]
[numthreads(0, 1, 1)] void main() {}
-[compute shader fail] +[compute shader fail todo]
[numthreads(1, 0, 1)] void main() {}
-[compute shader fail] +[compute shader fail todo]
[numthreads(1, 1, 0)] void main() {}
-[compute shader fail] +[compute shader fail todo]
[numthreads(-1, 1, 1)] void main() {}
-[compute shader fail] +[compute shader fail todo]
[numthreads(1, -1, 1)] void main() {}
-[compute shader fail] +[compute shader fail todo]
[numthreads(1, 1, -1)] void main() {}
-[compute shader fail] +[compute shader fail todo]
[numthreads(1, -1, -1)] void main() {} @@ -68,12 +68,12 @@ void main() {} [numthreads(int(1), 1, 1)] void main() {}
-[compute shader fail] +[compute shader fail todo]
[numthreads(float(1), 1, 1)] void main() {}
-[compute shader fail] +[compute shader fail todo]
[numthreads(uint1(1), 1, 1)] void main() {} @@ -103,7 +103,7 @@ void main() {}
void main() {}
-[compute shader fail] +[compute shader fail todo]
[NumThreads(1, 1, 1)] void main() {} @@ -115,21 +115,21 @@ void main();
void main() {}
-[compute shader fail] +[compute shader fail todo]
void main() {}
[numthreads(1, 1, 1)] void main();
-[compute shader fail] +[compute shader fail todo]
void main();
[numthreads(1, 1, 1)] void main() {}
-[compute shader fail] +[compute shader fail todo]
/* Expressions with side effects are forbidden in attributes (but not if the * attribute is ignored). */ @@ -139,14 +139,14 @@ static int x = 1; [numthreads(x++, 1, 1)] void main() {}
-[compute shader fail] +[compute shader fail todo]
static int x = 1;
[numthreads(++x, 1, 1)] void main() {}
-[compute shader fail] +[compute shader fail todo]
static int x = 1;