vkd3d-shader/ir: Lower IMUL and UMUL to IMUL_LOW.

This commit is contained in:
Giovanni Mascellani
2025-06-10 17:11:31 +02:00
committed by Henri Verbeet
parent 4a39db797b
commit 31581b0002
Notes: Henri Verbeet 2025-06-24 16:31:58 +02:00
Approved-by: Elizabeth Figura (@zfigura)
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1583
4 changed files with 26 additions and 95 deletions

View File

@@ -1250,37 +1250,6 @@ static void shader_glsl_movc(struct vkd3d_glsl_generator *gen, const struct vkd3
glsl_dst_cleanup(&dst, &gen->string_buffers); glsl_dst_cleanup(&dst, &gen->string_buffers);
} }
static void shader_glsl_mul_extended(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins)
{
struct glsl_src src[2];
struct glsl_dst dst;
uint32_t mask;
if (ins->dst[0].reg.type != VKD3DSPR_NULL)
{
/* FIXME: imulExtended()/umulExtended() from ARB_gpu_shader5/GLSL 4.00+. */
mask = glsl_dst_init(&dst, gen, ins, &ins->dst[0]);
shader_glsl_print_assignment(gen, &dst, "<unhandled 64-bit multiplication>");
glsl_dst_cleanup(&dst, &gen->string_buffers);
vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL,
"Internal compiler error: Unhandled 64-bit integer multiplication.");
}
if (ins->dst[1].reg.type != VKD3DSPR_NULL)
{
mask = glsl_dst_init(&dst, gen, ins, &ins->dst[1]);
glsl_src_init(&src[0], gen, &ins->src[0], mask);
glsl_src_init(&src[1], gen, &ins->src[1], mask);
shader_glsl_print_assignment(gen, &dst, "%s * %s", src[0].str->buffer, src[1].str->buffer);
glsl_src_cleanup(&src[1], &gen->string_buffers);
glsl_src_cleanup(&src[0], &gen->string_buffers);
glsl_dst_cleanup(&dst, &gen->string_buffers);
}
}
static void shader_glsl_print_sysval_name(struct vkd3d_string_buffer *buffer, struct vkd3d_glsl_generator *gen, static void shader_glsl_print_sysval_name(struct vkd3d_string_buffer *buffer, struct vkd3d_glsl_generator *gen,
enum vkd3d_shader_sysval_semantic sysval, unsigned int idx) enum vkd3d_shader_sysval_semantic sysval, unsigned int idx)
{ {
@@ -1584,9 +1553,6 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen,
case VKD3DSIH_UMIN: case VKD3DSIH_UMIN:
shader_glsl_intrinsic(gen, ins, "min"); shader_glsl_intrinsic(gen, ins, "min");
break; break;
case VKD3DSIH_IMUL:
shader_glsl_mul_extended(gen, ins);
break;
case VKD3DSIH_IMUL_LOW: case VKD3DSIH_IMUL_LOW:
shader_glsl_binop(gen, ins, "*"); shader_glsl_binop(gen, ins, "*");
break; break;

View File

@@ -1146,6 +1146,24 @@ static enum vkd3d_result vsir_program_lower_precise_mad(struct vsir_program *pro
return VKD3D_OK; return VKD3D_OK;
} }
static enum vkd3d_result vsir_program_lower_imul(struct vsir_program *program,
struct vkd3d_shader_instruction *imul, struct vsir_transformation_context *ctx)
{
if (imul->dst[0].reg.type != VKD3DSPR_NULL)
{
vkd3d_shader_error(ctx->message_context, &imul->location,
VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED,
"Extended multiplication is not implemented.");
return VKD3D_ERROR_NOT_IMPLEMENTED;
}
imul->dst[0] = imul->dst[1];
imul->dst_count = 1;
imul->opcode = VKD3DSIH_IMUL_LOW;
return VKD3D_OK;
}
static enum vkd3d_result vsir_program_lower_sm1_sincos(struct vsir_program *program, static enum vkd3d_result vsir_program_lower_sm1_sincos(struct vsir_program *program,
struct vkd3d_shader_instruction *sincos) struct vkd3d_shader_instruction *sincos)
{ {
@@ -1526,6 +1544,12 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr
vkd3d_shader_instruction_make_nop(ins); vkd3d_shader_instruction_make_nop(ins);
break; break;
case VKD3DSIH_IMUL:
case VKD3DSIH_UMUL:
if ((ret = vsir_program_lower_imul(program, ins, ctx)) < 0)
return ret;
break;
case VKD3DSIH_SINCOS: case VKD3DSIH_SINCOS:
if (ins->dst_count == 1) if (ins->dst_count == 1)
{ {

View File

@@ -1191,37 +1191,6 @@ static void msl_movc(struct msl_generator *gen, const struct vkd3d_shader_instru
msl_dst_cleanup(&dst, &gen->string_buffers); msl_dst_cleanup(&dst, &gen->string_buffers);
} }
static void msl_mul64(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins)
{
struct msl_src src[2];
struct msl_dst dst;
uint32_t mask;
if (ins->dst[0].reg.type != VKD3DSPR_NULL)
{
/* TODO: mulhi(). */
mask = msl_dst_init(&dst, gen, ins, &ins->dst[0]);
msl_print_assignment(gen, &dst, "<unhandled 64-bit multiplication>");
msl_dst_cleanup(&dst, &gen->string_buffers);
msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL,
"Internal compiler error: Unhandled 64-bit integer multiplication.");
}
if (ins->dst[1].reg.type != VKD3DSPR_NULL)
{
mask = msl_dst_init(&dst, gen, ins, &ins->dst[1]);
msl_src_init(&src[0], gen, &ins->src[0], mask);
msl_src_init(&src[1], gen, &ins->src[1], mask);
msl_print_assignment(gen, &dst, "%s * %s", src[0].str->buffer, src[1].str->buffer);
msl_src_cleanup(&src[1], &gen->string_buffers);
msl_src_cleanup(&src[0], &gen->string_buffers);
msl_dst_cleanup(&dst, &gen->string_buffers);
}
}
static void msl_ret(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) static void msl_ret(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins)
{ {
msl_print_indent(gen->buffer, gen->indent); msl_print_indent(gen->buffer, gen->indent);
@@ -1337,8 +1306,8 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d
case VKD3DSIH_MIN: case VKD3DSIH_MIN:
msl_intrinsic(gen, ins, "min"); msl_intrinsic(gen, ins, "min");
break; break;
case VKD3DSIH_IMUL: case VKD3DSIH_IMUL_LOW:
msl_mul64(gen, ins); msl_binop(gen, ins, "*");
break; break;
case VKD3DSIH_INE: case VKD3DSIH_INE:
case VKD3DSIH_NEU: case VKD3DSIH_NEU:

View File

@@ -8020,30 +8020,6 @@ static void spirv_compiler_emit_rcp(struct spirv_compiler *compiler,
spirv_compiler_emit_store_dst(compiler, dst, val_id); spirv_compiler_emit_store_dst(compiler, dst, val_id);
} }
static void spirv_compiler_emit_imul(struct spirv_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
uint32_t type_id, val_id, src0_id, src1_id;
if (dst[0].reg.type != VKD3DSPR_NULL)
FIXME("Extended multiplies not implemented.\n"); /* SpvOpSMulExtended/SpvOpUMulExtended */
if (dst[1].reg.type == VKD3DSPR_NULL)
return;
type_id = spirv_compiler_get_type_id_for_dst(compiler, &dst[1]);
src0_id = spirv_compiler_emit_load_src(compiler, &src[0], dst[1].write_mask);
src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst[1].write_mask);
val_id = vkd3d_spirv_build_op_imul(builder, type_id, src0_id, src1_id);
spirv_compiler_emit_store_dst(compiler, &dst[1], val_id);
}
static void spirv_compiler_emit_imad(struct spirv_compiler *compiler, static void spirv_compiler_emit_imad(struct spirv_compiler *compiler,
const struct vkd3d_shader_instruction *instruction) const struct vkd3d_shader_instruction *instruction)
{ {
@@ -10737,10 +10713,6 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler,
case VKD3DSIH_RCP: case VKD3DSIH_RCP:
spirv_compiler_emit_rcp(compiler, instruction); spirv_compiler_emit_rcp(compiler, instruction);
break; break;
case VKD3DSIH_IMUL:
case VKD3DSIH_UMUL:
spirv_compiler_emit_imul(compiler, instruction);
break;
case VKD3DSIH_IMAD: case VKD3DSIH_IMAD:
spirv_compiler_emit_imad(compiler, instruction); spirv_compiler_emit_imad(compiler, instruction);
break; break;