From 5e86d5c21b7900bc64cd111ad10dd73d445fd194 Mon Sep 17 00:00:00 2001 From: Giovanni Mascellani Date: Wed, 28 May 2025 22:16:34 +0200 Subject: [PATCH] vkd3d-shader/dxil: Emit 16-bit arrays as minimum precision types. The type is not explicitly annotated as minimum precision, because no backend currently cares about that bit anyway. We're still relying on the fact that in SM 6.0 16-bit types are always understood as minimum precision. --- libs/vkd3d-shader/dxil.c | 40 +++++++++++++++++----- libs/vkd3d-shader/spirv.c | 71 --------------------------------------- 2 files changed, 31 insertions(+), 80 deletions(-) diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 09895b201..b25655a5c 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -3179,6 +3179,7 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co struct vkd3d_shader_immediate_constant_buffer *icb; const struct sm6_type *elem_type; unsigned int i, size, count; + uint64_t *data64; elem_type = type->u.array.elem_type; /* Multidimensional arrays are emitted in flattened form. */ @@ -3230,16 +3231,37 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co return VKD3D_OK; count = type->u.array.count; - if (size > sizeof(icb->data[0])) + switch (icb->data_type) { - uint64_t *data = (uint64_t *)icb->data; - for (i = 0; i < count; ++i) - data[i] = operands[i]; - } - else - { - for (i = 0; i < count; ++i) - icb->data[i] = operands[i]; + case VKD3D_DATA_HALF: + for (i = 0; i < count; ++i) + icb->data[i] = half_to_float(operands[i]); + icb->data_type = VKD3D_DATA_FLOAT; + break; + + case VKD3D_DATA_UINT16: + for (i = 0; i < count; ++i) + icb->data[i] = (int16_t)operands[i]; + icb->data_type = VKD3D_DATA_UINT; + break; + + case VKD3D_DATA_FLOAT: + case VKD3D_DATA_UINT: + for (i = 0; i < count; ++i) + icb->data[i] = operands[i]; + break; + + case VKD3D_DATA_DOUBLE: + case VKD3D_DATA_UINT64: + data64 = (uint64_t *)icb->data; + for (i = 0; i < count; ++i) + data64[i] = operands[i]; + break; + + default: + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Invalid array of type %u.", icb->data_type); + return VKD3D_ERROR_INVALID_SHADER; } return VKD3D_OK; diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 92a31a989..4a576868c 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -4527,70 +4527,6 @@ static uint32_t spirv_compiler_emit_bool_to_double(struct spirv_compiler *compil return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); } -/* Based on the implementation in the OpenGL Mathematics library. */ -static uint32_t half_to_float(uint16_t value) -{ - uint32_t s = (value & 0x8000u) << 16; - uint32_t e = (value >> 10) & 0x1fu; - uint32_t m = value & 0x3ffu; - - if (!e) - { - if (!m) - { - /* Plus or minus zero */ - return s; - } - else - { - /* Denormalized number -- renormalize it */ - - while (!(m & 0x400u)) - { - m <<= 1; - --e; - } - - ++e; - m &= ~0x400u; - } - } - else if (e == 31u) - { - /* Positive or negative infinity for zero 'm'. - * Nan for non-zero 'm' -- preserve sign and significand bits */ - return s | 0x7f800000u | (m << 13); - } - - /* Normalized number */ - e += 127u - 15u; - m <<= 13; - - /* Assemble s, e and m. */ - return s | (e << 23) | m; -} - -static uint32_t convert_raw_constant32(enum vkd3d_data_type data_type, unsigned int uint_value) -{ - int16_t i; - - /* TODO: native 16-bit support. */ - if (data_type != VKD3D_DATA_UINT16 && data_type != VKD3D_DATA_HALF) - return uint_value; - - if (data_type == VKD3D_DATA_HALF) - return half_to_float(uint_value); - - /* Values in DXIL have no signedness, so it is ambiguous whether 16-bit constants should or - * should not be sign-extended when 16-bit execution is not supported. The AMD RX 580 Windows - * driver has no 16-bit support, and sign-extends all 16-bit constant ints to 32 bits. These - * results differ from SM 5. The RX 6750 XT supports 16-bit execution, so constants are not - * extended, and results match SM 5. It seems best to replicate the sign-extension, and if - * execution is 16-bit, the values will be truncated. */ - i = uint_value; - return (int32_t)i; -} - static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compiler, const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask) { @@ -4754,13 +4690,6 @@ static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compil switch (icb->data_type) { - case VKD3D_DATA_HALF: - case VKD3D_DATA_UINT16: - /* Scalar only. */ - for (i = 0; i < element_count; ++i) - elements[i] = vkd3d_spirv_get_op_constant(builder, elem_type_id, - convert_raw_constant32(icb->data_type, icb->data[i])); - break; case VKD3D_DATA_FLOAT: case VKD3D_DATA_INT: case VKD3D_DATA_UINT: