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.
This commit is contained in:
Giovanni Mascellani
2025-05-28 22:16:34 +02:00
committed by Henri Verbeet
parent 1d780e1a6b
commit 5e86d5c21b
Notes: Henri Verbeet 2025-06-11 20:36:59 +02:00
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1558
2 changed files with 31 additions and 80 deletions

View File

@@ -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;

View File

@@ -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: