Goes atop MRs 409 and 436. The last three commits belong to this MR.
-- v3: vkd3d-shader/dxil: Implement the DXIL CMP2 instruction. vkd3d-shader/spirv: Support orderedness inversion in comparison instructions. vkd3d-shader/spirv: Support bool result in spirv_compiler_emit_comparison_instruction(). vkd3d-shader/dxil: Implement the DXIL CAST instruction. vkd3d-shader/spirv: Support double in spirv_compiler_emit_ftou(). vkd3d-shader/spirv: Support double in spirv_compiler_emit_ftoi(). vkd3d-shader/spirv: Handle unsigned result in spirv_compiler_emit_ftoi(). vkd3d-shader/spirv: Introduce integer width cast instructions. vkd3d-shader/spirv: Support bool cast in spirv_compiler_emit_alu_instruction(). vkd3d-shader/spirv: Support bool logic ops in spirv_compiler_emit_alu_instruction(). vkd3d-shader/spirv: Support bitcast in spirv_compiler_emit_load_ssa_reg().
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 1 + libs/vkd3d-shader/spirv.c | 10 ++++++++++ libs/vkd3d-shader/vkd3d_shader_private.h | 1 + 3 files changed, 12 insertions(+)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index e0e242cb7..b29877106 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -1937,6 +1937,7 @@ static void register_init_ssa_vector(struct vkd3d_shader_register *reg, const st id = sm6_parser_alloc_ssa_id(sm6); data_type = vkd3d_data_type_from_sm6_type(sm6_type_get_scalar_type(type, 0)); register_init_with_id(reg, VKD3DSPR_SSA, data_type, id); + reg->u.ssa_data_type = data_type; reg->dimension = component_count > 1 ? VSIR_DIMENSION_VEC4 : VSIR_DIMENSION_SCALAR; }
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index a25edb644..e88858791 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -3751,6 +3751,7 @@ static uint32_t spirv_compiler_emit_load_ssa_reg(struct spirv_compiler *compiler unsigned int swizzle) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + enum vkd3d_shader_component_type reg_component_type; unsigned int component_idx; uint32_t type_id, val_id;
@@ -3759,7 +3760,16 @@ static uint32_t spirv_compiler_emit_load_ssa_reg(struct spirv_compiler *compiler assert(vkd3d_swizzle_is_scalar(swizzle));
if (reg->dimension == VSIR_DIMENSION_SCALAR) + { + reg_component_type = vkd3d_component_type_from_data_type(reg->u.ssa_data_type); + if (component_type != reg_component_type) + { + type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); + val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); + } + return val_id; + }
type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); component_idx = vkd3d_swizzle_get_component(swizzle, 0); diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index ab7300115..66d6455d8 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -818,6 +818,7 @@ struct vkd3d_shader_register uint64_t immconst_uint64[VKD3D_DVEC2_SIZE]; double immconst_double[VKD3D_DVEC2_SIZE]; unsigned fp_body_idx; + enum vkd3d_data_type ssa_data_type; } u; };
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/spirv.c | 49 +++++++++++++++++++++++- libs/vkd3d-shader/vkd3d_shader_private.h | 1 + 2 files changed, 49 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index e88858791..5c0d70107 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -1150,6 +1150,20 @@ static uint32_t vkd3d_spirv_get_op_type_pointer(struct vkd3d_spirv_builder *buil vkd3d_spirv_build_op_type_pointer); }
+static uint32_t vkd3d_spirv_build_op_constant_bool(struct vkd3d_spirv_builder *builder, + uint32_t result_type, uint32_t value) +{ + return vkd3d_spirv_build_op_tr(builder, &builder->global_stream, + value ? SpvOpConstantTrue : SpvOpConstantFalse, result_type); +} + +static uint32_t vkd3d_spirv_get_op_constant_bool(struct vkd3d_spirv_builder *builder, + uint32_t result_type, uint32_t value) +{ + return vkd3d_spirv_build_once2(builder, value ? SpvOpConstantTrue : SpvOpConstantFalse, result_type, value, + vkd3d_spirv_build_op_constant_bool); +} + /* Types larger than 32-bits are not supported. */ static uint32_t vkd3d_spirv_build_op_constant(struct vkd3d_spirv_builder *builder, uint32_t result_type, uint32_t value) @@ -1802,6 +1816,8 @@ static uint32_t vkd3d_spirv_get_type_id_for_data_type(struct vkd3d_spirv_builder break; case VKD3D_DATA_DOUBLE: return vkd3d_spirv_get_op_type_float(builder, 64); + case VKD3D_DATA_BOOL: + return vkd3d_spirv_get_op_type_bool(builder); default: FIXME("Unhandled data type %#x.\n", data_type); return 0; @@ -2880,6 +2896,13 @@ static uint32_t spirv_compiler_get_constant(struct spirv_compiler *compiler, case VKD3D_SHADER_COMPONENT_INT: case VKD3D_SHADER_COMPONENT_FLOAT: break; + case VKD3D_SHADER_COMPONENT_BOOL: + if (component_count == 1) + return vkd3d_spirv_get_op_constant_bool(builder, type_id, *values); + FIXME("Unsupported vector of bool.\n"); + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_TYPE, + "Vectors of bool type are not supported."); + return vkd3d_spirv_get_op_undef(builder, type_id); default: FIXME("Unhandled component_type %#x.\n", component_type); return vkd3d_spirv_get_op_undef(builder, type_id); @@ -6607,6 +6630,21 @@ static SpvOp spirv_compiler_map_alu_instruction(const struct vkd3d_shader_instru return SpvOpMax; }
+static SpvOp spirv_compiler_map_logical_instruction(const struct vkd3d_shader_instruction *instruction) +{ + switch (instruction->handler_idx) + { + case VKD3DSIH_AND: + return SpvOpLogicalAnd; + case VKD3DSIH_OR: + return SpvOpLogicalOr; + case VKD3DSIH_XOR: + return SpvOpLogicalNotEqual; + default: + return SpvOpMax; + } +} + static void spirv_compiler_emit_alu_instruction(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { @@ -6618,7 +6656,16 @@ static void spirv_compiler_emit_alu_instruction(struct spirv_compiler *compiler, unsigned int i; SpvOp op;
- op = spirv_compiler_map_alu_instruction(instruction); + if (src->reg.data_type == VKD3D_DATA_BOOL && dst->reg.data_type == VKD3D_DATA_BOOL) + { + /* VSIR supports logic ops AND/OR/XOR on bool values. */ + op = spirv_compiler_map_logical_instruction(instruction); + } + else + { + op = spirv_compiler_map_alu_instruction(instruction); + } + if (op == SpvOpMax) { ERR("Unexpected instruction %#x.\n", instruction->handler_idx); diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 66d6455d8..0eb71c435 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -93,6 +93,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_IDX_UNSUPPORTED = 2003, VKD3D_SHADER_ERROR_SPV_STENCIL_EXPORT_UNSUPPORTED = 2004, VKD3D_SHADER_ERROR_SPV_OUT_OF_MEMORY = 2005, + VKD3D_SHADER_ERROR_SPV_INVALID_TYPE = 2006,
VKD3D_SHADER_WARNING_SPV_INVALID_SWIZZLE = 2300,
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/spirv.c | 73 ++++++++++++++++++++++-- libs/vkd3d-shader/vkd3d_shader_private.h | 1 + 2 files changed, 70 insertions(+), 4 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 5c0d70107..3c5138f71 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -4246,6 +4246,30 @@ static uint32_t spirv_compiler_emit_bool_to_int(struct spirv_compiler *compiler, return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); }
+static uint32_t spirv_compiler_emit_bool_to_float(struct spirv_compiler *compiler, + unsigned int component_count, uint32_t val_id, bool signedness) +{ + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id, true_id, false_id; + + true_id = spirv_compiler_get_constant_float_vector(compiler, signedness ? -1.0f : 1.0f, component_count); + false_id = spirv_compiler_get_constant_float_vector(compiler, 0.0f, component_count); + type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, component_count); + return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); +} + +static uint32_t spirv_compiler_emit_bool_to_double(struct spirv_compiler *compiler, + unsigned int component_count, uint32_t val_id, bool signedness) +{ + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id, true_id, false_id; + + true_id = spirv_compiler_get_constant_double_vector(compiler, signedness ? -1.0 : 1.0, component_count); + false_id = spirv_compiler_get_constant_double_vector(compiler, 0.0, component_count); + type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_DOUBLE, component_count); + return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); +} + typedef uint32_t (*vkd3d_spirv_builtin_fixup_pfn)(struct spirv_compiler *compiler, uint32_t val_id);
@@ -6645,6 +6669,35 @@ static SpvOp spirv_compiler_map_logical_instruction(const struct vkd3d_shader_in } }
+static void spirv_compiler_emit_bool_cast(struct spirv_compiler *compiler, + const struct vkd3d_shader_instruction *instruction) +{ + const struct vkd3d_shader_dst_param *dst = instruction->dst; + const struct vkd3d_shader_src_param *src = instruction->src; + uint32_t val_id; + + assert(src->reg.data_type == VKD3D_DATA_BOOL && dst->reg.data_type != VKD3D_DATA_BOOL); + + val_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); + if (dst->reg.data_type == VKD3D_DATA_FLOAT) + { + val_id = spirv_compiler_emit_bool_to_float(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOF); + } + else if (dst->reg.data_type == VKD3D_DATA_DOUBLE) + { + /* ITOD is not supported. Frontends which emit bool casts must use ITOF for double. */ + val_id = spirv_compiler_emit_bool_to_double(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOF); + } + else + { + WARN("Unhandled data type %u.\n", dst->reg.data_type); + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_TYPE, + "Register data type %u is unhandled.", dst->reg.data_type); + } + + spirv_compiler_emit_store_dst(compiler, dst, val_id); +} + static void spirv_compiler_emit_alu_instruction(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { @@ -6653,13 +6706,23 @@ static void spirv_compiler_emit_alu_instruction(struct spirv_compiler *compiler, const struct vkd3d_shader_src_param *src = instruction->src; uint32_t src_ids[SPIRV_MAX_SRC_COUNT]; uint32_t type_id, val_id; + SpvOp op = SpvOpMax; unsigned int i; - SpvOp op;
- if (src->reg.data_type == VKD3D_DATA_BOOL && dst->reg.data_type == VKD3D_DATA_BOOL) + if (src->reg.data_type == VKD3D_DATA_BOOL) { - /* VSIR supports logic ops AND/OR/XOR on bool values. */ - op = spirv_compiler_map_logical_instruction(instruction); + if (dst->reg.data_type == VKD3D_DATA_BOOL) + { + /* VSIR supports logic ops AND/OR/XOR on bool values. */ + op = spirv_compiler_map_logical_instruction(instruction); + } + else if (instruction->handler_idx == VKD3DSIH_ITOF || instruction->handler_idx == VKD3DSIH_UTOF) + { + /* VSIR supports cast from bool to signed/unsigned integer types and floating point types, + * where bool is treated as a 1-bit integer and a signed 'true' value converts to -1. */ + spirv_compiler_emit_bool_cast(compiler, instruction); + return; + } } else { @@ -6669,6 +6732,8 @@ static void spirv_compiler_emit_alu_instruction(struct spirv_compiler *compiler, if (op == SpvOpMax) { ERR("Unexpected instruction %#x.\n", instruction->handler_idx); + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_HANDLER, + "Encountered invalid/unhandled instruction handler %#x.", instruction->handler_idx); return; }
diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 0eb71c435..fb41d2f3c 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -94,6 +94,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_SPV_STENCIL_EXPORT_UNSUPPORTED = 2004, VKD3D_SHADER_ERROR_SPV_OUT_OF_MEMORY = 2005, VKD3D_SHADER_ERROR_SPV_INVALID_TYPE = 2006, + VKD3D_SHADER_ERROR_SPV_INVALID_HANDLER = 2007,
VKD3D_SHADER_WARNING_SPV_INVALID_SWIZZLE = 2300,
From: Conor McCarthy cmccarthy@codeweavers.com
ITOI and UTOU may cast from a bool to a 32-bit integer. Cast to a 64-bit integer from a smaller type will be added later. --- libs/vkd3d-shader/d3d_asm.c | 2 ++ libs/vkd3d-shader/spirv.c | 17 ++++++++++++----- libs/vkd3d-shader/vkd3d_shader_private.h | 2 ++ 3 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d-shader/d3d_asm.c index 5cea0c0c2..0a9561d05 100644 --- a/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d-shader/d3d_asm.c @@ -199,6 +199,7 @@ static const char * const shader_opcode_names[] = [VKD3DSIH_ISHR ] = "ishr", [VKD3DSIH_ITOD ] = "itod", [VKD3DSIH_ITOF ] = "itof", + [VKD3DSIH_ITOI ] = "itoi", [VKD3DSIH_LABEL ] = "label", [VKD3DSIH_LD ] = "ld", [VKD3DSIH_LD2DMS ] = "ld2dms", @@ -306,6 +307,7 @@ static const char * const shader_opcode_names[] = [VKD3DSIH_USHR ] = "ushr", [VKD3DSIH_UTOD ] = "utod", [VKD3DSIH_UTOF ] = "utof", + [VKD3DSIH_UTOU ] = "utou", [VKD3DSIH_XOR ] = "xor", };
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 3c5138f71..260844f99 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -4235,12 +4235,12 @@ static uint32_t spirv_compiler_emit_int_to_bool(struct spirv_compiler *compiler, }
static uint32_t spirv_compiler_emit_bool_to_int(struct spirv_compiler *compiler, - unsigned int component_count, uint32_t val_id) + unsigned int component_count, uint32_t val_id, bool signedness) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; uint32_t type_id, true_id, false_id;
- true_id = spirv_compiler_get_constant_uint_vector(compiler, 0xffffffff, component_count); + true_id = spirv_compiler_get_constant_uint_vector(compiler, signedness ? 0xffffffff : 1, component_count); false_id = spirv_compiler_get_constant_uint_vector(compiler, 0, component_count); type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, component_count); return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); @@ -4312,7 +4312,7 @@ static uint32_t sv_instance_id_fixup(struct spirv_compiler *compiler, static uint32_t sv_front_face_fixup(struct spirv_compiler *compiler, uint32_t front_facing_id) { - return spirv_compiler_emit_bool_to_int(compiler, 1, front_facing_id); + return spirv_compiler_emit_bool_to_int(compiler, 1, front_facing_id, true); }
/* frag_coord.w = 1.0f / frag_coord.w */ @@ -6688,6 +6688,10 @@ static void spirv_compiler_emit_bool_cast(struct spirv_compiler *compiler, /* ITOD is not supported. Frontends which emit bool casts must use ITOF for double. */ val_id = spirv_compiler_emit_bool_to_double(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOF); } + else if (dst->reg.data_type == VKD3D_DATA_UINT) + { + val_id = spirv_compiler_emit_bool_to_int(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOI); + } else { WARN("Unhandled data type %u.\n", dst->reg.data_type); @@ -6716,7 +6720,8 @@ static void spirv_compiler_emit_alu_instruction(struct spirv_compiler *compiler, /* VSIR supports logic ops AND/OR/XOR on bool values. */ op = spirv_compiler_map_logical_instruction(instruction); } - else if (instruction->handler_idx == VKD3DSIH_ITOF || instruction->handler_idx == VKD3DSIH_UTOF) + else if (instruction->handler_idx == VKD3DSIH_ITOF || instruction->handler_idx == VKD3DSIH_UTOF + || instruction->handler_idx == VKD3DSIH_ITOI || instruction->handler_idx == VKD3DSIH_UTOU) { /* VSIR supports cast from bool to signed/unsigned integer types and floating point types, * where bool is treated as a 1-bit integer and a signed 'true' value converts to -1. */ @@ -7405,7 +7410,7 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co result_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, op, type_id, src0_id, src1_id);
- result_id = spirv_compiler_emit_bool_to_int(compiler, component_count, result_id); + result_id = spirv_compiler_emit_bool_to_int(compiler, component_count, result_id, true); spirv_compiler_emit_store_reg(compiler, &dst->reg, dst->write_mask, result_id); }
@@ -9516,12 +9521,14 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, case VKD3DSIH_ISHR: case VKD3DSIH_ITOD: case VKD3DSIH_ITOF: + case VKD3DSIH_ITOI: case VKD3DSIH_MUL: case VKD3DSIH_NOT: case VKD3DSIH_OR: case VKD3DSIH_USHR: case VKD3DSIH_UTOD: case VKD3DSIH_UTOF: + case VKD3DSIH_UTOU: case VKD3DSIH_XOR: spirv_compiler_emit_alu_instruction(compiler, instruction); break; diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index fb41d2f3c..d36a921af 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -386,6 +386,7 @@ enum vkd3d_shader_opcode VKD3DSIH_ISHR, VKD3DSIH_ITOD, VKD3DSIH_ITOF, + VKD3DSIH_ITOI, VKD3DSIH_LABEL, VKD3DSIH_LD, VKD3DSIH_LD2DMS, @@ -493,6 +494,7 @@ enum vkd3d_shader_opcode VKD3DSIH_USHR, VKD3DSIH_UTOD, VKD3DSIH_UTOF, + VKD3DSIH_UTOU, VKD3DSIH_XOR,
VKD3DSIH_INVALID,
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/spirv.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 260844f99..2482d0d1f 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -2969,12 +2969,6 @@ static uint32_t spirv_compiler_get_constant_vector(struct spirv_compiler *compil return spirv_compiler_get_constant(compiler, component_type, component_count, values); }
-static uint32_t spirv_compiler_get_constant_int_vector(struct spirv_compiler *compiler, - uint32_t value, unsigned int component_count) -{ - return spirv_compiler_get_constant_vector(compiler, VKD3D_SHADER_COMPONENT_INT, component_count, value); -} - static uint32_t spirv_compiler_get_constant_uint_vector(struct spirv_compiler *compiler, uint32_t value, unsigned int component_count) { @@ -7177,6 +7171,7 @@ static void spirv_compiler_emit_ftoi(struct spirv_compiler *compiler, const struct vkd3d_shader_dst_param *dst = instruction->dst; const struct vkd3d_shader_src_param *src = instruction->src; uint32_t src_type_id, dst_type_id, condition_type_id; + enum vkd3d_shader_component_type component_type; unsigned int component_count;
assert(instruction->dst_count == 1); @@ -7194,8 +7189,11 @@ static void spirv_compiler_emit_ftoi(struct spirv_compiler *compiler, int_min_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);
+ /* VSIR allows the destination of a signed conversion to be unsigned. */ + component_type = vkd3d_component_type_from_data_type(dst->reg.data_type); + 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); + int_max_id = spirv_compiler_get_constant_vector(compiler, component_type, component_count, INT_MAX); 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, SpvOpFOrdGreaterThanEqual, condition_type_id, val_id, float_max_id); @@ -7203,7 +7201,7 @@ static void spirv_compiler_emit_ftoi(struct spirv_compiler *compiler, val_id = vkd3d_spirv_build_op_tr1(builder, &builder->function_stream, SpvOpConvertFToS, dst_type_id, val_id); val_id = vkd3d_spirv_build_op_select(builder, dst_type_id, condition_id, int_max_id, val_id);
- zero_id = spirv_compiler_get_constant_int_vector(compiler, 0, component_count); + zero_id = spirv_compiler_get_constant_vector(compiler, component_type, component_count, 0); condition_id = vkd3d_spirv_build_op_tr1(builder, &builder->function_stream, SpvOpIsNan, condition_type_id, src_id); val_id = vkd3d_spirv_build_op_select(builder, dst_type_id, condition_id, zero_id, val_id);
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/spirv.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 2482d0d1f..5b8f7f691 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -7186,13 +7186,22 @@ 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);
/* VSIR allows the destination of a signed conversion to be unsigned. */ component_type = vkd3d_component_type_from_data_type(dst->reg.data_type);
- float_max_id = spirv_compiler_get_constant_float_vector(compiler, 2147483648.0f, component_count); int_max_id = spirv_compiler_get_constant_vector(compiler, component_type, component_count, INT_MAX); 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, @@ -9509,7 +9518,6 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, case VKD3DSIH_DIV: case VKD3DSIH_DMUL: case VKD3DSIH_DTOF: - case VKD3DSIH_DTOI: case VKD3DSIH_DTOU: case VKD3DSIH_FREM: case VKD3DSIH_FTOD: @@ -9577,6 +9585,7 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, case VKD3DSIH_UDIV: spirv_compiler_emit_int_div(compiler, instruction); break; + case VKD3DSIH_DTOI: case VKD3DSIH_FTOI: spirv_compiler_emit_ftoi(compiler, instruction); break;
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/spirv.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 5b8f7f691..c808a945d 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -7239,10 +7239,19 @@ 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, @@ -9518,7 +9527,6 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, case VKD3DSIH_DIV: case VKD3DSIH_DMUL: case VKD3DSIH_DTOF: - case VKD3DSIH_DTOU: case VKD3DSIH_FREM: case VKD3DSIH_FTOD: case VKD3DSIH_IADD: @@ -9589,6 +9597,7 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, case VKD3DSIH_FTOI: spirv_compiler_emit_ftoi(compiler, instruction); break; + case VKD3DSIH_DTOU: case VKD3DSIH_FTOU: spirv_compiler_emit_ftou(compiler, instruction); break;
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 172 ++++++++++++++++++ tests/hlsl/arithmetic-int-uniform.shader_test | 14 +- tests/hlsl/array-index-expr.shader_test | 16 +- tests/hlsl/asfloat.shader_test | 2 +- tests/hlsl/asuint.shader_test | 4 +- tests/hlsl/d3dcolor-to-ubyte4.shader_test | 4 +- tests/hlsl/function-cast.shader_test | 4 +- tests/hlsl/lerp.shader_test | 2 +- .../shader-interstage-interface.shader_test | 2 +- 9 files changed, 196 insertions(+), 24 deletions(-)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index b29877106..17521d3ef 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -289,6 +289,23 @@ enum dx_intrinsic_opcode DX_CBUFFER_LOAD_LEGACY = 59, };
+enum dxil_cast_code +{ + CAST_TRUNC = 0, + CAST_ZEXT = 1, + CAST_SEXT = 2, + CAST_FPTOUI = 3, + CAST_FPTOSI = 4, + CAST_UITOFP = 5, + CAST_SITOFP = 6, + CAST_FPTRUNC = 7, + CAST_FPEXT = 8, + CAST_PTRTOINT = 9, + CAST_INTTOPTR = 10, + CAST_BITCAST = 11, + CAST_ADDRSPACECAST = 12, +}; + struct sm6_pointer_info { const struct sm6_type *type; @@ -3249,6 +3266,158 @@ static void sm6_parser_emit_call(struct sm6_parser *sm6, const struct dxil_recor fn_value->u.function.name, &operands[1], operand_count - 1, ins, dst); }
+static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_type *from, + const struct sm6_type *to, struct sm6_parser *sm6) +{ + enum vkd3d_shader_opcode op = VKD3DSIH_INVALID; + bool from_int, to_int; + bool is_valid = false; + + /* NOTE: DXIL currently doesn't use vectors here. */ + if (!sm6_type_is_scalar(from) || !sm6_type_is_scalar(to)) + { + FIXME("Unhandled non-scalar type class %u and/or %u.\n", from->class, to->class); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Cast of non-scalar types is not implemented."); + /* width is not available for non-scalar types so we can't attempt to compile it. */ + return VKD3DSIH_INVALID; + } + if (to->u.width == 8 || from->u.width == 8) + { + FIXME("Unhandled 8-bit value.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Cast to/from an 8-bit type is not implemented."); + return VKD3DSIH_INVALID; + } + + from_int = sm6_type_is_integer(from); + to_int = sm6_type_is_integer(to); + + /* DXC emits minimum precision types as 16-bit. These must be emitted + * as 32-bit in VSIR, so all width extensions to 32 bits are no-ops. */ + switch (code) + { + case CAST_TRUNC: + /* nop or min precision. TODO: native 16-bit */ + if (to->u.width == from->u.width || (to->u.width == 16 && from->u.width == 32)) + op = VKD3DSIH_NOP; + else + op = VKD3DSIH_UTOU; + is_valid = from_int && to_int && to->u.width <= from->u.width; + break; + case CAST_ZEXT: + case CAST_SEXT: + /* nop or min precision. TODO: native 16-bit */ + if (to->u.width == from->u.width || (to->u.width == 32 && from->u.width == 16)) + { + op = VKD3DSIH_NOP; + is_valid = from_int && to_int; + } + else if (to->u.width > from->u.width) + { + op = (code == CAST_ZEXT) ? VKD3DSIH_UTOU : VKD3DSIH_ITOI; + assert(from->u.width == 1 || to->u.width == 64); + is_valid = from_int && to_int; + } + break; + case CAST_FPTOUI: + op = VKD3DSIH_FTOU; + is_valid = !from_int && to_int && to->u.width > 1; + break; + case CAST_FPTOSI: + op = VKD3DSIH_FTOI; + is_valid = !from_int && to_int && to->u.width > 1; + break; + case CAST_UITOFP: + op = VKD3DSIH_UTOF; + is_valid = from_int && !to_int; + break; + case CAST_SITOFP: + op = VKD3DSIH_ITOF; + is_valid = from_int && !to_int; + break; + case CAST_FPTRUNC: + /* TODO: native 16-bit */ + op = (from->u.width == 64) ? VKD3DSIH_DTOF : VKD3DSIH_NOP; + is_valid = !from_int && !to_int; + break; + case CAST_FPEXT: + /* TODO: native 16-bit */ + op = (to->u.width == 64) ? VKD3DSIH_FTOD : VKD3DSIH_NOP; + is_valid = !from_int && !to_int; + break; + case CAST_BITCAST: + op = VKD3DSIH_MOV; + is_valid = to->u.width == from->u.width; + break; + default: + FIXME("Unhandled cast op %"PRIu64".\n", code); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Cast operation %"PRIu64" is unhandled.\n", code); + return VKD3DSIH_INVALID; + } + + if (!is_valid) + { + FIXME("Invalid types %u and/or %u for op %"PRIu64".\n", from->class, to->class, code); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Cast operation %"PRIu64" from type class %u, width %u to type class %u, width %u is invalid.\n", + code, from->class, from->u.width, to->class, to->u.width); + return VKD3DSIH_INVALID; + } + + return op; +} + +static void sm6_parser_emit_cast(struct sm6_parser *sm6, const struct dxil_record *record, + struct vkd3d_shader_instruction *ins, struct sm6_value *dst) +{ + struct vkd3d_shader_src_param *src_param; + enum vkd3d_shader_opcode handler_idx; + const struct sm6_value *value; + const struct sm6_type *type; + unsigned int i = 0; + + if (!(value = sm6_parser_get_value_by_ref(sm6, record, NULL, &i))) + return; + + if (!dxil_record_validate_operand_count(record, i + 2, i + 2, sm6)) + return; + + if (!(type = sm6_parser_get_type(sm6, record->operands[i++]))) + return; + + dst->type = type; + + if (sm6_type_is_pointer(type)) + { + *dst = *value; + dst->type = type; + ins->handler_idx = VKD3DSIH_NOP; + return; + } + + if ((handler_idx = sm6_map_cast_op(record->operands[i], value->type, type, sm6)) == VKD3DSIH_INVALID) + return; + + vsir_instruction_init(ins, &sm6->p.location, handler_idx); + + if (handler_idx == VKD3DSIH_NOP) + { + dst->u.reg = value->u.reg; + return; + } + + src_param = instruction_src_params_alloc(ins, 1, sm6); + src_param_init_from_value(src_param, value); + + instruction_dst_param_init_ssa_scalar(ins, sm6); + + /* bitcast */ + if (handler_idx == VKD3DSIH_MOV) + src_param->reg.data_type = dst->u.reg.data_type; +} + static void sm6_parser_emit_extractval(struct sm6_parser *sm6, const struct dxil_record *record, struct vkd3d_shader_instruction *ins, struct sm6_value *dst) { @@ -3465,6 +3634,9 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const case FUNC_CODE_INST_CALL: sm6_parser_emit_call(sm6, record, code_block, ins, dst); break; + case FUNC_CODE_INST_CAST: + sm6_parser_emit_cast(sm6, record, ins, dst); + break; case FUNC_CODE_INST_EXTRACTVAL: sm6_parser_emit_extractval(sm6, record, ins, dst); break; diff --git a/tests/hlsl/arithmetic-int-uniform.shader_test b/tests/hlsl/arithmetic-int-uniform.shader_test index 726a191a7..7f5cdaaa6 100644 --- a/tests/hlsl/arithmetic-int-uniform.shader_test +++ b/tests/hlsl/arithmetic-int-uniform.shader_test @@ -10,7 +10,7 @@ float4 main() : SV_TARGET
[test] uniform 0 float4 5.0 16.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (21.0, -11.0, 80.0, 0.0)
[pixel shader] @@ -25,7 +25,7 @@ float4 main() : SV_TARGET
[test] uniform 0 float4 5.0 16.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (5.0, 5.0, -5.0, 3.0)
[pixel shader] @@ -40,7 +40,7 @@ float4 main() : SV_TARGET
[test] uniform 0 float4 42.0 5.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (8.0, -8.0, -8.0, 8.0)
[pixel shader] @@ -55,7 +55,7 @@ float4 main() : SV_TARGET
[test] uniform 0 float4 42.0 5.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (2.0, -2.0, 2.0, -2.0)
[pixel shader] @@ -70,7 +70,7 @@ float4 main() : SV_TARGET
[test] uniform 0 float4 45.0 5.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (9.0, -9.0, -9.0, 9.0)
[pixel shader] @@ -85,7 +85,7 @@ float4 main() : SV_TARGET
[test] uniform 0 float4 45.0 5.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (0.0, 0.0, 0.0, 0.0)
[pixel shader] @@ -117,5 +117,5 @@ float4 main() : sv_target [test] uniform 0 float4 45.0 5.0 50.0 10.0 uniform 4 float4 3.0 8.0 2.0 5.0 -todo(sm>=6) draw quad +draw quad probe all rgba (9.0, 5.0, 1.0, 3.0) diff --git a/tests/hlsl/array-index-expr.shader_test b/tests/hlsl/array-index-expr.shader_test index b7d91ea09..0b45df927 100644 --- a/tests/hlsl/array-index-expr.shader_test +++ b/tests/hlsl/array-index-expr.shader_test @@ -12,17 +12,17 @@ uniform 0 float4 1.0 2.0 3.0 4.0 uniform 4 float4 5.0 6.0 7.0 8.0 uniform 8 float4 9.0 10.0 11.0 12.0 uniform 12 float4 0 0 0 0 -todo draw quad -todo probe all rgba (1.0, 2.0, 3.0, 4.0) +todo(sm<6) draw quad +todo(sm<6) probe all rgba (1.0, 2.0, 3.0, 4.0) uniform 12 float4 1 0 0 0 -todo draw quad -todo probe all rgba (5.0, 6.0, 7.0, 8.0) +todo(sm<6) draw quad +todo(sm<6) probe all rgba (5.0, 6.0, 7.0, 8.0) uniform 12 float4 0 1 0 0 -todo draw quad -todo probe all rgba (5.0, 6.0, 7.0, 8.0) +todo(sm<6) draw quad +todo(sm<6) probe all rgba (5.0, 6.0, 7.0, 8.0) uniform 12 float4 1 1 0 0 -todo draw quad -todo probe all rgba (9.0, 10.0, 11.0, 12.0) +todo(sm<6) draw quad +todo(sm<6) probe all rgba (9.0, 10.0, 11.0, 12.0)
[pixel shader] diff --git a/tests/hlsl/asfloat.shader_test b/tests/hlsl/asfloat.shader_test index f43f2fdff..2184c1869 100644 --- a/tests/hlsl/asfloat.shader_test +++ b/tests/hlsl/asfloat.shader_test @@ -20,7 +20,7 @@ float4 main() : sv_target
[test] uniform 0 float4 123.0 -2.0 456 0.01 -todo(sm>=6) draw quad +draw quad probe (320,240) rgba (123.0, -2.0, 456.0, 0.01)
[pixel shader] diff --git a/tests/hlsl/asuint.shader_test b/tests/hlsl/asuint.shader_test index 0a2e39e53..50b0895e9 100644 --- a/tests/hlsl/asuint.shader_test +++ b/tests/hlsl/asuint.shader_test @@ -20,7 +20,7 @@ float4 main() : sv_target
[test] uniform 0 uint4 123 0xc0000000 456 0x7fd69345 -todo(sm>=6) draw quad +draw quad probe (320,240) rgba (123.0, 3221225472.0, 456.0, 2144768896.0)
@@ -37,7 +37,7 @@ float4 main() : sv_target uniform 0 uint4 11 12 0 0 uniform 4 uint4 13 14 0 0 uniform 8 uint4 20 21 22 23 -todo(sm>=6) draw quad +draw quad probe (320,240) rgba (13.0, 21.0, 0.0, 0.0)
diff --git a/tests/hlsl/d3dcolor-to-ubyte4.shader_test b/tests/hlsl/d3dcolor-to-ubyte4.shader_test index 01b7f2f64..dca307cdb 100644 --- a/tests/hlsl/d3dcolor-to-ubyte4.shader_test +++ b/tests/hlsl/d3dcolor-to-ubyte4.shader_test @@ -11,7 +11,7 @@ float4 main() : sv_target
[test] uniform 0 float4 -0.5 6.5 7.5 3.4 -todo(sm>=6) draw quad +draw quad probe all rgba (1912.0, 1657.0, -127.0, 867.0) 1
[pixel shader] @@ -24,5 +24,5 @@ float4 main() : sv_target
[test] uniform 0 float4 -0.5 6.5 7.5 3.4 -todo(sm>=6) draw quad +draw quad probe all rgba (-127.0, -127.0, -127.0, -127.0) 1 diff --git a/tests/hlsl/function-cast.shader_test b/tests/hlsl/function-cast.shader_test index a2b9cf4f4..c92289863 100644 --- a/tests/hlsl/function-cast.shader_test +++ b/tests/hlsl/function-cast.shader_test @@ -18,7 +18,7 @@ float4 main() : sv_target
[test] uniform 0 float4 -1.9 -1.0 2.9 4.0 -todo draw quad +todo(sm<6) draw quad probe all rgba (-1.0, -1.0, 2.0, 4.0)
% As above, but cast "x" to float4 first. @@ -89,5 +89,5 @@ float4 main() : sv_target
[test] uniform 0 int4 -2 0 1 -3000000 -todo draw quad +todo(sm<6) draw quad probe all rgba (-1.0, 0.0, 1.0, -3000000.0) diff --git a/tests/hlsl/lerp.shader_test b/tests/hlsl/lerp.shader_test index 413bfe833..15e90cef9 100644 --- a/tests/hlsl/lerp.shader_test +++ b/tests/hlsl/lerp.shader_test @@ -32,7 +32,7 @@ float4 main() : SV_TARGET uniform 0 int4 2 3 4 0 uniform 4 int4 0 -10 10 1000000 uniform 8 int4 0 1 -1 1000000 -todo(sm>=6) draw quad +draw quad probe all rgba (2.0, -10.0, -2.0, 1e12)
diff --git a/tests/hlsl/shader-interstage-interface.shader_test b/tests/hlsl/shader-interstage-interface.shader_test index 271eb3bbe..584b88cf9 100644 --- a/tests/hlsl/shader-interstage-interface.shader_test +++ b/tests/hlsl/shader-interstage-interface.shader_test @@ -52,5 +52,5 @@ void main(float4 position : SV_Position, float2 t0 : TEXCOORD0, }
[test] -todo(sm>=6) draw triangle strip 4 +draw triangle strip 4 probe all rgba (10.0, 8.0, 7.0, 3.0)
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/spirv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index c808a945d..88bc89704 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -7426,7 +7426,8 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co result_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, op, type_id, src0_id, src1_id);
- result_id = spirv_compiler_emit_bool_to_int(compiler, component_count, result_id, true); + if (dst->reg.data_type != VKD3D_DATA_BOOL) + result_id = spirv_compiler_emit_bool_to_int(compiler, component_count, result_id, true); spirv_compiler_emit_store_reg(compiler, &dst->reg, dst->write_mask, result_id); }
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/spirv.c | 6 ++++++ libs/vkd3d-shader/vkd3d_shader_private.h | 1 + 2 files changed, 7 insertions(+)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 88bc89704..828bc430a 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -7394,8 +7394,13 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co const struct vkd3d_shader_src_param *src = instruction->src; uint32_t src0_id, src1_id, type_id, result_id; unsigned int component_count; + SpvOp unordered_flag = 0; SpvOp op;
+ /* All unordered SpvOp variants equal (ordered_opcode | 1). */ + if (instruction->flags & VKD3DSI_FCMP_INVERT_ORDEREDNESS) + unordered_flag = SpvOpOrdered ^ SpvOpUnordered; + switch (instruction->handler_idx) { case VKD3DSIH_DEQ: @@ -7416,6 +7421,7 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co ERR("Unexpected instruction %#x.\n", instruction->handler_idx); return; } + op ^= unordered_flag;
component_count = vkd3d_write_mask_component_count(dst->write_mask);
diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index d36a921af..18cfb2fcd 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -732,6 +732,7 @@ enum vkd3d_tessellator_domain #define VKD3DSI_RESINFO_UINT 0x2 #define VKD3DSI_SAMPLE_INFO_UINT 0x1 #define VKD3DSI_SAMPLER_COMPARISON_MODE 0x1 +#define VKD3DSI_FCMP_INVERT_ORDEREDNESS 0x1
#define VKD3DSI_PRECISE_X 0x100 #define VKD3DSI_PRECISE_Y 0x200
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 180 +++++++++++++++++++++++ libs/vkd3d-shader/vkd3d_shader_private.h | 2 + tests/hlsl/all.shader_test | 14 +- tests/hlsl/any.shader_test | 36 ++--- tests/hlsl/bool-cast.shader_test | 4 +- tests/hlsl/cast-to-float.shader_test | 2 +- tests/hlsl/cast-to-half.shader_test | 2 +- tests/hlsl/cast-to-int.shader_test | 2 +- tests/hlsl/cast-to-uint.shader_test | 2 +- tests/hlsl/sign.shader_test | 20 +-- 10 files changed, 223 insertions(+), 41 deletions(-)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 17521d3ef..00a05f050 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -306,6 +306,36 @@ enum dxil_cast_code CAST_ADDRSPACECAST = 12, };
+enum dxil_predicate +{ + FCMP_FALSE = 0, + FCMP_OEQ = 1, + FCMP_OGT = 2, + FCMP_OGE = 3, + FCMP_OLT = 4, + FCMP_OLE = 5, + FCMP_ONE = 6, + FCMP_ORD = 7, + FCMP_UNO = 8, + FCMP_UEQ = 9, + FCMP_UGT = 10, + FCMP_UGE = 11, + FCMP_ULT = 12, + FCMP_ULE = 13, + FCMP_UNE = 14, + FCMP_TRUE = 15, + ICMP_EQ = 32, + ICMP_NE = 33, + ICMP_UGT = 34, + ICMP_UGE = 35, + ICMP_ULT = 36, + ICMP_ULE = 37, + ICMP_SGT = 38, + ICMP_SGE = 39, + ICMP_SLT = 40, + ICMP_SLE = 41, +}; + struct sm6_pointer_info { const struct sm6_type *type; @@ -514,6 +544,7 @@ struct sm6_parser
struct sm6_type *types; size_t type_count; + struct sm6_type *bool_type; struct sm6_type *metadata_type; struct sm6_type *handle_type;
@@ -1388,6 +1419,8 @@ static enum vkd3d_result sm6_parser_type_table_init(struct sm6_parser *sm6) switch ((width = record->operands[0])) { case 1: + sm6->bool_type = type; + break; case 8: case 16: case 32: @@ -3418,6 +3451,150 @@ static void sm6_parser_emit_cast(struct sm6_parser *sm6, const struct dxil_recor src_param->reg.data_type = dst->u.reg.data_type; }
+struct sm6_cmp_info +{ + enum vkd3d_shader_opcode handler_idx; + bool src_swap; + unsigned int flags; +}; + +static const struct sm6_cmp_info *sm6_map_cmp2_op(uint64_t code) +{ + static const struct sm6_cmp_info cmp_op_table[] = + { + [FCMP_FALSE] = {VKD3DSIH_INVALID}, + [FCMP_OEQ] = {VKD3DSIH_EQ}, + [FCMP_OGT] = {VKD3DSIH_LT, true}, + [FCMP_OGE] = {VKD3DSIH_GE}, + [FCMP_OLT] = {VKD3DSIH_LT}, + [FCMP_OLE] = {VKD3DSIH_GE, true}, + [FCMP_ONE] = {VKD3DSIH_NE, false, VKD3DSI_FCMP_INVERT_ORDEREDNESS}, + [FCMP_ORD] = {VKD3DSIH_INVALID}, + [FCMP_UNO] = {VKD3DSIH_INVALID}, + [FCMP_UEQ] = {VKD3DSIH_EQ, false, VKD3DSI_FCMP_INVERT_ORDEREDNESS}, + [FCMP_UGT] = {VKD3DSIH_LT, true, VKD3DSI_FCMP_INVERT_ORDEREDNESS}, + [FCMP_UGE] = {VKD3DSIH_GE, false, VKD3DSI_FCMP_INVERT_ORDEREDNESS}, + [FCMP_ULT] = {VKD3DSIH_LT, false, VKD3DSI_FCMP_INVERT_ORDEREDNESS}, + [FCMP_ULE] = {VKD3DSIH_GE, true, VKD3DSI_FCMP_INVERT_ORDEREDNESS}, + [FCMP_UNE] = {VKD3DSIH_NE}, + [FCMP_TRUE] = {VKD3DSIH_INVALID}, + + [ICMP_EQ] = {VKD3DSIH_IEQ}, + [ICMP_NE] = {VKD3DSIH_INE}, + [ICMP_UGT] = {VKD3DSIH_ULT, true}, + [ICMP_UGE] = {VKD3DSIH_UGE}, + [ICMP_ULT] = {VKD3DSIH_ULT}, + [ICMP_ULE] = {VKD3DSIH_UGE, true}, + [ICMP_SGT] = {VKD3DSIH_ILT, true}, + [ICMP_SGE] = {VKD3DSIH_IGE}, + [ICMP_SLT] = {VKD3DSIH_ILT}, + [ICMP_SLE] = {VKD3DSIH_IGE, true}, + }; + + return (code < ARRAY_SIZE(cmp_op_table)) ? &cmp_op_table[code] : NULL; +} + +static void sm6_parser_emit_cmp2(struct sm6_parser *sm6, const struct dxil_record *record, + struct vkd3d_shader_instruction *ins, struct sm6_value *dst) +{ + struct vkd3d_shader_src_param *src_params; + const struct sm6_type *type_a, *type_b; + const struct sm6_cmp_info *cmp; + const struct sm6_value *a, *b; + unsigned int i = 0; + bool is_int, is_fp; + uint64_t code; + + if (!(dst->type = sm6->bool_type)) + { + WARN("Bool type not found.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, + "Module does not define a boolean type for comparison results."); + return; + } + + a = sm6_parser_get_value_by_ref(sm6, record, NULL, &i); + b = sm6_parser_get_value_by_ref(sm6, record, a->type, &i); + if (!a || !b) + return; + + if (!dxil_record_validate_operand_count(record, i + 1, i + 2, sm6)) + return; + + type_a = a->type; + type_b = b->type; + is_int = sm6_type_is_bool_i16_i32_i64(type_a); + is_fp = sm6_type_is_floating_point(type_a); + + code = record->operands[i++]; + + if ((!is_int && !is_fp) || is_int != (code >= ICMP_EQ)) + { + FIXME("Invalid operation %"PRIu64" on type class %u.\n", code, type_a->class); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Comparison operation %"PRIu64" on type class %u is invalid.", code, type_a->class); + return; + } + + if (type_a != type_b) + { + WARN("Type mismatch, type %u width %u vs type %u width %u.\n", type_a->class, + type_a->u.width, type_b->class, type_b->u.width); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, + "Type mismatch in comparison operation arguments."); + } + + if (!(cmp = sm6_map_cmp2_op(code)) || !cmp->handler_idx || cmp->handler_idx == VKD3DSIH_INVALID) + { + FIXME("Unhandled operation %"PRIu64".\n", code); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Comparison operation %"PRIu64" is unhandled.", code); + return; + } + + vsir_instruction_init(ins, &sm6->p.location, cmp->handler_idx); + ins->flags = cmp->flags; + + if (record->operand_count > i) + { + uint64_t flags = record->operands[i]; + bool silence_warning = false; + + if (is_fp) + { + if (!(flags & FP_ALLOW_UNSAFE_ALGEBRA)) + ins->flags |= VKD3DSI_PRECISE_X; + flags &= ~FP_ALLOW_UNSAFE_ALGEBRA; + /* SPIR-V FPFastMathMode is only available in the Kernel executon model. */ + silence_warning = !(flags & ~(FP_NO_NAN | FP_NO_INF | FP_NO_SIGNED_ZEROS | FP_ALLOW_RECIPROCAL)); + } + if (flags && silence_warning) + { + TRACE("Ignoring fast FP modifier %#"PRIx64".\n", flags); + } + else if (flags) + { + WARN("Ignoring flags %#"PRIx64".\n", flags); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, + "Ignoring flags %#"PRIx64" for a comparison operation.", flags); + } + } + + src_params = instruction_src_params_alloc(ins, 2, sm6); + if (cmp->src_swap) + { + src_param_init_from_value(&src_params[0], b); + src_param_init_from_value(&src_params[1], a); + } + else + { + src_param_init_from_value(&src_params[0], a); + src_param_init_from_value(&src_params[1], b); + } + + instruction_dst_param_init_ssa_scalar(ins, sm6); +} + static void sm6_parser_emit_extractval(struct sm6_parser *sm6, const struct dxil_record *record, struct vkd3d_shader_instruction *ins, struct sm6_value *dst) { @@ -3637,6 +3814,9 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const case FUNC_CODE_INST_CAST: sm6_parser_emit_cast(sm6, record, ins, dst); break; + case FUNC_CODE_INST_CMP2: + sm6_parser_emit_cmp2(sm6, record, ins, dst); + break; case FUNC_CODE_INST_EXTRACTVAL: sm6_parser_emit_extractval(sm6, record, ins, dst); break; diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 18cfb2fcd..b54b4f19e 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1419,6 +1419,8 @@ static inline enum vkd3d_shader_component_type vkd3d_component_type_from_data_ty return VKD3D_SHADER_COMPONENT_INT; case VKD3D_DATA_DOUBLE: return VKD3D_SHADER_COMPONENT_DOUBLE; + case VKD3D_DATA_BOOL: + return VKD3D_SHADER_COMPONENT_BOOL; default: FIXME("Unhandled data type %#x.\n", data_type); /* fall-through */ diff --git a/tests/hlsl/all.shader_test b/tests/hlsl/all.shader_test index 564cc5b00..7bdb0dc82 100644 --- a/tests/hlsl/all.shader_test +++ b/tests/hlsl/all.shader_test @@ -11,17 +11,17 @@ float4 main() : sv_target
[test] uniform 0 float4 -1.1 1.6 1.3 0.5 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.0, 1.0, 1.0)
[test] uniform 0 float4 0.0 1.6 1.3 0.5 -todo(sm>=6) draw quad +draw quad probe all rgba (0.0, 0.0, 0.0, 0.0)
[test] uniform 0 float4 1.0 0.0 1.3 0.5 -todo(sm>=6) draw quad +draw quad probe all rgba (0.0, 0.0, 0.0, 0.0)
[pixel shader] @@ -34,12 +34,12 @@ float4 main() : sv_target
[test] uniform 0 float4 1.0 0.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.0, 1.0, 1.0)
[test] uniform 0 float4 0.0 0.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (0.0, 0.0, 0.0, 0.0)
[pixel shader] @@ -53,11 +53,11 @@ float4 main() : sv_target [test] uniform 0 float4 1.0 2.0 0.0 0.0 uniform 4 float4 3.0 4.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.0, 1.0, 1.0)
[test] uniform 0 float4 1.0 2.0 0.0 0.0 uniform 4 float4 0.0 4.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (0.0, 0.0, 0.0, 0.0) diff --git a/tests/hlsl/any.shader_test b/tests/hlsl/any.shader_test index 9b8b922c9..f2298d3a3 100644 --- a/tests/hlsl/any.shader_test +++ b/tests/hlsl/any.shader_test @@ -8,25 +8,25 @@ float4 main() : sv_target
[test] uniform 0 float4 1.0 1.0 1.0 1.0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.0, 1.0, 1.0) uniform 0 float4 1.0 0.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.0, 1.0, 1.0) uniform 0 float4 0.0 1.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.0, 1.0, 1.0) uniform 0 float4 0.0 0.0 1.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.0, 1.0, 1.0) uniform 0 float4 0.0 0.0 0.0 1.0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.0, 1.0, 1.0) uniform 0 float4 0.0 0.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (0.0, 0.0, 0.0, 0.0) uniform 0 float4 -1.0 -1.0 -1.0 -1.0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.0, 1.0, 1.0)
[pixel shader] @@ -39,13 +39,13 @@ float4 main() : sv_target
[test] uniform 0 float4 1.0 0.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.0, 1.0, 1.0) uniform 0 float4 0.0 0.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (0.0, 0.0, 0.0, 0.0) uniform 0 float4 -1.0 0.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.0, 1.0, 1.0)
[require] @@ -61,22 +61,22 @@ float4 main() : sv_target
[test] uniform 0 uint4 1 1 1 1 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.0, 1.0, 1.0) uniform 0 uint4 1 0 0 0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.0, 1.0, 1.0) uniform 0 uint4 0 1 0 0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.0, 1.0, 1.0) uniform 0 uint4 0 0 1 0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.0, 1.0, 1.0) uniform 0 uint4 0 0 0 1 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.0, 1.0, 1.0) uniform 0 uint4 0 0 0 0 -todo(sm>=6) draw quad +draw quad probe all rgba (0.0, 0.0, 0.0, 0.0)
[pixel shader] @@ -89,8 +89,8 @@ float4 main() : sv_target
[test] uniform 0 uint4 1 0 0 0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.0, 1.0, 1.0) uniform 0 uint4 0 0 0 0 -todo(sm>=6) draw quad +draw quad probe all rgba (0.0, 0.0, 0.0, 0.0) diff --git a/tests/hlsl/bool-cast.shader_test b/tests/hlsl/bool-cast.shader_test index dc75ea376..09ca12e2b 100644 --- a/tests/hlsl/bool-cast.shader_test +++ b/tests/hlsl/bool-cast.shader_test @@ -30,7 +30,7 @@ float4 main() : SV_TARGET [test] uniform 0 float4 0.0 0.0 2.0 4.0 uniform 4 int4 0 1 0 10 -todo(sm>=6) draw quad +draw quad probe all rgba (0.0, 10.0, 1.0, 11.0)
@@ -44,5 +44,5 @@ float4 main() : sv_target
[test] uniform 0 uint4 0x00000001 0x00000002 0x80000000 0x00000000 -todo(sm>=6) draw quad +draw quad probe all rgba (2.0, 2.0, 2.0, 0.0) diff --git a/tests/hlsl/cast-to-float.shader_test b/tests/hlsl/cast-to-float.shader_test index 7c32acfa3..caaf98c02 100644 --- a/tests/hlsl/cast-to-float.shader_test +++ b/tests/hlsl/cast-to-float.shader_test @@ -17,7 +17,7 @@ uniform 0 int -1 uniform 1 uint 3 uniform 2 int -2 uniform 3 float 0.5 -todo(sm>=6) draw quad +draw quad probe all rgba (0.5, 0.5, 0.5, 0.5)
[pixel shader] diff --git a/tests/hlsl/cast-to-half.shader_test b/tests/hlsl/cast-to-half.shader_test index 1579c63f3..b8feb6760 100644 --- a/tests/hlsl/cast-to-half.shader_test +++ b/tests/hlsl/cast-to-half.shader_test @@ -17,7 +17,7 @@ uniform 0 int -1 uniform 1 uint 3 uniform 2 int -2 uniform 3 float 0.5 -todo(sm>=6) draw quad +draw quad probe all rgba (0.5, 0.5, 0.5, 0.5)
[pixel shader] diff --git a/tests/hlsl/cast-to-int.shader_test b/tests/hlsl/cast-to-int.shader_test index ae566a039..3e850fb5b 100644 --- a/tests/hlsl/cast-to-int.shader_test +++ b/tests/hlsl/cast-to-int.shader_test @@ -23,7 +23,7 @@ uniform 0 float 2.6 uniform 1 int -2 uniform 2 int -2 uniform 3 float -3.6 -todo(sm>=6) draw quad +draw quad probe all rgba (0.5, 0.5, 0.5, 0.5)
[pixel shader] diff --git a/tests/hlsl/cast-to-uint.shader_test b/tests/hlsl/cast-to-uint.shader_test index dece99b75..07479984a 100644 --- a/tests/hlsl/cast-to-uint.shader_test +++ b/tests/hlsl/cast-to-uint.shader_test @@ -23,7 +23,7 @@ uniform 0 float 2.6 uniform 1 int 2 uniform 2 int -2 uniform 3 float -3.6 -todo(sm>=6) draw quad +draw quad probe all rgba (0.5, 0.5, 0.5, 0.5)
[pixel shader] diff --git a/tests/hlsl/sign.shader_test b/tests/hlsl/sign.shader_test index 54b953681..5d8b43168 100644 --- a/tests/hlsl/sign.shader_test +++ b/tests/hlsl/sign.shader_test @@ -8,13 +8,13 @@ float4 main() : sv_target
[test] uniform 0 float4 1.0 0.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.0, 1.0, 1.0) uniform 0 float4 -1.0 0.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (-1.0, -1.0, -1.0, -1.0) uniform 0 float4 0.0 0.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (0.0, 0.0, 0.0, 0.0)
[pixel shader] @@ -27,7 +27,7 @@ float4 main() : sv_target
[test] uniform 0 float4 1.0 2.0 3.0 4.0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.0, 1.0, 1.0)
[pixel shader] @@ -41,7 +41,7 @@ float4 main() : sv_target [test] uniform 0 float4 1.0 2.0 0.0 0.0 uniform 4 float4 3.0 4.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.0, 1.0, 1.0)
[require] @@ -58,13 +58,13 @@ float4 main() : sv_target
[test] uniform 0 int4 1 0 0 0 -todo(sm>=6) draw quad +draw quad probe all rgba (1, 1, 1, 1) uniform 0 int4 -1 0 0 0 -todo(sm>=6) draw quad +draw quad probe all rgba (-1, -1, -1, -1) uniform 0 int4 0 0 0 0 -todo(sm>=6) draw quad +draw quad probe all rgba (0, 0, 0, 0)
[pixel shader] @@ -77,7 +77,7 @@ float4 main() : sv_target
[test] uniform 0 int4 1 2 3 4 -todo(sm>=6) draw quad +draw quad probe all rgba (1, 1, 1, 1)
[pixel shader] @@ -91,5 +91,5 @@ float4 main() : sv_target [test] uniform 0 int4 1 2 0 0 uniform 4 int4 3 4 0 0 -todo(sm>=6) draw quad +draw quad probe all rgba (1, 1, 1, 1)