From: Zebediah Figura zfigura@codeweavers.com
--- libs/vkd3d-shader/hlsl.c | 51 +++++++++++++++++++++++++++++++++ libs/vkd3d-shader/hlsl.h | 8 ++++++ libs/vkd3d-shader/hlsl.y | 61 +++++++++++----------------------------- 3 files changed, 75 insertions(+), 45 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index be5b4052..b8cf6813 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -2988,6 +2988,16 @@ void hlsl_add_function(struct hlsl_ctx *ctx, char *name, struct hlsl_ir_function struct hlsl_ir_function *func; struct rb_entry *func_entry;
+ if (ctx->internal_func_name) + { + char *internal_name; + + if (!(internal_name = hlsl_strdup(ctx, ctx->internal_func_name))) + return; + vkd3d_free(name); + name = internal_name; + } + func_entry = rb_get(&ctx->functions, name); if (func_entry) { @@ -3519,3 +3529,44 @@ int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d hlsl_ctx_cleanup(&ctx); return ret; } + +struct hlsl_ir_function_decl *hlsl_compile_internal_function(struct hlsl_ctx *ctx, const char *name, const char *hlsl) +{ + const struct hlsl_ir_function_decl *saved_cur_function = ctx->cur_function; + struct vkd3d_shader_code code = {.code = hlsl, .size = strlen(hlsl)}; + const char *saved_internal_func_name = ctx->internal_func_name; + struct vkd3d_string_buffer *internal_name; + struct hlsl_ir_function_decl *func; + void *saved_scanner = ctx->scanner; + int ret; + + TRACE("name %s, hlsl %s.\n", debugstr_a(name), debugstr_a(hlsl)); + + /* The actual name of the function is mangled with a unique prefix, both to + * allow defining multiple variants of a function with the same name, and to + * avoid polluting the user name space. */ + + if (!(internal_name = hlsl_get_string_buffer(ctx))) + return NULL; + vkd3d_string_buffer_printf(internal_name, "<%s-%u>", name, ctx->internal_name_counter++); + + /* Save and restore everything that matters. + * Note that saving the scope stack is hard, and shouldn't be necessary. */ + + ctx->scanner = NULL; + ctx->internal_func_name = internal_name->buffer; + ctx->cur_function = NULL; + ret = hlsl_lexer_compile(ctx, &code); + ctx->scanner = saved_scanner; + ctx->internal_func_name = saved_internal_func_name; + ctx->cur_function = saved_cur_function; + if (ret) + { + ERR("Failed to compile intrinsic, error %u.\n", ret); + hlsl_release_string_buffer(ctx, internal_name); + return NULL; + } + func = hlsl_get_func_decl(ctx, internal_name->buffer); + hlsl_release_string_buffer(ctx, internal_name); + return func; +} diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 567e2908..26b0b89e 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -836,6 +836,12 @@ struct hlsl_ctx * compute shader profiles. It is set using the numthreads() attribute in the entry point. */ uint32_t thread_count[3];
+ /* In some cases we generate opcodes by parsing an HLSL function and then + * invoking it. If not NULL, this field is the name of the function that we + * are currently parsing, "mangled" with an internal prefix to avoid + * polluting the user namespace. */ + const char *internal_func_name; + /* Whether the parser is inside a state block (effects' metadata) inside a variable declaration. */ uint32_t in_state_block : 1; /* Whether the numthreads() attribute has been provided in the entry-point function. */ @@ -1262,6 +1268,8 @@ bool hlsl_sm4_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_sem bool output, enum vkd3d_shader_register_type *type, enum vkd3d_sm4_swizzle_type *swizzle_type, bool *has_idx); int hlsl_sm4_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, struct vkd3d_shader_code *out);
+struct hlsl_ir_function_decl *hlsl_compile_internal_function(struct hlsl_ctx *ctx, const char *name, const char *hlsl); + int hlsl_lexer_compile(struct hlsl_ctx *ctx, const struct vkd3d_shader_code *hlsl);
#endif diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 4e3a10c8..d1854fde 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -3422,58 +3422,29 @@ static bool intrinsic_sin(struct hlsl_ctx *ctx, static bool intrinsic_smoothstep(struct hlsl_ctx *ctx, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { - struct hlsl_ir_node *min_arg, *max_arg, *x_arg, *p, *p_num, *p_denom, *res, *one, *minus_two, *three; - - if (!elementwise_intrinsic_float_convert_args(ctx, params, loc)) - return false; - - min_arg = params->args[0]; - max_arg = params->args[1]; - x_arg = params->args[2]; - - if (!(min_arg = add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_NEG, min_arg, loc))) - return false; - - if (!(p_num = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_ADD, x_arg, min_arg, loc))) - return false; - - if (!(p_denom = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_ADD, max_arg, min_arg, loc))) - return false; - - if (!(one = hlsl_new_float_constant(ctx, 1.0, loc))) - return false; - hlsl_block_add_instr(params->instrs, one); - - if (!(p_denom = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_DIV, one, p_denom, loc))) - return false; - - if (!(p = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MUL, p_num, p_denom, loc))) - return false; - - if (!(p = add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_SAT, p, loc))) - return false; - - if (!(minus_two = hlsl_new_float_constant(ctx, -2.0, loc))) - return false; - hlsl_block_add_instr(params->instrs, minus_two); - - if (!(three = hlsl_new_float_constant(ctx, 3.0, loc))) - return false; - hlsl_block_add_instr(params->instrs, three); + struct hlsl_ir_function_decl *func; + struct hlsl_type *type; + char *body;
- if (!(res = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MUL, minus_two, p, loc))) - return false; + static const char template[] = + "%s smoothstep(%s low, %s high, %s x)\n" + "{\n" + " %s p = saturate((x - low) / (high - low));\n" + " return (p * p) * (3 - 2 * p);\n" + "}";
- if (!(res = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_ADD, three, res, loc))) + if (!(type = elementwise_intrinsic_get_common_type(ctx, params, loc))) return false; + type = hlsl_get_numeric_type(ctx, type->class, HLSL_TYPE_FLOAT, type->dimx, type->dimy);
- if (!(p = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MUL, p, p, loc))) + if (!(body = hlsl_sprintf_alloc(ctx, template, type->name, type->name, type->name, type->name, type->name))) return false; - - if (!(res = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MUL, p, res, loc))) + func = hlsl_compile_internal_function(ctx, "smoothstep", body); + vkd3d_free(body); + if (!func) return false;
- return true; + return add_user_call(ctx, func, params, loc); }
static bool intrinsic_sqrt(struct hlsl_ctx *ctx,