mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-12-15 08:03:30 -08:00
vkd3d: Add barriers between render passes to the same image.
This commit is contained in:
Notes:
Henri Verbeet
2025-11-24 19:12:52 +01:00
Approved-by: Giovanni Mascellani (@giomasce) Approved-by: Henri Verbeet (@hverbeet) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1825
@@ -31,6 +31,43 @@ static void d3d12_command_queue_submit_locked(struct d3d12_command_queue *queue)
|
||||
static HRESULT d3d12_command_queue_flush_ops(struct d3d12_command_queue *queue, bool *flushed_any);
|
||||
static HRESULT d3d12_command_queue_flush_ops_locked(struct d3d12_command_queue *queue, bool *flushed_any);
|
||||
|
||||
static void vkd3d_resource_list_cleanup(struct vkd3d_resource_list *list)
|
||||
{
|
||||
vkd3d_free(list->resources);
|
||||
}
|
||||
|
||||
static void vkd3d_resource_list_init(struct vkd3d_resource_list *list)
|
||||
{
|
||||
list->resources = NULL;
|
||||
list->count = 0;
|
||||
list->capacity = 0;
|
||||
}
|
||||
|
||||
static bool vkd3d_resource_list_contains(const struct vkd3d_resource_list *list, struct d3d12_resource *resource)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < list->count; i++)
|
||||
{
|
||||
if (list->resources[i] == resource)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void vkd3d_resource_list_append(struct vkd3d_resource_list *list, struct d3d12_resource *resource)
|
||||
{
|
||||
if (!vkd3d_array_reserve((void **)&list->resources, &list->capacity, list->count + 1, sizeof(*list->resources)))
|
||||
ERR("Failed to grow resource list.\n");
|
||||
list->resources[list->count++] = resource;
|
||||
}
|
||||
|
||||
static void vkd3d_resource_list_clear(struct vkd3d_resource_list *list)
|
||||
{
|
||||
list->count = 0;
|
||||
}
|
||||
|
||||
static void vkd3d_null_event_signal(struct vkd3d_null_event *e)
|
||||
{
|
||||
vkd3d_mutex_lock(&e->mutex);
|
||||
@@ -2533,6 +2570,9 @@ static ULONG STDMETHODCALLTYPE d3d12_command_list_Release(ID3D12GraphicsCommandL
|
||||
vkd3d_pipeline_bindings_cleanup(&list->pipeline_bindings[VKD3D_PIPELINE_BIND_POINT_COMPUTE]);
|
||||
vkd3d_pipeline_bindings_cleanup(&list->pipeline_bindings[VKD3D_PIPELINE_BIND_POINT_GRAPHICS]);
|
||||
|
||||
vkd3d_resource_list_cleanup(&list->rtv_resources_since_last_barrier);
|
||||
vkd3d_resource_list_cleanup(&list->dsv_resources_since_last_barrier);
|
||||
|
||||
vkd3d_free(list);
|
||||
|
||||
d3d12_device_release(device);
|
||||
@@ -2659,6 +2699,10 @@ static void d3d12_command_list_reset_state(struct d3d12_command_list *list,
|
||||
list->fb_width = 0;
|
||||
list->fb_height = 0;
|
||||
list->fb_layer_count = 0;
|
||||
memset(list->rtv_resources, 0, sizeof(list->rtv_resources));
|
||||
list->dsv_resource = NULL;
|
||||
vkd3d_resource_list_clear(&list->rtv_resources_since_last_barrier);
|
||||
vkd3d_resource_list_clear(&list->dsv_resources_since_last_barrier);
|
||||
|
||||
list->xfb_enabled = false;
|
||||
list->has_depth_bounds = false;
|
||||
@@ -3469,6 +3513,82 @@ static bool d3d12_command_list_update_compute_state(struct d3d12_command_list *l
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Add a barrier to prevent hazards between multiple render passes to the same image. */
|
||||
static void d3d12_command_list_emit_rt_barrier(struct d3d12_command_list *list, bool colour, bool depth)
|
||||
{
|
||||
const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
|
||||
VkMemoryBarrier barrier = { VK_STRUCTURE_TYPE_MEMORY_BARRIER };
|
||||
VkPipelineStageFlags srcStage = 0;
|
||||
VkPipelineStageFlags dstStage = 0;
|
||||
|
||||
if (colour)
|
||||
{
|
||||
srcStage |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
dstStage |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
barrier.srcAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
barrier.dstAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
|
||||
}
|
||||
|
||||
if (depth)
|
||||
{
|
||||
srcStage |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||
dstStage |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||
barrier.srcAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||
barrier.dstAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
|
||||
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
|
||||
}
|
||||
|
||||
VK_CALL(vkCmdPipelineBarrier(list->vk_command_buffer, srcStage, dstStage,
|
||||
VK_DEPENDENCY_BY_REGION_BIT, 1, &barrier, 0, NULL, 0, NULL));
|
||||
if (colour)
|
||||
vkd3d_resource_list_clear(&list->rtv_resources_since_last_barrier);
|
||||
if (depth)
|
||||
vkd3d_resource_list_clear(&list->rtv_resources_since_last_barrier);
|
||||
}
|
||||
|
||||
static void d3d12_command_list_check_render_pass_hazards(struct d3d12_command_list *list)
|
||||
{
|
||||
struct d3d12_graphics_pipeline_state *graphics = &list->state->u.graphics;
|
||||
bool rtv_hazard = false;
|
||||
bool dsv_hazard = false;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < graphics->rt_count; ++i)
|
||||
{
|
||||
if (graphics->null_attachment_mask & (1u << i))
|
||||
continue;
|
||||
|
||||
if (!list->rtv_resources[i])
|
||||
continue;
|
||||
|
||||
if (vkd3d_resource_list_contains(&list->rtv_resources_since_last_barrier, list->rtv_resources[i]))
|
||||
{
|
||||
rtv_hazard = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dsv_hazard = d3d12_command_list_has_depth_stencil_view(list) && list->dsv_resource
|
||||
&& vkd3d_resource_list_contains(&list->dsv_resources_since_last_barrier, list->dsv_resource);
|
||||
|
||||
if (rtv_hazard || dsv_hazard)
|
||||
d3d12_command_list_emit_rt_barrier(list, rtv_hazard, dsv_hazard);
|
||||
|
||||
for (i = 0; i < graphics->rt_count; ++i)
|
||||
{
|
||||
if (graphics->null_attachment_mask & (1u << i))
|
||||
continue;
|
||||
|
||||
if (!list->rtv_resources[i])
|
||||
continue;
|
||||
|
||||
vkd3d_resource_list_append(&list->rtv_resources_since_last_barrier, list->rtv_resources[i]);
|
||||
}
|
||||
|
||||
if (d3d12_command_list_has_depth_stencil_view(list) && list->dsv_resource)
|
||||
vkd3d_resource_list_append(&list->dsv_resources_since_last_barrier, list->dsv_resource);
|
||||
}
|
||||
|
||||
static bool d3d12_command_list_begin_render_pass(struct d3d12_command_list *list)
|
||||
{
|
||||
const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
|
||||
@@ -3486,6 +3606,8 @@ static bool d3d12_command_list_begin_render_pass(struct d3d12_command_list *list
|
||||
if (list->current_render_pass != VK_NULL_HANDLE)
|
||||
return true;
|
||||
|
||||
d3d12_command_list_check_render_pass_hazards(list);
|
||||
|
||||
vk_render_pass = list->pso_render_pass;
|
||||
VKD3D_ASSERT(vk_render_pass);
|
||||
|
||||
@@ -5137,6 +5259,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_OMSetRenderTargets(ID3D12Graphi
|
||||
{
|
||||
WARN("RTV descriptor %u is not initialized.\n", i);
|
||||
list->rtvs[i] = VK_NULL_HANDLE;
|
||||
list->rtv_resources[i] = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -5150,6 +5273,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_OMSetRenderTargets(ID3D12Graphi
|
||||
}
|
||||
|
||||
list->rtvs[i] = view->v.u.vk_image_view;
|
||||
list->rtv_resources[i] = rtv_desc->resource;
|
||||
list->fb_width = max(list->fb_width, rtv_desc->width);
|
||||
list->fb_height = max(list->fb_height, rtv_desc->height);
|
||||
list->fb_layer_count = max(list->fb_layer_count, rtv_desc->layer_count);
|
||||
@@ -5171,9 +5295,11 @@ static void STDMETHODCALLTYPE d3d12_command_list_OMSetRenderTargets(ID3D12Graphi
|
||||
{
|
||||
WARN("Failed to add view.\n");
|
||||
list->dsv = VK_NULL_HANDLE;
|
||||
list->dsv_resource = NULL;
|
||||
}
|
||||
|
||||
list->dsv = view->v.u.vk_image_view;
|
||||
list->dsv_resource = dsv_desc->resource;
|
||||
list->fb_width = max(list->fb_width, dsv_desc->width);
|
||||
list->fb_height = max(list->fb_height, dsv_desc->height);
|
||||
list->fb_layer_count = max(list->fb_layer_count, dsv_desc->layer_count);
|
||||
@@ -5209,8 +5335,6 @@ static void d3d12_command_list_clear(struct d3d12_command_list *list,
|
||||
unsigned int i;
|
||||
VkResult vr;
|
||||
|
||||
d3d12_command_list_end_current_render_pass(list);
|
||||
|
||||
if (!rect_count)
|
||||
{
|
||||
full_rect.top = 0;
|
||||
@@ -5344,6 +5468,12 @@ static void STDMETHODCALLTYPE d3d12_command_list_ClearDepthStencilView(ID3D12Gra
|
||||
ds_reference.attachment = 0;
|
||||
ds_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
|
||||
d3d12_command_list_end_current_render_pass(list);
|
||||
|
||||
if (vkd3d_resource_list_contains(&list->dsv_resources_since_last_barrier, dsv_desc->resource))
|
||||
d3d12_command_list_emit_rt_barrier(list, false, true);
|
||||
vkd3d_resource_list_append(&list->dsv_resources_since_last_barrier, dsv_desc->resource);
|
||||
|
||||
d3d12_command_list_clear(list, &attachment_desc, NULL, &ds_reference,
|
||||
dsv_desc->view, dsv_desc->width, dsv_desc->height, dsv_desc->layer_count,
|
||||
&clear_value, rect_count, rects);
|
||||
@@ -5398,6 +5528,12 @@ static void STDMETHODCALLTYPE d3d12_command_list_ClearRenderTargetView(ID3D12Gra
|
||||
clear_value.color.float32[3] = color[3];
|
||||
}
|
||||
|
||||
d3d12_command_list_end_current_render_pass(list);
|
||||
|
||||
if (vkd3d_resource_list_contains(&list->rtv_resources_since_last_barrier, rtv_desc->resource))
|
||||
d3d12_command_list_emit_rt_barrier(list, true, false);
|
||||
vkd3d_resource_list_append(&list->rtv_resources_since_last_barrier, rtv_desc->resource);
|
||||
|
||||
d3d12_command_list_clear(list, &attachment_desc, &color_reference, NULL,
|
||||
rtv_desc->view, rtv_desc->width, rtv_desc->height, rtv_desc->layer_count,
|
||||
&clear_value, rect_count, rects);
|
||||
@@ -6395,6 +6531,9 @@ static HRESULT d3d12_command_list_init(struct d3d12_command_list *list,
|
||||
|
||||
list->type = type;
|
||||
|
||||
vkd3d_resource_list_init(&list->rtv_resources_since_last_barrier);
|
||||
vkd3d_resource_list_init(&list->dsv_resources_since_last_barrier);
|
||||
|
||||
if (FAILED(hr = vkd3d_private_store_init(&list->private_store)))
|
||||
return hr;
|
||||
|
||||
|
||||
@@ -1277,6 +1277,13 @@ enum vkd3d_pipeline_bind_point
|
||||
VKD3D_PIPELINE_BIND_POINT_COUNT = 0x2,
|
||||
};
|
||||
|
||||
struct vkd3d_resource_list
|
||||
{
|
||||
struct d3d12_resource **resources;
|
||||
size_t count;
|
||||
size_t capacity;
|
||||
};
|
||||
|
||||
/* ID3D12CommandList */
|
||||
struct d3d12_command_list
|
||||
{
|
||||
@@ -1302,6 +1309,13 @@ struct d3d12_command_list
|
||||
unsigned int fb_layer_count;
|
||||
VkFormat dsv_format;
|
||||
|
||||
/* Resources for views bound to d3d12 state */
|
||||
struct d3d12_resource *rtv_resources[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT];
|
||||
struct d3d12_resource *dsv_resource;
|
||||
/* Resources bound since the last pipeline barrier */
|
||||
struct vkd3d_resource_list rtv_resources_since_last_barrier;
|
||||
struct vkd3d_resource_list dsv_resources_since_last_barrier;
|
||||
|
||||
bool xfb_enabled;
|
||||
bool has_depth_bounds;
|
||||
bool is_predicated;
|
||||
|
||||
Reference in New Issue
Block a user