Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/HansKristian-Work/vkd3d-proton.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoresullivan-nvidia <esullivan@nvidia.com>2022-10-05 13:10:16 +0300
committerHans-Kristian Arntzen <post@arntzen-software.no>2022-10-11 12:36:42 +0300
commitf97edc79ff06065628588cfcaf26d48b2220328b (patch)
tree3271a9e5bcd244b6b4033a9858ebd918c399be29
parentc42f24a2b0da37f03758f1ab97f3fa98b082c2e0 (diff)
vkd3d: Add PREALLOCATE_SRV_MIP_CLAMPS workaround for Halo Infinite
Halo Infinite currently has a race condition that can result in a GPU fault on NVIDIA hardware. The root cause of this race condition is the application overwriting existing SRV descriptors with a new mip clamp value asynchronously to the applications GPU submission timeline. This is problematic for vkd3d because it requires creating a new VkImageView to represent the SRV with the updated mip clamp value. If this SRV is being created after work has been submitted that accesses it, the GPU may not see the correct descriptor state possibly resulting in a fault. This commit adds the VKD3D_CONFIG_FLAG_PREALLOCATE_SRV_MIP_CLAMPS configuration as a workaround to the race condition. It works by preallocating all the VkImageViews for each possible mip clamp level the application may attempt to create for the resource. Technically this is still a race condition but the end result isn't a GPU fault if the race condition is lost. Instead the shader will just sample from the texture with the previous SRVs mip clamp level rather than the updated one. These are the same outcomes that are possible on RADV without this workaround. Signed-off-by: Eric Sullivan <esullivan@nvidia.com>
-rw-r--r--include/vkd3d.h1
-rw-r--r--libs/vkd3d/device.c3
-rw-r--r--libs/vkd3d/resource.c25
3 files changed, 28 insertions, 1 deletions
diff --git a/include/vkd3d.h b/include/vkd3d.h
index 907e4f0f..b0817a04 100644
--- a/include/vkd3d.h
+++ b/include/vkd3d.h
@@ -92,6 +92,7 @@ extern "C" {
#define VKD3D_CONFIG_FLAG_ALLOW_SBT_COLLECTION (1ull << 30)
#define VKD3D_CONFIG_FLAG_FORCE_NATIVE_FP16 (1ull << 31)
#define VKD3D_CONFIG_FLAG_USE_HOST_IMPORT_FALLBACK (1ull << 32)
+#define VKD3D_CONFIG_FLAG_PREALLOCATE_SRV_MIP_CLAMPS (1ull << 33)
typedef HRESULT (*PFN_vkd3d_signal_event)(HANDLE event);
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index 3b60a151..b9ad3afe 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -521,7 +521,7 @@ static const struct vkd3d_instance_application_meta application_override[] = {
* Game also relies on indirectly modifying CBV root descriptors, which means we are forced to rely on RAW_VA_CBV. */
{ VKD3D_STRING_COMPARE_EXACT, "HaloInfinite.exe",
VKD3D_CONFIG_FLAG_ZERO_MEMORY_WORKAROUNDS_COMMITTED_BUFFER_UAV | VKD3D_CONFIG_FLAG_FORCE_RAW_VA_CBV |
- VKD3D_CONFIG_FLAG_USE_HOST_IMPORT_FALLBACK, 0 },
+ VKD3D_CONFIG_FLAG_USE_HOST_IMPORT_FALLBACK | VKD3D_CONFIG_FLAG_PREALLOCATE_SRV_MIP_CLAMPS, 0 },
/* (1182900) Workaround amdgpu kernel bug with host memory import and concurrent submissions. */
{ VKD3D_STRING_COMPARE_EXACT, "APlagueTaleRequiem_x64.exe", VKD3D_CONFIG_FLAG_USE_HOST_IMPORT_FALLBACK, 0 },
/* Shadow of the Tomb Raider (750920).
@@ -719,6 +719,7 @@ static const struct vkd3d_debug_option vkd3d_config_options[] =
{"force_raw_va_cbv", VKD3D_CONFIG_FLAG_FORCE_RAW_VA_CBV},
{"allow_sbt_collection", VKD3D_CONFIG_FLAG_ALLOW_SBT_COLLECTION},
{"host_import_fallback", VKD3D_CONFIG_FLAG_USE_HOST_IMPORT_FALLBACK},
+ {"preallocate_srv_mip_clamps", VKD3D_CONFIG_FLAG_PREALLOCATE_SRV_MIP_CLAMPS},
};
static void vkd3d_config_flags_init_once(void)
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c
index f017ce6a..11f5ff30 100644
--- a/libs/vkd3d/resource.c
+++ b/libs/vkd3d/resource.c
@@ -20,6 +20,7 @@
#define VKD3D_DBG_CHANNEL VKD3D_DBG_CHANNEL_API
#include <float.h>
+#include <math.h>
#include "vkd3d_private.h"
#include "vkd3d_rw_spinlock.h"
@@ -4432,6 +4433,30 @@ static void vkd3d_create_texture_srv(vkd3d_cpu_descriptor_va_t desc_va,
if (key.u.texture.miplevel_count == VK_REMAINING_MIP_LEVELS)
key.u.texture.miplevel_count = resource->desc.MipLevels - key.u.texture.miplevel_idx;
+ if ((vkd3d_config_flags & VKD3D_CONFIG_FLAG_PREALLOCATE_SRV_MIP_CLAMPS) &&
+ desc->ViewDimension != D3D12_SRV_DIMENSION_TEXTURE2DMS &&
+ desc->ViewDimension != D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY)
+ {
+ key.u.texture.miplevel_clamp = floor(key.u.texture.miplevel_clamp);
+
+ if (!hash_map_find(&resource->view_map.map, &key))
+ {
+ uint32_t starting_mip = key.u.texture.miplevel_idx;
+ uint32_t mip_count = key.u.texture.miplevel_count != UINT32_MAX ?
+ key.u.texture.miplevel_count :
+ resource->desc.MipLevels - starting_mip;
+ uint32_t i;
+
+ struct vkd3d_view_key preallocate_key = key;
+
+ for (i = starting_mip; i < mip_count; i++)
+ {
+ preallocate_key.u.texture.miplevel_clamp = (float)(i);
+ vkd3d_view_map_create_view(&resource->view_map, device, &preallocate_key);
+ }
+ }
+ }
+
if (!(view = vkd3d_view_map_create_view(&resource->view_map, device, &key)))
return;