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

Reply via email to