mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-04-13 05:43:18 -07:00
vkd3d-shader/hlsl: Implement indirect addressing for d3dbc target profiles.
This commit is contained in:
parent
0e0ed72652
commit
fd02d69dda
Notes:
Henri Verbeet
2025-04-02 19:43:14 +02:00
Approved-by: Elizabeth Figura (@zfigura) Approved-by: Henri Verbeet (@hverbeet) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1434
@ -1771,10 +1771,18 @@ static void write_sm1_dst_register(struct vkd3d_bytecode_buffer *buffer, const s
|
||||
|
||||
static void write_sm1_src_register(struct vkd3d_bytecode_buffer *buffer, const struct vkd3d_shader_src_param *reg)
|
||||
{
|
||||
uint32_t offset = reg->reg.idx_count ? reg->reg.idx[0].offset : 0;
|
||||
uint32_t address_mode = VKD3D_SM1_ADDRESS_MODE_ABSOLUTE, offset = 0;
|
||||
|
||||
if (reg->reg.idx_count)
|
||||
{
|
||||
offset = reg->reg.idx[0].offset;
|
||||
if (reg->reg.idx[0].rel_addr)
|
||||
address_mode = VKD3D_SM1_ADDRESS_MODE_RELATIVE;
|
||||
}
|
||||
|
||||
put_u32(buffer, VKD3D_SM1_INSTRUCTION_PARAMETER
|
||||
| sm1_encode_register_type(®->reg)
|
||||
| (address_mode << VKD3D_SM1_ADDRESS_MODE_SHIFT)
|
||||
| (reg->modifiers << VKD3D_SM1_SRC_MODIFIER_SHIFT)
|
||||
| (swizzle_from_vsir(reg->swizzle) << VKD3D_SM1_SWIZZLE_SHIFT)
|
||||
| (offset & VKD3D_SM1_REGISTER_NUMBER_MASK));
|
||||
@ -1784,6 +1792,7 @@ static void d3dbc_write_instruction(struct d3dbc_compiler *d3dbc, const struct v
|
||||
{
|
||||
const struct vkd3d_shader_version *version = &d3dbc->program->shader_version;
|
||||
struct vkd3d_bytecode_buffer *buffer = &d3dbc->buffer;
|
||||
const struct vkd3d_shader_src_param *src;
|
||||
const struct vkd3d_sm1_opcode_info *info;
|
||||
unsigned int i;
|
||||
uint32_t token;
|
||||
@ -1814,13 +1823,10 @@ static void d3dbc_write_instruction(struct d3dbc_compiler *d3dbc, const struct v
|
||||
|
||||
for (i = 0; i < ins->src_count; ++i)
|
||||
{
|
||||
if (ins->src[i].reg.idx[0].rel_addr)
|
||||
{
|
||||
vkd3d_shader_error(d3dbc->message_context, &ins->location, VKD3D_SHADER_ERROR_D3DBC_NOT_IMPLEMENTED,
|
||||
"Unhandled relative addressing on source register.");
|
||||
d3dbc->failed = true;
|
||||
}
|
||||
write_sm1_src_register(buffer, &ins->src[i]);
|
||||
src = &ins->src[i];
|
||||
write_sm1_src_register(buffer, src);
|
||||
if (src->reg.idx_count && src->reg.idx[0].rel_addr)
|
||||
write_sm1_src_register(buffer, src->reg.idx[0].rel_addr);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1944,6 +1950,7 @@ static void d3dbc_write_vsir_instruction(struct d3dbc_compiler *d3dbc, const str
|
||||
case VKD3DSIH_MAX:
|
||||
case VKD3DSIH_MIN:
|
||||
case VKD3DSIH_MOV:
|
||||
case VKD3DSIH_MOVA:
|
||||
case VKD3DSIH_MUL:
|
||||
case VKD3DSIH_SINCOS:
|
||||
case VKD3DSIH_SLT:
|
||||
|
@ -3123,6 +3123,11 @@ static bool validate_nonconstant_vector_store_derefs(struct hlsl_ctx *ctx, struc
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool deref_supports_sm1_indirect_addressing(struct hlsl_ctx *ctx, const struct hlsl_deref *deref)
|
||||
{
|
||||
return ctx->profile->type == VKD3D_SHADER_TYPE_VERTEX && deref->var->is_uniform;
|
||||
}
|
||||
|
||||
/* This pass flattens array (and row_major matrix) loads that include the indexing of a non-constant
|
||||
* index into multiple constant loads, where the value of only one of them ends up in the resulting
|
||||
* node.
|
||||
@ -3149,6 +3154,9 @@ static bool lower_nonconstant_array_loads(struct hlsl_ctx *ctx, struct hlsl_ir_n
|
||||
if (deref->path_len == 0)
|
||||
return false;
|
||||
|
||||
if (deref_supports_sm1_indirect_addressing(ctx, deref))
|
||||
return false;
|
||||
|
||||
for (i = deref->path_len - 1; ; --i)
|
||||
{
|
||||
if (deref->path[i].node->type != HLSL_IR_CONSTANT)
|
||||
@ -8352,11 +8360,51 @@ static void sm1_generate_vsir_init_dst_param_from_deref(struct hlsl_ctx *ctx,
|
||||
hlsl_fixme(ctx, loc, "Translate relative addressing on dst register for vsir.");
|
||||
}
|
||||
|
||||
static void sm1_generate_vsir_instr_mova(struct hlsl_ctx *ctx,
|
||||
struct vsir_program *program, struct hlsl_ir_node *instr)
|
||||
{
|
||||
enum vkd3d_shader_opcode opcode = hlsl_version_ge(ctx, 2, 0) ? VKD3DSIH_MOVA : VKD3DSIH_MOV;
|
||||
struct vkd3d_shader_dst_param *dst_param;
|
||||
struct vkd3d_shader_instruction *ins;
|
||||
|
||||
VKD3D_ASSERT(instr->reg.allocated);
|
||||
|
||||
if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, opcode, 1, 1)))
|
||||
return;
|
||||
|
||||
dst_param = &ins->dst[0];
|
||||
vsir_register_init(&dst_param->reg, VKD3DSPR_ADDR, VKD3D_DATA_FLOAT, 0);
|
||||
dst_param->write_mask = VKD3DSP_WRITEMASK_0;
|
||||
|
||||
VKD3D_ASSERT(instr->data_type->class <= HLSL_CLASS_VECTOR);
|
||||
VKD3D_ASSERT(instr->data_type->e.numeric.dimx == 1);
|
||||
vsir_src_from_hlsl_node(&ins->src[0], ctx, instr, VKD3DSP_WRITEMASK_ALL);
|
||||
}
|
||||
|
||||
static struct vkd3d_shader_src_param *sm1_generate_vsir_new_address_src(struct hlsl_ctx *ctx,
|
||||
struct vsir_program *program)
|
||||
{
|
||||
struct vkd3d_shader_src_param *idx_src;
|
||||
|
||||
if (!(idx_src = vsir_program_get_src_params(program, 1)))
|
||||
{
|
||||
ctx->result = VKD3D_ERROR_OUT_OF_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(idx_src, 0, sizeof(*idx_src));
|
||||
vsir_register_init(&idx_src->reg, VKD3DSPR_ADDR, VKD3D_DATA_FLOAT, 0);
|
||||
idx_src->reg.dimension = VSIR_DIMENSION_VEC4;
|
||||
idx_src->swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X);
|
||||
return idx_src;
|
||||
}
|
||||
|
||||
static void sm1_generate_vsir_init_src_param_from_deref(struct hlsl_ctx *ctx,
|
||||
struct vkd3d_shader_src_param *src_param, struct hlsl_deref *deref,
|
||||
unsigned int dst_writemask, const struct vkd3d_shader_location *loc)
|
||||
struct vsir_program *program, struct vkd3d_shader_src_param *src_param,
|
||||
struct hlsl_deref *deref, uint32_t dst_writemask, const struct vkd3d_shader_location *loc)
|
||||
{
|
||||
enum vkd3d_shader_register_type type = VKD3DSPR_TEMP;
|
||||
struct vkd3d_shader_src_param *src_rel_addr = NULL;
|
||||
struct vkd3d_shader_version version;
|
||||
uint32_t register_index;
|
||||
unsigned int writemask;
|
||||
@ -8374,12 +8422,26 @@ static void sm1_generate_vsir_init_src_param_from_deref(struct hlsl_ctx *ctx,
|
||||
}
|
||||
else if (deref->var->is_uniform)
|
||||
{
|
||||
type = VKD3DSPR_CONST;
|
||||
unsigned int offset = deref->const_offset;
|
||||
|
||||
reg = hlsl_reg_from_deref(ctx, deref);
|
||||
register_index = reg.id;
|
||||
writemask = reg.writemask;
|
||||
VKD3D_ASSERT(reg.allocated);
|
||||
type = VKD3DSPR_CONST;
|
||||
register_index = deref->var->regs[HLSL_REGSET_NUMERIC].id + offset / 4;
|
||||
|
||||
writemask = 0xf & (0xf << (offset % 4));
|
||||
if (deref->var->regs[HLSL_REGSET_NUMERIC].writemask)
|
||||
writemask = hlsl_combine_writemasks(deref->var->regs[HLSL_REGSET_NUMERIC].writemask, writemask);
|
||||
|
||||
if (deref->rel_offset.node)
|
||||
{
|
||||
VKD3D_ASSERT(deref_supports_sm1_indirect_addressing(ctx, deref));
|
||||
|
||||
if (!(src_rel_addr = sm1_generate_vsir_new_address_src(ctx, program)))
|
||||
{
|
||||
ctx->result = VKD3D_ERROR_OUT_OF_MEMORY;
|
||||
return;
|
||||
}
|
||||
}
|
||||
VKD3D_ASSERT(deref->var->regs[HLSL_REGSET_NUMERIC].allocated);
|
||||
}
|
||||
else if (deref->var->is_input_semantic)
|
||||
{
|
||||
@ -8413,10 +8475,8 @@ static void sm1_generate_vsir_init_src_param_from_deref(struct hlsl_ctx *ctx,
|
||||
vsir_register_init(&src_param->reg, type, VKD3D_DATA_FLOAT, 1);
|
||||
src_param->reg.dimension = VSIR_DIMENSION_VEC4;
|
||||
src_param->reg.idx[0].offset = register_index;
|
||||
src_param->reg.idx[0].rel_addr = src_rel_addr;
|
||||
src_param->swizzle = generate_vsir_get_src_swizzle(writemask, dst_writemask);
|
||||
|
||||
if (deref->rel_offset.node)
|
||||
hlsl_fixme(ctx, loc, "Translate relative addressing on src register for vsir.");
|
||||
}
|
||||
|
||||
static void sm1_generate_vsir_instr_load(struct hlsl_ctx *ctx, struct vsir_program *program,
|
||||
@ -8427,13 +8487,16 @@ static void sm1_generate_vsir_instr_load(struct hlsl_ctx *ctx, struct vsir_progr
|
||||
|
||||
VKD3D_ASSERT(instr->reg.allocated);
|
||||
|
||||
if (load->src.rel_offset.node)
|
||||
sm1_generate_vsir_instr_mova(ctx, program, load->src.rel_offset.node);
|
||||
|
||||
if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_MOV, 1, 1)))
|
||||
return;
|
||||
|
||||
vsir_dst_from_hlsl_node(&ins->dst[0], ctx, instr);
|
||||
|
||||
sm1_generate_vsir_init_src_param_from_deref(ctx, &ins->src[0], &load->src, ins->dst[0].write_mask,
|
||||
&ins->location);
|
||||
sm1_generate_vsir_init_src_param_from_deref(ctx, program, &ins->src[0],
|
||||
&load->src, ins->dst[0].write_mask, &ins->location);
|
||||
}
|
||||
|
||||
static void sm1_generate_vsir_instr_resource_load(struct hlsl_ctx *ctx,
|
||||
@ -8486,7 +8549,7 @@ static void sm1_generate_vsir_instr_resource_load(struct hlsl_ctx *ctx,
|
||||
src_param = &ins->src[0];
|
||||
vsir_src_from_hlsl_node(src_param, ctx, coords, VKD3DSP_WRITEMASK_ALL);
|
||||
|
||||
sm1_generate_vsir_init_src_param_from_deref(ctx, &ins->src[1], &load->resource,
|
||||
sm1_generate_vsir_init_src_param_from_deref(ctx, program, &ins->src[1], &load->resource,
|
||||
VKD3DSP_WRITEMASK_ALL, &ins->location);
|
||||
|
||||
if (load->load_type == HLSL_RESOURCE_SAMPLE_GRAD)
|
||||
|
Loading…
x
Reference in New Issue
Block a user