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 <mykhailo.skorokhodov@globallogic.com>
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18854>
This commit is contained in:
Mykhailo Skorokhodov
2022-09-28 05:12:19 +03:00
committed by Marge Bot
parent 829d74b2f2
commit 8c4c4c3ee1
4 changed files with 104 additions and 1 deletions

View File

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

View File

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

View File

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

View File

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