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

github.com/ValveSoftware/vkd3d.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans-Kristian Arntzen <post@arntzen-software.no>2021-11-29 14:38:42 +0300
committerArkadiusz Hiler <ahiler@codeweavers.com>2021-12-20 12:59:12 +0300
commitdaf8732546b1538e4882dcfab9fcff9a479f7d67 (patch)
tree5d5fddaf677ab49b9d3c52fbce1b70ee3d007732
parentc0a3fa8adc589454a05ee2dd28430cae73b67890 (diff)
vkd3d: Workaround broken barriers in DEATHLOOP.deathloop-broken-barriers-workaround
In DEATHLOOP, there is a render pass which renders out a simple image, which is then directly followed by a compute dispatch, reading that image. The image is still in RENDER_TARGET state, and color buffers are *not* flushed properly on at least RADV, manifesting as a very distracting glitch pattern. This is a game bug, but for the time being, we have to workaround it, *sigh*. For a simple workaround, we can detect patterns where we see these events in succession: - Color RT is started - StateBefore == RENDER_TARGET is not observed - Dispatch() In particular, when entering the options menu, highly distracting glitches are observed in the background. Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
-rw-r--r--include/vkd3d.h1
-rw-r--r--libs/vkd3d/command.c34
-rw-r--r--libs/vkd3d/device.c4
-rw-r--r--libs/vkd3d/vkd3d_private.h8
4 files changed, 46 insertions, 1 deletions
diff --git a/include/vkd3d.h b/include/vkd3d.h
index 274ab301..07a5ea7e 100644
--- a/include/vkd3d.h
+++ b/include/vkd3d.h
@@ -76,6 +76,7 @@ enum vkd3d_config_flags
VKD3D_CONFIG_FLAG_FORCE_HOST_CACHED = 0x00002000,
VKD3D_CONFIG_FLAG_DXR11 = 0x00004000,
VKD3D_CONFIG_FLAG_FORCE_NO_INVARIANT_POSITION = 0x00008000,
+ VKD3D_CONFIG_FLAG_WORKAROUND_MISSING_COLOR_COMPUTE_BARRIERS = 0x00010000,
};
typedef HRESULT (*PFN_vkd3d_signal_event)(HANDLE event);
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c
index f14ca3ec..0956ab07 100644
--- a/libs/vkd3d/command.c
+++ b/libs/vkd3d/command.c
@@ -2891,6 +2891,8 @@ static void d3d12_command_list_emit_render_pass_transition(struct d3d12_command_
stage_mask |= new_stages;
j++;
}
+
+ list->workaround_state.has_pending_color_write = true;
}
dsv = &list->dsv;
@@ -4287,6 +4289,8 @@ static void d3d12_command_list_reset_api_state(struct d3d12_command_list *list,
list->cbv_srv_uav_descriptors = NULL;
list->vrs_image = NULL;
+ list->workaround_state.has_pending_color_write = false;
+
ID3D12GraphicsCommandList_SetPipelineState(iface, initial_pipeline_state);
}
@@ -5528,6 +5532,31 @@ static void STDMETHODCALLTYPE d3d12_command_list_DrawIndexedInstanced(d3d12_comm
VK_CALL(vkCmdDrawIndexedIndirect(list->vk_command_buffer, scratch.buffer, scratch.offset, 1, 0));
}
+static void d3d12_command_list_workaround_handle_missing_color_compute_barriers(struct d3d12_command_list *list)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
+ VkMemoryBarrier barrier;
+
+ if (list->workaround_state.has_pending_color_write &&
+ (vkd3d_config_flags & VKD3D_CONFIG_FLAG_WORKAROUND_MISSING_COLOR_COMPUTE_BARRIERS))
+ {
+ /* Very specifically, every render pass which writes color sets
+ * has_pending_color_write = true.
+ * If we observe a StateBefore == RENDER_TARGET, clear the flag.
+ * If we come to a plain dispatch with this flag set,
+ * insert a simple memory barrier. The image will still have wrong layout,
+ * but this is good enough to workaround the game bug. */
+ barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
+ barrier.pNext = NULL;
+ barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+ VK_CALL(vkCmdPipelineBarrier(list->vk_command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+ VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &barrier, 0, NULL, 0, NULL));
+ list->workaround_state.has_pending_color_write = false;
+ WARN("Injecting workaround barrier!\n");
+ }
+}
+
static void STDMETHODCALLTYPE d3d12_command_list_Dispatch(d3d12_command_list_iface *iface,
UINT x, UINT y, UINT z)
{
@@ -5554,6 +5583,8 @@ static void STDMETHODCALLTYPE d3d12_command_list_Dispatch(d3d12_command_list_ifa
return;
}
+ d3d12_command_list_workaround_handle_missing_color_compute_barriers(list);
+
if (!list->predicate_va)
VK_CALL(vkCmdDispatch(list->vk_command_buffer, x, y, z));
else
@@ -6952,6 +6983,9 @@ static void STDMETHODCALLTYPE d3d12_command_list_ResourceBarrier(d3d12_command_l
VkImageLayout old_layout = VK_IMAGE_LAYOUT_UNDEFINED;
VkImageLayout new_layout = VK_IMAGE_LAYOUT_UNDEFINED;
+ if (transition->StateBefore == D3D12_RESOURCE_STATE_RENDER_TARGET)
+ list->workaround_state.has_pending_color_write = false;
+
if (!is_valid_resource_state(transition->StateBefore))
{
d3d12_command_list_mark_as_invalid(list,
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index 2b7ae2e5..e4f0c6fc 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -478,7 +478,9 @@ struct vkd3d_instance_application_meta
static const struct vkd3d_instance_application_meta application_override[] = {
/* MSVC fails to compile empty array. */
{ VKD3D_STRING_COMPARE_EXACT, "GravityMark.exe", VKD3D_CONFIG_FLAG_FORCE_MINIMUM_SUBGROUP_SIZE, 0 },
- { VKD3D_STRING_COMPARE_EXACT, "Deathloop.exe", VKD3D_CONFIG_FLAG_IGNORE_RTV_HOST_VISIBLE, 0 },
+ /* The game forgets to do a barrier when going from render pass to compute. */
+ { VKD3D_STRING_COMPARE_EXACT, "Deathloop.exe",
+ VKD3D_CONFIG_FLAG_IGNORE_RTV_HOST_VISIBLE | VKD3D_CONFIG_FLAG_WORKAROUND_MISSING_COLOR_COMPUTE_BARRIERS, 0 },
/* Shadow of the Tomb Raider (750920).
* Invariant workarounds actually cause more issues than they resolve on NV.
* RADV already has workarounds by default.
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index 5e1d650b..e9e117bb 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -1973,6 +1973,14 @@ struct d3d12_command_list
size_t dsv_resource_tracking_count;
size_t dsv_resource_tracking_size;
+ /* Hackery needed for game workarounds. */
+ struct
+ {
+ /* Used to keep track of COLOR write -> COMPUTE where game forget to insert barrier
+ * before the dispatch. */
+ bool has_pending_color_write;
+ } workaround_state;
+
struct vkd3d_private_store private_store;
};