anv: implement the meat of VK_KHR_dynamic_rendering
Includes a fake framebuffer allocation that's necessary for the code we still use from the regular render passes. v3: (Lionel) - Reuse the attachment count from the faux render pass, remove now unused function - Add a cmd_buffer_end_rendering function to match begin_rendering, making use of the split stuff from end_subpass v4: (Lionel) - Don't bother with mark_images_writen or resolves on suspend case - Remove flush at the end of end_rendering, it's not needed Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13980>
This commit is contained in:
parent
4ad9ccd28a
commit
5d9e8bc9be
|
@ -6978,6 +6978,332 @@ void genX(CmdEndRenderPass2)(
|
|||
cmd_buffer->state.subpass = NULL;
|
||||
}
|
||||
|
||||
static VkAttachmentLoadOp
|
||||
get_effective_load_op(VkAttachmentLoadOp load_op, bool resuming)
|
||||
{
|
||||
if (load_op == VK_ATTACHMENT_LOAD_OP_CLEAR && resuming)
|
||||
load_op = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
return load_op;
|
||||
}
|
||||
|
||||
static VkResult
|
||||
genX(cmd_buffer_setup_attachments_dynrender)(struct anv_cmd_buffer *cmd_buffer,
|
||||
const VkRenderingInfoKHR *info)
|
||||
{
|
||||
struct anv_cmd_state *state = &cmd_buffer->state;
|
||||
uint32_t att_count = state->pass->attachment_count;
|
||||
bool suspending = info->flags & VK_RENDERING_SUSPENDING_BIT_KHR;
|
||||
bool resuming = info->flags & VK_RENDERING_RESUMING_BIT_KHR;
|
||||
VkResult result;
|
||||
|
||||
result = cmd_buffer_alloc_state_attachments(cmd_buffer, att_count);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
|
||||
for (uint32_t i = 0; i < info->colorAttachmentCount; ++i) {
|
||||
const VkRenderingAttachmentInfoKHR *att = &info->pColorAttachments[i];
|
||||
struct anv_attachment_state *att_state = &state->attachments[i];
|
||||
ANV_FROM_HANDLE(anv_image_view, iview, att->imageView);
|
||||
if (!iview)
|
||||
continue;
|
||||
|
||||
att_state->image_view = iview;
|
||||
att_state->current_layout = att->imageLayout;
|
||||
|
||||
att_state->aux_usage =
|
||||
anv_layout_to_aux_usage(&cmd_buffer->device->info, iview->image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||
att->imageLayout);
|
||||
|
||||
VkAttachmentLoadOp load_op = get_effective_load_op(att->loadOp, resuming);
|
||||
if (load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
|
||||
att_state->pending_clear_aspects = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
att_state->clear_value = att->clearValue;
|
||||
|
||||
const uint32_t num_layers = iview->planes[0].isl.array_len;
|
||||
att_state->pending_clear_views = (1 << num_layers) - 1;
|
||||
|
||||
att_state->fast_clear =
|
||||
anv_can_fast_clear_color_view(cmd_buffer->device, iview,
|
||||
att_state->current_layout,
|
||||
vk_to_isl_color(att_state->clear_value.color),
|
||||
info->layerCount,
|
||||
info->renderArea);
|
||||
|
||||
uint32_t level = iview->planes[0].isl.base_level;
|
||||
|
||||
uint32_t base_layer;
|
||||
if (iview->image->vk.image_type == VK_IMAGE_TYPE_3D)
|
||||
base_layer = 0;
|
||||
else
|
||||
base_layer = iview->planes[0].isl.base_array_layer;
|
||||
|
||||
clear_color_attachment(cmd_buffer, att_state, level,
|
||||
base_layer);
|
||||
}
|
||||
|
||||
if (!suspending && att->resolveMode != VK_RESOLVE_MODE_NONE) {
|
||||
state->attachments[i + info->colorAttachmentCount].image_view =
|
||||
anv_image_view_from_handle(att->resolveImageView);
|
||||
}
|
||||
}
|
||||
|
||||
const VkRenderingAttachmentInfoKHR *d_att = info->pDepthAttachment;
|
||||
const VkRenderingAttachmentInfoKHR *s_att = info->pStencilAttachment;
|
||||
const VkRenderingAttachmentInfoKHR *d_or_s_att = d_att ? d_att : s_att;
|
||||
if (d_or_s_att && d_or_s_att->imageView) {
|
||||
uint32_t ds_idx = att_count - 1;
|
||||
|
||||
if (!suspending && d_or_s_att->resolveImageView) {
|
||||
state->attachments[ds_idx].image_view =
|
||||
anv_image_view_from_handle(d_or_s_att->resolveImageView);
|
||||
ds_idx -= 1;
|
||||
}
|
||||
|
||||
struct anv_attachment_state *att_state = &state->attachments[ds_idx];
|
||||
|
||||
att_state->image_view =
|
||||
anv_image_view_from_handle(d_or_s_att->imageView);
|
||||
|
||||
VkImageAspectFlags clear_aspects = 0;
|
||||
if (d_att && d_att->imageView) {
|
||||
VkAttachmentLoadOp load_op = get_effective_load_op(d_att->loadOp, resuming);
|
||||
if (load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
|
||||
clear_aspects |= VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
}
|
||||
|
||||
att_state->aux_usage =
|
||||
anv_layout_to_aux_usage(&cmd_buffer->device->info,
|
||||
att_state->image_view->image,
|
||||
VK_IMAGE_ASPECT_DEPTH_BIT,
|
||||
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
|
||||
d_att->imageLayout);
|
||||
|
||||
att_state->current_layout = d_att->imageLayout;
|
||||
}
|
||||
if (s_att && s_att->imageView) {
|
||||
VkAttachmentLoadOp load_op = get_effective_load_op(s_att->loadOp, resuming);
|
||||
if (load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
|
||||
clear_aspects |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
}
|
||||
|
||||
att_state->current_stencil_layout = s_att->imageLayout;
|
||||
}
|
||||
|
||||
att_state->pending_clear_aspects = clear_aspects;
|
||||
att_state->clear_value = d_or_s_att->clearValue;
|
||||
|
||||
if (clear_aspects) {
|
||||
struct anv_image_view *iview = att_state->image_view;
|
||||
|
||||
const uint32_t num_layers = iview->planes[0].isl.array_len;
|
||||
att_state->pending_clear_views = (1 << num_layers) - 1;
|
||||
|
||||
att_state->fast_clear =
|
||||
anv_can_hiz_clear_ds_view(cmd_buffer->device, iview,
|
||||
att_state->current_layout,
|
||||
clear_aspects,
|
||||
att_state->clear_value.depthStencil.depth,
|
||||
info->renderArea);
|
||||
|
||||
uint32_t level = iview->planes[0].isl.base_level;
|
||||
|
||||
uint32_t base_layer, layer_count;
|
||||
if (iview->image->vk.image_type == VK_IMAGE_TYPE_3D) {
|
||||
base_layer = 0;
|
||||
layer_count = anv_minify(iview->image->vk.extent.depth, level);
|
||||
} else {
|
||||
base_layer = iview->planes[0].isl.base_array_layer;
|
||||
layer_count = info->layerCount;
|
||||
}
|
||||
|
||||
clear_depth_stencil_attachment(cmd_buffer, att_state, level,
|
||||
base_layer, layer_count);
|
||||
}
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_buffer_begin_rendering(struct anv_cmd_buffer *cmd_buffer,
|
||||
const VkRenderingInfoKHR *info)
|
||||
{
|
||||
struct anv_cmd_state *cmd_state = &cmd_buffer->state;
|
||||
struct anv_render_pass *pass = cmd_state->pass;
|
||||
struct anv_subpass *subpass = cmd_state->subpass;
|
||||
|
||||
cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_RENDER_TARGETS;
|
||||
|
||||
/* Our implementation of VK_KHR_multiview uses instancing to draw the
|
||||
* different views. If the client asks for instancing, we need to use the
|
||||
* Instance Data Step Rate to ensure that we repeat the client's
|
||||
* per-instance data once for each view. Since this bit is in
|
||||
* VERTEX_BUFFER_STATE on gfx7, we need to dirty vertex buffers at the top
|
||||
* of each subpass.
|
||||
*/
|
||||
if (GFX_VER == 7)
|
||||
cmd_buffer->state.gfx.vb_dirty |= ~0;
|
||||
|
||||
/* XXX: Does this still apply here */
|
||||
/* It is possible to start a render pass with an old pipeline. Because the
|
||||
* render pass and subpass index are both baked into the pipeline, this is
|
||||
* highly unlikely. In order to do so, it requires that you have a render
|
||||
* pass with a single subpass and that you use that render pass twice
|
||||
* back-to-back and use the same pipeline at the start of the second render
|
||||
* pass as at the end of the first. In order to avoid unpredictable issues
|
||||
* with this edge case, we just dirty the pipeline at the start of every
|
||||
* subpass.
|
||||
*/
|
||||
cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_PIPELINE;
|
||||
|
||||
VkResult result = genX(cmd_buffer_alloc_att_surf_states)(cmd_buffer,
|
||||
pass, subpass);
|
||||
if (result != VK_SUCCESS)
|
||||
return;
|
||||
|
||||
isl_null_fill_state(&cmd_buffer->device->isl_dev,
|
||||
cmd_state->null_surface_state.map,
|
||||
.size = isl_extent3d(info->renderArea.extent.width,
|
||||
info->renderArea.extent.height,
|
||||
info->layerCount));
|
||||
|
||||
for (uint32_t i = 0; i < info->colorAttachmentCount; i++) {
|
||||
const VkRenderingAttachmentInfoKHR *att = &info->pColorAttachments[i];
|
||||
if (!att->imageView)
|
||||
continue;
|
||||
|
||||
struct anv_attachment_state *att_state = &cmd_state->attachments[i];
|
||||
struct anv_image_view *iview = att_state->image_view;
|
||||
|
||||
struct anv_surface_state *surface_state = &att_state->color;
|
||||
isl_surf_usage_flags_t isl_surf_usage = ISL_SURF_USAGE_RENDER_TARGET_BIT;
|
||||
enum isl_aux_usage isl_aux_usage = att_state->aux_usage;
|
||||
|
||||
/* We had better have a surface state when we get here */
|
||||
assert(surface_state->state.map);
|
||||
|
||||
VkAttachmentLoadOp load_op =
|
||||
get_effective_load_op(att->loadOp,
|
||||
info->flags & VK_RENDERING_RESUMING_BIT_KHR);
|
||||
union isl_color_value clear_color = { .u32 = { 0, } };
|
||||
if (load_op == VK_ATTACHMENT_LOAD_OP_CLEAR &&
|
||||
att_state->fast_clear)
|
||||
anv_clear_color_from_att_state(&clear_color, att_state, iview);
|
||||
|
||||
anv_image_fill_surface_state(cmd_buffer->device,
|
||||
iview->image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
&iview->planes[0].isl,
|
||||
isl_surf_usage,
|
||||
isl_aux_usage,
|
||||
&clear_color,
|
||||
0,
|
||||
surface_state,
|
||||
NULL);
|
||||
|
||||
add_surface_state_relocs(cmd_buffer, *surface_state);
|
||||
|
||||
if (GFX_VER < 10 &&
|
||||
load_op == VK_ATTACHMENT_LOAD_OP_LOAD &&
|
||||
iview->image->planes[0].aux_usage != ISL_AUX_USAGE_NONE &&
|
||||
iview->planes[0].isl.base_level == 0 &&
|
||||
iview->planes[0].isl.base_array_layer == 0) {
|
||||
genX(copy_fast_clear_dwords)(cmd_buffer, surface_state->state,
|
||||
iview->image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
false /* copy to ss */);
|
||||
}
|
||||
}
|
||||
|
||||
#if GFX_VER >= 11
|
||||
/* The PIPE_CONTROL command description says:
|
||||
*
|
||||
* "Whenever a Binding Table Index (BTI) used by a Render Taget Message
|
||||
* points to a different RENDER_SURFACE_STATE, SW must issue a Render
|
||||
* Target Cache Flush by enabling this bit. When render target flush
|
||||
* is set due to new association of BTI, PS Scoreboard Stall bit must
|
||||
* be set in this packet."
|
||||
*/
|
||||
anv_add_pending_pipe_bits(cmd_buffer,
|
||||
ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT |
|
||||
ANV_PIPE_STALL_AT_SCOREBOARD_BIT,
|
||||
"change RT");
|
||||
#endif
|
||||
|
||||
cmd_buffer_emit_depth_stencil(cmd_buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_buffer_end_rendering(struct anv_cmd_buffer *cmd_buffer)
|
||||
{
|
||||
struct anv_cmd_state *cmd_state = &cmd_buffer->state;
|
||||
struct anv_subpass *subpass = cmd_state->subpass;
|
||||
uint32_t subpass_id = anv_get_subpass_id(&cmd_buffer->state);
|
||||
struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
|
||||
|
||||
cmd_buffer_clear_state_pointers(cmd_state);
|
||||
|
||||
if (!cmd_buffer->state.dynamic_render_pass.suspending) {
|
||||
cmd_buffer_mark_images_written(cmd_buffer, cmd_state, subpass, fb);
|
||||
|
||||
cmd_buffer_resolve_attachments(cmd_buffer, cmd_state, subpass, fb, subpass_id);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
setup_dynamic_framebuffer(struct anv_framebuffer *fb,
|
||||
const VkRenderingInfoKHR *info)
|
||||
{
|
||||
fb->width = info->renderArea.extent.width + info->renderArea.offset.x;
|
||||
fb->height = info->renderArea.extent.height + info->renderArea.offset.y;
|
||||
fb->layers = info->layerCount;
|
||||
}
|
||||
|
||||
void genX(CmdBeginRenderingKHR)(
|
||||
VkCommandBuffer commandBuffer,
|
||||
const VkRenderingInfoKHR* pRenderingInfo)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
VkResult result;
|
||||
|
||||
cmd_buffer->state.framebuffer = &cmd_buffer->state.dynamic_render_pass.framebuffer;
|
||||
setup_dynamic_framebuffer(cmd_buffer->state.framebuffer, pRenderingInfo);
|
||||
|
||||
cmd_buffer->state.render_area = pRenderingInfo->renderArea;
|
||||
|
||||
anv_dynamic_pass_init_full(&cmd_buffer->state.dynamic_render_pass,
|
||||
pRenderingInfo);
|
||||
cmd_buffer->state.pass = &cmd_buffer->state.dynamic_render_pass.pass;
|
||||
cmd_buffer->state.subpass = &cmd_buffer->state.dynamic_render_pass.subpass;
|
||||
|
||||
result = genX(cmd_buffer_setup_attachments_dynrender)(cmd_buffer,
|
||||
pRenderingInfo);
|
||||
if (result != VK_SUCCESS) {
|
||||
assert(anv_batch_has_error(&cmd_buffer->batch));
|
||||
return;
|
||||
}
|
||||
genX(flush_pipeline_select_3d)(cmd_buffer);
|
||||
|
||||
cmd_buffer_begin_rendering(cmd_buffer, pRenderingInfo);
|
||||
}
|
||||
|
||||
void genX(CmdEndRenderingKHR)(
|
||||
VkCommandBuffer commandBuffer)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
|
||||
if (anv_batch_has_error(&cmd_buffer->batch))
|
||||
return;
|
||||
|
||||
cmd_buffer_end_rendering(cmd_buffer);
|
||||
|
||||
cmd_buffer->state.framebuffer = NULL;
|
||||
cmd_buffer->state.pass = NULL;
|
||||
cmd_buffer->state.subpass = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
genX(cmd_emit_conditional_render_predicate)(struct anv_cmd_buffer *cmd_buffer)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue