diff --git a/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d-shader/d3dbc.c index 2dbdb926..3ab42c81 100644 --- a/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d-shader/d3dbc.c @@ -1468,6 +1468,7 @@ bool hlsl_sm1_usage_from_semantic(const char *semantic_name, struct d3dbc_compiler { + const struct vkd3d_sm1_opcode_info *opcode_table; struct vsir_program *program; struct vkd3d_bytecode_buffer buffer; struct vkd3d_shader_message_context *message_context; @@ -2170,6 +2171,75 @@ static void d3dbc_write_cast(struct d3dbc_compiler *d3dbc, const struct hlsl_ir_ } } +static const struct vkd3d_sm1_opcode_info *shader_sm1_get_opcode_info_from_vsir( + struct d3dbc_compiler *d3dbc, enum vkd3d_shader_opcode vkd3d_opcode) +{ + const struct vkd3d_shader_version *version = &d3dbc->program->shader_version; + const struct vkd3d_sm1_opcode_info *info; + unsigned int i = 0; + + for (;;) + { + info = &d3dbc->opcode_table[i++]; + if (info->vkd3d_opcode == VKD3DSIH_INVALID) + return NULL; + + if (vkd3d_opcode == info->vkd3d_opcode + && vkd3d_shader_ver_ge(version, info->min_version.major, info->min_version.minor) + && (vkd3d_shader_ver_le(version, info->max_version.major, info->max_version.minor) + || !info->max_version.major)) + return info; + } +} + +static uint32_t swizzle_from_vsir(uint32_t swizzle) +{ + uint32_t x = vsir_swizzle_get_component(swizzle, 0); + uint32_t y = vsir_swizzle_get_component(swizzle, 1); + uint32_t z = vsir_swizzle_get_component(swizzle, 2); + uint32_t w = vsir_swizzle_get_component(swizzle, 3); + + if (x & ~0x3u || y & ~0x3u || z & ~0x3u || w & ~0x3u) + ERR("Unexpected vsir swizzle: 0x%08x.\n", swizzle); + + return ((x & 0x3u) << VKD3D_SM1_SWIZZLE_COMPONENT_SHIFT(0)) + | ((y & 0x3) << VKD3D_SM1_SWIZZLE_COMPONENT_SHIFT(1)) + | ((z & 0x3) << VKD3D_SM1_SWIZZLE_COMPONENT_SHIFT(2)) + | ((w & 0x3) << VKD3D_SM1_SWIZZLE_COMPONENT_SHIFT(3)); +} + +static void sm1_src_reg_from_vsir(struct d3dbc_compiler *d3dbc, const struct vkd3d_shader_src_param *param, + struct sm1_src_register *src, const struct vkd3d_shader_location *loc) +{ + src->mod = (uint32_t)param->modifiers << VKD3D_SM1_SRC_MODIFIER_SHIFT; + src->reg = param->reg.idx[0].offset; + src->type = param->reg.type; + src->swizzle = swizzle_from_vsir(param->swizzle); + + if (param->reg.idx[0].rel_addr) + { + vkd3d_shader_error(d3dbc->message_context, loc, VKD3D_SHADER_ERROR_D3DBC_NOT_IMPLEMENTED, + "Unhandled relative addressing on source register."); + d3dbc->failed = true; + } +} + +static void sm1_dst_reg_from_vsir(struct d3dbc_compiler *d3dbc, const struct vkd3d_shader_dst_param *param, + struct sm1_dst_register *dst, const struct vkd3d_shader_location *loc) +{ + dst->mod = (uint32_t)param->modifiers << VKD3D_SM1_DST_MODIFIER_SHIFT; + dst->reg = param->reg.idx[0].offset; + dst->type = param->reg.type; + dst->writemask = param->write_mask; + + if (param->reg.idx[0].rel_addr) + { + vkd3d_shader_error(d3dbc->message_context, loc, VKD3D_SHADER_ERROR_D3DBC_NOT_IMPLEMENTED, + "Unhandled relative addressing on destination register."); + d3dbc->failed = true; + } +} + 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; @@ -2258,6 +2328,43 @@ static void d3dbc_write_vsir_dcl(struct d3dbc_compiler *d3dbc, const struct vkd3 } } +static void d3dbc_write_vsir_simple_instruction(struct d3dbc_compiler *d3dbc, + const struct vkd3d_shader_instruction *ins) +{ + const struct vkd3d_sm1_opcode_info *info; + struct sm1_instruction instr = {0}; + + info = shader_sm1_get_opcode_info_from_vsir(d3dbc, ins->opcode); + + if (ins->dst_count != info->dst_count) + { + vkd3d_shader_error(d3dbc->message_context, &ins->location, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_COUNT, + "Invalid destination count %u for vsir instruction %#x (expected %u).", + ins->dst_count, ins->opcode, info->dst_count); + d3dbc->failed = true; + return; + } + if (ins->src_count != info->src_count) + { + vkd3d_shader_error(d3dbc->message_context, &ins->location, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_COUNT, + "Invalid source count %u for vsir instruction %#x (expected %u).", + ins->src_count, ins->opcode, info->src_count); + d3dbc->failed = true; + return; + } + + instr.opcode = (D3DSHADER_INSTRUCTION_OPCODE_TYPE)info->sm1_opcode; + instr.has_dst = info->dst_count; + instr.src_count = info->src_count; + + if (instr.has_dst) + sm1_dst_reg_from_vsir(d3dbc, &ins->dst[0], &instr.dst, &ins->location); + for (unsigned int i = 0; i < instr.src_count; ++i) + sm1_src_reg_from_vsir(d3dbc, &ins->src[i], &instr.srcs[i], &ins->location); + + d3dbc_write_instruction(d3dbc, &instr); +} + static void d3dbc_write_vsir_instruction(struct d3dbc_compiler *d3dbc, const struct vkd3d_shader_instruction *ins) { switch (ins->opcode) @@ -2270,6 +2377,10 @@ static void d3dbc_write_vsir_instruction(struct d3dbc_compiler *d3dbc, const str d3dbc_write_vsir_dcl(d3dbc, ins); break; + case VKD3DSIH_MOV: + d3dbc_write_vsir_simple_instruction(d3dbc, ins); + break; + default: vkd3d_shader_error(d3dbc->message_context, &ins->location, VKD3D_SHADER_ERROR_D3DBC_INVALID_OPCODE, "vsir instruction with opcode %#x.", ins->opcode); @@ -2343,30 +2454,6 @@ static void d3dbc_write_semantic_dcls(struct d3dbc_compiler *d3dbc) } } -static void d3dbc_write_constant(struct d3dbc_compiler *d3dbc, const struct hlsl_ir_node *instr) -{ - const struct hlsl_ir_constant *constant = hlsl_ir_constant(instr); - struct sm1_instruction sm1_instr = - { - .opcode = D3DSIO_MOV, - - .dst.type = VKD3DSPR_TEMP, - .dst.reg = instr->reg.id, - .dst.writemask = instr->reg.writemask, - .has_dst = 1, - - .srcs[0].type = VKD3DSPR_CONST, - .srcs[0].reg = constant->reg.id, - .srcs[0].swizzle = hlsl_swizzle_from_writemask(constant->reg.writemask), - .src_count = 1, - }; - - VKD3D_ASSERT(instr->reg.allocated); - VKD3D_ASSERT(constant->reg.allocated); - sm1_map_src_swizzle(&sm1_instr.srcs[0], sm1_instr.dst.writemask); - d3dbc_write_instruction(d3dbc, &sm1_instr); -} - static void d3dbc_write_per_component_unary_op(struct d3dbc_compiler *d3dbc, const struct hlsl_ir_node *instr, D3DSHADER_INSTRUCTION_OPCODE_TYPE opcode) { @@ -2847,10 +2934,6 @@ static void d3dbc_write_block(struct d3dbc_compiler *d3dbc, const struct hlsl_bl case HLSL_IR_CALL: vkd3d_unreachable(); - case HLSL_IR_CONSTANT: - d3dbc_write_constant(d3dbc, instr); - break; - case HLSL_IR_EXPR: d3dbc_write_expr(d3dbc, instr); break; @@ -2911,6 +2994,21 @@ int d3dbc_compile(struct vsir_program *program, uint64_t config_flags, d3dbc.ctx = ctx; d3dbc.program = program; d3dbc.message_context = message_context; + switch (version->type) + { + case VKD3D_SHADER_TYPE_VERTEX: + d3dbc.opcode_table = vs_opcode_table; + break; + + case VKD3D_SHADER_TYPE_PIXEL: + d3dbc.opcode_table = ps_opcode_table; + break; + + default: + vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_D3DBC_INVALID_PROFILE, + "Invalid shader type %u.", version->type); + return VKD3D_ERROR_INVALID_SHADER; + } put_u32(buffer, sm1_version(version->type, version->major, version->minor)); diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 996b7a41..a4f84506 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -70,6 +70,14 @@ static inline unsigned int hlsl_swizzle_get_component(uint32_t swizzle, unsigned return (swizzle >> HLSL_SWIZZLE_SHIFT(idx)) & HLSL_SWIZZLE_MASK; } +static inline uint32_t vsir_swizzle_from_hlsl(uint32_t swizzle) +{ + return vkd3d_shader_create_swizzle(hlsl_swizzle_get_component(swizzle, 0), + hlsl_swizzle_get_component(swizzle, 1), + hlsl_swizzle_get_component(swizzle, 2), + hlsl_swizzle_get_component(swizzle, 3)); +} + enum hlsl_type_class { HLSL_CLASS_SCALAR, diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 225c3b67..7bab56d8 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -6014,6 +6014,16 @@ static void sm1_generate_vsir_signature(struct hlsl_ctx *ctx, struct vsir_progra } } +static uint32_t sm1_generate_vsir_get_src_swizzle(uint32_t src_writemask, uint32_t dst_writemask) +{ + uint32_t swizzle; + + swizzle = hlsl_swizzle_from_writemask(src_writemask); + swizzle = hlsl_map_swizzle(swizzle, dst_writemask); + swizzle = vsir_swizzle_from_hlsl(swizzle); + return swizzle; +} + static void sm1_generate_vsir_constant_defs(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_block *block) { @@ -6157,6 +6167,70 @@ static void sm1_generate_vsir_sampler_dcls(struct hlsl_ctx *ctx, } } +static void sm1_generate_vsir_instr_constant(struct hlsl_ctx *ctx, + struct vsir_program *program, struct hlsl_ir_constant *constant) +{ + struct vkd3d_shader_instruction_array *instructions = &program->instructions; + struct hlsl_ir_node *instr = &constant->node; + struct vkd3d_shader_dst_param *dst_param; + struct vkd3d_shader_src_param *src_param; + struct vkd3d_shader_instruction *ins; + struct hlsl_ir_node *vsir_instr; + + VKD3D_ASSERT(instr->reg.allocated); + VKD3D_ASSERT(constant->reg.allocated); + + if (!shader_instruction_array_reserve(instructions, instructions->count + 1)) + { + ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; + return; + } + ins = &instructions->elements[instructions->count]; + if (!vsir_instruction_init_with_params(program, ins, &instr->loc, VKD3DSIH_MOV, 1, 1)) + { + ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; + return; + } + ++instructions->count; + + src_param = &ins->src[0]; + vsir_register_init(&src_param->reg, VKD3DSPR_CONST, VKD3D_DATA_FLOAT, 1); + src_param->reg.idx[0].offset = constant->reg.id; + src_param->swizzle = sm1_generate_vsir_get_src_swizzle(constant->reg.writemask, instr->reg.writemask); + + dst_param = &ins->dst[0]; + vsir_register_init(&dst_param->reg, VKD3DSPR_TEMP, VKD3D_DATA_FLOAT, 1); + dst_param->reg.idx[0].offset = instr->reg.id; + dst_param->write_mask = instr->reg.writemask; + + if (!(vsir_instr = hlsl_new_vsir_instruction_ref(ctx, instructions->count - 1, + instr->data_type, &instr->reg, &instr->loc))) + { + ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; + return; + } + + list_add_before(&instr->entry, &vsir_instr->entry); + hlsl_replace_node(instr, vsir_instr); +} + +static bool sm1_generate_vsir_instr(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) +{ + struct vsir_program *program = context; + + switch (instr->type) + { + case HLSL_IR_CONSTANT: + sm1_generate_vsir_instr_constant(ctx, program, hlsl_ir_constant(instr)); + return true; + + default: + break; + } + + return false; +} + /* OBJECTIVE: Translate all the information from ctx and entry_func to the * vsir_program and ctab blob, so they can be used as input to d3dbc_compile() * without relying on ctx and entry_func. */ @@ -6192,6 +6266,8 @@ static void sm1_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl sm1_generate_vsir_constant_defs(ctx, program, &block); sm1_generate_vsir_sampler_dcls(ctx, program, &block); list_move_head(&entry_func->body.instrs, &block.instrs); + + hlsl_transform_ir(ctx, sm1_generate_vsir_instr, &entry_func->body, program); } static struct hlsl_ir_jump *loop_unrolling_find_jump(struct hlsl_block *block, struct hlsl_ir_node *stop_point, diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 631d634d..93dff4e8 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -170,6 +170,9 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_INDEX = 7005, VKD3D_SHADER_ERROR_D3DBC_UNDECLARED_SEMANTIC = 7006, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_TYPE = 7007, + VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_COUNT = 7008, + VKD3D_SHADER_ERROR_D3DBC_NOT_IMPLEMENTED = 7009, + VKD3D_SHADER_ERROR_D3DBC_INVALID_PROFILE = 7010, VKD3D_SHADER_WARNING_D3DBC_IGNORED_INSTRUCTION_FLAGS= 7300,