diff options
author | Georg Lehmann <dadschoorse@gmail.com> | 2022-10-05 22:14:44 +0300 |
---|---|---|
committer | Hans-Kristian Arntzen <post@arntzen-software.no> | 2022-10-06 11:59:56 +0300 |
commit | a23862e658a674625759dec80f49646e61ede159 (patch) | |
tree | 9b5cfcf7e39bbab9d9301f4b6b207fd25e440c39 | |
parent | 556c70a9b0e18f3c37b69fa297fbce9869fd3c90 (diff) |
vkd3d-shader: Return -1 for FIRSTBIT_(S)HI when we have to.
With the added benefit that vulkan drivers can optimize this to the native
dxbc instruction.
Signed-off-by: Georg Lehmann <dadschoorse@gmail.com>
-rw-r--r-- | libs/vkd3d-shader/spirv.c | 22 | ||||
-rw-r--r-- | tests/d3d12_shaders.c | 2 |
2 files changed, 18 insertions, 6 deletions
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 74917fa8..319e6cb0 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -7873,11 +7873,11 @@ static enum GLSLstd450 vkd3d_dxbc_compiler_map_ext_glsl_instruction( static void vkd3d_dxbc_compiler_emit_ext_glsl_instruction(struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { + uint32_t instr_set_id, type_id, val_id, sub_id, bool_id, cmp_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 src_id[VKD3D_DXBC_MAX_SOURCE_COUNT]; - uint32_t instr_set_id, type_id, val_id; enum GLSLstd450 glsl_inst; unsigned int i; @@ -7904,11 +7904,23 @@ static void vkd3d_dxbc_compiler_emit_ext_glsl_instruction(struct vkd3d_dxbc_comp if (instruction->handler_idx == VKD3DSIH_FIRSTBIT_HI || instruction->handler_idx == VKD3DSIH_FIRSTBIT_SHI) { - /* In D3D bits are numbered from the most significant bit. */ - val_id = vkd3d_spirv_build_op_isub(builder, type_id, - vkd3d_dxbc_compiler_get_constant_uint_vector(compiler, 31, + /* In dxbc bits are numbered from the most significant bit. + * Emit (findMSB(x) == -1) ? findMSB(x) : 31 - findMSB(x) + * because the result needs to stay -1 if it was -1. + */ + sub_id = vkd3d_spirv_build_op_isub(builder, type_id, + vkd3d_dxbc_compiler_get_constant_uint_vector(compiler, 31, vkd3d_write_mask_component_count(dst->write_mask)), - val_id); + val_id); + + bool_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_BOOL, + vkd3d_write_mask_component_count(dst->write_mask)); + + cmp_id = vkd3d_spirv_build_op_iequal(builder, bool_id, val_id, + vkd3d_dxbc_compiler_get_constant_uint_vector(compiler, + -1, vkd3d_write_mask_component_count(dst->write_mask))); + + val_id = vkd3d_spirv_build_op_select(builder, type_id, cmp_id, val_id, sub_id); } if (glsl_inst == GLSLstd450Fma && (instruction->flags & VKD3DSI_PRECISE_XYZW)) diff --git a/tests/d3d12_shaders.c b/tests/d3d12_shaders.c index 0f5c5594..7291ab14 100644 --- a/tests/d3d12_shaders.c +++ b/tests/d3d12_shaders.c @@ -2677,7 +2677,7 @@ void test_shader_instructions(void) {&ps_bfrev, {{{0xffff0000}}}, {{0x0000ffff, 0xffff0000, 0x00000000, 0xffff0000}}}, {&ps_bfrev, {{{0xffffffff}}}, {{0xffffffff, 0xffffffff, 0xffff0000, 0xffff0000}}}, - {&ps_bits, {{{ 0, 0}}}, {{ 0, ~0u, ~0u, ~0u}}, false, false, true}, + {&ps_bits, {{{ 0, 0}}}, {{ 0, ~0u, ~0u, ~0u}}}, {&ps_bits, {{{ ~0u, ~0u}}}, {{32, 0, 0, ~0u}}}, {&ps_bits, {{{0x7fffffff, 0x7fffffff}}}, {{31, 0, 1, 30}}}, {&ps_bits, {{{0x80000000, 0x80000000}}}, {{ 1, 31, 0, 30}}}, |