vkd3d-shader/hlsl: Store simple SM4 expressions in the vsir program.

This commit is contained in:
Francisco Casas 2024-11-01 01:08:16 -03:00 committed by Henri Verbeet
parent b4608e99e3
commit ab60f4e082
Notes: Henri Verbeet 2024-11-05 20:06:02 +01:00
Approved-by: Elizabeth Figura (@zfigura)
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1246
2 changed files with 399 additions and 382 deletions

View File

@ -7791,15 +7791,359 @@ static void sm4_generate_vsir_instr_dcl_indexable_temp(struct hlsl_ctx *ctx,
add_last_vsir_instr_to_block(ctx, program, block);
}
static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx,
struct vsir_program *program, struct hlsl_ir_expr *expr)
static bool type_is_float(const struct hlsl_type *type)
{
return type->e.numeric.type == HLSL_TYPE_FLOAT || type->e.numeric.type == HLSL_TYPE_HALF;
}
static bool type_is_integer(const struct hlsl_type *type)
{
return type->e.numeric.type == HLSL_TYPE_BOOL
|| type->e.numeric.type == HLSL_TYPE_INT
|| type->e.numeric.type == HLSL_TYPE_UINT;
}
static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx,
struct vsir_program *program, struct hlsl_ir_expr *expr, const char *dst_type_name)
{
const struct hlsl_type *dst_type = expr->node.data_type;
const struct hlsl_type *src_type = NULL;
VKD3D_ASSERT(expr->node.reg.allocated);
if (expr->operands[0].node)
src_type = expr->operands[0].node->data_type;
switch (expr->op)
{
case HLSL_OP1_ABS:
VKD3D_ASSERT(type_is_float(dst_type));
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_MOV, VKD3DSPSM_ABS, 0, true);
return true;
case HLSL_OP1_BIT_NOT:
VKD3D_ASSERT(type_is_integer(dst_type));
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_NOT, 0, 0, true);
return true;
case HLSL_OP1_CEIL:
VKD3D_ASSERT(type_is_float(dst_type));
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_ROUND_PI, 0, 0, true);
return true;
case HLSL_OP1_DSX:
VKD3D_ASSERT(type_is_float(dst_type));
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_DSX, 0, 0, true);
return true;
case HLSL_OP1_DSX_COARSE:
VKD3D_ASSERT(type_is_float(dst_type));
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_DSX_COARSE, 0, 0, true);
return true;
case HLSL_OP1_DSX_FINE:
VKD3D_ASSERT(type_is_float(dst_type));
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_DSX_FINE, 0, 0, true);
return true;
case HLSL_OP1_DSY:
VKD3D_ASSERT(type_is_float(dst_type));
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_DSY, 0, 0, true);
return true;
case HLSL_OP1_DSY_COARSE:
VKD3D_ASSERT(type_is_float(dst_type));
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_DSY_COARSE, 0, 0, true);
return true;
case HLSL_OP1_DSY_FINE:
VKD3D_ASSERT(type_is_float(dst_type));
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_DSY_FINE, 0, 0, true);
return true;
case HLSL_OP1_EXP2:
VKD3D_ASSERT(type_is_float(dst_type));
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_EXP, 0, 0, true);
return true;
case HLSL_OP1_F16TOF32:
VKD3D_ASSERT(type_is_float(dst_type));
VKD3D_ASSERT(hlsl_version_ge(ctx, 5, 0));
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_F16TOF32, 0, 0, true);
return true;
case HLSL_OP1_F32TOF16:
VKD3D_ASSERT(dst_type->e.numeric.type == HLSL_TYPE_UINT);
VKD3D_ASSERT(hlsl_version_ge(ctx, 5, 0));
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_F32TOF16, 0, 0, true);
return true;
case HLSL_OP1_FLOOR:
VKD3D_ASSERT(type_is_float(dst_type));
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_ROUND_NI, 0, 0, true);
return true;
case HLSL_OP1_FRACT:
VKD3D_ASSERT(type_is_float(dst_type));
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_FRC, 0, 0, true);
return true;
case HLSL_OP1_LOG2:
VKD3D_ASSERT(type_is_float(dst_type));
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_LOG, 0, 0, true);
return true;
case HLSL_OP1_LOGIC_NOT:
VKD3D_ASSERT(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_NOT, 0, 0, true);
return true;
case HLSL_OP1_NEG:
switch (dst_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_MOV, VKD3DSPSM_NEG, 0, true);
return true;
case HLSL_TYPE_INT:
case HLSL_TYPE_UINT:
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_INEG, 0, 0, true);
return true;
default:
hlsl_fixme(ctx, &expr->node.loc, "SM4 %s negation expression.", dst_type_name);
return false;
}
case HLSL_OP1_REINTERPRET:
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_MOV, 0, 0, true);
return true;
case HLSL_OP1_ROUND:
VKD3D_ASSERT(type_is_float(dst_type));
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_ROUND_NE, 0, 0, true);
return true;
case HLSL_OP1_RSQ:
VKD3D_ASSERT(type_is_float(dst_type));
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_RSQ, 0, 0, true);
return true;
case HLSL_OP1_SQRT:
VKD3D_ASSERT(type_is_float(dst_type));
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_SQRT, 0, 0, true);
return true;
case HLSL_OP1_TRUNC:
VKD3D_ASSERT(type_is_float(dst_type));
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_ROUND_Z, 0, 0, true);
return true;
case HLSL_OP2_ADD:
switch (dst_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_ADD, 0, 0, true);
return true;
case HLSL_TYPE_INT:
case HLSL_TYPE_UINT:
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_IADD, 0, 0, true);
return true;
default:
hlsl_fixme(ctx, &expr->node.loc, "SM4 %s addition expression.", dst_type_name);
return false;
}
case HLSL_OP2_BIT_AND:
VKD3D_ASSERT(type_is_integer(dst_type));
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_AND, 0, 0, true);
return true;
case HLSL_OP2_BIT_OR:
VKD3D_ASSERT(type_is_integer(dst_type));
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_OR, 0, 0, true);
return true;
case HLSL_OP2_BIT_XOR:
VKD3D_ASSERT(type_is_integer(dst_type));
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_XOR, 0, 0, true);
return true;
case HLSL_OP2_EQUAL:
VKD3D_ASSERT(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
switch (src_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_EQO, 0, 0, true);
return true;
case HLSL_TYPE_BOOL:
case HLSL_TYPE_INT:
case HLSL_TYPE_UINT:
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_IEQ, 0, 0, true);
return true;
default:
hlsl_fixme(ctx, &expr->node.loc, "SM4 equality between \"%s\" operands.",
debug_hlsl_type(ctx, src_type));
return false;
}
case HLSL_OP2_GEQUAL:
VKD3D_ASSERT(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
switch (src_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_GEO, 0, 0, true);
return true;
case HLSL_TYPE_INT:
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_IGE, 0, 0, true);
return true;
case HLSL_TYPE_BOOL:
case HLSL_TYPE_UINT:
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_UGE, 0, 0, true);
return true;
default:
hlsl_fixme(ctx, &expr->node.loc, "SM4 greater-than-or-equal between \"%s\" operands.",
debug_hlsl_type(ctx, src_type));
return false;
}
case HLSL_OP2_LESS:
VKD3D_ASSERT(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
switch (src_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_LTO, 0, 0, true);
return true;
case HLSL_TYPE_INT:
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_ILT, 0, 0, true);
return true;
case HLSL_TYPE_BOOL:
case HLSL_TYPE_UINT:
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_ULT, 0, 0, true);
return true;
default:
hlsl_fixme(ctx, &expr->node.loc, "SM4 less-than between \"%s\" operands.",
debug_hlsl_type(ctx, src_type));
return false;
}
case HLSL_OP2_LOGIC_AND:
VKD3D_ASSERT(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_AND, 0, 0, true);
return true;
case HLSL_OP2_LOGIC_OR:
VKD3D_ASSERT(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_OR, 0, 0, true);
return true;
case HLSL_OP2_LSHIFT:
VKD3D_ASSERT(type_is_integer(dst_type));
VKD3D_ASSERT(dst_type->e.numeric.type != HLSL_TYPE_BOOL);
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_ISHL, 0, 0, true);
return true;
case HLSL_OP3_MAD:
switch (dst_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_MAD, 0, 0, true);
return true;
case HLSL_TYPE_INT:
case HLSL_TYPE_UINT:
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_IMAD, 0, 0, true);
return true;
default:
hlsl_fixme(ctx, &expr->node.loc, "SM4 %s MAD expression.", dst_type_name);
return false;
}
case HLSL_OP2_MAX:
switch (dst_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_MAX, 0, 0, true);
return true;
case HLSL_TYPE_INT:
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_IMAX, 0, 0, true);
return true;
case HLSL_TYPE_UINT:
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_UMAX, 0, 0, true);
return true;
default:
hlsl_fixme(ctx, &expr->node.loc, "SM4 %s maximum expression.", dst_type_name);
return false;
}
case HLSL_OP2_MIN:
switch (dst_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_MIN, 0, 0, true);
return true;
case HLSL_TYPE_INT:
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_IMIN, 0, 0, true);
return true;
case HLSL_TYPE_UINT:
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_UMIN, 0, 0, true);
return true;
default:
hlsl_fixme(ctx, &expr->node.loc, "SM4 %s minimum expression.", dst_type_name);
return false;
}
case HLSL_OP2_NEQUAL:
VKD3D_ASSERT(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
switch (src_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_NEU, 0, 0, true);
return true;
case HLSL_TYPE_BOOL:
case HLSL_TYPE_INT:
case HLSL_TYPE_UINT:
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_INE, 0, 0, true);
return true;
default:
hlsl_fixme(ctx, &expr->node.loc, "SM4 inequality between \"%s\" operands.",
debug_hlsl_type(ctx, src_type));
return false;
}
case HLSL_OP2_RSHIFT:
VKD3D_ASSERT(type_is_integer(dst_type));
VKD3D_ASSERT(dst_type->e.numeric.type != HLSL_TYPE_BOOL);
generate_vsir_instr_expr_single_instr_op(ctx, program, expr,
dst_type->e.numeric.type == HLSL_TYPE_INT ? VKD3DSIH_ISHR : VKD3DSIH_USHR, 0, 0, true);
return true;
case HLSL_OP3_TERNARY:
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_MOVC, 0, 0, true);
return true;
default:
return false;
}
@ -7807,6 +8151,7 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx,
static void sm4_generate_vsir_block(struct hlsl_ctx *ctx, struct hlsl_block *block, struct vsir_program *program)
{
struct vkd3d_string_buffer *dst_type_string;
struct hlsl_ir_node *instr, *next;
struct hlsl_ir_switch_case *c;
@ -7831,8 +8176,13 @@ static void sm4_generate_vsir_block(struct hlsl_ctx *ctx, struct hlsl_block *blo
break;
case HLSL_IR_EXPR:
if (sm4_generate_vsir_instr_expr(ctx, program, hlsl_ir_expr(instr)))
if (!(dst_type_string = hlsl_type_to_string(ctx, instr->data_type)))
break;
if (sm4_generate_vsir_instr_expr(ctx, program, hlsl_ir_expr(instr), dst_type_string->buffer))
replace_instr_with_last_vsir_instr(ctx, program, instr);
hlsl_release_string_buffer(ctx, dst_type_string);
break;
case HLSL_IR_IF:

View File

@ -2995,20 +2995,6 @@ int tpf_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t con
static void write_sm4_block(struct tpf_compiler *tpf, const struct hlsl_block *block);
static bool type_is_integer(const struct hlsl_type *type)
{
switch (type->e.numeric.type)
{
case HLSL_TYPE_BOOL:
case HLSL_TYPE_INT:
case HLSL_TYPE_UINT:
return true;
default:
return false;
}
}
bool sm4_register_from_semantic_name(const struct vkd3d_shader_version *version,
const char *semantic_name, bool output, enum vkd3d_shader_register_type *type, bool *has_idx)
{
@ -5137,26 +5123,6 @@ static void write_sm4_binary_op_with_two_destinations(const struct tpf_compiler
write_sm4_instruction(tpf, &instr);
}
static void write_sm4_ternary_op(const struct tpf_compiler *tpf, enum vkd3d_sm4_opcode opcode,
const struct hlsl_ir_node *dst, const struct hlsl_ir_node *src1, const struct hlsl_ir_node *src2,
const struct hlsl_ir_node *src3)
{
struct sm4_instruction instr;
memset(&instr, 0, sizeof(instr));
instr.opcode = opcode;
sm4_dst_from_node(&instr.dsts[0], dst);
instr.dst_count = 1;
sm4_src_from_node(tpf, &instr.srcs[0], src1, instr.dsts[0].write_mask);
sm4_src_from_node(tpf, &instr.srcs[1], src2, instr.dsts[0].write_mask);
sm4_src_from_node(tpf, &instr.srcs[2], src3, instr.dsts[0].write_mask);
instr.src_count = 3;
write_sm4_instruction(tpf, &instr);
}
static void write_sm4_ld(const struct tpf_compiler *tpf, const struct hlsl_ir_node *dst,
const struct hlsl_deref *resource, const struct hlsl_ir_node *coords,
const struct hlsl_ir_node *sample_index, const struct hlsl_ir_node *texel_offset,
@ -5526,7 +5492,6 @@ static void write_sm4_expr(const struct tpf_compiler *tpf, const struct hlsl_ir_
const struct vkd3d_shader_version *version = &tpf->program->shader_version;
const struct hlsl_ir_node *arg1 = expr->operands[0].node;
const struct hlsl_ir_node *arg2 = expr->operands[1].node;
const struct hlsl_ir_node *arg3 = expr->operands[2].node;
const struct hlsl_type *dst_type = expr->node.data_type;
struct vkd3d_string_buffer *dst_type_string;
@ -5545,109 +5510,15 @@ static void write_sm4_expr(const struct tpf_compiler *tpf, const struct hlsl_ir_
"GetRenderTargetSampleCount() can only be used from a pixel shader using version 4.1 or higher.");
break;
case HLSL_OP1_BIT_NOT:
VKD3D_ASSERT(type_is_integer(dst_type));
write_sm4_unary_op(tpf, VKD3D_SM4_OP_NOT, &expr->node, arg1, 0);
break;
case HLSL_OP1_CAST:
write_sm4_cast(tpf, expr);
break;
case HLSL_OP1_CEIL:
VKD3D_ASSERT(type_is_float(dst_type));
write_sm4_unary_op(tpf, VKD3D_SM4_OP_ROUND_PI, &expr->node, arg1, 0);
break;
case HLSL_OP1_COS:
VKD3D_ASSERT(type_is_float(dst_type));
write_sm4_unary_op_with_two_destinations(tpf, VKD3D_SM4_OP_SINCOS, &expr->node, 1, arg1);
break;
case HLSL_OP1_DSX:
VKD3D_ASSERT(type_is_float(dst_type));
write_sm4_unary_op(tpf, VKD3D_SM4_OP_DERIV_RTX, &expr->node, arg1, 0);
break;
case HLSL_OP1_DSX_COARSE:
VKD3D_ASSERT(type_is_float(dst_type));
write_sm4_unary_op(tpf, VKD3D_SM5_OP_DERIV_RTX_COARSE, &expr->node, arg1, 0);
break;
case HLSL_OP1_DSX_FINE:
VKD3D_ASSERT(type_is_float(dst_type));
write_sm4_unary_op(tpf, VKD3D_SM5_OP_DERIV_RTX_FINE, &expr->node, arg1, 0);
break;
case HLSL_OP1_DSY:
VKD3D_ASSERT(type_is_float(dst_type));
write_sm4_unary_op(tpf, VKD3D_SM4_OP_DERIV_RTY, &expr->node, arg1, 0);
break;
case HLSL_OP1_DSY_COARSE:
VKD3D_ASSERT(type_is_float(dst_type));
write_sm4_unary_op(tpf, VKD3D_SM5_OP_DERIV_RTY_COARSE, &expr->node, arg1, 0);
break;
case HLSL_OP1_DSY_FINE:
VKD3D_ASSERT(type_is_float(dst_type));
write_sm4_unary_op(tpf, VKD3D_SM5_OP_DERIV_RTY_FINE, &expr->node, arg1, 0);
break;
case HLSL_OP1_EXP2:
VKD3D_ASSERT(type_is_float(dst_type));
write_sm4_unary_op(tpf, VKD3D_SM4_OP_EXP, &expr->node, arg1, 0);
break;
case HLSL_OP1_F16TOF32:
VKD3D_ASSERT(type_is_float(dst_type));
VKD3D_ASSERT(hlsl_version_ge(tpf->ctx, 5, 0));
write_sm4_unary_op(tpf, VKD3D_SM5_OP_F16TOF32, &expr->node, arg1, 0);
break;
case HLSL_OP1_F32TOF16:
VKD3D_ASSERT(dst_type->e.numeric.type == HLSL_TYPE_UINT);
VKD3D_ASSERT(hlsl_version_ge(tpf->ctx, 5, 0));
write_sm4_unary_op(tpf, VKD3D_SM5_OP_F32TOF16, &expr->node, arg1, 0);
break;
case HLSL_OP1_FLOOR:
VKD3D_ASSERT(type_is_float(dst_type));
write_sm4_unary_op(tpf, VKD3D_SM4_OP_ROUND_NI, &expr->node, arg1, 0);
break;
case HLSL_OP1_FRACT:
VKD3D_ASSERT(type_is_float(dst_type));
write_sm4_unary_op(tpf, VKD3D_SM4_OP_FRC, &expr->node, arg1, 0);
break;
case HLSL_OP1_LOG2:
VKD3D_ASSERT(type_is_float(dst_type));
write_sm4_unary_op(tpf, VKD3D_SM4_OP_LOG, &expr->node, arg1, 0);
break;
case HLSL_OP1_LOGIC_NOT:
VKD3D_ASSERT(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
write_sm4_unary_op(tpf, VKD3D_SM4_OP_NOT, &expr->node, arg1, 0);
break;
case HLSL_OP1_NEG:
switch (dst_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
write_sm4_unary_op(tpf, VKD3D_SM4_OP_MOV, &expr->node, arg1, VKD3DSPSM_NEG);
break;
case HLSL_TYPE_INT:
case HLSL_TYPE_UINT:
write_sm4_unary_op(tpf, VKD3D_SM4_OP_INEG, &expr->node, arg1, 0);
break;
default:
hlsl_fixme(tpf->ctx, &expr->node.loc, "SM4 %s negation expression.", dst_type_string->buffer);
}
break;
case HLSL_OP1_RCP:
switch (dst_type->e.numeric.type)
{
@ -5686,20 +5557,6 @@ static void write_sm4_expr(const struct tpf_compiler *tpf, const struct hlsl_ir_
}
break;
case HLSL_OP1_REINTERPRET:
write_sm4_unary_op(tpf, VKD3D_SM4_OP_MOV, &expr->node, arg1, 0);
break;
case HLSL_OP1_ROUND:
VKD3D_ASSERT(type_is_float(dst_type));
write_sm4_unary_op(tpf, VKD3D_SM4_OP_ROUND_NE, &expr->node, arg1, 0);
break;
case HLSL_OP1_RSQ:
VKD3D_ASSERT(type_is_float(dst_type));
write_sm4_unary_op(tpf, VKD3D_SM4_OP_RSQ, &expr->node, arg1, 0);
break;
case HLSL_OP1_SAT:
VKD3D_ASSERT(type_is_float(dst_type));
write_sm4_unary_op(tpf, VKD3D_SM4_OP_MOV
@ -5712,48 +5569,6 @@ static void write_sm4_expr(const struct tpf_compiler *tpf, const struct hlsl_ir_
write_sm4_unary_op_with_two_destinations(tpf, VKD3D_SM4_OP_SINCOS, &expr->node, 0, arg1);
break;
case HLSL_OP1_SQRT:
VKD3D_ASSERT(type_is_float(dst_type));
write_sm4_unary_op(tpf, VKD3D_SM4_OP_SQRT, &expr->node, arg1, 0);
break;
case HLSL_OP1_TRUNC:
VKD3D_ASSERT(type_is_float(dst_type));
write_sm4_unary_op(tpf, VKD3D_SM4_OP_ROUND_Z, &expr->node, arg1, 0);
break;
case HLSL_OP2_ADD:
switch (dst_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
write_sm4_binary_op(tpf, VKD3D_SM4_OP_ADD, &expr->node, arg1, arg2);
break;
case HLSL_TYPE_INT:
case HLSL_TYPE_UINT:
write_sm4_binary_op(tpf, VKD3D_SM4_OP_IADD, &expr->node, arg1, arg2);
break;
default:
hlsl_fixme(tpf->ctx, &expr->node.loc, "SM4 %s addition expression.", dst_type_string->buffer);
}
break;
case HLSL_OP2_BIT_AND:
VKD3D_ASSERT(type_is_integer(dst_type));
write_sm4_binary_op(tpf, VKD3D_SM4_OP_AND, &expr->node, arg1, arg2);
break;
case HLSL_OP2_BIT_OR:
VKD3D_ASSERT(type_is_integer(dst_type));
write_sm4_binary_op(tpf, VKD3D_SM4_OP_OR, &expr->node, arg1, arg2);
break;
case HLSL_OP2_BIT_XOR:
VKD3D_ASSERT(type_is_integer(dst_type));
write_sm4_binary_op(tpf, VKD3D_SM4_OP_XOR, &expr->node, arg1, arg2);
break;
case HLSL_OP2_DIV:
switch (dst_type->e.numeric.type)
{
@ -5799,146 +5614,6 @@ static void write_sm4_expr(const struct tpf_compiler *tpf, const struct hlsl_ir_
}
break;
case HLSL_OP2_EQUAL:
{
const struct hlsl_type *src_type = arg1->data_type;
VKD3D_ASSERT(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
switch (src_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
write_sm4_binary_op(tpf, VKD3D_SM4_OP_EQ, &expr->node, arg1, arg2);
break;
case HLSL_TYPE_BOOL:
case HLSL_TYPE_INT:
case HLSL_TYPE_UINT:
write_sm4_binary_op(tpf, VKD3D_SM4_OP_IEQ, &expr->node, arg1, arg2);
break;
default:
hlsl_fixme(tpf->ctx, &expr->node.loc, "SM4 equality between \"%s\" operands.",
debug_hlsl_type(tpf->ctx, src_type));
break;
}
break;
}
case HLSL_OP2_GEQUAL:
{
const struct hlsl_type *src_type = arg1->data_type;
VKD3D_ASSERT(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
switch (src_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
write_sm4_binary_op(tpf, VKD3D_SM4_OP_GE, &expr->node, arg1, arg2);
break;
case HLSL_TYPE_INT:
write_sm4_binary_op(tpf, VKD3D_SM4_OP_IGE, &expr->node, arg1, arg2);
break;
case HLSL_TYPE_BOOL:
case HLSL_TYPE_UINT:
write_sm4_binary_op(tpf, VKD3D_SM4_OP_UGE, &expr->node, arg1, arg2);
break;
default:
hlsl_fixme(tpf->ctx, &expr->node.loc, "SM4 greater-than-or-equal between \"%s\" operands.",
debug_hlsl_type(tpf->ctx, src_type));
break;
}
break;
}
case HLSL_OP2_LESS:
{
const struct hlsl_type *src_type = arg1->data_type;
VKD3D_ASSERT(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
switch (src_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
write_sm4_binary_op(tpf, VKD3D_SM4_OP_LT, &expr->node, arg1, arg2);
break;
case HLSL_TYPE_INT:
write_sm4_binary_op(tpf, VKD3D_SM4_OP_ILT, &expr->node, arg1, arg2);
break;
case HLSL_TYPE_BOOL:
case HLSL_TYPE_UINT:
write_sm4_binary_op(tpf, VKD3D_SM4_OP_ULT, &expr->node, arg1, arg2);
break;
default:
hlsl_fixme(tpf->ctx, &expr->node.loc, "SM4 less-than between \"%s\" operands.",
debug_hlsl_type(tpf->ctx, src_type));
break;
}
break;
}
case HLSL_OP2_LOGIC_AND:
VKD3D_ASSERT(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
write_sm4_binary_op(tpf, VKD3D_SM4_OP_AND, &expr->node, arg1, arg2);
break;
case HLSL_OP2_LOGIC_OR:
VKD3D_ASSERT(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
write_sm4_binary_op(tpf, VKD3D_SM4_OP_OR, &expr->node, arg1, arg2);
break;
case HLSL_OP2_LSHIFT:
VKD3D_ASSERT(type_is_integer(dst_type));
VKD3D_ASSERT(dst_type->e.numeric.type != HLSL_TYPE_BOOL);
write_sm4_binary_op(tpf, VKD3D_SM4_OP_ISHL, &expr->node, arg1, arg2);
break;
case HLSL_OP2_MAX:
switch (dst_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
write_sm4_binary_op(tpf, VKD3D_SM4_OP_MAX, &expr->node, arg1, arg2);
break;
case HLSL_TYPE_INT:
write_sm4_binary_op(tpf, VKD3D_SM4_OP_IMAX, &expr->node, arg1, arg2);
break;
case HLSL_TYPE_UINT:
write_sm4_binary_op(tpf, VKD3D_SM4_OP_UMAX, &expr->node, arg1, arg2);
break;
default:
hlsl_fixme(tpf->ctx, &expr->node.loc, "SM4 %s maximum expression.", dst_type_string->buffer);
}
break;
case HLSL_OP2_MIN:
switch (dst_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
write_sm4_binary_op(tpf, VKD3D_SM4_OP_MIN, &expr->node, arg1, arg2);
break;
case HLSL_TYPE_INT:
write_sm4_binary_op(tpf, VKD3D_SM4_OP_IMIN, &expr->node, arg1, arg2);
break;
case HLSL_TYPE_UINT:
write_sm4_binary_op(tpf, VKD3D_SM4_OP_UMIN, &expr->node, arg1, arg2);
break;
default:
hlsl_fixme(tpf->ctx, &expr->node.loc, "SM4 %s minimum expression.", dst_type_string->buffer);
}
break;
case HLSL_OP2_MOD:
switch (dst_type->e.numeric.type)
{
@ -5970,60 +5645,6 @@ static void write_sm4_expr(const struct tpf_compiler *tpf, const struct hlsl_ir_
}
break;
case HLSL_OP2_NEQUAL:
{
const struct hlsl_type *src_type = arg1->data_type;
VKD3D_ASSERT(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
switch (src_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
write_sm4_binary_op(tpf, VKD3D_SM4_OP_NE, &expr->node, arg1, arg2);
break;
case HLSL_TYPE_BOOL:
case HLSL_TYPE_INT:
case HLSL_TYPE_UINT:
write_sm4_binary_op(tpf, VKD3D_SM4_OP_INE, &expr->node, arg1, arg2);
break;
default:
hlsl_fixme(tpf->ctx, &expr->node.loc, "SM4 inequality between \"%s\" operands.",
debug_hlsl_type(tpf->ctx, src_type));
break;
}
break;
}
case HLSL_OP2_RSHIFT:
VKD3D_ASSERT(type_is_integer(dst_type));
VKD3D_ASSERT(dst_type->e.numeric.type != HLSL_TYPE_BOOL);
write_sm4_binary_op(tpf, dst_type->e.numeric.type == HLSL_TYPE_INT ? VKD3D_SM4_OP_ISHR : VKD3D_SM4_OP_USHR,
&expr->node, arg1, arg2);
break;
case HLSL_OP3_TERNARY:
write_sm4_ternary_op(tpf, VKD3D_SM4_OP_MOVC, &expr->node, arg1, arg2, arg3);
break;
case HLSL_OP3_MAD:
switch (dst_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
write_sm4_ternary_op(tpf, VKD3D_SM4_OP_MAD, &expr->node, arg1, arg2, arg3);
break;
case HLSL_TYPE_INT:
case HLSL_TYPE_UINT:
write_sm4_ternary_op(tpf, VKD3D_SM4_OP_IMAD, &expr->node, arg1, arg2, arg3);
break;
default:
hlsl_fixme(tpf->ctx, &expr->node.loc, "SM4 %s negation expression.", dst_type_string->buffer);
}
break;
default:
hlsl_fixme(tpf->ctx, &expr->node.loc, "SM4 %s expression.", debug_hlsl_expr_op(expr->op));
}
@ -6476,7 +6097,53 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_
tpf_dcl_siv_semantic(tpf, VKD3D_SM4_OP_DCL_OUTPUT_SIV, &ins->declaration.register_semantic, 0);
break;
case VKD3DSIH_ADD:
case VKD3DSIH_AND:
case VKD3DSIH_DSX:
case VKD3DSIH_DSX_COARSE:
case VKD3DSIH_DSX_FINE:
case VKD3DSIH_DSY:
case VKD3DSIH_DSY_COARSE:
case VKD3DSIH_DSY_FINE:
case VKD3DSIH_EQO:
case VKD3DSIH_EXP:
case VKD3DSIH_F16TOF32:
case VKD3DSIH_F32TOF16:
case VKD3DSIH_FRC:
case VKD3DSIH_GEO:
case VKD3DSIH_IADD:
case VKD3DSIH_IEQ:
case VKD3DSIH_IGE:
case VKD3DSIH_ILT:
case VKD3DSIH_INE:
case VKD3DSIH_IMAD:
case VKD3DSIH_IMAX:
case VKD3DSIH_IMIN:
case VKD3DSIH_INEG:
case VKD3DSIH_ISHL:
case VKD3DSIH_ISHR:
case VKD3DSIH_LOG:
case VKD3DSIH_LTO:
case VKD3DSIH_MAD:
case VKD3DSIH_MAX:
case VKD3DSIH_MIN:
case VKD3DSIH_MOV:
case VKD3DSIH_MOVC:
case VKD3DSIH_NEU:
case VKD3DSIH_NOT:
case VKD3DSIH_OR:
case VKD3DSIH_ROUND_NE:
case VKD3DSIH_ROUND_NI:
case VKD3DSIH_ROUND_PI:
case VKD3DSIH_ROUND_Z:
case VKD3DSIH_RSQ:
case VKD3DSIH_SQRT:
case VKD3DSIH_UGE:
case VKD3DSIH_ULT:
case VKD3DSIH_UMAX:
case VKD3DSIH_UMIN:
case VKD3DSIH_USHR:
case VKD3DSIH_XOR:
tpf_simple_instruction(tpf, ins);
break;