zink: emit float controls

This is required by OpenCL who relies on flushing behavior to match the
runtimes advertized feature, but also later once rusticl does support
denorms, to flush them if applications whish to do so.

Signed-off-by: Karol Herbst <kherbst@redhat.com>
Acked-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25837>
This commit is contained in:
Karol Herbst 2023-10-21 10:03:36 +02:00 committed by Marge Bot
parent 700a2dc648
commit e3a0df6468
4 changed files with 58 additions and 0 deletions

View file

@ -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,

View file

@ -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);

View file

@ -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))

View file

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