Module: Mesa Branch: staging/23.3 Commit: 3d31646c7e07450878b98fe8e6bf0a14d45216de URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=3d31646c7e07450878b98fe8e6bf0a14d45216de
Author: Friedrich Vock <friedrich.v...@gmx.de> Date: Wed Nov 29 01:20:54 2023 +0100 radv,vtn,driconf: Add and use radv_rt_ssbo_non_uniform workaround for Crysis 2/3 Remastered Crysis 2 and 3 Remastered's RT shaders non-uniformly index into SSBO descriptor arrays without specifying the NonUniformEXT qualifier on the relevant access chains/load ops. This leads to artifacts around objects. To add insult to injury, the game fails to provide a meaningful applicationName/engineName in the Vulkan part of the DX11-Vulkan interop solution used for RT. Both of these fields are set to "nvpro-sample" (perhaps the code has been copied from NVIDIA's sample applications). Therefore, fall back to executable name matching. Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/9883 Cc: mesa-stable Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26391> (cherry picked from commit f1817ab7e03f188164c7d6850149781066418d49) --- .pick_status.json | 2 +- src/amd/vulkan/radv_instance.c | 3 +++ src/amd/vulkan/radv_pipeline.c | 1 + src/amd/vulkan/radv_private.h | 1 + src/amd/vulkan/radv_shader.c | 1 + src/amd/vulkan/radv_shader.h | 1 + src/compiler/spirv/nir_spirv.h | 2 ++ src/compiler/spirv/vtn_variables.c | 3 +++ src/util/00-radv-defaults.conf | 8 ++++++++ src/util/driconf.h | 4 ++++ 10 files changed, 25 insertions(+), 1 deletion(-) diff --git a/.pick_status.json b/.pick_status.json index 882b5efe2bb..866721e4d95 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -524,7 +524,7 @@ "description": "radv,vtn,driconf: Add and use radv_rt_ssbo_non_uniform workaround for Crysis 2/3 Remastered", "nominated": true, "nomination_type": 0, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": null, "notes": null diff --git a/src/amd/vulkan/radv_instance.c b/src/amd/vulkan/radv_instance.c index 6cd78b4265f..14032b93a19 100644 --- a/src/amd/vulkan/radv_instance.c +++ b/src/amd/vulkan/radv_instance.c @@ -153,6 +153,7 @@ static const driOptionDescription radv_dri_options[] = { DRI_CONF_RADV_FLUSH_BEFORE_TIMESTAMP_WRITE(false) DRI_CONF_RADV_RT_WAVE64(false) DRI_CONF_DUAL_COLOR_BLEND_BY_LOCATION(false) + DRI_CONF_RADV_SSBO_NON_UNIFORM(false) DRI_CONF_RADV_APP_LAYER() DRI_CONF_SECTION_END }; @@ -203,6 +204,8 @@ radv_init_dri_options(struct radv_instance *instance) instance->tex_non_uniform = driQueryOptionb(&instance->dri_options, "radv_tex_non_uniform"); + instance->ssbo_non_uniform = driQueryOptionb(&instance->dri_options, "radv_ssbo_non_uniform"); + instance->app_layer = driQueryOptionstr(&instance->dri_options, "radv_app_layer"); instance->flush_before_timestamp_write = diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c index d9b5eb2a098..26303796128 100644 --- a/src/amd/vulkan/radv_pipeline.c +++ b/src/amd/vulkan/radv_pipeline.c @@ -162,6 +162,7 @@ radv_generate_pipeline_key(const struct radv_device *device, const VkPipelineSha key.image_2d_view_of_3d = device->image_2d_view_of_3d && device->physical_device->rad_info.gfx_level == GFX9; key.tex_non_uniform = device->instance->tex_non_uniform; + key.ssbo_non_uniform = device->instance->ssbo_non_uniform; for (unsigned i = 0; i < num_stages; ++i) { const VkPipelineShaderStageCreateInfo *const stage = &stages[i]; diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index bb2b9925c7b..1d2e3f90769 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -416,6 +416,7 @@ struct radv_instance { bool flush_before_query_copy; bool enable_unified_heap_on_apu; bool tex_non_uniform; + bool ssbo_non_uniform; bool flush_before_timestamp_write; bool force_rt_wave64; bool dual_color_blend_by_location; diff --git a/src/amd/vulkan/radv_shader.c b/src/amd/vulkan/radv_shader.c index 84f33eeea15..54d1800a9ef 100644 --- a/src/amd/vulkan/radv_shader.c +++ b/src/amd/vulkan/radv_shader.c @@ -461,6 +461,7 @@ radv_shader_spirv_to_nir(struct radv_device *device, const struct radv_shader_st .private_data = &spirv_debug_data, }, .force_tex_non_uniform = key->tex_non_uniform, + .force_ssbo_non_uniform = key->ssbo_non_uniform, }; nir = spirv_to_nir(spirv, stage->spirv.size / 4, spec_entries, num_spec_entries, stage->stage, stage->entrypoint, &spirv_options, &device->physical_device->nir_options[stage->stage]); diff --git a/src/amd/vulkan/radv_shader.h b/src/amd/vulkan/radv_shader.h index 445f8b8e0a5..c728412832b 100644 --- a/src/amd/vulkan/radv_shader.h +++ b/src/amd/vulkan/radv_shader.h @@ -95,6 +95,7 @@ struct radv_pipeline_key { uint32_t dynamic_provoking_vtx_mode : 1; uint32_t dynamic_line_rast_mode : 1; uint32_t tex_non_uniform : 1; + uint32_t ssbo_non_uniform : 1; uint32_t enable_remove_point_size : 1; uint32_t unknown_rast_prim : 1; uint32_t mesh_shader_queries : 1; diff --git a/src/compiler/spirv/nir_spirv.h b/src/compiler/spirv/nir_spirv.h index 1369a0e6b47..bfcccdc0fcc 100644 --- a/src/compiler/spirv/nir_spirv.h +++ b/src/compiler/spirv/nir_spirv.h @@ -116,6 +116,8 @@ struct spirv_to_nir_options { /* Force texture sampling to be non-uniform. */ bool force_tex_non_uniform; + /* Force SSBO accesses to be non-uniform. */ + bool force_ssbo_non_uniform; /* In Debug Builds, instead of emitting an OS break on failure, just return NULL from * spirv_to_nir(). This is useful for the unit tests that want to report a test failed diff --git a/src/compiler/spirv/vtn_variables.c b/src/compiler/spirv/vtn_variables.c index d00e3d785fd..651041ad4c0 100644 --- a/src/compiler/spirv/vtn_variables.c +++ b/src/compiler/spirv/vtn_variables.c @@ -2632,6 +2632,9 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode, /* Workaround for https://gitlab.freedesktop.org/mesa/mesa/-/issues/3406 */ access |= base->access & ACCESS_NON_UNIFORM; + if (base->mode == vtn_variable_mode_ssbo && b->options->force_ssbo_non_uniform) + access |= ACCESS_NON_UNIFORM; + struct vtn_pointer *ptr = vtn_pointer_dereference(b, base, chain); ptr->ptr_type = ptr_type; ptr->access |= access; diff --git a/src/util/00-radv-defaults.conf b/src/util/00-radv-defaults.conf index b13d92f84ce..0dcec733e52 100644 --- a/src/util/00-radv-defaults.conf +++ b/src/util/00-radv-defaults.conf @@ -148,6 +148,14 @@ Application bugs worked around in this file: <option name="radv_invariant_geom" value="true"/> </application> + <application name="Crysis 2 Remastered" executable="Crysis2Remastered.exe"> + <option name="radv_ssbo_non_uniform" value="true" /> + </application> + + <application name="Crysis 3 Remastered" executable="Crysis3Remastered.exe"> + <option name="radv_ssbo_non_uniform" value="true" /> + </application> + <!-- OpenGL Game workarounds (zink) --> <application name="Black Geyser: Couriers of Darkness" executable="BlackGeyser.x86_64"> <option name="radv_zero_vram" value="true" /> diff --git a/src/util/driconf.h b/src/util/driconf.h index e24c1eefd43..c79f969d517 100644 --- a/src/util/driconf.h +++ b/src/util/driconf.h @@ -674,6 +674,10 @@ DRI_CONF_OPT_B(radv_tex_non_uniform, def, \ "Always mark texture sample operations as non-uniform.") +#define DRI_CONF_RADV_SSBO_NON_UNIFORM(def) \ + DRI_CONF_OPT_B(radv_ssbo_non_uniform, def, \ + "Always mark SSBO operations as non-uniform.") + #define DRI_CONF_RADV_FLUSH_BEFORE_TIMESTAMP_WRITE(def) \ DRI_CONF_OPT_B(radv_flush_before_timestamp_write, def, \ "Wait for previous commands to finish before writing timestamps")