From 54c14c8709cc3e09b9eaf3ca5650ce8884bad34b Mon Sep 17 00:00:00 2001 From: Joshua Ashton Date: Wed, 21 Oct 2020 07:13:57 +0100 Subject: [PATCH] fp64 draft --- demos/demo_xcb.h | 2 +- include/vkd3d_shader.h | 1 + libs/vkd3d-shader/dxbc.c | 25 +++ libs/vkd3d-shader/spirv.c | 198 ++++++++++++++++++++--- libs/vkd3d-shader/trace.c | 2 + libs/vkd3d-shader/vkd3d_shader_private.h | 30 +++- tests/d3d12.c | 22 +++ 7 files changed, 260 insertions(+), 20 deletions(-) diff --git a/demos/demo_xcb.h b/demos/demo_xcb.h index e08bfb55..1c12f4d8 100644 --- a/demos/demo_xcb.h +++ b/demos/demo_xcb.h @@ -506,7 +506,7 @@ static inline struct demo_swapchain *demo_swapchain_create(ID3D12CommandQueue *c resource_create_info.desc.SampleDesc.Quality = 0; resource_create_info.desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; resource_create_info.desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; - resource_create_info.flags = VKD3D_RESOURCE_INITIAL_STATE_TRANSITION | VKD3D_RESOURCE_PRESENT_STATE_TRANSITION; + resource_create_info.flags = VKD3D_RESOURCE_PRESENT_STATE_TRANSITION; resource_create_info.present_state = D3D12_RESOURCE_STATE_PRESENT; for (i = 0; i < image_count; ++i) { diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index 1948cf7a..c6a3c6c5 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -573,6 +573,7 @@ enum vkd3d_component_type VKD3D_TYPE_INT = 2, VKD3D_TYPE_FLOAT = 3, VKD3D_TYPE_BOOL, + VKD3D_TYPE_DOUBLE, VKD3D_TYPE_COUNT, VKD3D_FORCE_32_BIT_ENUM(VKD3D_COMPONENT_TYPE), diff --git a/libs/vkd3d-shader/dxbc.c b/libs/vkd3d-shader/dxbc.c index ad0230dd..a6782cc7 100644 --- a/libs/vkd3d-shader/dxbc.c +++ b/libs/vkd3d-shader/dxbc.c @@ -477,6 +477,7 @@ enum vkd3d_sm4_data_type VKD3D_SM4_DATA_INT = 0x3, VKD3D_SM4_DATA_UINT = 0x4, VKD3D_SM4_DATA_FLOAT = 0x5, + VKD3D_SM4_DATA_DOUBLE = 0x6, }; enum vkd3d_sm4_sampler_mode @@ -567,6 +568,7 @@ static const enum vkd3d_data_type data_type_table[] = /* VKD3D_SM4_DATA_INT */ VKD3D_DATA_INT, /* VKD3D_SM4_DATA_UINT */ VKD3D_DATA_UINT, /* VKD3D_SM4_DATA_FLOAT */ VKD3D_DATA_FLOAT, + /* VKD3D_SM4_DATA_DOUBLE */ VKD3D_DATA_DOUBLE, }; static bool shader_is_sm_5_1(const struct vkd3d_sm4_data *priv) @@ -1022,6 +1024,7 @@ static void shader_sm5_read_sync(struct vkd3d_shader_instruction *ins, * R -> VKD3D_DATA_RESOURCE * S -> VKD3D_DATA_SAMPLER * U -> VKD3D_DATA_UAV + * d -> VKD3D_DATA_DOUBLE */ static const struct vkd3d_sm4_opcode_info opcode_table[] = { @@ -1275,6 +1278,26 @@ static const struct vkd3d_sm4_opcode_info opcode_table[] = {VKD3D_SM5_OP_SAMPLE_D_CLAMP_FEEDBACK, VKD3DSIH_SAMPLE_GRAD_FEEDBACK, "fu", "fRSfff"}, {VKD3D_SM5_OP_SAMPLE_C_CLAMP_FEEDBACK, VKD3DSIH_SAMPLE_C_FEEDBACK, "fu", "fRSff"}, {VKD3D_SM5_OP_CHECK_ACCESS_FULLY_MAPPED, VKD3DSIH_CHECK_ACCESS_FULLY_MAPPED, "u", "u"}, + + {VKD3D_SM5_OP_DADD, VKD3DSIH_DADD, "d", "dd"}, + {VKD3D_SM5_OP_DMAX, VKD3DSIH_DMAX, "d", "dd"}, + {VKD3D_SM5_OP_DMIN, VKD3DSIH_DMIN, "d", "dd"}, + {VKD3D_SM5_OP_DMUL, VKD3DSIH_DMUL, "d", "dd"}, + {VKD3D_SM5_OP_DEQ, VKD3DSIH_DEQ, "u", "dd"}, + {VKD3D_SM5_OP_DGE, VKD3DSIH_DGE, "u", "dd"}, + {VKD3D_SM5_OP_DLT, VKD3DSIH_DLT, "u", "dd"}, + {VKD3D_SM5_OP_DNE, VKD3DSIH_DNE, "u", "dd"}, + {VKD3D_SM5_OP_DMOV, VKD3DSIH_DMOV, "d", "d"}, + {VKD3D_SM5_OP_DMOVC, VKD3DSIH_DMOVC, "d", "udd"}, + {VKD3D_SM5_OP_DTOF, VKD3DSIH_DTOF, "f", "d"}, + {VKD3D_SM5_OP_FTOD, VKD3DSIH_FTOD, "d", "f"}, + {VKD3D_SM5_OP_DDIV, VKD3DSIH_DDIV, "d", "dd"}, + {VKD3D_SM5_OP_DFMA, VKD3DSIH_DFMA, "d", "ddd"}, + {VKD3D_SM5_OP_DRCP, VKD3DSIH_DRCP, "d", "d"}, + {VKD3D_SM5_OP_DTOI, VKD3DSIH_DTOI, "i", "d"}, + {VKD3D_SM5_OP_DTOU, VKD3DSIH_DTOU, "u", "d"}, + {VKD3D_SM5_OP_ITOD, VKD3DSIH_ITOD, "d", "i"}, + {VKD3D_SM5_OP_UTOD, VKD3DSIH_UTOD, "d", "u"}, }; static const enum vkd3d_shader_register_type register_type_table[] = @@ -1378,6 +1401,8 @@ static enum vkd3d_data_type map_data_type(char t) return VKD3D_DATA_SAMPLER; case 'U': return VKD3D_DATA_UAV; + case 'd': + return VKD3D_DATA_DOUBLE; default: ERR("Invalid data type '%c'.\n", t); return VKD3D_DATA_FLOAT; diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index ebf2d4b0..1937b1bf 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -1019,19 +1019,18 @@ static uint32_t vkd3d_spirv_get_op_type_pointer(struct vkd3d_spirv_builder *buil vkd3d_spirv_build_op_type_pointer); } -/* 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) + uint32_t result_type, const uint32_t* value, unsigned int dword_count) { - return vkd3d_spirv_build_op_tr1(builder, &builder->global_stream, - SpvOpConstant, result_type, value); + return vkd3d_spirv_build_op_trv(builder, &builder->global_stream, + SpvOpConstant, result_type, value, dword_count); } static uint32_t vkd3d_spirv_get_op_constant(struct vkd3d_spirv_builder *builder, - uint32_t result_type, uint32_t value) + uint32_t result_type, const uint32_t* value, unsigned int dword_count) { - return vkd3d_spirv_build_once2(builder, SpvOpConstant, result_type, value, - vkd3d_spirv_build_op_constant); + return vkd3d_spirv_build_once1v(builder, SpvOpConstant, result_type, + value, dword_count, vkd3d_spirv_build_op_constant); } static uint32_t vkd3d_spirv_build_op_constant_composite(struct vkd3d_spirv_builder *builder, @@ -1601,6 +1600,9 @@ static uint32_t vkd3d_spirv_get_type_id(struct vkd3d_spirv_builder *builder, case VKD3D_TYPE_FLOAT: return vkd3d_spirv_get_op_type_float(builder, 32); break; + case VKD3D_TYPE_DOUBLE: + return vkd3d_spirv_get_op_type_float(builder, 64); + break; case VKD3D_TYPE_INT: case VKD3D_TYPE_UINT: return vkd3d_spirv_get_op_type_int(builder, 32, component_type == VKD3D_TYPE_INT); @@ -1616,11 +1618,19 @@ static uint32_t vkd3d_spirv_get_type_id(struct vkd3d_spirv_builder *builder, else { assert(component_type != VKD3D_TYPE_VOID); + assert(component_count != 0); scalar_id = vkd3d_spirv_get_type_id(builder, component_type, 1); return vkd3d_spirv_get_op_type_vector(builder, scalar_id, component_count); } } +static unsigned int vkd3d_spirv_get_type_dword_count(enum vkd3d_component_type type, unsigned int component_count) +{ + unsigned int type_size = type == VKD3D_TYPE_DOUBLE ? 2 : 1; + + return type_size * component_count; +} + static uint32_t vkd3d_spirv_get_sparse_result_type(struct vkd3d_spirv_builder *builder, uint32_t sampled_type_id) { uint32_t members[2]; @@ -2497,7 +2507,7 @@ static uint32_t vkd3d_dxbc_compiler_get_constant(struct vkd3d_dxbc_compiler *com { uint32_t type_id, scalar_type_id, component_ids[VKD3D_VEC4_SIZE]; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - unsigned int i; + unsigned int i, dword_count; assert(0 < component_count && component_count <= VKD3D_VEC4_SIZE); type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); @@ -2507,21 +2517,24 @@ static uint32_t vkd3d_dxbc_compiler_get_constant(struct vkd3d_dxbc_compiler *com case VKD3D_TYPE_UINT: case VKD3D_TYPE_INT: case VKD3D_TYPE_FLOAT: + case VKD3D_TYPE_DOUBLE: break; default: FIXME("Unhandled component_type %#x.\n", component_type); return vkd3d_spirv_build_op_undef(builder, &builder->global_stream, type_id); } + dword_count = vkd3d_spirv_get_type_dword_count(component_type, component_count); + if (component_count == 1) { - return vkd3d_spirv_get_op_constant(builder, type_id, *values); + return vkd3d_spirv_get_op_constant(builder, type_id, values, dword_count); } else { scalar_type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); for (i = 0; i < component_count; ++i) - component_ids[i] = vkd3d_spirv_get_op_constant(builder, scalar_type_id, values[i]); + component_ids[i] = vkd3d_spirv_get_op_constant(builder, scalar_type_id, values, dword_count / component_count); return vkd3d_spirv_get_op_constant_composite(builder, type_id, component_ids, component_count); } } @@ -2559,14 +2572,27 @@ static uint32_t vkd3d_dxbc_compiler_get_constant_float_vector(struct vkd3d_dxbc_ VKD3D_TYPE_FLOAT, component_count, (const uint32_t *)values); } +static uint32_t vkd3d_dxbc_compiler_get_constant_double_vector(struct vkd3d_dxbc_compiler *compiler, + double value, unsigned int component_count) +{ + const double values[] = {value, value}; + return vkd3d_dxbc_compiler_get_constant(compiler, + VKD3D_TYPE_DOUBLE, component_count, (const uint32_t *)values); +} + + static uint32_t vkd3d_dxbc_compiler_get_type_id_for_reg(struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_register *reg, DWORD write_mask) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + unsigned int component_count = vkd3d_write_mask_component_count(write_mask); + + if (reg->data_type == VKD3D_DATA_DOUBLE) + component_count /= 2; return vkd3d_spirv_get_type_id(builder, vkd3d_component_type_from_data_type(reg->data_type), - vkd3d_write_mask_component_count(write_mask)); + component_count); } static uint32_t vkd3d_dxbc_compiler_get_type_id_for_dst(struct vkd3d_dxbc_compiler *compiler, @@ -3235,8 +3261,11 @@ static uint32_t vkd3d_dxbc_compiler_emit_load_constant_buffer(struct vkd3d_dxbc_ } else { + uint32_t values[2] = { 0, 0 }; + unsigned int dword_count = vkd3d_spirv_get_type_dword_count( + register_info->component_type, 1); WARN("Root constant index out of bounds: cb %u, member %u\n", reg->idx[0].offset, index); - component_ids[j++] = vkd3d_spirv_get_op_constant(builder, type_id, 0); + component_ids[j++] = vkd3d_spirv_get_op_constant(builder, type_id, values, dword_count); continue; } } @@ -3316,6 +3345,9 @@ static uint32_t vkd3d_dxbc_compiler_emit_load_reg(struct vkd3d_dxbc_compiler *co if (component_type != reg_info.component_type) { + if (component_type == VKD3D_TYPE_DOUBLE) + component_count /= 2; + type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); } @@ -3495,6 +3527,10 @@ static void vkd3d_dxbc_compiler_emit_store_reg(struct vkd3d_dxbc_compiler *compi if (component_type != reg_info.component_type) { unsigned int component_count = vkd3d_write_mask_component_count(write_mask); + + if (reg_info.component_type == VKD3D_TYPE_DOUBLE) + component_count /= 2; + type_id = vkd3d_spirv_get_type_id(builder, reg_info.component_type, component_count); val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); component_type = reg_info.component_type; @@ -4460,6 +4496,35 @@ static unsigned int vkd3d_dxbc_compiler_get_output_variable_index( return register_idx; } +static DWORD vkd3d_dxbc_compiler_double_source_mask_fixup(enum vkd3d_data_type src, enum vkd3d_data_type dst, DWORD mask) +{ + if (src == dst) + return mask; + + if (src == VKD3D_DATA_DOUBLE) + { + unsigned int component_count = vkd3d_write_mask_component_count(mask); + if (component_count >= 2) + return VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1 | VKD3DSP_WRITEMASK_2 | VKD3DSP_WRITEMASK_3; + else if (component_count == 1) + return VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1; + else + return 0; + } + else if (dst == VKD3D_DATA_DOUBLE) + { + unsigned int component_count = vkd3d_write_mask_component_count(mask); + if (component_count >= 3) + return VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1; + else if (component_count >= 1) + return VKD3DSP_WRITEMASK_0; + else + return 0; + } + + return mask; +} + static unsigned int get_shader_output_swizzle(const struct vkd3d_dxbc_compiler *compiler, unsigned int register_idx) { @@ -5310,6 +5375,7 @@ static size_t vkd3d_dxbc_compiler_get_current_function_location(struct vkd3d_dxb static void vkd3d_dxbc_compiler_emit_dcl_global_flags(struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; unsigned int flags = instruction->flags; if (flags & VKD3DSGF_FORCE_EARLY_DEPTH_STENCIL) @@ -5318,6 +5384,12 @@ static void vkd3d_dxbc_compiler_emit_dcl_global_flags(struct vkd3d_dxbc_compiler flags &= ~VKD3DSGF_FORCE_EARLY_DEPTH_STENCIL; } + if ((flags & VKD3DSGF_ENABLE_DOUBLE_PRECISION_FLOAT_OPS) || (flags & VKD3DSGF_ENABLE_11_1_DOUBLE_EXTENSIONS)) + { + vkd3d_spirv_enable_capability(builder, SpvCapabilityFloat64); + flags &= ~(VKD3DSGF_ENABLE_DOUBLE_PRECISION_FLOAT_OPS | VKD3DSGF_ENABLE_11_1_DOUBLE_EXTENSIONS); + } + if (flags & ~(VKD3DSGF_REFACTORING_ALLOWED | VKD3DSGF_ENABLE_RAW_AND_STRUCTURED_BUFFERS)) FIXME("Unhandled global flags %#x.\n", flags); else @@ -6641,10 +6713,12 @@ static SpvOp vkd3d_dxbc_compiler_map_alu_instruction(const struct vkd3d_shader_i } alu_ops[] = { + {VKD3DSIH_DADD, SpvOpFAdd}, {VKD3DSIH_ADD, SpvOpFAdd}, {VKD3DSIH_AND, SpvOpBitwiseAnd}, {VKD3DSIH_BFREV, SpvOpBitReverse}, {VKD3DSIH_COUNTBITS, SpvOpBitCount}, + {VKD3DSIH_DDIV, SpvOpFDiv}, {VKD3DSIH_DIV, SpvOpFDiv}, {VKD3DSIH_FTOI, SpvOpConvertFToS}, {VKD3DSIH_FTOU, SpvOpConvertFToU}, @@ -6653,6 +6727,7 @@ static SpvOp vkd3d_dxbc_compiler_map_alu_instruction(const struct vkd3d_shader_i {VKD3DSIH_ISHL, SpvOpShiftLeftLogical}, {VKD3DSIH_ISHR, SpvOpShiftRightArithmetic}, {VKD3DSIH_ITOF, SpvOpConvertSToF}, + {VKD3DSIH_DMUL, SpvOpFMul}, {VKD3DSIH_MUL, SpvOpFMul}, {VKD3DSIH_NOT, SpvOpNot}, {VKD3DSIH_OR, SpvOpBitwiseOr}, @@ -6721,8 +6796,11 @@ static enum GLSLstd450 vkd3d_dxbc_compiler_map_ext_glsl_instruction( {VKD3DSIH_IMAX, GLSLstd450SMax}, {VKD3DSIH_IMIN, GLSLstd450SMin}, {VKD3DSIH_LOG, GLSLstd450Log2}, + {VKD3DSIH_DFMA, GLSLstd450Fma}, {VKD3DSIH_MAD, GLSLstd450Fma}, + {VKD3DSIH_DMAX, GLSLstd450NMax}, {VKD3DSIH_MAX, GLSLstd450NMax}, + {VKD3DSIH_DMIN, GLSLstd450NMin}, {VKD3DSIH_MIN, GLSLstd450NMin}, {VKD3DSIH_ROUND_NE, GLSLstd450RoundEven}, {VKD3DSIH_ROUND_NI, GLSLstd450Floor}, @@ -6805,13 +6883,21 @@ static void vkd3d_dxbc_compiler_emit_movc(struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_src_param *src = instruction->src; uint32_t condition_id, src1_id, src2_id, type_id, val_id; unsigned int component_count; + DWORD condition_mask; - condition_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], dst->write_mask); + condition_mask = vkd3d_dxbc_compiler_double_source_mask_fixup(src[0].reg.data_type, dst->reg.data_type, dst->write_mask); + condition_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], condition_mask); src1_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[1], dst->write_mask); src2_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[2], dst->write_mask); component_count = vkd3d_write_mask_component_count(dst->write_mask); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_FLOAT, component_count); + if (instruction->handler_idx == VKD3DSIH_DMOVC) + { + component_count /= 2; + type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_DOUBLE, component_count); + } + else + type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_FLOAT, component_count); condition_id = vkd3d_dxbc_compiler_emit_int_to_bool(compiler, VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, condition_id); @@ -6891,15 +6977,23 @@ static void vkd3d_dxbc_compiler_emit_rcp(struct vkd3d_dxbc_compiler *compiler, struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; const struct vkd3d_shader_dst_param *dst = instruction->dst; const struct vkd3d_shader_src_param *src = instruction->src; - uint32_t type_id, src_id, val_id; + uint32_t type_id, src_id, val_id, one_id; unsigned int component_count; component_count = vkd3d_write_mask_component_count(dst->write_mask); type_id = vkd3d_dxbc_compiler_get_type_id_for_dst(compiler, dst); + if (instruction->handler_idx == VKD3DSIH_DRCP) + { + component_count /= 2; + one_id = vkd3d_dxbc_compiler_get_constant_double_vector(compiler, 1.0, component_count); + } + else + one_id = vkd3d_dxbc_compiler_get_constant_float_vector(compiler, 1.0f, component_count); + src_id = vkd3d_dxbc_compiler_emit_load_src(compiler, src, dst->write_mask); val_id = vkd3d_spirv_build_op_fdiv(builder, type_id, - vkd3d_dxbc_compiler_get_constant_float_vector(compiler, 1.0f, component_count), src_id); + one_id, src_id); vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id); } @@ -7170,17 +7264,22 @@ static void vkd3d_dxbc_compiler_emit_comparison_instruction(struct vkd3d_dxbc_co const struct vkd3d_shader_src_param *src = instruction->src; uint32_t src0_id, src1_id, type_id, result_id; unsigned int component_count; + DWORD src_mask; SpvOp op; 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; @@ -7191,8 +7290,9 @@ static void vkd3d_dxbc_compiler_emit_comparison_instruction(struct vkd3d_dxbc_co component_count = vkd3d_write_mask_component_count(dst->write_mask); - src0_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], dst->write_mask); - src1_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[1], dst->write_mask); + src_mask = vkd3d_dxbc_compiler_double_source_mask_fixup(src->reg.data_type, dst->reg.data_type, dst->write_mask); + src0_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], src_mask); + src1_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[1], src_mask); type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_BOOL, component_count); result_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, @@ -9298,6 +9398,47 @@ static void vkd3d_dxbc_compiler_emit_check_sparse_access(struct vkd3d_dxbc_compi vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id); } +static void vkd3d_dxbc_compiler_emit_double_conversion(struct vkd3d_dxbc_compiler *compiler, + const struct vkd3d_shader_instruction *instruction) +{ + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + const struct vkd3d_shader_dst_param *dst = instruction->dst; + const struct vkd3d_shader_src_param *src = instruction->src; + enum vkd3d_component_type component_type; + uint32_t src_id, val_id, type_id; + unsigned int component_count; + DWORD src_mask; + SpvOp op; + + switch (instruction->handler_idx) + { + case VKD3DSIH_DTOF: + case VKD3DSIH_FTOD: op = SpvOpFConvert; break; + case VKD3DSIH_DTOI: op = SpvOpConvertFToS; break; + case VKD3DSIH_DTOU: op = SpvOpConvertFToU; break; + case VKD3DSIH_ITOD: op = SpvOpConvertSToF; break; + case VKD3DSIH_UTOD: op = SpvOpConvertUToF; break; + default: + ERR("Unexpected instruction %#x.\n", instruction->handler_idx); + return; + } + + src_mask = vkd3d_dxbc_compiler_double_source_mask_fixup(src->reg.data_type, dst->reg.data_type, dst->write_mask); + src_id = vkd3d_dxbc_compiler_emit_load_src(compiler, src, src_mask); + + component_type = vkd3d_component_type_from_data_type(dst->reg.data_type); + component_count = vkd3d_write_mask_component_count(dst->write_mask); + if (component_type == VKD3D_TYPE_DOUBLE) + component_count /= 2; + type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); + + val_id = vkd3d_spirv_build_op_trv(builder, &builder->function_stream, + op, type_id, &src_id, 1); + + //vkd3d_dxbc_compiler_emit_store_reg(compiler, &dst->reg, , val_id); + vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id); +} + /* This function is called after declarations are processed. */ static void vkd3d_dxbc_compiler_emit_main_prolog(struct vkd3d_dxbc_compiler *compiler) { @@ -9427,19 +9568,23 @@ int vkd3d_dxbc_compiler_handle_instruction(struct vkd3d_dxbc_compiler *compiler, case VKD3DSIH_HS_JOIN_PHASE: vkd3d_dxbc_compiler_enter_shader_phase(compiler, instruction); break; + case VKD3DSIH_DMOV: case VKD3DSIH_MOV: vkd3d_dxbc_compiler_emit_mov(compiler, instruction); break; + case VKD3DSIH_DMOVC: case VKD3DSIH_MOVC: vkd3d_dxbc_compiler_emit_movc(compiler, instruction); break; case VKD3DSIH_SWAPC: vkd3d_dxbc_compiler_emit_swapc(compiler, instruction); break; + case VKD3DSIH_DADD: case VKD3DSIH_ADD: case VKD3DSIH_AND: case VKD3DSIH_BFREV: case VKD3DSIH_COUNTBITS: + case VKD3DSIH_DDIV: case VKD3DSIH_DIV: case VKD3DSIH_FTOI: case VKD3DSIH_FTOU: @@ -9448,6 +9593,7 @@ int vkd3d_dxbc_compiler_handle_instruction(struct vkd3d_dxbc_compiler *compiler, case VKD3DSIH_ISHL: case VKD3DSIH_ISHR: case VKD3DSIH_ITOF: + case VKD3DSIH_DMUL: case VKD3DSIH_MUL: case VKD3DSIH_NOT: case VKD3DSIH_OR: @@ -9464,8 +9610,11 @@ int vkd3d_dxbc_compiler_handle_instruction(struct vkd3d_dxbc_compiler *compiler, case VKD3DSIH_IMAX: case VKD3DSIH_IMIN: case VKD3DSIH_LOG: + case VKD3DSIH_DFMA: case VKD3DSIH_MAD: + case VKD3DSIH_DMAX: case VKD3DSIH_MAX: + case VKD3DSIH_DMIN: case VKD3DSIH_MIN: case VKD3DSIH_ROUND_NE: case VKD3DSIH_ROUND_NI: @@ -9482,6 +9631,7 @@ int vkd3d_dxbc_compiler_handle_instruction(struct vkd3d_dxbc_compiler *compiler, case VKD3DSIH_DP2: vkd3d_dxbc_compiler_emit_dot(compiler, instruction); break; + case VKD3DSIH_DRCP: case VKD3DSIH_RCP: vkd3d_dxbc_compiler_emit_rcp(compiler, instruction); break; @@ -9499,13 +9649,17 @@ int vkd3d_dxbc_compiler_handle_instruction(struct vkd3d_dxbc_compiler *compiler, case VKD3DSIH_UDIV: vkd3d_dxbc_compiler_emit_udiv(compiler, instruction); break; + case VKD3DSIH_DEQ: case VKD3DSIH_EQ: + case VKD3DSIH_DGE: case VKD3DSIH_GE: case VKD3DSIH_IEQ: case VKD3DSIH_IGE: case VKD3DSIH_ILT: case VKD3DSIH_INE: + case VKD3DSIH_DLT: case VKD3DSIH_LT: + case VKD3DSIH_DNE: case VKD3DSIH_NE: case VKD3DSIH_UGE: case VKD3DSIH_ULT: @@ -9666,6 +9820,14 @@ int vkd3d_dxbc_compiler_handle_instruction(struct vkd3d_dxbc_compiler *compiler, case VKD3DSIH_NOP: /* nothing to do */ break; + case VKD3DSIH_DTOF: + case VKD3DSIH_FTOD: + case VKD3DSIH_DTOI: + case VKD3DSIH_DTOU: + case VKD3DSIH_ITOD: + case VKD3DSIH_UTOD: + vkd3d_dxbc_compiler_emit_double_conversion(compiler, instruction); + break; default: FIXME("Unhandled instruction %#x.\n", instruction->handler_idx); } diff --git a/libs/vkd3d-shader/trace.c b/libs/vkd3d-shader/trace.c index 5e598ea9..4c8cd831 100644 --- a/libs/vkd3d-shader/trace.c +++ b/libs/vkd3d-shader/trace.c @@ -358,6 +358,8 @@ static void shader_dump_global_flags(struct vkd3d_string_buffer *buffer, DWORD g {VKD3DSGF_FORCE_EARLY_DEPTH_STENCIL, "forceEarlyDepthStencil"}, {VKD3DSGF_ENABLE_RAW_AND_STRUCTURED_BUFFERS, "enableRawAndStructuredBuffers"}, {VKD3DSGF_ENABLE_MINIMUM_PRECISION, "enableMinimumPrecision"}, + {VKD3DSGF_ENABLE_DOUBLE_PRECISION_FLOAT_OPS, "enableDoublePrecisionFloatOps"}, + {VKD3DSGF_ENABLE_11_1_DOUBLE_EXTENSIONS, "enable11_1DoubleExtensions"}, }; for (i = 0; i < ARRAY_SIZE(global_flag_info); ++i) diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index a24d5314..84b7c34e 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -276,6 +276,26 @@ enum VKD3D_SHADER_INSTRUCTION_HANDLER VKD3DSIH_UTOF, VKD3DSIH_XOR, + VKD3DSIH_DADD, + VKD3DSIH_DMAX, + VKD3DSIH_DMIN, + VKD3DSIH_DMUL, + VKD3DSIH_DEQ, + VKD3DSIH_DGE, + VKD3DSIH_DLT, + VKD3DSIH_DNE, + VKD3DSIH_DMOV, + VKD3DSIH_DMOVC, + VKD3DSIH_DTOF, + VKD3DSIH_FTOD, + VKD3DSIH_DDIV, + VKD3DSIH_DFMA, + VKD3DSIH_DRCP, + VKD3DSIH_DTOI, + VKD3DSIH_DTOU, + VKD3DSIH_ITOD, + VKD3DSIH_UTOD, + VKD3DSIH_INVALID, }; @@ -347,6 +367,7 @@ enum vkd3d_data_type VKD3D_DATA_UNORM, VKD3D_DATA_SNORM, VKD3D_DATA_OPAQUE, + VKD3D_DATA_DOUBLE, }; enum vkd3d_immconst_type @@ -396,9 +417,12 @@ enum vkd3d_shader_interpolation_mode enum vkd3d_shader_global_flags { VKD3DSGF_REFACTORING_ALLOWED = 0x01, + VKD3DSGF_ENABLE_DOUBLE_PRECISION_FLOAT_OPS = 0x02, VKD3DSGF_FORCE_EARLY_DEPTH_STENCIL = 0x04, VKD3DSGF_ENABLE_RAW_AND_STRUCTURED_BUFFERS = 0x08, - VKD3DSGF_ENABLE_MINIMUM_PRECISION = 0x20 + VKD3DSGF_ENABLE_MINIMUM_PRECISION = 0x20, + VKD3DSGF_ENABLE_11_1_DOUBLE_EXTENSIONS = 0x40, + }; enum vkd3d_shader_sync_flags @@ -782,6 +806,8 @@ static inline enum vkd3d_component_type vkd3d_component_type_from_data_type( return VKD3D_TYPE_UINT; case VKD3D_DATA_INT: return VKD3D_TYPE_INT; + case VKD3D_DATA_DOUBLE: + return VKD3D_TYPE_DOUBLE; default: FIXME("Unhandled data type %#x.\n", data_type); return VKD3D_TYPE_UINT; @@ -799,6 +825,8 @@ static inline enum vkd3d_data_type vkd3d_data_type_from_component_type( return VKD3D_DATA_UINT; case VKD3D_TYPE_INT: return VKD3D_DATA_INT; + case VKD3D_TYPE_DOUBLE: + return VKD3D_DATA_DOUBLE; default: FIXME("Unhandled component type %#x.\n", component_type); return VKD3D_DATA_FLOAT; diff --git a/tests/d3d12.c b/tests/d3d12.c index 1a82f293..8057b264 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -9762,6 +9762,22 @@ static void test_shader_instructions(void) 0x00100e46, 0x00000001, 0x0100003e, }; static struct named_shader ps_swapc5 = {"swapc5", ps_swapc5_code, sizeof(ps_swapc5_code)}; + static const DWORD ps_double_code[] = + { +#if 0 + double2 src0; + double2 src1; + float4 src2; + + void main(out float4 dst : SV_Target) + { + double2 tmp = src0 + src1; + + dst.xyzw = tmp.xyxy; + } +#endif + }; + static struct named_shader ps_double = {"double", ps_double_code, sizeof(ps_double_code)}; static const struct { const struct named_shader *ps; @@ -9998,6 +10014,12 @@ static void test_shader_instructions(void) struct vec4 src1; struct vec4 src2; } f; + struct + { + struct dvec2 src0; + struct dvec2 src1; + struct vec4 src2; + } d; } input; union {