From: Mykhailo Skorokhodov Date: Wed, 28 Sep 2022 02:12:19 +0000 (+0300) Subject: anv: Add softtp64 workaround X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8c4c4c3ee1a24b73fa29f30a05e873e9e13dddc7;p=platform%2Fupstream%2Fmesa.git anv: Add softtp64 workaround Pass float64.glsl into nir_lower_doubles() resolves the problem on ICL/TGL when the shader uses float64, but the device doesn't support that type. Signed-off-by: Mykhailo Skorokhodov Reviewed-by: Lionel Landwerlin Part-of: --- diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c index 337045b..b49e1e8 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -3588,6 +3588,11 @@ 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 && + device->physical->instance->fp64_workaround_enabled) + anv_load_fp64_shader(device); + result = anv_device_init_rt_shaders(device); if (result != VK_SUCCESS) { result = vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); diff --git a/src/intel/vulkan/anv_pipeline.c b/src/intel/vulkan/anv_pipeline.c index 82c1a10..ef9b1f9 100644 --- a/src/intel/vulkan/anv_pipeline.c +++ b/src/intel/vulkan/anv_pipeline.c @@ -176,6 +176,29 @@ anv_nir_lower_mesh_ext(nir_shader *nir) &state); } +static bool +nir_shader_uses_64bit_alu(nir_shader *shader) +{ + nir_foreach_function(function, shader) { + if (!function->impl) + continue; + + nir_foreach_block(block, function->impl) { + nir_foreach_instr(instr, block) { + if (instr->type != nir_instr_type_alu) + continue; + nir_alu_instr *alu = nir_instr_as_alu(instr); + if (nir_alu_type_get_base_type(nir_op_infos[alu->op].output_type) != nir_type_float) + continue; + if (alu->dest.dest.ssa.bit_size == 64) + return true; + } + } + } + + return false; +} + /* Eventually, this will become part of anv_CreateShader. Unfortunately, * we can't do that yet because we don't have the ability to copy nir. */ @@ -297,7 +320,10 @@ anv_shader_stage_to_nir(struct anv_device *device, /* Vulkan uses the separate-shader linking model */ nir->info.separate_shader = true; - brw_preprocess_nir(compiler, nir, NULL); + assert(device->info->has_64bit_float || instance->fp64_workaround_enabled || + !nir_shader_uses_64bit_alu(nir)); + + brw_preprocess_nir(compiler, nir, device->fp64_nir); if (nir->info.stage == MESA_SHADER_MESH && !nir->info.mesh.nv) { bool progress = false; diff --git a/src/intel/vulkan/anv_pipeline_cache.c b/src/intel/vulkan/anv_pipeline_cache.c index 25458e1..b94eea7 100644 --- a/src/intel/vulkan/anv_pipeline_cache.c +++ b/src/intel/vulkan/anv_pipeline_cache.c @@ -30,6 +30,8 @@ #include "anv_private.h" #include "nir/nir_xfb_info.h" #include "vulkan/util/vk_util.h" +#include "compiler/spirv/nir_spirv.h" +#include "float64_spv.h" static bool anv_shader_bin_serialize(struct vk_pipeline_cache_object *object, @@ -414,3 +416,68 @@ anv_device_upload_nir(struct anv_device *device, vk_pipeline_cache_add_nir(cache, sha1_key, SHA1_KEY_SIZE, 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"; + struct mesa_sha1 sha1_ctx; + uint8_t sha1[20]; + _mesa_sha1_init(&sha1_ctx); + _mesa_sha1_update(&sha1_ctx, shader_name, strlen(shader_name)); + _mesa_sha1_final(&sha1_ctx, sha1); + + device->fp64_nir = + anv_device_search_for_nir(device, device->internal_cache, + nir_options, sha1, NULL); + + /* The shader found, no need to call spirv_to_nir() again. */ + if (device->fp64_nir) + return; + + struct spirv_to_nir_options spirv_options = { + .caps = { + .address = true, + .float64 = true, + .int8 = true, + .int16 = true, + .int64 = true, + }, + .environment = MESA_SHADER_VERTEX, + .create_library = true + }; + + nir_shader* nir = + spirv_to_nir(float64_spv_source, sizeof(float64_spv_source) / 4, + NULL, 0, PIPE_SHADER_VERTEX, "main", + &spirv_options, nir_options); + + assert(nir != NULL); + + nir_validate_shader(nir, "after spirv_to_nir"); + nir_validate_ssa_dominance(nir, "after spirv_to_nir"); + + NIR_PASS_V(nir, nir_lower_variable_initializers, nir_var_function_temp); + NIR_PASS_V(nir, nir_lower_returns); + NIR_PASS_V(nir, nir_inline_functions); + NIR_PASS_V(nir, nir_opt_deref); + + NIR_PASS_V(nir, nir_lower_vars_to_ssa); + NIR_PASS_V(nir, nir_copy_prop); + NIR_PASS_V(nir, nir_opt_dce); + NIR_PASS_V(nir, nir_opt_cse); + NIR_PASS_V(nir, nir_opt_gcm, true); + NIR_PASS_V(nir, nir_opt_peephole_select, 1, false, false); + NIR_PASS_V(nir, nir_opt_dce); + + NIR_PASS_V(nir, nir_lower_explicit_io, nir_var_function_temp, + nir_address_format_62bit_generic); + + anv_device_upload_nir(device, device->internal_cache, + nir, sha1); + + device->fp64_nir = nir; +} \ No newline at end of file diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 1eb16d7..2b27e01 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -1145,6 +1145,9 @@ anv_device_upload_nir(struct anv_device *device, const struct nir_shader *nir, unsigned char sha1_key[20]); +void +anv_load_fp64_shader(struct anv_device *device); + enum anv_rt_bvh_build_method { ANV_BVH_BUILD_METHOD_TRIVIAL, ANV_BVH_BUILD_METHOD_NEW_SAH, @@ -1262,6 +1265,8 @@ struct anv_device { struct intel_debug_block_frame *debug_frame_desc; struct intel_ds_device ds; + + nir_shader *fp64_nir; }; static inline struct anv_state