Module: Mesa Branch: main Commit: 6afa1b3bade64e0676b349d7d57b3c89b5ec3e9e URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=6afa1b3bade64e0676b349d7d57b3c89b5ec3e9e
Author: Karol Herbst <kher...@redhat.com> Date: Fri Oct 27 00:31:27 2023 +0200 zink: handle denorm preserve execution modes Signed-off-by: Karol Herbst <kher...@redhat.com> Acked-by: Mike Blumenkrantz <michael.blumenkra...@gmail.com> Reviewed-by: Georg Lehmann <dadschoo...@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25937> --- .../drivers/zink/nir_to_spirv/nir_to_spirv.c | 45 ++++++++++++++++++---- src/gallium/drivers/zink/zink_compiler.c | 13 +++++-- src/gallium/drivers/zink/zink_types.h | 5 ++- 3 files changed, 51 insertions(+), 12 deletions(-) diff --git a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c index 2bf5c0fab7a..3c8d2a53af3 100644 --- a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c +++ b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c @@ -4554,35 +4554,66 @@ nir_to_spirv(struct nir_shader *s, const struct zink_shader_info *sinfo, uint32_ bool flush_16_bit = nir_is_denorm_flush_to_zero(execution_mode, 16); bool flush_32_bit = nir_is_denorm_flush_to_zero(execution_mode, 32); bool flush_64_bit = nir_is_denorm_flush_to_zero(execution_mode, 64); - bool emit_cap = false; + bool preserve_16_bit = nir_is_denorm_preserve(execution_mode, 16); + bool preserve_32_bit = nir_is_denorm_preserve(execution_mode, 32); + bool preserve_64_bit = nir_is_denorm_preserve(execution_mode, 64); + bool emit_cap_flush = false; + bool emit_cap_preserve = false; - if (!sinfo->float_controls.flush_denorms_all_independence) { + if (!sinfo->float_controls.denorms_all_independence) { bool flush = flush_16_bit && flush_64_bit; - if (!sinfo->float_controls.flush_denorms_32_bit_independence) { + bool preserve = preserve_16_bit && preserve_64_bit; + + if (!sinfo->float_controls.denorms_32_bit_independence) { flush = flush && flush_32_bit; + preserve = preserve && preserve_32_bit; + flush_32_bit = flush; + preserve_32_bit = preserve; } + flush_16_bit = flush; flush_64_bit = flush; + preserve_16_bit = preserve; + preserve_64_bit = preserve; } if (flush_16_bit && sinfo->float_controls.flush_denorms & BITFIELD_BIT(0)) { - emit_cap = true; + emit_cap_flush = true; spirv_builder_emit_exec_mode_literal(&ctx.builder, entry_point, SpvExecutionModeDenormFlushToZero, 16); } if (flush_32_bit && sinfo->float_controls.flush_denorms & BITFIELD_BIT(1)) { - emit_cap = true; + emit_cap_flush = true; spirv_builder_emit_exec_mode_literal(&ctx.builder, entry_point, SpvExecutionModeDenormFlushToZero, 32); } if (flush_64_bit && sinfo->float_controls.flush_denorms & BITFIELD_BIT(2)) { - emit_cap = true; + emit_cap_flush = true; spirv_builder_emit_exec_mode_literal(&ctx.builder, entry_point, SpvExecutionModeDenormFlushToZero, 64); } - if (emit_cap) + + if (preserve_16_bit && sinfo->float_controls.preserve_denorms & BITFIELD_BIT(0)) { + emit_cap_preserve = true; + spirv_builder_emit_exec_mode_literal(&ctx.builder, entry_point, + SpvExecutionModeDenormPreserve, 16); + } + if (preserve_32_bit && sinfo->float_controls.preserve_denorms & BITFIELD_BIT(1)) { + emit_cap_preserve = true; + spirv_builder_emit_exec_mode_literal(&ctx.builder, entry_point, + SpvExecutionModeDenormPreserve, 32); + } + if (preserve_64_bit && sinfo->float_controls.preserve_denorms & BITFIELD_BIT(2)) { + emit_cap_preserve = true; + spirv_builder_emit_exec_mode_literal(&ctx.builder, entry_point, + SpvExecutionModeDenormPreserve, 64); + } + + if (emit_cap_flush) spirv_builder_emit_cap(&ctx.builder, SpvCapabilityDenormFlushToZero); + if (emit_cap_preserve) + spirv_builder_emit_cap(&ctx.builder, SpvCapabilityDenormPreserve); } switch (s->info.stage) { diff --git a/src/gallium/drivers/zink/zink_compiler.c b/src/gallium/drivers/zink/zink_compiler.c index 68719acd4b6..2e56a57b077 100644 --- a/src/gallium/drivers/zink/zink_compiler.c +++ b/src/gallium/drivers/zink/zink_compiler.c @@ -5386,11 +5386,18 @@ zink_shader_create(struct zink_screen *screen, struct nir_shader *nir) if (screen->info.props12.shaderDenormFlushToZeroFloat64) ret->sinfo.float_controls.flush_denorms |= 0x4; - ret->sinfo.float_controls.flush_denorms_all_independence = + if (screen->info.props12.shaderDenormPreserveFloat16) + ret->sinfo.float_controls.preserve_denorms |= 0x1; + if (screen->info.props12.shaderDenormPreserveFloat32) + ret->sinfo.float_controls.preserve_denorms |= 0x2; + if (screen->info.props12.shaderDenormPreserveFloat64) + ret->sinfo.float_controls.preserve_denorms |= 0x4; + + ret->sinfo.float_controls.denorms_all_independence = screen->info.props12.denormBehaviorIndependence == VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL; - ret->sinfo.float_controls.flush_denorms_32_bit_independence = - ret->sinfo.float_controls.flush_denorms_all_independence || + ret->sinfo.float_controls.denorms_32_bit_independence = + ret->sinfo.float_controls.denorms_all_independence || screen->info.props12.denormBehaviorIndependence == VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY; } ret->sinfo.bindless_set_idx = screen->desc_set_id[ZINK_DESCRIPTOR_BINDLESS]; diff --git a/src/gallium/drivers/zink/zink_types.h b/src/gallium/drivers/zink/zink_types.h index eabe85b183e..aa104196a06 100644 --- a/src/gallium/drivers/zink/zink_types.h +++ b/src/gallium/drivers/zink/zink_types.h @@ -776,8 +776,9 @@ struct zink_shader_info { bool have_workgroup_memory_explicit_layout; struct { uint8_t flush_denorms:3; // 16, 32, 64 - bool flush_denorms_32_bit_independence:1; - bool flush_denorms_all_independence:1; + uint8_t preserve_denorms:3; // 16, 32, 64 + bool denorms_32_bit_independence:1; + bool denorms_all_independence:1; } float_controls; unsigned bindless_set_idx; };