vkd3d-shader: Correctly handle infinity in f32tof16.

Signed-off-by: Philip Rebohle <philip.rebohle@tu-dortmund.de>
This commit is contained in:
Philip Rebohle 2020-11-23 15:01:58 +01:00 committed by Hans-Kristian Arntzen
parent ced72326be
commit 9d57489225
1 changed files with 42 additions and 4 deletions

View File

@ -1393,6 +1393,13 @@ static uint32_t vkd3d_spirv_build_op_shift_right_logical(struct vkd3d_spirv_buil
SpvOpShiftRightLogical, result_type, base, shift);
}
static uint32_t vkd3d_spirv_build_op_logical_not(struct vkd3d_spirv_builder *builder,
uint32_t result_type, uint32_t operand)
{
return vkd3d_spirv_build_op_tr1(builder, &builder->function_stream,
SpvOpLogicalNot, result_type, operand);
}
static uint32_t vkd3d_spirv_build_op_logical_and(struct vkd3d_spirv_builder *builder,
uint32_t result_type, uint32_t operand0, uint32_t operand1)
{
@ -1400,6 +1407,13 @@ static uint32_t vkd3d_spirv_build_op_logical_and(struct vkd3d_spirv_builder *bui
SpvOpLogicalAnd, result_type, operand0, operand1);
}
static uint32_t vkd3d_spirv_build_op_iequal(struct vkd3d_spirv_builder *builder,
uint32_t result_type, uint32_t operand0, uint32_t operand1)
{
return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
SpvOpIEqual, result_type, operand0, operand1);
}
static uint32_t vkd3d_spirv_build_op_uless_than(struct vkd3d_spirv_builder *builder,
uint32_t result_type, uint32_t operand0, uint32_t operand1)
{
@ -1428,6 +1442,13 @@ static uint32_t vkd3d_spirv_build_op_bitcast(struct vkd3d_spirv_builder *builder
SpvOpBitcast, result_type, operand);
}
static uint32_t vkd3d_spirv_build_op_is_inf(struct vkd3d_spirv_builder *builder,
uint32_t result_type, uint32_t operand)
{
return vkd3d_spirv_build_op_tr1(builder, &builder->function_stream,
SpvOpIsInf, result_type, operand);
}
static uint32_t vkd3d_spirv_build_op_image_texel_pointer(struct vkd3d_spirv_builder *builder,
uint32_t result_type, uint32_t image_id, uint32_t coordinate_id, uint32_t sample_id)
{
@ -7550,9 +7571,11 @@ static void vkd3d_dxbc_compiler_emit_f32tof16(struct vkd3d_dxbc_compiler *compil
const struct vkd3d_shader_instruction *instruction)
{
uint32_t instr_set_id, type_id, scalar_type_id, src_id, zero_id, constituents[2];
uint32_t one_id, bool_id, f16_infinity_id, f16_mask_id, dst_id, vec2_id;
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 is_src_inf_id, is_dst_inf_id;
uint32_t components[VKD3D_VEC4_SIZE];
unsigned int i, j;
DWORD write_mask;
@ -7561,8 +7584,11 @@ static void vkd3d_dxbc_compiler_emit_f32tof16(struct vkd3d_dxbc_compiler *compil
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_FLOAT, 2);
scalar_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_UINT, 1);
zero_id = vkd3d_dxbc_compiler_get_constant_float(compiler, 0.0f);
one_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, 1);
f16_infinity_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, 0x7C00);
f16_mask_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, 0x7FFF);
bool_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_BOOL, 1);
/* FIXME: Consider a single PackHalf2x16 intruction per 2 components. */
assert(dst->write_mask & VKD3DSP_WRITEMASK_ALL);
for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i)
{
@ -7572,10 +7598,22 @@ static void vkd3d_dxbc_compiler_emit_f32tof16(struct vkd3d_dxbc_compiler *compil
src_id = vkd3d_dxbc_compiler_emit_load_src(compiler, src, write_mask);
constituents[0] = src_id;
constituents[1] = zero_id;
src_id = vkd3d_spirv_build_op_composite_construct(builder,
vec2_id = vkd3d_spirv_build_op_composite_construct(builder,
type_id, constituents, ARRAY_SIZE(constituents));
components[j++] = vkd3d_spirv_build_op_ext_inst(builder, scalar_type_id,
instr_set_id, GLSLstd450PackHalf2x16, &src_id, 1);
dst_id = vkd3d_spirv_build_op_ext_inst(builder, scalar_type_id,
instr_set_id, GLSLstd450PackHalf2x16, &vec2_id, 1);
/* Make sure we only return infinity if the input is infinite. Some
* drivers and GPU architectures will return infinity for numbers
* larger than the highest representable 16-bit float. */
is_src_inf_id = vkd3d_spirv_build_op_is_inf(builder, bool_id, src_id);
is_dst_inf_id = vkd3d_spirv_build_op_iequal(builder, bool_id, f16_infinity_id,
vkd3d_spirv_build_op_and(builder, scalar_type_id, dst_id, f16_mask_id));
components[j++] = vkd3d_spirv_build_op_select(builder, scalar_type_id,
vkd3d_spirv_build_op_logical_and(builder, bool_id, is_dst_inf_id,
vkd3d_spirv_build_op_logical_not(builder, bool_id, is_src_inf_id)),
vkd3d_spirv_build_op_isub(builder, scalar_type_id, dst_id, one_id), dst_id);
}
vkd3d_dxbc_compiler_emit_store_dst_components(compiler,