From: Conor McCarthy cmccarthy@codeweavers.com
Instructions such as DMOV, DADD, DEQ, etc. are redundant because parameter width is specified by register data type. --- libs/vkd3d-shader/ir.c | 144 +++++++++++++++++++++++ libs/vkd3d-shader/spirv.c | 61 ++++------ libs/vkd3d-shader/vkd3d_shader_private.h | 1 + 3 files changed, 167 insertions(+), 39 deletions(-)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 8cf92656b..9d15d148e 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -1424,6 +1424,147 @@ static enum vkd3d_result normalise_combined_samplers(struct vkd3d_shader_parser return VKD3D_OK; }
+static void src_param_validate_is_double(const struct vkd3d_shader_src_param *src, + enum vkd3d_shader_opcode handler_idx, struct vkd3d_shader_parser *parser) +{ + if (src->reg.data_type != VKD3D_DATA_DOUBLE) + { + WARN("Invalid data type %#x.\n", src->reg.data_type); + vkd3d_shader_parser_error(parser, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, + "Source parameter type %#x for instruction handler %#x is not double.", + src->reg.data_type, handler_idx); + } +} + +static void dst_param_validate_is_double(const struct vkd3d_shader_dst_param *dst, + enum vkd3d_shader_opcode handler_idx, struct vkd3d_shader_parser *parser) +{ + if (dst->reg.data_type != VKD3D_DATA_DOUBLE) + { + WARN("Invalid data type %#x.\n", dst->reg.data_type); + vkd3d_shader_parser_error(parser, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, + "Destination parameter type %#x for instruction handler %#x is not double.", + dst->reg.data_type, handler_idx); + } +} + +static void instruction_validate_src_params_are_double(const struct vkd3d_shader_instruction *ins, + struct vkd3d_shader_parser *parser) +{ + unsigned int i; + for (i = 0; i < ins->src_count; ++i) + src_param_validate_is_double(&ins->src[i], ins->handler_idx, parser); +} + +static void instruction_validate_dst_params_are_double(const struct vkd3d_shader_instruction *ins, + struct vkd3d_shader_parser *parser) +{ + unsigned int i; + for (i = 0; i < ins->dst_count; ++i) + dst_param_validate_is_double(&ins->dst[i], ins->handler_idx, parser); +} + +static void instruction_validate_all_params_are_double(const struct vkd3d_shader_instruction *ins, + struct vkd3d_shader_parser *parser) +{ + instruction_validate_src_params_are_double(ins, parser); + instruction_validate_dst_params_are_double(ins, parser); +} + +static void normalise_double_opcode_variants(struct vkd3d_shader_parser *parser) +{ + unsigned int i, j; + + for (i = 0; i < parser->instructions.count; ++i) + { + struct vkd3d_shader_instruction *ins = &parser->instructions.elements[i]; + + switch (ins->handler_idx) + { + case VKD3DSIH_DMOV: + instruction_validate_all_params_are_double(ins, parser); + ins->handler_idx = VKD3DSIH_MOV; + break; + case VKD3DSIH_DMOVC: + for (j = 1; j < ins->src_count; ++j) + src_param_validate_is_double(&ins->src[j], ins->handler_idx, parser); + instruction_validate_dst_params_are_double(ins, parser); + ins->handler_idx = VKD3DSIH_MOVC; + break; + case VKD3DSIH_DADD: + instruction_validate_all_params_are_double(ins, parser); + ins->handler_idx = VKD3DSIH_ADD; + break; + case VKD3DSIH_DDIV: + instruction_validate_all_params_are_double(ins, parser); + ins->handler_idx = VKD3DSIH_DIV; + break; + case VKD3DSIH_DMUL: + instruction_validate_all_params_are_double(ins, parser); + ins->handler_idx = VKD3DSIH_MUL; + break; + case VKD3DSIH_DTOF: + instruction_validate_src_params_are_double(ins, parser); + ins->handler_idx = VKD3DSIH_FTOF; + break; + case VKD3DSIH_DTOI: + instruction_validate_src_params_are_double(ins, parser); + ins->handler_idx = VKD3DSIH_FTOI; + break; + case VKD3DSIH_DTOU: + instruction_validate_src_params_are_double(ins, parser); + ins->handler_idx = VKD3DSIH_FTOU; + break; + case VKD3DSIH_FTOD: + instruction_validate_dst_params_are_double(ins, parser); + ins->handler_idx = VKD3DSIH_FTOF; + break; + case VKD3DSIH_ITOD: + instruction_validate_dst_params_are_double(ins, parser); + ins->handler_idx = VKD3DSIH_ITOF; + break; + case VKD3DSIH_UTOD: + instruction_validate_dst_params_are_double(ins, parser); + ins->handler_idx = VKD3DSIH_UTOF; + break; + case VKD3DSIH_DFMA: + instruction_validate_all_params_are_double(ins, parser); + ins->handler_idx = VKD3DSIH_MAD; + break; + case VKD3DSIH_DMAX: + instruction_validate_all_params_are_double(ins, parser); + ins->handler_idx = VKD3DSIH_MAX; + break; + case VKD3DSIH_DMIN: + instruction_validate_all_params_are_double(ins, parser); + ins->handler_idx = VKD3DSIH_MIN; + break; + case VKD3DSIH_DRCP: + instruction_validate_all_params_are_double(ins, parser); + ins->handler_idx = VKD3DSIH_RCP; + break; + case VKD3DSIH_DEQ: + instruction_validate_src_params_are_double(ins, parser); + ins->handler_idx = VKD3DSIH_EQ; + break; + case VKD3DSIH_DGE: + instruction_validate_src_params_are_double(ins, parser); + ins->handler_idx = VKD3DSIH_GE; + break; + case VKD3DSIH_DLT: + instruction_validate_src_params_are_double(ins, parser); + ins->handler_idx = VKD3DSIH_LT; + break; + case VKD3DSIH_DNE: + instruction_validate_src_params_are_double(ins, parser); + ins->handler_idx = VKD3DSIH_NE; + break; + default: + break; + } + } +} + enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, const struct vkd3d_shader_compile_info *compile_info) { @@ -1457,6 +1598,9 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, if (result >= 0) result = normalise_combined_samplers(parser);
+ if (result >= 0) + normalise_double_opcode_variants(parser); + if (result >= 0 && TRACE_ON()) vkd3d_shader_trace(instructions, &parser->shader_version);
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 6faac0ccd..b8b19c69d 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -6595,25 +6595,17 @@ static SpvOp spirv_compiler_map_alu_instruction(const struct vkd3d_shader_instru {VKD3DSIH_AND, SpvOpBitwiseAnd}, {VKD3DSIH_BFREV, SpvOpBitReverse}, {VKD3DSIH_COUNTBITS, SpvOpBitCount}, - {VKD3DSIH_DADD, SpvOpFAdd}, - {VKD3DSIH_DDIV, SpvOpFDiv}, {VKD3DSIH_DIV, SpvOpFDiv}, - {VKD3DSIH_DMUL, SpvOpFMul}, - {VKD3DSIH_DTOF, SpvOpFConvert}, - {VKD3DSIH_DTOI, SpvOpConvertFToS}, - {VKD3DSIH_DTOU, SpvOpConvertFToU}, - {VKD3DSIH_FTOD, SpvOpFConvert}, + {VKD3DSIH_FTOF, SpvOpFConvert}, {VKD3DSIH_IADD, SpvOpIAdd}, {VKD3DSIH_INEG, SpvOpSNegate}, {VKD3DSIH_ISHL, SpvOpShiftLeftLogical}, {VKD3DSIH_ISHR, SpvOpShiftRightArithmetic}, - {VKD3DSIH_ITOD, SpvOpConvertSToF}, {VKD3DSIH_ITOF, SpvOpConvertSToF}, {VKD3DSIH_MUL, SpvOpFMul}, {VKD3DSIH_NOT, SpvOpNot}, {VKD3DSIH_OR, SpvOpBitwiseOr}, {VKD3DSIH_USHR, SpvOpShiftRightLogical}, - {VKD3DSIH_UTOD, SpvOpConvertUToF}, {VKD3DSIH_UTOF, SpvOpConvertUToF}, {VKD3DSIH_XOR, SpvOpBitwiseXor}, }; @@ -6687,9 +6679,6 @@ static enum GLSLstd450 spirv_compiler_map_ext_glsl_instruction( } glsl_insts[] = { - {VKD3DSIH_DFMA, GLSLstd450Fma}, - {VKD3DSIH_DMAX, GLSLstd450NMax}, - {VKD3DSIH_DMIN, GLSLstd450NMin}, {VKD3DSIH_EXP, GLSLstd450Exp2}, {VKD3DSIH_FIRSTBIT_HI, GLSLstd450FindUMsb}, {VKD3DSIH_FIRSTBIT_LO, GLSLstd450FindILsb}, @@ -7091,10 +7080,18 @@ static void spirv_compiler_emit_ftoi(struct spirv_compiler *compiler, dst_type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); src_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask);
- int_min_id = spirv_compiler_get_constant_float_vector(compiler, -2147483648.0f, component_count); + if (src->reg.data_type == VKD3D_DATA_DOUBLE) + { + int_min_id = spirv_compiler_get_constant_double_vector(compiler, -2147483648.0, component_count); + float_max_id = spirv_compiler_get_constant_double_vector(compiler, 2147483648.0, component_count); + } + else + { + int_min_id = spirv_compiler_get_constant_float_vector(compiler, -2147483648.0f, component_count); + float_max_id = spirv_compiler_get_constant_float_vector(compiler, 2147483648.0f, component_count); + } val_id = vkd3d_spirv_build_op_glsl_std450_max(builder, src_type_id, src_id, int_min_id);
- float_max_id = spirv_compiler_get_constant_float_vector(compiler, 2147483648.0f, component_count); int_max_id = spirv_compiler_get_constant_int_vector(compiler, INT_MAX, component_count); condition_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count); condition_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, @@ -7132,10 +7129,18 @@ static void spirv_compiler_emit_ftou(struct spirv_compiler *compiler, dst_type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); src_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask);
- zero_id = spirv_compiler_get_constant_float_vector(compiler, 0.0f, component_count); + if (src->reg.data_type == VKD3D_DATA_DOUBLE) + { + zero_id = spirv_compiler_get_constant_double_vector(compiler, 0.0, component_count); + float_max_id = spirv_compiler_get_constant_double_vector(compiler, 4294967296.0, component_count); + } + else + { + zero_id = spirv_compiler_get_constant_float_vector(compiler, 0.0f, component_count); + float_max_id = spirv_compiler_get_constant_float_vector(compiler, 4294967296.0f, component_count); + } val_id = vkd3d_spirv_build_op_glsl_std450_max(builder, src_type_id, src_id, zero_id);
- float_max_id = spirv_compiler_get_constant_float_vector(compiler, 4294967296.0f, component_count); uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, UINT_MAX, component_count); condition_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count); condition_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, @@ -7282,17 +7287,13 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co
switch (instruction->handler_idx) { - case VKD3DSIH_DEQ: case VKD3DSIH_EQ: op = SpvOpFOrdEqual; break; - case VKD3DSIH_DGE: case VKD3DSIH_GE: op = SpvOpFOrdGreaterThanEqual; break; case VKD3DSIH_IEQ: op = SpvOpIEqual; break; case VKD3DSIH_IGE: op = SpvOpSGreaterThanEqual; break; case VKD3DSIH_ILT: op = SpvOpSLessThan; break; case VKD3DSIH_INE: op = SpvOpINotEqual; break; - case VKD3DSIH_DLT: case VKD3DSIH_LT: op = SpvOpFOrdLessThan; break; - case VKD3DSIH_DNE: case VKD3DSIH_NE: op = SpvOpFUnordNotEqual; break; case VKD3DSIH_UGE: op = SpvOpUGreaterThanEqual; break; case VKD3DSIH_ULT: op = SpvOpULessThan; break; @@ -9391,11 +9392,9 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, case VKD3DSIH_HS_JOIN_PHASE: spirv_compiler_enter_shader_phase(compiler, instruction); break; - case VKD3DSIH_DMOV: case VKD3DSIH_MOV: spirv_compiler_emit_mov(compiler, instruction); break; - case VKD3DSIH_DMOVC: case VKD3DSIH_MOVC: spirv_compiler_emit_movc(compiler, instruction); break; @@ -9406,32 +9405,21 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, case VKD3DSIH_AND: case VKD3DSIH_BFREV: case VKD3DSIH_COUNTBITS: - case VKD3DSIH_DADD: - case VKD3DSIH_DDIV: case VKD3DSIH_DIV: - case VKD3DSIH_DMUL: - case VKD3DSIH_DTOF: - case VKD3DSIH_DTOI: - case VKD3DSIH_DTOU: - case VKD3DSIH_FTOD: + case VKD3DSIH_FTOF: case VKD3DSIH_IADD: case VKD3DSIH_INEG: case VKD3DSIH_ISHL: case VKD3DSIH_ISHR: - case VKD3DSIH_ITOD: case VKD3DSIH_ITOF: case VKD3DSIH_MUL: case VKD3DSIH_NOT: case VKD3DSIH_OR: case VKD3DSIH_USHR: - case VKD3DSIH_UTOD: case VKD3DSIH_UTOF: case VKD3DSIH_XOR: spirv_compiler_emit_alu_instruction(compiler, instruction); break; - case VKD3DSIH_DFMA: - case VKD3DSIH_DMAX: - case VKD3DSIH_DMIN: case VKD3DSIH_EXP: case VKD3DSIH_FIRSTBIT_HI: case VKD3DSIH_FIRSTBIT_LO: @@ -9458,7 +9446,6 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, case VKD3DSIH_DP2: spirv_compiler_emit_dot(compiler, instruction); break; - case VKD3DSIH_DRCP: case VKD3DSIH_RCP: spirv_compiler_emit_rcp(compiler, instruction); break; @@ -9480,10 +9467,6 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, case VKD3DSIH_FTOU: spirv_compiler_emit_ftou(compiler, instruction); break; - case VKD3DSIH_DEQ: - case VKD3DSIH_DGE: - case VKD3DSIH_DLT: - case VKD3DSIH_DNE: case VKD3DSIH_EQ: case VKD3DSIH_GE: case VKD3DSIH_IEQ: diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 912267e0e..81227758a 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -337,6 +337,7 @@ enum vkd3d_shader_opcode VKD3DSIH_FIRSTBIT_SHI, VKD3DSIH_FRC, VKD3DSIH_FTOD, + VKD3DSIH_FTOF, VKD3DSIH_FTOI, VKD3DSIH_FTOU, VKD3DSIH_GATHER4,