From 96fcc9490766c82944e09eb5d549386679236bd9 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Tue, 11 Nov 2025 08:00:39 +1100 Subject: [PATCH] Updated vkd3d to 1569bb3fb8c745d895ad555da1de5e6a2a846218. --- libs/vkd3d/libs/vkd3d-shader/fx.c | 2 +- libs/vkd3d/libs/vkd3d-shader/hlsl.h | 5 +- libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 189 ++++++++---------- .../libs/vkd3d-shader/hlsl_constant_ops.c | 45 ++--- libs/vkd3d/libs/vkd3d-shader/ir.c | 11 +- 5 files changed, 115 insertions(+), 137 deletions(-) diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c index a14346a45d2..4848c531ced 100644 --- a/libs/vkd3d/libs/vkd3d-shader/fx.c +++ b/libs/vkd3d/libs/vkd3d-shader/fx.c @@ -1607,7 +1607,7 @@ static void write_fx_2_type_iter(const struct hlsl_type *type, const char *name, } buffer = &fx->unstructured; - offset = put_u32(buffer, hlsl_sm1_base_type(type, ctx->is_combined_sampler)); + offset = put_u32(buffer, hlsl_sm1_base_type(type, ctx->is_combined_sampler, HLSL_SAMPLER_DIM_GENERIC)); put_u32(buffer, get_fx_2_type_class(type)); *ctx->names++ = put_u32(buffer, 0); *ctx->semantics++ = put_u32(buffer, 0); diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h index 87cfaf83f76..0202d71cc23 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h @@ -1844,18 +1844,19 @@ unsigned int hlsl_offset_from_deref_safe(struct hlsl_ctx *ctx, const struct hlsl struct hlsl_reg hlsl_reg_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref); bool hlsl_copy_propagation_execute(struct hlsl_ctx *ctx, struct hlsl_block *block); +struct hlsl_ir_node *hlsl_fold_binary_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block); struct hlsl_ir_node *hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block); struct hlsl_ir_node *hlsl_fold_constant_identities(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block); -bool hlsl_normalize_binary_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context); struct hlsl_ir_node *hlsl_fold_constant_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block); bool hlsl_transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx, struct hlsl_ir_node *, void *), struct hlsl_block *block, void *context); D3DXPARAMETER_CLASS hlsl_sm1_class(const struct hlsl_type *type); -D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type, bool is_combined_sampler); +D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type, + bool is_combined_sampler, enum hlsl_sampler_dim sampler_dim); struct extern_resource { diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c index 6fe29e5bfed..8bb23e0690d 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c @@ -938,7 +938,8 @@ static bool call_replace_func(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, if ((replacement = func(ctx, instr, &block))) { list_move_before(&instr->entry, &block.instrs); - hlsl_replace_node(instr, replacement); + if (replacement != instr) + hlsl_replace_node(instr, replacement); return true; } else @@ -955,7 +956,10 @@ static bool call_replace_func(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, * * New instructions should be added to "block", and the replacement instruction * should be returned. If the instruction should be left alone, NULL should be - * returned instead. */ + * returned instead. + * + * It is legal to return the same instruction from the replace function, in + * which case replace_ir() returns true but hlsl_replace_node() is skipped. */ static bool replace_ir(struct hlsl_ctx *ctx, PFN_replace_func func, struct hlsl_block *block) { return hlsl_transform_ir(ctx, call_replace_func, block, func); @@ -4095,7 +4099,6 @@ static bool lower_conditional_block_stores(struct hlsl_ctx *ctx, struct hlsl_ir_ static bool lower_conditional_block_discard_nz(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_ir_node *cond, bool is_then) { - struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = {0}; struct hlsl_ir_node *discard_cond, *new_cond = NULL; struct hlsl_ir_jump *jump; struct hlsl_block block; @@ -4118,12 +4121,8 @@ static bool lower_conditional_block_discard_nz(struct hlsl_ctx *ctx, struct hlsl cond = hlsl_block_add_unary_expr(ctx, &block, HLSL_OP1_LOGIC_NOT, cond, &instr->loc); discard_cond = hlsl_block_add_cast(ctx, &block, discard_cond, cond->data_type, &instr->loc); - operands[0] = cond; - operands[1] = discard_cond; - /* discard_nz (cond && discard_cond) */ - new_cond = hlsl_block_add_expr(ctx, &block, HLSL_OP2_LOGIC_AND, operands, - hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), &jump->node.loc); + new_cond = hlsl_block_add_binary_expr(ctx, &block, HLSL_OP2_LOGIC_AND, cond, discard_cond); list_move_before(&jump->node.entry, &block.instrs); hlsl_src_remove(&jump->condition); @@ -5250,49 +5249,37 @@ static struct hlsl_ir_node *lower_ternary(struct hlsl_ctx *ctx, struct hlsl_ir_n return hlsl_block_add_expr(ctx, block, HLSL_OP3_CMP, operands, first->data_type, &instr->loc); } -static bool lower_resource_load_bias(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) +static struct hlsl_ir_node *lower_resource_load_bias(struct hlsl_ctx *ctx, + struct hlsl_ir_node *instr, struct hlsl_block *block) { - struct hlsl_ir_node *swizzle, *store; + struct hlsl_ir_node *swizzle, *tmp_load; struct hlsl_ir_resource_load *load; - struct hlsl_ir_load *tmp_load; struct hlsl_ir_var *tmp_var; - struct hlsl_deref deref; if (instr->type != HLSL_IR_RESOURCE_LOAD) - return false; + return NULL; load = hlsl_ir_resource_load(instr); if (load->load_type != HLSL_RESOURCE_SAMPLE_LOD && load->load_type != HLSL_RESOURCE_SAMPLE_LOD_BIAS) - return false; + return NULL; if (!load->lod.node) - return false; + return NULL; if (!(tmp_var = hlsl_new_synthetic_var(ctx, "coords-with-lod", hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, 4), &instr->loc))) - return false; - - if (!(swizzle = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(X, X, X, X), 4, load->lod.node, &load->lod.node->loc))) - return false; - list_add_before(&instr->entry, &swizzle->entry); - - if (!(store = hlsl_new_simple_store(ctx, tmp_var, swizzle))) - return false; - list_add_before(&instr->entry, &store->entry); + return NULL; - hlsl_init_simple_deref_from_var(&deref, tmp_var); - if (!(store = hlsl_new_store_index(ctx, &deref, NULL, load->coords.node, 0, &instr->loc))) - return false; - list_add_before(&instr->entry, &store->entry); + swizzle = hlsl_block_add_swizzle(ctx, block, HLSL_SWIZZLE(X, X, X, X), 4, load->lod.node, &load->lod.node->loc); + hlsl_block_add_simple_store(ctx, block, tmp_var, swizzle); + hlsl_block_add_simple_store(ctx, block, tmp_var, load->coords.node); - if (!(tmp_load = hlsl_new_var_load(ctx, tmp_var, &instr->loc))) - return false; - list_add_before(&instr->entry, &tmp_load->node.entry); + tmp_load = hlsl_block_add_simple_load(ctx, block, tmp_var, &instr->loc); hlsl_src_remove(&load->coords); - hlsl_src_from_node(&load->coords, &tmp_load->node); + hlsl_src_from_node(&load->coords, tmp_load); hlsl_src_remove(&load->lod); - return true; + return &load->node; } static struct hlsl_ir_node *lower_comparison_operators(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, @@ -5746,34 +5733,29 @@ static bool lower_discard_neg(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, return true; } -static bool lower_discard_nz(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) +static struct hlsl_ir_node *lower_discard_nz(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) { struct hlsl_ir_node *cond, *cond_cast, *abs, *neg; struct hlsl_type *float_type; struct hlsl_ir_jump *jump; - struct hlsl_block block; if (instr->type != HLSL_IR_JUMP) - return false; + return NULL; jump = hlsl_ir_jump(instr); if (jump->type != HLSL_IR_JUMP_DISCARD_NZ) - return false; + return NULL; cond = jump->condition.node; float_type = hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, cond->data_type->e.numeric.dimx); - hlsl_block_init(&block); - - cond_cast = hlsl_block_add_cast(ctx, &block, cond, float_type, &instr->loc); - abs = hlsl_block_add_unary_expr(ctx, &block, HLSL_OP1_ABS, cond_cast, &instr->loc); - neg = hlsl_block_add_unary_expr(ctx, &block, HLSL_OP1_NEG, abs, &instr->loc); + cond_cast = hlsl_block_add_cast(ctx, block, cond, float_type, &instr->loc); + abs = hlsl_block_add_unary_expr(ctx, block, HLSL_OP1_ABS, cond_cast, &instr->loc); + neg = hlsl_block_add_unary_expr(ctx, block, HLSL_OP1_NEG, abs, &instr->loc); - list_move_tail(&instr->entry, &block.instrs); hlsl_src_remove(&jump->condition); hlsl_src_from_node(&jump->condition, neg); jump->type = HLSL_IR_JUMP_DISCARD_NEG; - - return true; + return &jump->node; } static bool cast_discard_neg_conditions_to_vec4(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) @@ -8551,96 +8533,74 @@ static enum hlsl_ir_expr_op invert_comparison_op(enum hlsl_ir_expr_op op) } } -static bool fold_unary_identities(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) +static struct hlsl_ir_node *fold_unary_identities(struct hlsl_ctx *ctx, + struct hlsl_ir_node *instr, struct hlsl_block *block) { - struct hlsl_ir_node *res = NULL; struct hlsl_ir_expr *expr, *x; if (instr->type != HLSL_IR_EXPR) - return false; + return NULL; if (instr->data_type->class > HLSL_CLASS_VECTOR) - return false; + return NULL; expr = hlsl_ir_expr(instr); if (!expr->operands[0].node) - return false; + return NULL; if (expr->operands[0].node->type != HLSL_IR_EXPR) - return false; + return NULL; x = hlsl_ir_expr(expr->operands[0].node); switch (expr->op) { case HLSL_OP1_ABS: + /* ||x|| -> |x| */ if (x->op == HLSL_OP1_ABS) - { - /* ||x|| -> |x| */ - hlsl_replace_node(instr, &x->node); - return true; - } + return &x->node; + /* |-x| -> |x| */ if (x->op == HLSL_OP1_NEG) { - /* |-x| -> |x| */ hlsl_src_remove(&expr->operands[0]); hlsl_src_from_node(&expr->operands[0], x->operands[0].node); - return true; + return &expr->node; } break; case HLSL_OP1_BIT_NOT: + /* ~(~x) -> x */ if (x->op == HLSL_OP1_BIT_NOT) - { - /* ~(~x) -> x */ - hlsl_replace_node(instr, x->operands[0].node); - return true; - } + return x->operands[0].node; break; case HLSL_OP1_CEIL: case HLSL_OP1_FLOOR: + /* f(g(x)) -> g(x), where f(), g() are floor() or ceil() functions. */ if (x->op == HLSL_OP1_CEIL || x->op == HLSL_OP1_FLOOR) - { - /* f(g(x)) -> g(x), where f(), g() are floor() or ceil() functions. */ - hlsl_replace_node(instr, &x->node); - return true; - } + return &x->node; break; case HLSL_OP1_NEG: + /* -(-x) -> x */ if (x->op == HLSL_OP1_NEG) - { - /* -(-x) -> x */ - hlsl_replace_node(instr, x->operands[0].node); - return true; - } + return x->operands[0].node; break; case HLSL_OP1_LOGIC_NOT: + /* !!x -> x */ if (x->op == HLSL_OP1_LOGIC_NOT) - { - /* !!x -> x */ - hlsl_replace_node(instr, x->operands[0].node); - return true; - } + return x->operands[0].node; if (hlsl_is_comparison_op(x->op) && hlsl_base_type_is_integer(x->operands[0].node->data_type->e.numeric.type) && hlsl_base_type_is_integer(x->operands[1].node->data_type->e.numeric.type)) { struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = {x->operands[0].node, x->operands[1].node}; - struct hlsl_block block; - - hlsl_block_init(&block); /* !(x == y) -> x != y, !(x < y) -> x >= y, etc. */ - res = hlsl_block_add_expr(ctx, &block, invert_comparison_op(x->op), + return hlsl_block_add_expr(ctx, block, invert_comparison_op(x->op), operands, instr->data_type, &instr->loc); - - list_move_before(&instr->entry, &block.instrs); - hlsl_replace_node(instr, res); - return true; } break; @@ -8649,7 +8609,7 @@ static bool fold_unary_identities(struct hlsl_ctx *ctx, struct hlsl_ir_node *ins break; } - return false; + return NULL; } static bool nodes_are_equivalent(const struct hlsl_ir_node *c1, const struct hlsl_ir_node *c2) @@ -8784,8 +8744,8 @@ static bool simplify_exprs(struct hlsl_ctx *ctx, struct hlsl_block *block) do { progress = replace_ir(ctx, hlsl_fold_constant_exprs, block); - progress |= hlsl_transform_ir(ctx, hlsl_normalize_binary_exprs, block, NULL); - progress |= hlsl_transform_ir(ctx, fold_unary_identities, block, NULL); + progress |= replace_ir(ctx, hlsl_fold_binary_exprs, block); + progress |= replace_ir(ctx, fold_unary_identities, block); progress |= replace_ir(ctx, fold_conditional_identities, block); progress |= replace_ir(ctx, hlsl_fold_constant_identities, block); progress |= replace_ir(ctx, hlsl_fold_constant_swizzles, block); @@ -10053,7 +10013,7 @@ static void sm1_generate_vsir_init_dst_param_from_deref(struct hlsl_ctx *ctx, else writemask = (1u << deref->var->data_type->e.numeric.dimx) - 1; - if (version.type == VKD3D_SHADER_TYPE_PIXEL && (!ascii_strcasecmp(semantic_name, "PSIZE") + if (version.type == VKD3D_SHADER_TYPE_VERTEX && (!ascii_strcasecmp(semantic_name, "PSIZE") || (!ascii_strcasecmp(semantic_name, "FOG") && version.major < 3))) { /* These are always 1-component, but for some reason are written @@ -10525,7 +10485,8 @@ D3DXPARAMETER_CLASS hlsl_sm1_class(const struct hlsl_type *type) vkd3d_unreachable(); } -D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type, bool is_combined_sampler) +D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type, + bool is_combined_sampler, enum hlsl_sampler_dim sampler_dim) { enum hlsl_type_class class = type->class; @@ -10564,7 +10525,7 @@ D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type, bool is_comb break; case HLSL_CLASS_SAMPLER: - switch (type->sampler_dim) + switch (sampler_dim) { case HLSL_SAMPLER_DIM_1D: return D3DXPT_SAMPLER1D; @@ -10602,7 +10563,7 @@ D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type, bool is_comb break; case HLSL_CLASS_ARRAY: - return hlsl_sm1_base_type(type->e.array.type, is_combined_sampler); + return hlsl_sm1_base_type(type->e.array.type, is_combined_sampler, sampler_dim); case HLSL_CLASS_STRUCT: return D3DXPT_VOID; @@ -10640,15 +10601,19 @@ D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type, bool is_comb vkd3d_unreachable(); } -static void write_sm1_type(struct vkd3d_bytecode_buffer *buffer, - struct hlsl_type *type, bool is_combined_sampler, unsigned int ctab_start) +static void write_sm1_type(struct vkd3d_bytecode_buffer *buffer, struct hlsl_type *type, + bool is_combined_sampler, enum hlsl_sampler_dim sampler_dim, unsigned int ctab_start) { const struct hlsl_type *array_type = hlsl_get_multiarray_element_type(type); unsigned int array_size = hlsl_get_multiarray_size(type); struct hlsl_struct_field *field; size_t i; - if (type->bytecode_offset) + /* Native deduplicates types, but emits the correct dimension for generic + * samplers. Apparently it deals with this by never deduplicating any + * sampler types. This is not very efficient, but we may as well do the + * same. */ + if (type->bytecode_offset && array_type->class != HLSL_CLASS_SAMPLER) return; if (array_type->class == HLSL_CLASS_STRUCT) @@ -10660,7 +10625,7 @@ static void write_sm1_type(struct vkd3d_bytecode_buffer *buffer, { field = &array_type->e.record.fields[i]; field->name_bytecode_offset = put_string(buffer, field->name); - write_sm1_type(buffer, field->type, false, ctab_start); + write_sm1_type(buffer, field->type, false, HLSL_SAMPLER_DIM_GENERIC, ctab_start); } fields_offset = bytecode_align(buffer) - ctab_start; @@ -10680,9 +10645,11 @@ static void write_sm1_type(struct vkd3d_bytecode_buffer *buffer, else { type->bytecode_offset = put_u32(buffer, - vkd3d_make_u32(hlsl_sm1_class(type), hlsl_sm1_base_type(array_type, is_combined_sampler))); + vkd3d_make_u32(hlsl_sm1_class(type), hlsl_sm1_base_type(array_type, is_combined_sampler, sampler_dim))); if (hlsl_is_numeric_type(array_type)) put_u32(buffer, vkd3d_make_u32(array_type->e.numeric.dimy, array_type->e.numeric.dimx)); + else if (is_combined_sampler) + put_u32(buffer, vkd3d_make_u32(1, 4)); else put_u32(buffer, vkd3d_make_u32(1, 1)); put_u32(buffer, vkd3d_make_u32(array_size, 0)); @@ -10736,7 +10703,9 @@ static void write_sm1_uniforms(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffe ++uniform_count; - if (var->is_param && var->is_uniform) + /* Not var->is_uniform. The $ prefix is only added if the variable + * is actually declared with a 'uniform' modifier. */ + if (var->is_param && (var->storage_modifiers & HLSL_STORAGE_UNIFORM)) { char *new_name; @@ -10793,17 +10762,33 @@ static void write_sm1_uniforms(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffe { for (r = 0; r <= HLSL_REGSET_LAST; ++r) { + enum hlsl_sampler_dim sampler_dim = HLSL_SAMPLER_DIM_GENERIC; size_t var_offset, name_offset; if (var->semantic.name || !var->regs[r].allocated || !var->last_read) continue; + /* Arrays can be used with multiple different dimensions. + * The dimension written into the CTAB is the dimension of the + * first usage, which is not really that sensible... */ + if (r == HLSL_REGSET_SAMPLERS) + { + for (unsigned int i = 0; i < var->bind_count[r]; ++i) + { + if (var->objects_usage[r][i].sampler_dim != HLSL_SAMPLER_DIM_GENERIC) + { + sampler_dim = var->objects_usage[r][i].sampler_dim; + break; + } + } + } + var_offset = vars_start + (uniform_count * 5 * sizeof(uint32_t)); name_offset = put_string(buffer, var->name); set_u32(buffer, var_offset, name_offset - ctab_start); - write_sm1_type(buffer, var->data_type, var->is_combined_sampler, ctab_start); + write_sm1_type(buffer, var->data_type, var->is_combined_sampler, sampler_dim, ctab_start); set_u32(buffer, var_offset + 3 * sizeof(uint32_t), var->data_type->bytecode_offset - ctab_start); if (var->default_values) @@ -15101,8 +15086,8 @@ static void process_entry_function(struct hlsl_ctx *ctx, struct list *semantic_v } else { - hlsl_transform_ir(ctx, lower_discard_nz, body, NULL); - hlsl_transform_ir(ctx, lower_resource_load_bias, body, NULL); + replace_ir(ctx, lower_discard_nz, body); + replace_ir(ctx, lower_resource_load_bias, body); } compute_liveness(ctx, body); diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c index 1c44e5fa37a..627418165bc 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c @@ -1818,26 +1818,23 @@ static struct hlsl_ir_node *collect_exprs(struct hlsl_ctx *ctx, struct hlsl_bloc return hlsl_block_add_expr(ctx, block, opl, operands, instr->data_type, &instr->loc); } -bool hlsl_normalize_binary_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) +struct hlsl_ir_node *hlsl_fold_binary_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) { struct hlsl_ir_node *arg1, *arg2, *tmp; struct hlsl_ir_expr *expr; enum hlsl_base_type type; enum hlsl_ir_expr_op op; - struct hlsl_block block; bool progress = false; if (instr->type != HLSL_IR_EXPR) - return false; + return NULL; expr = hlsl_ir_expr(instr); if (instr->data_type->class > HLSL_CLASS_VECTOR) - return false; + return NULL; if (expr->operands[2].node) - return false; - - hlsl_block_init(&block); + return NULL; arg1 = expr->operands[0].node; arg2 = expr->operands[1].node; @@ -1845,15 +1842,11 @@ bool hlsl_normalize_binary_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst op = expr->op; if (!arg1 || !arg2) - return false; + return NULL; - if ((tmp = collect_exprs(ctx, &block, instr, op, arg1, arg2))) - { - /* (x OPL a) OPR (x OPL b) -> x OPL (a OPR b) */ - list_move_before(&instr->entry, &block.instrs); - hlsl_replace_node(instr, tmp); - return true; - } + /* (x OPL a) OPR (x OPL b) -> x OPL (a OPR b) */ + if ((tmp = collect_exprs(ctx, block, instr, op, arg1, arg2))) + return tmp; if (is_op_commutative(op) && arg1->type == HLSL_IR_CONSTANT && arg2->type != HLSL_IR_CONSTANT) { @@ -1876,13 +1869,13 @@ bool hlsl_normalize_binary_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst { /* (x OP a) OP b -> x OP (a OP b) */ arg1 = e1->operands[0].node; - arg2 = hlsl_block_add_binary_expr(ctx, &block, op, e1->operands[1].node, arg2); + arg2 = hlsl_block_add_binary_expr(ctx, block, op, e1->operands[1].node, arg2); progress = true; } else if (is_op_commutative(op)) { /* (x OP a) OP y -> (x OP y) OP a */ - arg1 = hlsl_block_add_binary_expr(ctx, &block, op, e1->operands[0].node, arg2); + arg1 = hlsl_block_add_binary_expr(ctx, block, op, e1->operands[0].node, arg2); arg2 = e1->operands[1].node; progress = true; } @@ -1892,13 +1885,13 @@ bool hlsl_normalize_binary_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst && e2->operands[0].node->type != HLSL_IR_CONSTANT && e2->operands[1].node->type == HLSL_IR_CONSTANT) { /* x OP (y OP a) -> (x OP y) OP a */ - arg1 = hlsl_block_add_binary_expr(ctx, &block, op, arg1, e2->operands[0].node); + arg1 = hlsl_block_add_binary_expr(ctx, block, op, arg1, e2->operands[0].node); arg2 = e2->operands[1].node; progress = true; } if (!progress && e1 && e1->op == op - && (tmp = collect_exprs(ctx, &block, instr, op, e1->operands[1].node, arg2))) + && (tmp = collect_exprs(ctx, block, instr, op, e1->operands[1].node, arg2))) { /* (y OPR (x OPL a)) OPR (x OPL b) -> y OPR (x OPL (a OPR b)) */ arg1 = e1->operands[0].node; @@ -1907,7 +1900,7 @@ bool hlsl_normalize_binary_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst } if (!progress && is_op_commutative(op) && e1 && e1->op == op - && (tmp = collect_exprs(ctx, &block, instr, op, e1->operands[0].node, arg2))) + && (tmp = collect_exprs(ctx, block, instr, op, e1->operands[0].node, arg2))) { /* ((x OPL a) OPR y) OPR (x OPL b) -> (x OPL (a OPR b)) OPR y */ arg1 = tmp; @@ -1916,7 +1909,7 @@ bool hlsl_normalize_binary_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst } if (!progress && e2 && e2->op == op - && (tmp = collect_exprs(ctx, &block, instr, op, arg1, e2->operands[0].node))) + && (tmp = collect_exprs(ctx, block, instr, op, arg1, e2->operands[0].node))) { /* (x OPL a) OPR ((x OPL b) OPR y) -> (x OPL (a OPR b)) OPR y */ arg1 = tmp; @@ -1925,7 +1918,7 @@ bool hlsl_normalize_binary_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst } if (!progress && is_op_commutative(op) && e2 && e2->op == op - && (tmp = collect_exprs(ctx, &block, instr, op, arg1, e2->operands[1].node))) + && (tmp = collect_exprs(ctx, block, instr, op, arg1, e2->operands[1].node))) { /* (x OPL a) OPR (y OPR (x OPL b)) -> (x OPL (a OPR b)) OPR y */ arg1 = tmp; @@ -1937,15 +1930,11 @@ bool hlsl_normalize_binary_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst if (progress) { struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = {arg1, arg2}; - struct hlsl_ir_node *res; - - res = hlsl_block_add_expr(ctx, &block, op, operands, instr->data_type, &instr->loc); - list_move_before(&instr->entry, &block.instrs); - hlsl_replace_node(instr, res); + return hlsl_block_add_expr(ctx, block, op, operands, instr->data_type, &instr->loc); } - return progress; + return NULL; } struct hlsl_ir_node *hlsl_fold_constant_swizzles(struct hlsl_ctx *ctx, diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c index 5b1d0449a64..6a1c5303eb4 100644 --- a/libs/vkd3d/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d/libs/vkd3d-shader/ir.c @@ -3846,16 +3846,19 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par break; case VKD3DSPR_RASTOUT: + /* Fog and point size are scalar, but fxc/d3dcompiler emits a full + * write mask when writing to them. */ + if (reg->idx[0].offset > 0) + { + write_mask = VKD3DSP_WRITEMASK_0; + dst_param->write_mask = write_mask; + } /* Leave point size as a system value for the backends to consume. */ if (reg->idx[0].offset == VSIR_RASTOUT_POINT_SIZE) return true; reg_idx = SM1_RASTOUT_REGISTER_OFFSET + reg->idx[0].offset; signature = normaliser->output_signature; reg->type = VKD3DSPR_OUTPUT; - /* Fog and point size are scalar, but fxc/d3dcompiler emits a full - * write mask when writing to them. */ - if (reg->idx[0].offset > 0) - write_mask = VKD3DSP_WRITEMASK_0; break; default: -- 2.51.0