vkd3d: Remove deferred clears.
Emitting render pass clears while we're in the process of starting a render pass overrides dsv layout tracking info. Signed-off-by: Philip Rebohle <philip.rebohle@tu-dortmund.de>
This commit is contained in:
parent
b05145b421
commit
7fea3527ed
|
@ -2703,28 +2703,6 @@ static void d3d12_command_list_clear_attachment_pass(struct d3d12_command_list *
|
|||
VK_CALL(vkCmdEndRenderPass2KHR(list->vk_command_buffer, &subpass_end_info));
|
||||
}
|
||||
|
||||
static void d3d12_command_list_clear_attachment_deferred(struct d3d12_command_list *list, unsigned int attachment_idx,
|
||||
VkImageAspectFlags clear_aspects, const VkClearValue *clear_value)
|
||||
{
|
||||
struct vkd3d_clear_state *clear_state = &list->clear_state;
|
||||
struct vkd3d_clear_attachment *attachment = &clear_state->attachments[attachment_idx];
|
||||
|
||||
/* If necessary, combine with previous clear so that e.g. a
|
||||
* depth-only clear does not override a stencil-only clear. */
|
||||
clear_state->attachment_mask |= 1u << attachment_idx;
|
||||
attachment->aspect_mask |= clear_aspects;
|
||||
attachment->discard_mask &= ~clear_aspects;
|
||||
|
||||
if (clear_aspects & VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
attachment->value.color = clear_value->color;
|
||||
|
||||
if (clear_aspects & VK_IMAGE_ASPECT_DEPTH_BIT)
|
||||
attachment->value.depthStencil.depth = clear_value->depthStencil.depth;
|
||||
|
||||
if (clear_aspects & VK_IMAGE_ASPECT_STENCIL_BIT)
|
||||
attachment->value.depthStencil.stencil = clear_value->depthStencil.stencil;
|
||||
}
|
||||
|
||||
static void d3d12_command_list_discard_attachment_barrier(struct d3d12_command_list *list,
|
||||
struct d3d12_resource *resource, const VkImageSubresourceLayers *subresource, bool is_bound)
|
||||
{
|
||||
|
@ -2772,144 +2750,6 @@ static void d3d12_command_list_discard_attachment_barrier(struct d3d12_command_l
|
|||
stages, stages, 0, 0, NULL, 0, NULL, 1, &barrier));
|
||||
}
|
||||
|
||||
static void d3d12_command_list_discard_attachment_deferred(struct d3d12_command_list *list,
|
||||
uint32_t attachment_idx, VkImageAspectFlags discard_aspects)
|
||||
{
|
||||
struct vkd3d_clear_state *clear_state = &list->clear_state;
|
||||
struct vkd3d_clear_attachment *attachment = &clear_state->attachments[attachment_idx];
|
||||
|
||||
clear_state->attachment_mask |= 1u << attachment_idx;
|
||||
attachment->aspect_mask &= ~discard_aspects;
|
||||
attachment->discard_mask |= discard_aspects;
|
||||
}
|
||||
|
||||
static bool d3d12_command_list_has_render_pass_rtv_clear(struct d3d12_command_list *list, unsigned int attachment_idx)
|
||||
{
|
||||
const struct d3d12_graphics_pipeline_state *graphics;
|
||||
|
||||
if (!d3d12_pipeline_state_is_graphics(list->state))
|
||||
return false;
|
||||
|
||||
graphics = &list->state->graphics;
|
||||
|
||||
return attachment_idx < graphics->rt_count &&
|
||||
!(graphics->null_attachment_mask & (1 << attachment_idx)) &&
|
||||
(list->clear_state.attachment_mask & (1 << attachment_idx));
|
||||
}
|
||||
|
||||
static bool d3d12_command_list_has_depth_stencil_view(struct d3d12_command_list *list);
|
||||
|
||||
static bool d3d12_command_list_has_render_pass_dsv_clear(struct d3d12_command_list *list)
|
||||
{
|
||||
struct vkd3d_clear_attachment *clear_attachment = &list->clear_state.attachments[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT];
|
||||
VkImageAspectFlags clear_aspects, write_aspects;
|
||||
|
||||
if (!d3d12_pipeline_state_is_graphics(list->state))
|
||||
return false;
|
||||
|
||||
if (!d3d12_command_list_has_depth_stencil_view(list))
|
||||
return false;
|
||||
|
||||
if (!(list->clear_state.attachment_mask & (1 << D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT)))
|
||||
return false;
|
||||
|
||||
/* If any of the aspects to clear are read-only in the render
|
||||
* pass, we have to perform the DSV clear in a separate pass. */
|
||||
write_aspects = vk_writable_aspects_from_image_layout(list->dsv_layout);
|
||||
clear_aspects = clear_attachment->aspect_mask | clear_attachment->discard_mask;
|
||||
return (write_aspects & clear_aspects) == clear_aspects;
|
||||
}
|
||||
|
||||
static void d3d12_command_list_emit_deferred_clear(struct d3d12_command_list *list, unsigned int attachment_idx)
|
||||
{
|
||||
struct vkd3d_clear_attachment *clear_attachment = &list->clear_state.attachments[attachment_idx];
|
||||
VkImageSubresourceLayers vk_subresource_layers;
|
||||
struct d3d12_resource *resource;
|
||||
struct vkd3d_view *view;
|
||||
|
||||
if (attachment_idx < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT)
|
||||
{
|
||||
resource = list->rtvs[attachment_idx].resource;
|
||||
view = list->rtvs[attachment_idx].view;
|
||||
}
|
||||
else
|
||||
{
|
||||
resource = list->dsv.resource;
|
||||
view = list->dsv.view;
|
||||
}
|
||||
|
||||
if (list->current_render_pass)
|
||||
{
|
||||
if (clear_attachment->aspect_mask)
|
||||
{
|
||||
d3d12_command_list_clear_attachment_inline(list, resource,
|
||||
view, attachment_idx, clear_attachment->aspect_mask,
|
||||
&clear_attachment->value, 0, NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (clear_attachment->aspect_mask)
|
||||
{
|
||||
d3d12_command_list_clear_attachment_pass(list, resource, view,
|
||||
clear_attachment->aspect_mask, &clear_attachment->value, 0, NULL,
|
||||
list->render_pass_suspended);
|
||||
}
|
||||
|
||||
if (clear_attachment->discard_mask)
|
||||
{
|
||||
vk_subresource_layers = vk_subresource_layers_from_view(view);
|
||||
|
||||
d3d12_command_list_discard_attachment_barrier(list, resource,
|
||||
&vk_subresource_layers, list->render_pass_suspended);
|
||||
}
|
||||
}
|
||||
|
||||
clear_attachment->aspect_mask = 0;
|
||||
clear_attachment->discard_mask = 0;
|
||||
}
|
||||
|
||||
static void d3d12_command_list_emit_render_pass_clears(struct d3d12_command_list *list, bool invert_mask)
|
||||
{
|
||||
struct vkd3d_clear_state *clear_state = &list->clear_state;
|
||||
uint64_t attachment_mask = 0;
|
||||
unsigned int i;
|
||||
|
||||
if (!clear_state->attachment_mask)
|
||||
return;
|
||||
|
||||
for (i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
|
||||
{
|
||||
if (d3d12_command_list_has_render_pass_rtv_clear(list, i))
|
||||
attachment_mask |= 1 << i;
|
||||
}
|
||||
|
||||
if (d3d12_command_list_has_render_pass_dsv_clear(list))
|
||||
attachment_mask |= 1 << D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT;
|
||||
|
||||
if (invert_mask)
|
||||
attachment_mask = (~attachment_mask) & clear_state->attachment_mask;
|
||||
|
||||
clear_state->attachment_mask &= ~attachment_mask;
|
||||
|
||||
while (attachment_mask)
|
||||
{
|
||||
unsigned int attachment_idx = vkd3d_bitmask_iter64(&attachment_mask);
|
||||
d3d12_command_list_emit_deferred_clear(list, attachment_idx);
|
||||
}
|
||||
}
|
||||
|
||||
static void d3d12_command_list_flush_deferred_clears(struct d3d12_command_list *list)
|
||||
{
|
||||
struct vkd3d_clear_state *clear_state = &list->clear_state;
|
||||
|
||||
while (clear_state->attachment_mask)
|
||||
{
|
||||
unsigned int attachment_idx = vkd3d_bitmask_iter64(&clear_state->attachment_mask);
|
||||
d3d12_command_list_emit_deferred_clear(list, attachment_idx);
|
||||
}
|
||||
}
|
||||
|
||||
enum vkd3d_render_pass_transition_mode
|
||||
{
|
||||
VKD3D_RENDER_PASS_TRANSITION_MODE_BEGIN,
|
||||
|
@ -2930,7 +2770,7 @@ static bool d3d12_resource_requires_shader_visibility_after_transition(
|
|||
|
||||
static VkPipelineStageFlags vk_render_pass_barrier_from_view(struct d3d12_command_list *list,
|
||||
const struct vkd3d_view *view, const struct d3d12_resource *resource,
|
||||
enum vkd3d_render_pass_transition_mode mode, VkImageLayout layout, bool clear, VkImageMemoryBarrier *vk_barrier)
|
||||
enum vkd3d_render_pass_transition_mode mode, VkImageLayout layout, VkImageMemoryBarrier *vk_barrier)
|
||||
{
|
||||
VkImageLayout outside_render_pass_layout;
|
||||
VkPipelineStageFlags stages;
|
||||
|
@ -2959,11 +2799,6 @@ static VkPipelineStageFlags vk_render_pass_barrier_from_view(struct d3d12_comman
|
|||
vk_barrier->oldLayout = outside_render_pass_layout;
|
||||
vk_barrier->newLayout = layout;
|
||||
|
||||
/* Ignore 3D images as re-initializing those may cause us to
|
||||
* discard the entire image, not just the layers to clear. */
|
||||
if (clear && resource->desc.Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D)
|
||||
vk_barrier->oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
/* If we're transitioning into depth state and we could potentially read
|
||||
* (we cannot know this here),
|
||||
* shader might want to read from it as well, so we have to make that visible here
|
||||
|
@ -3029,7 +2864,6 @@ static void d3d12_command_list_emit_render_pass_transition(struct d3d12_command_
|
|||
VkPipelineStageFlags stage_mask = 0;
|
||||
VkPipelineStageFlags new_stages;
|
||||
struct d3d12_rtv_desc *dsv;
|
||||
bool do_clear = false;
|
||||
uint32_t i, j;
|
||||
|
||||
for (i = 0, j = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
|
||||
|
@ -3039,11 +2873,8 @@ static void d3d12_command_list_emit_render_pass_transition(struct d3d12_command_
|
|||
if (!rtv->view)
|
||||
continue;
|
||||
|
||||
if (mode == VKD3D_RENDER_PASS_TRANSITION_MODE_BEGIN)
|
||||
do_clear = d3d12_command_list_has_render_pass_rtv_clear(list, i);
|
||||
|
||||
if ((new_stages = vk_render_pass_barrier_from_view(list, rtv->view, rtv->resource,
|
||||
mode, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, do_clear, &vk_image_barriers[j])))
|
||||
mode, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, &vk_image_barriers[j])))
|
||||
{
|
||||
stage_mask |= new_stages;
|
||||
j++;
|
||||
|
@ -3056,11 +2887,8 @@ static void d3d12_command_list_emit_render_pass_transition(struct d3d12_command_
|
|||
|
||||
if (dsv->view && list->dsv_layout)
|
||||
{
|
||||
if (mode == VKD3D_RENDER_PASS_TRANSITION_MODE_BEGIN)
|
||||
do_clear = d3d12_command_list_has_render_pass_dsv_clear(list);
|
||||
|
||||
if ((new_stages = vk_render_pass_barrier_from_view(list, dsv->view, dsv->resource,
|
||||
mode, list->dsv_layout, do_clear, &vk_image_barriers[j])))
|
||||
mode, list->dsv_layout, &vk_image_barriers[j])))
|
||||
{
|
||||
stage_mask |= new_stages;
|
||||
j++;
|
||||
|
@ -3604,13 +3432,6 @@ static void d3d12_command_list_end_current_render_pass(struct d3d12_command_list
|
|||
list->render_pass_suspended = suspend && (list->current_render_pass || list->render_pass_suspended);
|
||||
list->current_render_pass = VK_NULL_HANDLE;
|
||||
|
||||
/* Emit pending deferred clears. This can happen if
|
||||
* no draw got executed after the clear operation.
|
||||
* We are sensitive to list->render_pass_suspended here
|
||||
* so make sure we update that before doing deferred clears
|
||||
* since we need to know which image layouts to use. */
|
||||
d3d12_command_list_flush_deferred_clears(list);
|
||||
|
||||
if (list->xfb_enabled)
|
||||
{
|
||||
VkMemoryBarrier vk_barrier;
|
||||
|
@ -4392,7 +4213,6 @@ static void d3d12_command_list_reset_api_state(struct d3d12_command_list *list,
|
|||
|
||||
memset(list->rtvs, 0, sizeof(list->rtvs));
|
||||
memset(&list->dsv, 0, sizeof(list->dsv));
|
||||
memset(&list->clear_state, 0, sizeof(list->clear_state));
|
||||
list->dsv_layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
list->dsv_plane_optimal_mask = 0;
|
||||
list->fb_width = 0;
|
||||
|
@ -5482,11 +5302,6 @@ static bool d3d12_command_list_begin_render_pass(struct d3d12_command_list *list
|
|||
vk_render_pass = list->pso_render_pass;
|
||||
assert(vk_render_pass);
|
||||
|
||||
/* Emit deferred clears that we cannot clear inside the
|
||||
* render pass, e.g. when the attachments to clear are
|
||||
* not included in the current pipeline's render pass. */
|
||||
d3d12_command_list_emit_render_pass_clears(list, true);
|
||||
|
||||
if (!list->render_pass_suspended)
|
||||
d3d12_command_list_emit_render_pass_transition(list, VKD3D_RENDER_PASS_TRANSITION_MODE_BEGIN);
|
||||
|
||||
|
@ -5509,9 +5324,6 @@ static bool d3d12_command_list_begin_render_pass(struct d3d12_command_list *list
|
|||
|
||||
list->current_render_pass = vk_render_pass;
|
||||
|
||||
/* Emit deferred clears with vkCmdClearAttachment */
|
||||
d3d12_command_list_emit_render_pass_clears(list, false);
|
||||
|
||||
graphics = &list->state->graphics;
|
||||
if (graphics->xfb_enabled)
|
||||
{
|
||||
|
@ -7976,7 +7788,7 @@ static void d3d12_command_list_clear_attachment(struct d3d12_command_list *list,
|
|||
if (attachment_idx == D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT && list->current_render_pass)
|
||||
writable = (vk_writable_aspects_from_image_layout(list->dsv_layout) & clear_aspects) == clear_aspects;
|
||||
|
||||
if (attachment_idx < 0 || (!list->current_render_pass && !full_clear) || !writable)
|
||||
if (attachment_idx < 0 || !list->current_render_pass || !writable)
|
||||
{
|
||||
/* View currently not bound as a render target, or bound but
|
||||
* the render pass isn't active and we're only going to clear
|
||||
|
@ -7986,21 +7798,13 @@ static void d3d12_command_list_clear_attachment(struct d3d12_command_list *list,
|
|||
d3d12_command_list_clear_attachment_pass(list, resource, view,
|
||||
clear_aspects, clear_value, rect_count, rects, false);
|
||||
}
|
||||
else if (list->current_render_pass)
|
||||
else
|
||||
{
|
||||
/* View bound and render pass active, just emit the clear */
|
||||
d3d12_command_list_clear_attachment_inline(list, resource, view,
|
||||
attachment_idx, clear_aspects, clear_value,
|
||||
rect_count, rects);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* View bound but render pass not active, and we'll clear
|
||||
* the entire image. Defer the clear until we begin the
|
||||
* render pass to avoid unnecessary barriers. */
|
||||
d3d12_command_list_clear_attachment_deferred(list, attachment_idx,
|
||||
clear_aspects, clear_value);
|
||||
}
|
||||
}
|
||||
|
||||
static void STDMETHODCALLTYPE d3d12_command_list_ClearDepthStencilView(d3d12_command_list_iface *iface,
|
||||
|
@ -8440,9 +8244,9 @@ static void STDMETHODCALLTYPE d3d12_command_list_DiscardResource(d3d12_command_l
|
|||
VkImageSubresourceLayers vk_subresource_layers;
|
||||
unsigned int resource_subresource_count;
|
||||
VkImageSubresource vk_subresource;
|
||||
bool full_discard, is_bound;
|
||||
D3D12_RECT full_rect;
|
||||
int attachment_idx;
|
||||
bool full_discard;
|
||||
|
||||
TRACE("iface %p, resource %p, region %p.\n", iface, resource, region);
|
||||
|
||||
|
@ -8510,23 +8314,9 @@ static void STDMETHODCALLTYPE d3d12_command_list_DiscardResource(d3d12_command_l
|
|||
vk_subresource_layers = vk_subresource_layers_from_subresource(&vk_subresource);
|
||||
attachment_idx = d3d12_command_list_find_attachment_view(list, texture, &vk_subresource_layers);
|
||||
|
||||
if (attachment_idx < 0)
|
||||
{
|
||||
/* Image is not currently bound as an attachment */
|
||||
d3d12_command_list_end_current_render_pass(list, false);
|
||||
d3d12_command_list_discard_attachment_barrier(list, texture, &vk_subresource_layers, false);
|
||||
}
|
||||
else if (list->current_render_pass || list->render_pass_suspended)
|
||||
{
|
||||
/* Image is bound and the render pass is active */
|
||||
d3d12_command_list_end_current_render_pass(list, true);
|
||||
d3d12_command_list_discard_attachment_barrier(list, texture, &vk_subresource_layers, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Image is bound, but the render pass is not active */
|
||||
d3d12_command_list_discard_attachment_deferred(list, attachment_idx, vk_subresource.aspectMask);
|
||||
}
|
||||
is_bound = attachment_idx >= 0 && (list->current_render_pass || list->render_pass_suspended);
|
||||
d3d12_command_list_end_current_render_pass(list, is_bound);
|
||||
d3d12_command_list_discard_attachment_barrier(list, texture, &vk_subresource_layers, is_bound);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1684,19 +1684,6 @@ struct vkd3d_dynamic_state
|
|||
/* ID3D12CommandList */
|
||||
typedef ID3D12GraphicsCommandList5 d3d12_command_list_iface;
|
||||
|
||||
struct vkd3d_clear_attachment
|
||||
{
|
||||
VkImageAspectFlags aspect_mask;
|
||||
VkImageAspectFlags discard_mask;
|
||||
VkClearValue value;
|
||||
};
|
||||
|
||||
struct vkd3d_clear_state
|
||||
{
|
||||
uint64_t attachment_mask;
|
||||
struct vkd3d_clear_attachment attachments[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT + 1];
|
||||
};
|
||||
|
||||
enum vkd3d_initial_transition_type
|
||||
{
|
||||
VKD3D_INITIAL_TRANSITION_TYPE_RESOURCE,
|
||||
|
@ -1780,7 +1767,6 @@ struct d3d12_command_list
|
|||
|
||||
struct d3d12_rtv_desc rtvs[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT];
|
||||
struct d3d12_rtv_desc dsv;
|
||||
struct vkd3d_clear_state clear_state;
|
||||
uint32_t dsv_plane_optimal_mask;
|
||||
VkImageLayout dsv_layout;
|
||||
unsigned int fb_width;
|
||||
|
|
Loading…
Reference in New Issue