vkd3d-shader: Normalize TEXKILL to use a source register.

This commit is contained in:
Elizabeth Figura
2025-03-07 17:20:28 -06:00
committed by Henri Verbeet
parent 50ca4a2101
commit 315247bf02
Notes: Henri Verbeet 2025-04-30 17:02:44 +02:00
Approved-by: Francisco Casas (@fcasas)
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1475
3 changed files with 62 additions and 7 deletions

View File

@@ -1215,6 +1215,7 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, str
struct vkd3d_shader_src_param *src_params, *predicate;
const struct vkd3d_sm1_opcode_info *opcode_info;
struct vsir_program *program = sm1->p.program;
unsigned int vsir_dst_count, vsir_src_count;
struct vkd3d_shader_dst_param *dst_param;
const uint32_t **ptr = &sm1->ptr;
uint32_t opcode_token;
@@ -1241,6 +1242,17 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, str
goto fail;
}
if (opcode_info->vkd3d_opcode == VKD3DSIH_TEXKILL)
{
vsir_src_count = 1;
vsir_dst_count = 0;
}
else
{
vsir_src_count = opcode_info->src_count;
vsir_dst_count = opcode_info->dst_count;
}
vsir_instruction_init(ins, &sm1->p.location, opcode_info->vkd3d_opcode);
ins->flags = (opcode_token & VKD3D_SM1_INSTRUCTION_FLAGS_MASK) >> VKD3D_SM1_INSTRUCTION_FLAGS_SHIFT;
ins->coissue = opcode_token & VKD3D_SM1_COISSUE;
@@ -1248,9 +1260,9 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, str
ins->structured = false;
predicated = !!(opcode_token & VKD3D_SM1_INSTRUCTION_PREDICATED);
ins->predicate = predicate = predicated ? vsir_program_get_src_params(program, 1) : NULL;
ins->dst_count = opcode_info->dst_count;
ins->dst_count = vsir_dst_count;
ins->dst = dst_param = vsir_program_get_dst_params(program, ins->dst_count);
ins->src_count = opcode_info->src_count;
ins->src_count = vsir_src_count;
ins->src = src_params = vsir_program_get_src_params(program, ins->src_count);
if ((!predicate && predicated) || (!src_params && ins->src_count) || (!dst_param && ins->dst_count))
{
@@ -1298,6 +1310,25 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, str
shader_sm1_read_immconst(sm1, &p, &src_params[0], VSIR_DIMENSION_VEC4, VKD3D_DATA_INT);
shader_sm1_scan_register(sm1, &dst_param->reg, dst_param->write_mask, true);
}
else if (ins->opcode == VKD3DSIH_TEXKILL)
{
/* TEXKILL, uniquely, encodes its argument as a destination, when it is
* semantically a source. Since we have multiple passes which operate
* generically on sources or destinations, normalize that. */
const struct vkd3d_shader_register *reg;
struct vkd3d_shader_dst_param tmp_dst;
reg = &tmp_dst.reg;
shader_sm1_read_dst_param(sm1, &p, &tmp_dst);
shader_sm1_scan_register(sm1, reg, tmp_dst.write_mask, false);
vsir_src_param_init(&src_params[0], reg->type, reg->data_type, reg->idx_count);
src_params[0].reg = *reg;
src_params[0].swizzle = vsir_swizzle_from_writemask(tmp_dst.write_mask);
if (ins->predicate)
shader_sm1_read_src_param(sm1, &p, predicate);
}
else
{
/* Destination token */
@@ -1834,6 +1865,27 @@ static void d3dbc_write_instruction(struct d3dbc_compiler *d3dbc, const struct v
}
};
static void d3dbc_write_texkill(struct d3dbc_compiler *d3dbc, const struct vkd3d_shader_instruction *ins)
{
const struct vkd3d_shader_register *reg = &ins->src[0].reg;
struct vkd3d_shader_instruction tmp;
struct vkd3d_shader_dst_param dst;
/* TEXKILL, uniquely, encodes its argument as a destination, when it is
* semantically a source. We store it as a source in vsir, so convert it. */
vsir_dst_param_init(&dst, reg->type, reg->data_type, reg->idx_count);
dst.reg = *reg;
dst.write_mask = mask_from_swizzle(ins->src[0].swizzle);
tmp = *ins;
tmp.dst_count = 1;
tmp.dst = &dst;
tmp.src_count = 0;
d3dbc_write_instruction(d3dbc, &tmp);
}
static void d3dbc_write_vsir_def(struct d3dbc_compiler *d3dbc, const struct vkd3d_shader_instruction *ins)
{
const struct vkd3d_shader_version *version = &d3dbc->program->shader_version;
@@ -1938,6 +1990,10 @@ static void d3dbc_write_vsir_instruction(struct d3dbc_compiler *d3dbc, const str
d3dbc_write_vsir_dcl(d3dbc, ins);
break;
case VKD3DSIH_TEXKILL:
d3dbc_write_texkill(d3dbc, ins);
break;
case VKD3DSIH_ABS:
case VKD3DSIH_ADD:
case VKD3DSIH_CMP:
@@ -1959,7 +2015,6 @@ static void d3dbc_write_vsir_instruction(struct d3dbc_compiler *d3dbc, const str
case VKD3DSIH_SINCOS:
case VKD3DSIH_SLT:
case VKD3DSIH_TEX:
case VKD3DSIH_TEXKILL:
case VKD3DSIH_TEXLDD:
d3dbc_write_instruction(d3dbc, ins);
break;

View File

@@ -9263,10 +9263,10 @@ static void sm1_generate_vsir_instr_jump(struct hlsl_ctx *ctx,
if (jump->type == HLSL_IR_JUMP_DISCARD_NEG)
{
if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_TEXKILL, 1, 0)))
if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_TEXKILL, 0, 1)))
return;
vsir_dst_from_hlsl_node(&ins->dst[0], ctx, condition);
vsir_src_from_hlsl_node(&ins->src[0], ctx, condition, VKD3DSP_WRITEMASK_ALL);
}
else
{

View File

@@ -622,7 +622,7 @@ static enum vkd3d_result vsir_program_lower_texkill(struct vsir_program *program
if (*tmp_idx == ~0u)
*tmp_idx = program->temp_count++;
/* tmp = ins->dst[0] < 0 */
/* tmp = ins->src[0] < 0 */
ins = &instructions->elements[pos + 1];
if (!vsir_instruction_init_with_params(program, ins, &texkill->location, VKD3DSIH_LTO, 1, 2))
@@ -633,7 +633,7 @@ static enum vkd3d_result vsir_program_lower_texkill(struct vsir_program *program
ins->dst[0].reg.idx[0].offset = *tmp_idx;
ins->dst[0].write_mask = VKD3DSP_WRITEMASK_ALL;
ins->src[0].reg = texkill->dst[0].reg;
ins->src[0].reg = texkill->src[0].reg;
ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE;
vsir_register_init(&ins->src[1].reg, VKD3DSPR_IMMCONST, VKD3D_DATA_FLOAT, 0);
ins->src[1].reg.dimension = VSIR_DIMENSION_VEC4;