From: Francisco Casas fcasas@codeweavers.com
--- libs/vkd3d-shader/ir.c | 113 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 610d907d9..bfba388e0 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -244,6 +244,116 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr return VKD3D_OK; }
+static enum vkd3d_shader_opcode get_handler_idx_from_rel_op(enum vkd3d_shader_rel_op rel_op, + enum vkd3d_data_type data_type, bool *requires_swap) +{ + switch (rel_op) + { + case VKD3D_SHADER_REL_OP_LT: + case VKD3D_SHADER_REL_OP_GT: + + *requires_swap = (rel_op == VKD3D_SHADER_REL_OP_GT); + if (data_type == VKD3D_DATA_INT) + return VKD3DSIH_ILT; + else if(data_type_is_integer(data_type)) + return VKD3DSIH_ULT; + else if(data_type_is_64_bit(data_type)) + return VKD3DSIH_DLT; + else + return VKD3DSIH_LTO; + break; + + case VKD3D_SHADER_REL_OP_GE: + case VKD3D_SHADER_REL_OP_LE: + *requires_swap = (rel_op == VKD3D_SHADER_REL_OP_LE); + if (data_type == VKD3D_DATA_INT) + return VKD3DSIH_IGE; + else if(data_type_is_integer(data_type)) + return VKD3DSIH_UGE; + else if(data_type_is_64_bit(data_type)) + return VKD3DSIH_DGEO; + else + return VKD3DSIH_GEO; + break; + + case VKD3D_SHADER_REL_OP_EQ: + *requires_swap = false; + if (data_type_is_integer(data_type)) + return VKD3DSIH_IEQ; + else if(data_type_is_64_bit(data_type)) + return VKD3DSIH_DEQO; + else + return VKD3DSIH_EQO; + break; + + case VKD3D_SHADER_REL_OP_NE: + *requires_swap = false; + if (data_type_is_integer(data_type)) + return VKD3DSIH_INE; + else if(data_type_is_64_bit(data_type)) + return VKD3DSIH_DNE; + else + return VKD3DSIH_NEO; + break; + } + vkd3d_unreachable(); +} + +static enum vkd3d_result vsir_program_lower_ifc(struct vsir_program *program) +{ + struct vkd3d_shader_instruction_array *instructions = &program->instructions; + struct vkd3d_shader_instruction *ifc_ins, *ins; + enum vkd3d_shader_opcode handler_idx; + unsigned int tmp_idx = ~0u; + unsigned int i; + bool swap; + + for (i = 0; i < instructions->count; ++i) + { + ifc_ins = &instructions->elements[i]; + + if (ifc_ins->handler_idx != VKD3DSIH_IFC) + continue; + + if (!shader_instruction_array_insert_at(instructions, i + 1, 2)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + if (tmp_idx == ~0u) + tmp_idx = program->temp_count++; + + /* Replace ifc comparison with actual comparison, saving the result in the tmp register. */ + handler_idx = get_handler_idx_from_rel_op(ifc_ins->flags, ifc_ins->src[0].reg.data_type, &swap); + + ins = &instructions->elements[i + 1]; + if (!vsir_instruction_init_with_params(program, ins, &ifc_ins->location, handler_idx, 1, 2)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + vsir_register_init(&ins->dst[0].reg, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); + ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; + ins->dst[0].reg.idx[0].offset = tmp_idx; + ins->dst[0].write_mask = VKD3DSP_WRITEMASK_0; + + ins->src[0] = ifc_ins->src[swap]; + ins->src[1] = ifc_ins->src[!swap]; + + /* Create new if instruction using the previous result. */ + ins = &instructions->elements[i + 2]; + if (!vsir_instruction_init_with_params(program, ins, &ifc_ins->location, VKD3DSIH_IF, 0, 1)) + return VKD3D_ERROR_OUT_OF_MEMORY; + ins->flags = VKD3D_SHADER_CONDITIONAL_OP_NZ; + + vsir_register_init(&ins->src[0].reg, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); + ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; + ins->src[0].reg.idx[0].offset = tmp_idx; + ins->src[0].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); + + /* Make the original instruction no-op */ + vkd3d_shader_instruction_make_nop(ifc_ins); + } + + return VKD3D_OK; +} + static void shader_register_eliminate_phase_addressing(struct vkd3d_shader_register *reg, unsigned int instance_id) { @@ -5817,6 +5927,9 @@ enum vkd3d_result vsir_program_normalise(struct vsir_program *program, uint64_t if ((result = vsir_program_lower_instructions(program)) < 0) return result;
+ if ((result = vsir_program_lower_ifc(program)) < 0) + return result; + if (program->shader_version.major >= 6) { if ((result = vsir_program_materialise_phi_ssas_to_temps(program)) < 0)