From 7d3b62e13dbdea0509095108d466075cfeebba43 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Fri, 16 Jan 2026 09:48:45 +0200 Subject: [PATCH] anv: only load fp64 software shader when needed Signed-off-by: Lionel Landwerlin Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/14665 Reviewed-by: Allen Ballway Part-of: --- src/intel/vulkan/anv_blorp.c | 2 +- src/intel/vulkan/anv_device.c | 6 +-- src/intel/vulkan/anv_pipeline_cache.c | 58 ---------------------- src/intel/vulkan/anv_private.h | 5 +- src/intel/vulkan/anv_shader_compile.c | 6 ++- src/intel/vulkan/anv_util.c | 69 +++++++++++++++++++++++++++ 6 files changed, 79 insertions(+), 67 deletions(-) diff --git a/src/intel/vulkan/anv_blorp.c b/src/intel/vulkan/anv_blorp.c index 3348d95e589..38eb0e6c9a6 100644 --- a/src/intel/vulkan/anv_blorp.c +++ b/src/intel/vulkan/anv_blorp.c @@ -107,7 +107,7 @@ static nir_shader * get_fp64_nir(struct blorp_context *context) { struct anv_device *device = context->driver_ctx; - return device->fp64_nir; + return anv_ensure_fp64_shader(device); } static uint64_t diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c index 8b580e084ff..32ef3883dbf 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -1118,10 +1118,6 @@ VkResult anv_CreateDevice( goto fail_default_pipeline_cache; } - /* The device (currently is ICL/TGL) does not have float64 support. */ - if (!device->info->has_64bit_float) - anv_load_fp64_shader(device); - if (anv_needs_printf_buffer()) { result = anv_device_print_init(device); if (result != VK_SUCCESS) @@ -1244,6 +1240,7 @@ VkResult anv_CreateDevice( device->vk.disable_lto = device->physical->instance->disable_lto; simple_mtx_init(&device->accel_struct_build.mutex, mtx_plain); + simple_mtx_init(&device->fp64_mutex, mtx_plain); *pDevice = anv_device_to_handle(device); @@ -1469,6 +1466,7 @@ void anv_DestroyDevice( pthread_mutex_destroy(&device->mutex); simple_mtx_destroy(&device->accel_struct_build.mutex); + simple_mtx_destroy(&device->fp64_mutex); ralloc_free(device->fp64_nir); diff --git a/src/intel/vulkan/anv_pipeline_cache.c b/src/intel/vulkan/anv_pipeline_cache.c index 65b08b8ab6d..d6dca2f9614 100644 --- a/src/intel/vulkan/anv_pipeline_cache.c +++ b/src/intel/vulkan/anv_pipeline_cache.c @@ -33,7 +33,6 @@ #include "nir/nir_xfb_info.h" #include "vk_util.h" #include "compiler/spirv/nir_spirv.h" -#include "shaders/float64_spv.h" #include "util/u_printf.h" @@ -315,60 +314,3 @@ anv_device_upload_nir(struct anv_device *device, vk_pipeline_cache_add_nir(cache, blake3_key, BLAKE3_KEY_LEN, nir); } - -void -anv_load_fp64_shader(struct anv_device *device) -{ - const nir_shader_compiler_options *nir_options = - &device->physical->compiler->nir_options[MESA_SHADER_VERTEX]; - - const char* shader_name = "float64_spv_lib"; - blake3_hasher blake3_ctx; - uint8_t blake3[BLAKE3_KEY_LEN]; - _mesa_blake3_init(&blake3_ctx); - _mesa_blake3_update(&blake3_ctx, shader_name, strlen(shader_name)); - _mesa_blake3_final(&blake3_ctx, blake3); - - device->fp64_nir = - anv_device_search_for_nir(device, device->internal_cache, - nir_options, blake3, NULL); - - /* The shader found, no need to call spirv_to_nir() again. */ - if (device->fp64_nir) - return; - - const struct spirv_capabilities spirv_caps = { - .Addresses = true, - .Float64 = true, - .Int8 = true, - .Int16 = true, - .Int64 = true, - .Shader = true, - }; - - struct spirv_to_nir_options spirv_options = { - .capabilities = &spirv_caps, - .environment = NIR_SPIRV_VULKAN, - .create_library = true - }; - - nir_shader* nir = - spirv_to_nir(float64_spv_source, sizeof(float64_spv_source) / 4, - NULL, MESA_SHADER_VERTEX, "main", - &spirv_options, nir_options); - - assert(nir != NULL); - - nir_validate_shader(nir, "after spirv_to_nir"); - - NIR_PASS(_, nir, nir_lower_variable_initializers, nir_var_function_temp); - NIR_PASS(_, nir, nir_lower_returns); - NIR_PASS(_, nir, nir_inline_functions); - - nir_sweep(nir); - - anv_device_upload_nir(device, device->internal_cache, - nir, blake3); - - device->fp64_nir = nir; -} diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 519be0f3654..cd712813ee0 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -1920,8 +1920,8 @@ anv_device_upload_nir(struct anv_device *device, const struct nir_shader *nir, unsigned char blake3_key[BLAKE3_KEY_LEN]); -void -anv_load_fp64_shader(struct anv_device *device); +nir_shader * +anv_ensure_fp64_shader(struct anv_device *device); /** * This enum tracks the various HW instructions that hold graphics state @@ -2727,6 +2727,7 @@ struct anv_device { struct intel_ds_device ds; + simple_mtx_t fp64_mutex; nir_shader *fp64_nir; uint32_t draw_call_count; diff --git a/src/intel/vulkan/anv_shader_compile.c b/src/intel/vulkan/anv_shader_compile.c index 9c990f54bdb..a73a6fd67ea 100644 --- a/src/intel/vulkan/anv_shader_compile.c +++ b/src/intel/vulkan/anv_shader_compile.c @@ -1434,14 +1434,16 @@ anv_shader_lower_nir(struct anv_device *device, /* Workaround for apps that need fp64 support */ if (device->fp64_nir) { - NIR_PASS(_, nir, nir_lower_doubles, device->fp64_nir, + nir_shader *fp64_nir = anv_ensure_fp64_shader(device); + + NIR_PASS(_, nir, nir_lower_doubles, fp64_nir, nir->options->lower_doubles_options); bool fp_conv = false; NIR_PASS(fp_conv, nir, nir_lower_int64_float_conversions); if (fp_conv) { NIR_PASS(_, nir, nir_opt_algebraic); - NIR_PASS(_, nir, nir_lower_doubles, device->fp64_nir, + NIR_PASS(_, nir, nir_lower_doubles, fp64_nir, nir->options->lower_doubles_options); } } diff --git a/src/intel/vulkan/anv_util.c b/src/intel/vulkan/anv_util.c index e7d83a17795..033578b1967 100644 --- a/src/intel/vulkan/anv_util.c +++ b/src/intel/vulkan/anv_util.c @@ -35,6 +35,7 @@ #include "vk_enum_to_str.h" #include "compiler/brw/brw_nir_rt.h" +#include "shaders/float64_spv.h" #ifdef NO_REGEX typedef int regex_t; @@ -667,3 +668,71 @@ anv_cmd_buffer_dump_commands(struct anv_cmd_buffer *cmd_buffer, "post gfx cmd dump"); anv_genX(device->info, cmd_buffer_apply_pipe_flushes)(cmd_buffer); } + +nir_shader * +anv_ensure_fp64_shader(struct anv_device *device) +{ + assert(!device->info->has_64bit_float); + + if (device->fp64_nir) + return device->fp64_nir; + + simple_mtx_unlock(&device->fp64_mutex); + + if (!device->fp64_nir) { + const nir_shader_compiler_options *nir_options = + &device->physical->compiler->nir_options[MESA_SHADER_VERTEX]; + + const char* shader_name = "float64_spv_lib"; + blake3_hasher blake3_ctx; + uint8_t blake3[BLAKE3_KEY_LEN]; + _mesa_blake3_init(&blake3_ctx); + _mesa_blake3_update(&blake3_ctx, shader_name, strlen(shader_name)); + _mesa_blake3_final(&blake3_ctx, blake3); + + device->fp64_nir = + anv_device_search_for_nir(device, device->internal_cache, + nir_options, blake3, NULL); + + /* The shader found, no need to call spirv_to_nir() again. */ + if (!device->fp64_nir) { + const struct spirv_capabilities spirv_caps = { + .Addresses = true, + .Float64 = true, + .Int8 = true, + .Int16 = true, + .Int64 = true, + .Shader = true, + }; + + struct spirv_to_nir_options spirv_options = { + .capabilities = &spirv_caps, + .environment = NIR_SPIRV_VULKAN, + .create_library = true + }; + + nir_shader* nir = + spirv_to_nir(float64_spv_source, sizeof(float64_spv_source) / 4, + NULL, MESA_SHADER_VERTEX, "main", + &spirv_options, nir_options); + + assert(nir != NULL); + + nir_validate_shader(nir, "after spirv_to_nir"); + + NIR_PASS(_, nir, nir_lower_variable_initializers, nir_var_function_temp); + NIR_PASS(_, nir, nir_lower_returns); + NIR_PASS(_, nir, nir_inline_functions); + + nir_sweep(nir); + + anv_device_upload_nir(device, device->internal_cache, nir, blake3); + + device->fp64_nir = nir; + } + } + + simple_mtx_unlock(&device->fp64_mutex); + + return device->fp64_nir; +}