vulkan/render_pass: Add an optimization for UNDEFINED+LOAD_OP_CLEAR
Reviewed-by: Ivan Briano <ivan.briano@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14961>
This commit is contained in:
@@ -982,6 +982,110 @@ transition_image_range(const struct vk_image_view *image_view,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
can_use_attachment_initial_layout(struct vk_command_buffer *cmd_buffer,
|
||||||
|
uint32_t att_idx,
|
||||||
|
uint32_t view_mask,
|
||||||
|
VkImageLayout *layout_out,
|
||||||
|
VkImageLayout *stencil_layout_out)
|
||||||
|
{
|
||||||
|
const struct vk_render_pass *pass = cmd_buffer->render_pass;
|
||||||
|
const struct vk_framebuffer *framebuffer = cmd_buffer->framebuffer;
|
||||||
|
const struct vk_render_pass_attachment *rp_att = &pass->attachments[att_idx];
|
||||||
|
struct vk_attachment_state *att_state = &cmd_buffer->attachments[att_idx];
|
||||||
|
const struct vk_image_view *image_view = att_state->image_view;
|
||||||
|
|
||||||
|
if ((rp_att->aspects & ~VK_IMAGE_ASPECT_STENCIL_BIT) &&
|
||||||
|
rp_att->load_op != VK_ATTACHMENT_LOAD_OP_CLEAR)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ((rp_att->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) &&
|
||||||
|
rp_att->stencil_load_op != VK_ATTACHMENT_LOAD_OP_CLEAR)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (cmd_buffer->render_area.offset.x != 0 ||
|
||||||
|
cmd_buffer->render_area.offset.y != 0 ||
|
||||||
|
cmd_buffer->render_area.extent.width != image_view->extent.width ||
|
||||||
|
cmd_buffer->render_area.extent.height != image_view->extent.height)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (image_view->image->image_type == VK_IMAGE_TYPE_3D) {
|
||||||
|
/* For 3D images, the view has to be the whole thing */
|
||||||
|
if (image_view->base_array_layer != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (pass->is_multiview) {
|
||||||
|
if (!util_is_power_of_two_or_zero(view_mask + 1) ||
|
||||||
|
util_last_bit(view_mask) != image_view->layer_count)
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (framebuffer->layers != image_view->layer_count)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finally, check if the entire thing is undefined. It's ok to smash the
|
||||||
|
* view_mask now as the only thing using it will be the loop below.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* 3D is stupidly special. See transition_attachment() */
|
||||||
|
if (image_view->image->image_type == VK_IMAGE_TYPE_3D)
|
||||||
|
view_mask = 1;
|
||||||
|
|
||||||
|
VkImageLayout layout = VK_IMAGE_LAYOUT_MAX_ENUM;
|
||||||
|
VkImageLayout stencil_layout = VK_IMAGE_LAYOUT_MAX_ENUM;
|
||||||
|
|
||||||
|
assert(view_mask != 0);
|
||||||
|
u_foreach_bit(view, view_mask) {
|
||||||
|
assert(view >= 0 && view < MESA_VK_MAX_MULTIVIEW_VIEW_COUNT);
|
||||||
|
struct vk_attachment_view_state *att_view_state = &att_state->views[view];
|
||||||
|
|
||||||
|
if (rp_att->aspects & ~VK_IMAGE_ASPECT_STENCIL_BIT) {
|
||||||
|
if (layout == VK_IMAGE_LAYOUT_MAX_ENUM)
|
||||||
|
layout = att_view_state->layout;
|
||||||
|
else if (layout != att_view_state->layout)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rp_att->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
|
||||||
|
if (stencil_layout == VK_IMAGE_LAYOUT_MAX_ENUM)
|
||||||
|
stencil_layout = att_view_state->stencil_layout;
|
||||||
|
else if (stencil_layout != att_view_state->stencil_layout)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layout != VK_IMAGE_LAYOUT_MAX_ENUM)
|
||||||
|
*layout_out = layout;
|
||||||
|
else if (layout_out != NULL)
|
||||||
|
*layout_out = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
|
||||||
|
if (stencil_layout != VK_IMAGE_LAYOUT_MAX_ENUM)
|
||||||
|
*stencil_layout_out = stencil_layout;
|
||||||
|
else if (stencil_layout_out != NULL)
|
||||||
|
*stencil_layout_out = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_attachment_layout(struct vk_command_buffer *cmd_buffer,
|
||||||
|
uint32_t att_idx,
|
||||||
|
uint32_t view_mask,
|
||||||
|
VkImageLayout layout,
|
||||||
|
VkImageLayout stencil_layout)
|
||||||
|
{
|
||||||
|
struct vk_attachment_state *att_state = &cmd_buffer->attachments[att_idx];
|
||||||
|
|
||||||
|
u_foreach_bit(view, view_mask) {
|
||||||
|
assert(view >= 0 && view < MESA_VK_MAX_MULTIVIEW_VIEW_COUNT);
|
||||||
|
struct vk_attachment_view_state *att_view_state = &att_state->views[view];
|
||||||
|
|
||||||
|
att_view_state->layout = layout;
|
||||||
|
att_view_state->stencil_layout = stencil_layout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
transition_attachment(struct vk_command_buffer *cmd_buffer,
|
transition_attachment(struct vk_command_buffer *cmd_buffer,
|
||||||
uint32_t att_idx,
|
uint32_t att_idx,
|
||||||
@@ -1170,6 +1274,9 @@ begin_subpass(struct vk_command_buffer *cmd_buffer,
|
|||||||
|
|
||||||
STACK_ARRAY(VkRenderingAttachmentInfo, color_attachments,
|
STACK_ARRAY(VkRenderingAttachmentInfo, color_attachments,
|
||||||
subpass->color_count);
|
subpass->color_count);
|
||||||
|
STACK_ARRAY(VkRenderingAttachmentInitialLayoutInfoMESA,
|
||||||
|
color_attachment_initial_layouts,
|
||||||
|
subpass->color_count);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < subpass->color_count; i++) {
|
for (uint32_t i = 0; i < subpass->color_count; i++) {
|
||||||
const struct vk_subpass_attachment *sp_att =
|
const struct vk_subpass_attachment *sp_att =
|
||||||
@@ -1201,6 +1308,27 @@ begin_subpass(struct vk_command_buffer *cmd_buffer,
|
|||||||
color_attachment->loadOp = rp_att->load_op;
|
color_attachment->loadOp = rp_att->load_op;
|
||||||
color_attachment->clearValue = att_state->clear_value;
|
color_attachment->clearValue = att_state->clear_value;
|
||||||
att_state->views_loaded |= subpass->view_mask;
|
att_state->views_loaded |= subpass->view_mask;
|
||||||
|
|
||||||
|
VkImageLayout initial_layout;
|
||||||
|
if (can_use_attachment_initial_layout(cmd_buffer,
|
||||||
|
sp_att->attachment,
|
||||||
|
subpass->view_mask,
|
||||||
|
&initial_layout, NULL) &&
|
||||||
|
sp_att->layout != initial_layout) {
|
||||||
|
assert(color_attachment->loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR);
|
||||||
|
|
||||||
|
VkRenderingAttachmentInitialLayoutInfoMESA *color_initial_layout =
|
||||||
|
&color_attachment_initial_layouts[i];
|
||||||
|
*color_initial_layout = (VkRenderingAttachmentInitialLayoutInfoMESA) {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INITIAL_LAYOUT_INFO_MESA,
|
||||||
|
.initialLayout = initial_layout,
|
||||||
|
};
|
||||||
|
__vk_append_struct(color_attachment, color_initial_layout);
|
||||||
|
|
||||||
|
set_attachment_layout(cmd_buffer, sp_att->attachment,
|
||||||
|
subpass->view_mask,
|
||||||
|
sp_att->layout, VK_IMAGE_LAYOUT_UNDEFINED);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* We've seen at least one of the views of this attachment before so
|
/* We've seen at least one of the views of this attachment before so
|
||||||
* we need to LOAD_OP_LOAD.
|
* we need to LOAD_OP_LOAD.
|
||||||
@@ -1250,6 +1378,12 @@ begin_subpass(struct vk_command_buffer *cmd_buffer,
|
|||||||
VkRenderingAttachmentInfo stencil_attachment = {
|
VkRenderingAttachmentInfo stencil_attachment = {
|
||||||
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
||||||
};
|
};
|
||||||
|
VkRenderingAttachmentInitialLayoutInfoMESA depth_initial_layout = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INITIAL_LAYOUT_INFO_MESA,
|
||||||
|
};
|
||||||
|
VkRenderingAttachmentInitialLayoutInfoMESA stencil_initial_layout = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INITIAL_LAYOUT_INFO_MESA,
|
||||||
|
};
|
||||||
|
|
||||||
if (subpass->depth_stencil_attachment != NULL) {
|
if (subpass->depth_stencil_attachment != NULL) {
|
||||||
const struct vk_subpass_attachment *sp_att =
|
const struct vk_subpass_attachment *sp_att =
|
||||||
@@ -1281,6 +1415,33 @@ begin_subpass(struct vk_command_buffer *cmd_buffer,
|
|||||||
stencil_attachment.loadOp = rp_att->stencil_load_op;
|
stencil_attachment.loadOp = rp_att->stencil_load_op;
|
||||||
stencil_attachment.clearValue = att_state->clear_value;
|
stencil_attachment.clearValue = att_state->clear_value;
|
||||||
att_state->views_loaded |= subpass->view_mask;
|
att_state->views_loaded |= subpass->view_mask;
|
||||||
|
|
||||||
|
VkImageLayout initial_layout, initial_stencil_layout;
|
||||||
|
if (can_use_attachment_initial_layout(cmd_buffer,
|
||||||
|
sp_att->attachment,
|
||||||
|
subpass->view_mask,
|
||||||
|
&initial_layout,
|
||||||
|
&initial_stencil_layout)) {
|
||||||
|
if ((rp_att->aspects & VK_IMAGE_ASPECT_DEPTH_BIT) &&
|
||||||
|
sp_att->layout != initial_layout) {
|
||||||
|
assert(depth_attachment.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR);
|
||||||
|
depth_initial_layout.initialLayout = initial_layout;
|
||||||
|
__vk_append_struct(&depth_attachment,
|
||||||
|
&depth_initial_layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rp_att->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) &&
|
||||||
|
sp_att->stencil_layout != initial_stencil_layout) {
|
||||||
|
assert(stencil_attachment.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR);
|
||||||
|
stencil_initial_layout.initialLayout = initial_stencil_layout;
|
||||||
|
__vk_append_struct(&stencil_attachment,
|
||||||
|
&stencil_initial_layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
set_attachment_layout(cmd_buffer, sp_att->attachment,
|
||||||
|
subpass->view_mask,
|
||||||
|
sp_att->layout, sp_att->stencil_layout);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* We've seen at least one of the views of this attachment before so
|
/* We've seen at least one of the views of this attachment before so
|
||||||
* we need to LOAD_OP_LOAD.
|
* we need to LOAD_OP_LOAD.
|
||||||
@@ -1533,6 +1694,7 @@ begin_subpass(struct vk_command_buffer *cmd_buffer,
|
|||||||
&rendering);
|
&rendering);
|
||||||
|
|
||||||
STACK_ARRAY_FINISH(color_attachments);
|
STACK_ARRAY_FINISH(color_attachments);
|
||||||
|
STACK_ARRAY_FINISH(color_attachment_initial_layouts);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@@ -49,6 +49,36 @@ typedef struct VkRenderingSelfDependencyInfoMESA {
|
|||||||
VkBool32 stencilSelfDependency;
|
VkBool32 stencilSelfDependency;
|
||||||
} VkRenderingSelfDependencyInfoMESA;
|
} VkRenderingSelfDependencyInfoMESA;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pseudo-extension struct that may be chained into VkRenderingAttachmentInfo
|
||||||
|
* to indicate an initial layout for the attachment. This is only allowed if
|
||||||
|
* all of the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. VkRenderingAttachmentInfo::loadOp == LOAD_OP_CLEAR
|
||||||
|
*
|
||||||
|
* 2. VkRenderingInfo::renderArea is tne entire image view LOD
|
||||||
|
*
|
||||||
|
* 3. For 3D image attachments, VkRenderingInfo::viewMask == 0 AND
|
||||||
|
* VkRenderingInfo::layerCount references the entire bound image view
|
||||||
|
* OR VkRenderingInfo::viewMask is dense (no holes) and references the
|
||||||
|
* entire bound image view. (2D and 2D array images have no such
|
||||||
|
* requirement.)
|
||||||
|
*
|
||||||
|
* If this struct is included in the pNext chain of a
|
||||||
|
* VkRenderingAttachmentInfo, the driver is responsible for transitioning the
|
||||||
|
* bound region of the image from
|
||||||
|
* VkRenderingAttachmentInitialLayoutInfoMESA::initialLayout to
|
||||||
|
* VkRenderingAttachmentInfo::imageLayout prior to rendering.
|
||||||
|
*/
|
||||||
|
typedef struct VkRenderingAttachmentInitialLayoutInfoMESA {
|
||||||
|
VkStructureType sType;
|
||||||
|
#define VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INITIAL_LAYOUT_INFO_MESA (VkStructureType)1000044901
|
||||||
|
const void* pNext;
|
||||||
|
|
||||||
|
/** Initial layout of the attachment */
|
||||||
|
VkImageLayout initialLayout;
|
||||||
|
} VkRenderingAttachmentInitialLayoutInfoMESA;
|
||||||
|
|
||||||
struct vk_subpass_attachment {
|
struct vk_subpass_attachment {
|
||||||
/** VkAttachmentReference2::attachment */
|
/** VkAttachmentReference2::attachment */
|
||||||
uint32_t attachment;
|
uint32_t attachment;
|
||||||
|
Reference in New Issue
Block a user