diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 11cb2e7e..310560b2 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -1180,7 +1180,7 @@ 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, const struct vkd3d_shader_location *loc) { struct hlsl_ir_function_decl *decl; @@ -1189,11 +1189,11 @@ 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; 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 +2086,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 +2152,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 +2160,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..c7a19302 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,7 @@ 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, 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..f77b0b61 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 +%type attribute + +%type attribute_list + %type boolean %type buffer_type @@ -3196,6 +3208,7 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl %type func_declaration %type func_prototype +%type func_prototype_no_attrs %type complex_initializer %type complex_initializer_list @@ -3435,6 +3448,68 @@ 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 = new_array; + $$.attrs[$$.count++] = $2; + } + func_declaration: func_prototype compound_statement { @@ -3450,7 +3525,7 @@ func_declaration: hlsl_pop_scope(ctx); } -func_prototype: +func_prototype_no_attrs: /* var_modifiers is necessary to avoid shift/reduce conflicts. */ var_modifiers type var_identifier '(' parameters ')' colon_attribute { @@ -3483,12 +3558,21 @@ 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, &@3))) YYABORT; $$.name = $3; ctx->cur_function = $$.decl; } +func_prototype: + func_prototype_no_attrs + | attribute_list func_prototype_no_attrs + { + $2.decl->attr_count = $1.count; + $2.decl->attrs = $1.attrs; + $$ = $2; + } + 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 a750b55e..aae7cea1 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 db011873..cb6c2b5e 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; } @@ -55,12 +55,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; @@ -72,27 +72,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(); @@ -100,7 +100,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;