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:

committed by
Marge Bot

parent
829d74b2f2
commit
8c4c4c3ee1
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
@@ -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
|
||||
|
Reference in New Issue
Block a user