Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- libs/vkd3d-shader/hlsl_codegen.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index afa096b0..7395772f 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -1733,6 +1733,10 @@ static void write_sm1_expr(struct hlsl_ctx *ctx, struct bytecode_buffer *buffer, write_sm1_binary_op(ctx, buffer, D3DSIO_MUL, &instr->reg, &arg1->reg, &arg2->reg); break;
+ case HLSL_IR_BINOP_SUB: + write_sm1_binary_op(ctx, buffer, D3DSIO_SUB, &instr->reg, &arg1->reg, &arg2->reg); + break; + case HLSL_IR_UNOP_NEG: write_sm1_unary_op(ctx, buffer, D3DSIO_MOV, &instr->reg, &arg1->reg, D3DSPSM_NEG); break;
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- libs/vkd3d-shader/hlsl_codegen.c | 42 +++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 7395772f..aa1b8d59 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -332,7 +332,7 @@ static bool fold_constants(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, voi { struct hlsl_ir_constant *arg1, *arg2 = NULL, *res; struct hlsl_ir_expr *expr; - unsigned int i; + unsigned int i, dimx;
if (instr->type != HLSL_IR_EXPR) return false; @@ -346,6 +346,7 @@ static bool fold_constants(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, voi arg1 = hlsl_ir_constant(expr->operands[0].node); if (expr->operands[1].node) arg2 = hlsl_ir_constant(expr->operands[1].node); + dimx = instr->data_type->dimx;
if (!(res = hlsl_alloc(ctx, sizeof(*res)))) return false; @@ -353,10 +354,45 @@ static bool fold_constants(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, voi
switch (instr->data_type->base_type) { - case HLSL_TYPE_UINT: + case HLSL_TYPE_FLOAT: { - unsigned int i; + switch (expr->op) + { + case HLSL_IR_UNOP_CAST: + if (instr->data_type->dimx != arg1->node.data_type->dimx + || instr->data_type->dimy != arg1->node.data_type->dimy) + { + FIXME("Cast from %s to %s.\n", debug_hlsl_type(ctx, arg1->node.data_type), + debug_hlsl_type(ctx, instr->data_type)); + vkd3d_free(res); + return false; + }
+ switch (arg1->node.data_type->base_type) + { + case HLSL_TYPE_UINT: + for (i = 0; i < dimx; ++i) + res->value.f[i] = arg1->value.u[i]; + break; + + default: + FIXME("Cast from %s to %s.\n", debug_hlsl_type(ctx, arg1->node.data_type), + debug_hlsl_type(ctx, instr->data_type)); + vkd3d_free(res); + return false; + } + break; + + default: + FIXME("Fold float op %#x.\n", expr->op); + vkd3d_free(res); + return false; + } + break; + } + + case HLSL_TYPE_UINT: + { switch (expr->op) { case HLSL_IR_BINOP_ADD:
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- libs/vkd3d-shader/hlsl_codegen.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index aa1b8d59..3b1b19c1 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -1106,6 +1106,13 @@ static unsigned int map_swizzle(unsigned int swizzle, unsigned int writemask) { unsigned int i, ret = 0;
+ /* Leave replicate swizzles alone; some instructions need them. */ + if (swizzle == HLSL_SWIZZLE(X, X, X, X) + || swizzle == HLSL_SWIZZLE(Y, Y, Y, Y) + || swizzle == HLSL_SWIZZLE(Z, Z, Z, Z) + || swizzle == HLSL_SWIZZLE(W, W, W, W)) + return swizzle; + for (i = 0; i < 4; ++i) { if (writemask & (1 << i)) @@ -1750,6 +1757,7 @@ static void write_sm1_expr(struct hlsl_ctx *ctx, struct bytecode_buffer *buffer, struct hlsl_ir_expr *expr = hlsl_ir_expr(instr); struct hlsl_ir_node *arg1 = expr->operands[0].node; struct hlsl_ir_node *arg2 = expr->operands[1].node; + unsigned int i;
assert(instr->reg.allocated);
@@ -1777,6 +1785,17 @@ static void write_sm1_expr(struct hlsl_ctx *ctx, struct bytecode_buffer *buffer, write_sm1_unary_op(ctx, buffer, D3DSIO_MOV, &instr->reg, &arg1->reg, D3DSPSM_NEG); break;
+ case HLSL_IR_UNOP_RCP: + for (i = 0; i < instr->data_type->dimx; ++i) + { + struct hlsl_reg src = arg1->reg, dst = instr->reg; + + src.writemask = combine_writemasks(src.writemask, 1u << i); + dst.writemask = combine_writemasks(dst.writemask, 1u << i); + write_sm1_unary_op(ctx, buffer, D3DSIO_RCP, &dst, &src, 0); + } + break; + default: FIXME("Unhandled op %u.\n", expr->op); break;
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Essentially because the meaning of 'b' differs between SM1-3 and SM4+.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- libs/vkd3d-shader/hlsl.h | 2 +- libs/vkd3d-shader/hlsl.y | 22 +--------------------- 2 files changed, 2 insertions(+), 22 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 4fe90a91..906d864d 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -212,7 +212,7 @@ struct hlsl_src
struct hlsl_reg_reservation { - enum vkd3d_shader_register_type type; + char type; DWORD regnum; };
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index cab46aee..d8ad1f98 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -782,29 +782,9 @@ static bool add_func_parameter(struct hlsl_ctx *ctx, struct list *list,
static struct hlsl_reg_reservation *parse_reg_reservation(struct hlsl_ctx *ctx, const char *reg_string) { - enum vkd3d_shader_register_type type; struct hlsl_reg_reservation *reg_res; DWORD regnum = 0;
- switch (reg_string[0]) - { - case 'c': - type = VKD3DSPR_CONST; - break; - case 'i': - type = VKD3DSPR_CONSTINT; - break; - case 'b': - type = VKD3DSPR_CONSTBOOL; - break; - case 's': - type = VKD3DSPR_SAMPLER; - break; - default: - FIXME("Unsupported register type.\n"); - return NULL; - } - if (!sscanf(reg_string + 1, "%u", ®num)) { FIXME("Unsupported register reservation syntax.\n"); @@ -813,7 +793,7 @@ static struct hlsl_reg_reservation *parse_reg_reservation(struct hlsl_ctx *ctx,
if (!(reg_res = hlsl_alloc(ctx, sizeof(*reg_res)))) return NULL; - reg_res->type = type; + reg_res->type = reg_string[0]; reg_res->regnum = regnum; return reg_res; }
Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- I guess in the future we might go back to storing the register type as some (different) kind of enum, but this is certainly fine for the time being.
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- libs/vkd3d-shader/hlsl.c | 4 +-- libs/vkd3d-shader/hlsl.h | 2 +- libs/vkd3d-shader/hlsl.y | 44 +++++++++++++------------------- libs/vkd3d-shader/hlsl_codegen.c | 2 +- 4 files changed, 22 insertions(+), 30 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 441fd6c2..e9bfc374 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -95,7 +95,6 @@ void hlsl_free_var(struct hlsl_ir_var *decl) { vkd3d_free((void *)decl->name); vkd3d_free((void *)decl->semantic.name); - vkd3d_free((void *)decl->reg_reservation); vkd3d_free(decl); }
@@ -406,7 +405,8 @@ struct hlsl_ir_var *hlsl_new_var(struct hlsl_ctx *ctx, const char *name, struct if (semantic) var->semantic = *semantic; var->modifiers = modifiers; - var->reg_reservation = reg_reservation; + if (reg_reservation) + var->reg_reservation = *reg_reservation; return var; }
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 906d864d..d9e51b8d 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -223,7 +223,7 @@ struct hlsl_ir_var const char *name; struct hlsl_semantic semantic; unsigned int modifiers; - const struct hlsl_reg_reservation *reg_reservation; + struct hlsl_reg_reservation reg_reservation; struct list scope_entry, param_entry, extern_entry;
unsigned int first_write, last_read; diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index d8ad1f98..2e631fac 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -33,14 +33,14 @@ struct parse_parameter struct hlsl_type *type; const char *name; struct hlsl_semantic semantic; - const struct hlsl_reg_reservation *reg_reservation; + struct hlsl_reg_reservation reg_reservation; unsigned int modifiers; };
struct parse_colon_attribute { struct hlsl_semantic semantic; - struct hlsl_reg_reservation *reg_reservation; + struct hlsl_reg_reservation reg_reservation; };
struct parse_initializer @@ -64,7 +64,7 @@ struct parse_variable_def char *name; struct parse_array_sizes arrays; struct hlsl_semantic semantic; - struct hlsl_reg_reservation *reg_reservation; + struct hlsl_reg_reservation reg_reservation; struct parse_initializer initializer; };
@@ -767,7 +767,7 @@ static bool add_func_parameter(struct hlsl_ctx *ctx, struct list *list, hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, "Parameter '%s' is declared as both "out" and "uniform".", param->name);
- if (!(var = hlsl_new_var(ctx, param->name, param->type, loc, ¶m->semantic, param->modifiers, param->reg_reservation))) + if (!(var = hlsl_new_var(ctx, param->name, param->type, loc, ¶m->semantic, param->modifiers, ¶m->reg_reservation))) return false; var->is_param = 1;
@@ -780,22 +780,17 @@ static bool add_func_parameter(struct hlsl_ctx *ctx, struct list *list, return true; }
-static struct hlsl_reg_reservation *parse_reg_reservation(struct hlsl_ctx *ctx, const char *reg_string) +static struct hlsl_reg_reservation parse_reg_reservation(const char *reg_string) { - struct hlsl_reg_reservation *reg_res; - DWORD regnum = 0; + struct hlsl_reg_reservation reservation = {0};
- if (!sscanf(reg_string + 1, "%u", ®num)) + if (!sscanf(reg_string + 1, "%u", &reservation.regnum)) { FIXME("Unsupported register reservation syntax.\n"); - return NULL; + return reservation; } - - if (!(reg_res = hlsl_alloc(ctx, sizeof(*reg_res)))) - return NULL; - reg_res->type = reg_string[0]; - reg_res->regnum = regnum; - return reg_res; + reservation.type = reg_string[0]; + return reservation; }
static const struct hlsl_ir_function_decl *get_overloaded_func(struct rb_tree *funcs, char *name, @@ -1354,7 +1349,6 @@ static void free_parse_variable_def(struct parse_variable_def *v) vkd3d_free(v->arrays.sizes); vkd3d_free(v->name); vkd3d_free((void *)v->semantic.name); - vkd3d_free(v->reg_reservation); vkd3d_free(v); }
@@ -1393,7 +1387,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(ctx, v->name, type, v->loc, &v->semantic, modifiers, v->reg_reservation))) + if (!(var = hlsl_new_var(ctx, v->name, type, v->loc, &v->semantic, modifiers, &v->reg_reservation))) { free_parse_variable_def(v); continue; @@ -1564,7 +1558,7 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t struct parse_if_body if_body; enum parse_unary_op unary_op; enum parse_assign_op assign_op; - struct hlsl_reg_reservation *reg_reservation; + struct hlsl_reg_reservation reg_reservation; struct parse_colon_attribute colon_attribute; struct hlsl_semantic semantic; } @@ -1962,11 +1956,9 @@ func_prototype: "Semantics are not allowed on void functions."); }
- if ($7.reg_reservation) - { + if ($7.reg_reservation.type) 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))) YYABORT; $$.name = $3; @@ -1999,12 +1991,12 @@ colon_attribute: %empty { $$.semantic.name = NULL; - $$.reg_reservation = NULL; + $$.reg_reservation.type = 0; } | semantic { $$.semantic = $1; - $$.reg_reservation = NULL; + $$.reg_reservation.type = 0; } | register_opt { @@ -2028,7 +2020,7 @@ semantic: register_opt: ':' KW_REGISTER '(' any_identifier ')' { - $$ = parse_reg_reservation(ctx, $4); + $$ = parse_reg_reservation($4); vkd3d_free($4); } | ':' KW_REGISTER '(' any_identifier ',' any_identifier ')' @@ -2036,7 +2028,7 @@ register_opt: FIXME("Ignoring shader target %s in a register reservation.\n", debugstr_a($4)); vkd3d_free($4);
- $$ = parse_reg_reservation(ctx, $6); + $$ = parse_reg_reservation($6); vkd3d_free($6); }
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 3b1b19c1..366b8bda 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -35,7 +35,7 @@ static void prepend_uniform_copy(struct hlsl_ctx *ctx, struct list *instrs, stru /* Use the synthetic name for the temp, rather than the uniform, so that we * can write the uniform name into the shader reflection data. */
- if (!(uniform = hlsl_new_var(ctx, temp->name, temp->data_type, temp->loc, NULL, 0, temp->reg_reservation))) + if (!(uniform = hlsl_new_var(ctx, temp->name, temp->data_type, temp->loc, NULL, 0, &temp->reg_reservation))) return; list_add_before(&temp->scope_entry, &uniform->scope_entry); list_add_tail(&ctx->extern_vars, &uniform->extern_entry);
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- Just to make sure not to write uninitialized values in the shader when the last constant doesn't take the whole register.
libs/vkd3d-shader/hlsl_codegen.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 366b8bd..54c91bf 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -843,7 +843,12 @@ static void allocate_const_registers_recurse(struct hlsl_ctx *ctx, struct list * if (!hlsl_array_reserve(ctx, (void **)&defs->values, &defs->size, constant->reg.id + reg_size, sizeof(*defs->values))) return; - defs->count = max(defs->count, constant->reg.id + reg_size); + if (constant->reg.id + reg_size > defs->count) + { + memset(&defs->values[defs->count], 0, + sizeof(*defs->values) * (constant->reg.id + reg_size - defs->count)); + defs->count = constant->reg.id + reg_size; + }
assert(type->type <= HLSL_CLASS_LAST_NUMERIC);
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- Sorry for the delay, I totally missed this patch series... /me updates his email filtering rules
We should probably get rid of HLSL_IR_BINOP_SUB at some point: HLSL_IR_BINOP_ADD + HLSL_IR_UNOP_NEG does the same thing at least as well and it's one less case to handle in a number of places. Also on the output side, there is no corresponding SM4+ instruction and IIRC the native compiler doesn't generate SUB instructions for SM1 either.
On 6/17/21 4:48 AM, Matteo Bruni wrote:
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
Sorry for the delay, I totally missed this patch series... /me updates his email filtering rules
We should probably get rid of HLSL_IR_BINOP_SUB at some point: HLSL_IR_BINOP_ADD + HLSL_IR_UNOP_NEG does the same thing at least as well and it's one less case to handle in a number of places. Also on the output side, there is no corresponding SM4+ instruction and IIRC the native compiler doesn't generate SUB instructions for SM1 either.
I actually had an SM4-specific lowering pass for that already, but I figured as long as there's a SUB instruction for SM1 there's no reason not to use it...
Turns out you're right, though, it uses add + negative modifier. Guess that's one more instruction we could remove at parse time.