mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2024-11-21 16:46:41 -08:00
vkd3d-shader/spirv: Introduce HALF and UINT16 types for minimum precision.
Minimum precision types must always be implemented as 32-bit to match how reduced precision works in SPIR-V.
This commit is contained in:
parent
58123c2e10
commit
066ea75945
Notes:
Alexandre Julliard
2024-03-11 23:07:09 +01:00
Approved-by: Giovanni Mascellani (@giomasce) Approved-by: Conor McCarthy (@cmccarthy) Approved-by: Henri Verbeet (@hverbeet) Approved-by: Alexandre Julliard (@julliard) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/519
@ -649,6 +649,8 @@ static void shader_dump_data_type(struct vkd3d_d3d_asm_compiler *compiler, enum
|
|||||||
[VKD3D_DATA_UINT8 ] = "uint8",
|
[VKD3D_DATA_UINT8 ] = "uint8",
|
||||||
[VKD3D_DATA_UINT64 ] = "uint64",
|
[VKD3D_DATA_UINT64 ] = "uint64",
|
||||||
[VKD3D_DATA_BOOL ] = "bool",
|
[VKD3D_DATA_BOOL ] = "bool",
|
||||||
|
[VKD3D_DATA_UINT16 ] = "uint16",
|
||||||
|
[VKD3D_DATA_HALF ] = "half",
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *name;
|
const char *name;
|
||||||
|
@ -225,7 +225,7 @@ enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval_indexed(enum vkd3d
|
|||||||
|
|
||||||
static bool data_type_is_floating_point(enum vkd3d_data_type data_type)
|
static bool data_type_is_floating_point(enum vkd3d_data_type data_type)
|
||||||
{
|
{
|
||||||
return data_type == VKD3D_DATA_FLOAT || data_type == VKD3D_DATA_DOUBLE;
|
return data_type == VKD3D_DATA_HALF || data_type == VKD3D_DATA_FLOAT || data_type == VKD3D_DATA_DOUBLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define VKD3D_SPIRV_VERSION 0x00010000
|
#define VKD3D_SPIRV_VERSION 0x00010000
|
||||||
@ -1843,6 +1843,7 @@ static uint32_t vkd3d_spirv_get_type_id_for_data_type(struct vkd3d_spirv_builder
|
|||||||
{
|
{
|
||||||
switch (data_type)
|
switch (data_type)
|
||||||
{
|
{
|
||||||
|
case VKD3D_DATA_HALF: /* Minimum precision. TODO: native 16-bit */
|
||||||
case VKD3D_DATA_FLOAT:
|
case VKD3D_DATA_FLOAT:
|
||||||
case VKD3D_DATA_SNORM:
|
case VKD3D_DATA_SNORM:
|
||||||
case VKD3D_DATA_UNORM:
|
case VKD3D_DATA_UNORM:
|
||||||
@ -1850,6 +1851,7 @@ static uint32_t vkd3d_spirv_get_type_id_for_data_type(struct vkd3d_spirv_builder
|
|||||||
break;
|
break;
|
||||||
case VKD3D_DATA_INT:
|
case VKD3D_DATA_INT:
|
||||||
case VKD3D_DATA_UINT:
|
case VKD3D_DATA_UINT:
|
||||||
|
case VKD3D_DATA_UINT16: /* Minimum precision. TODO: native 16-bit */
|
||||||
return vkd3d_spirv_get_op_type_int(builder, 32, data_type == VKD3D_DATA_INT);
|
return vkd3d_spirv_get_op_type_int(builder, 32, data_type == VKD3D_DATA_INT);
|
||||||
break;
|
break;
|
||||||
case VKD3D_DATA_DOUBLE:
|
case VKD3D_DATA_DOUBLE:
|
||||||
@ -3758,6 +3760,70 @@ 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);
|
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,
|
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)
|
const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask)
|
||||||
{
|
{
|
||||||
@ -3770,14 +3836,15 @@ static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compile
|
|||||||
if (reg->dimension == VSIR_DIMENSION_SCALAR)
|
if (reg->dimension == VSIR_DIMENSION_SCALAR)
|
||||||
{
|
{
|
||||||
for (i = 0; i < component_count; ++i)
|
for (i = 0; i < component_count; ++i)
|
||||||
values[i] = *reg->u.immconst_u32;
|
values[i] = convert_raw_constant32(reg->data_type, reg->u.immconst_u32[0]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i)
|
for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i)
|
||||||
{
|
{
|
||||||
if (write_mask & (VKD3DSP_WRITEMASK_0 << i))
|
if (write_mask & (VKD3DSP_WRITEMASK_0 << i))
|
||||||
values[j++] = reg->u.immconst_u32[vsir_swizzle_get_component(swizzle, i)];
|
values[j++] = convert_raw_constant32(reg->data_type,
|
||||||
|
reg->u.immconst_u32[vsir_swizzle_get_component(swizzle, i)]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3921,6 +3988,13 @@ static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compil
|
|||||||
|
|
||||||
switch (icb->data_type)
|
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_FLOAT:
|
||||||
case VKD3D_DATA_INT:
|
case VKD3D_DATA_INT:
|
||||||
case VKD3D_DATA_UINT:
|
case VKD3D_DATA_UINT:
|
||||||
@ -6908,7 +6982,7 @@ static void spirv_compiler_emit_bool_cast(struct spirv_compiler *compiler,
|
|||||||
assert(src->reg.data_type == VKD3D_DATA_BOOL && dst->reg.data_type != VKD3D_DATA_BOOL);
|
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);
|
val_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask);
|
||||||
if (dst->reg.data_type == VKD3D_DATA_FLOAT)
|
if (dst->reg.data_type == VKD3D_DATA_HALF || dst->reg.data_type == VKD3D_DATA_FLOAT)
|
||||||
{
|
{
|
||||||
val_id = spirv_compiler_emit_bool_to_float(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOF);
|
val_id = spirv_compiler_emit_bool_to_float(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOF);
|
||||||
}
|
}
|
||||||
@ -6917,7 +6991,7 @@ 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. */
|
/* 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);
|
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)
|
else if (dst->reg.data_type == VKD3D_DATA_UINT16 || dst->reg.data_type == VKD3D_DATA_UINT)
|
||||||
{
|
{
|
||||||
val_id = spirv_compiler_emit_bool_to_int(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOI);
|
val_id = spirv_compiler_emit_bool_to_int(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOI);
|
||||||
}
|
}
|
||||||
|
@ -623,14 +623,16 @@ enum vkd3d_data_type
|
|||||||
VKD3D_DATA_UINT8,
|
VKD3D_DATA_UINT8,
|
||||||
VKD3D_DATA_UINT64,
|
VKD3D_DATA_UINT64,
|
||||||
VKD3D_DATA_BOOL,
|
VKD3D_DATA_BOOL,
|
||||||
|
VKD3D_DATA_UINT16,
|
||||||
|
VKD3D_DATA_HALF,
|
||||||
|
|
||||||
VKD3D_DATA_COUNT,
|
VKD3D_DATA_COUNT,
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline bool data_type_is_integer(enum vkd3d_data_type data_type)
|
static inline bool data_type_is_integer(enum vkd3d_data_type data_type)
|
||||||
{
|
{
|
||||||
return data_type == VKD3D_DATA_INT || data_type == VKD3D_DATA_UINT8 || data_type == VKD3D_DATA_UINT
|
return data_type == VKD3D_DATA_INT || data_type == VKD3D_DATA_UINT8 || data_type == VKD3D_DATA_UINT16
|
||||||
|| data_type == VKD3D_DATA_UINT64;
|
|| data_type == VKD3D_DATA_UINT || data_type == VKD3D_DATA_UINT64;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool data_type_is_bool(enum vkd3d_data_type data_type)
|
static inline bool data_type_is_bool(enum vkd3d_data_type data_type)
|
||||||
@ -1531,10 +1533,12 @@ static inline enum vkd3d_shader_component_type vkd3d_component_type_from_data_ty
|
|||||||
{
|
{
|
||||||
switch (data_type)
|
switch (data_type)
|
||||||
{
|
{
|
||||||
|
case VKD3D_DATA_HALF: /* Minimum precision. TODO: native 16-bit */
|
||||||
case VKD3D_DATA_FLOAT:
|
case VKD3D_DATA_FLOAT:
|
||||||
case VKD3D_DATA_UNORM:
|
case VKD3D_DATA_UNORM:
|
||||||
case VKD3D_DATA_SNORM:
|
case VKD3D_DATA_SNORM:
|
||||||
return VKD3D_SHADER_COMPONENT_FLOAT;
|
return VKD3D_SHADER_COMPONENT_FLOAT;
|
||||||
|
case VKD3D_DATA_UINT16: /* Minimum precision. TODO: native 16-bit */
|
||||||
case VKD3D_DATA_UINT:
|
case VKD3D_DATA_UINT:
|
||||||
return VKD3D_SHADER_COMPONENT_UINT;
|
return VKD3D_SHADER_COMPONENT_UINT;
|
||||||
case VKD3D_DATA_INT:
|
case VKD3D_DATA_INT:
|
||||||
|
Loading…
Reference in New Issue
Block a user