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 ce7efafe128..e46b1586025 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 @@ -4550,6 +4550,42 @@ nir_to_spirv(struct nir_shader *s, const struct zink_shader_info *sinfo, uint32_ emit_image(&ctx, var, get_bare_image_type(&ctx, var, false)); } + if (sinfo->float_controls.flush_denorms) { + unsigned execution_mode = s->info.float_controls_execution_mode; + 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; + + if (!sinfo->float_controls.flush_denorms_all_independence) { + bool flush = flush_16_bit && flush_64_bit; + if (!sinfo->float_controls.flush_denorms_32_bit_independence) { + flush = flush && flush_32_bit; + flush_32_bit = flush; + } + flush_16_bit = flush; + flush_64_bit = flush; + } + + if (flush_16_bit && sinfo->float_controls.flush_denorms & BITFIELD_BIT(0)) { + emit_cap = 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; + 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; + spirv_builder_emit_exec_mode_literal(&ctx.builder, entry_point, + SpvExecutionModeDenormFlushToZero, 64); + } + if (emit_cap) + spirv_builder_emit_cap(&ctx.builder, SpvCapabilityDenormFlushToZero); + } + switch (s->info.stage) { case MESA_SHADER_FRAGMENT: spirv_builder_emit_exec_mode(&ctx.builder, entry_point, diff --git a/src/gallium/drivers/zink/zink_compiler.c b/src/gallium/drivers/zink/zink_compiler.c index 646880b7d08..41d7fff635a 100644 --- a/src/gallium/drivers/zink/zink_compiler.c +++ b/src/gallium/drivers/zink/zink_compiler.c @@ -5377,6 +5377,21 @@ zink_shader_create(struct zink_screen *screen, struct nir_shader *nir) ret->sinfo.have_vulkan_memory_model = screen->info.have_KHR_vulkan_memory_model; ret->sinfo.have_workgroup_memory_explicit_layout = screen->info.have_KHR_workgroup_memory_explicit_layout; + if (screen->info.have_KHR_shader_float_controls) { + if (screen->info.props12.shaderDenormFlushToZeroFloat16) + ret->sinfo.float_controls.flush_denorms |= 0x1; + if (screen->info.props12.shaderDenormFlushToZeroFloat32) + ret->sinfo.float_controls.flush_denorms |= 0x2; + if (screen->info.props12.shaderDenormFlushToZeroFloat64) + ret->sinfo.float_controls.flush_denorms |= 0x4; + + ret->sinfo.float_controls.flush_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 || + screen->info.props12.denormBehaviorIndependence == VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY; + } ret->sinfo.bindless_set_idx = screen->desc_set_id[ZINK_DESCRIPTOR_BINDLESS]; util_queue_fence_init(&ret->precompile.fence); diff --git a/src/gallium/drivers/zink/zink_device_info.py b/src/gallium/drivers/zink/zink_device_info.py index 7dc980c44fc..2c3cde855ca 100644 --- a/src/gallium/drivers/zink/zink_device_info.py +++ b/src/gallium/drivers/zink/zink_device_info.py @@ -318,6 +318,8 @@ EXTENSIONS = [ alias="demote", features=True, conditions=["$feats.shaderDemoteToHelperInvocation"]), + Extension("VK_KHR_shader_float_controls", + alias="float_controls") ] # constructor: Versions(device_version(major, minor, patch), struct_version(major, minor)) diff --git a/src/gallium/drivers/zink/zink_types.h b/src/gallium/drivers/zink/zink_types.h index f05ed5ac91c..865fa7492c1 100644 --- a/src/gallium/drivers/zink/zink_types.h +++ b/src/gallium/drivers/zink/zink_types.h @@ -774,6 +774,11 @@ struct zink_shader_info { bool have_sparse; bool have_vulkan_memory_model; 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; + } float_controls; unsigned bindless_set_idx; };