diff options
-rw-r--r-- | src/intel/vulkan/anv_private.h | 8 | ||||
-rw-r--r-- | src/intel/vulkan/genX_cmd_buffer.c | 91 |
2 files changed, 96 insertions, 3 deletions
diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index ee533581ab4..0e209e1769f 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -1724,6 +1724,14 @@ struct anv_attachment_state { VkClearValue clear_value; bool clear_color_is_zero_one; bool clear_color_is_zero; + + /* When multiview is active, attachments with a renderpass clear + * operation have their respective layers cleared on the first + * subpass that uses them, and only in that subpass. We keep track + * of this using a bitfield to indicate which layers of an attachment + * have not been cleared yet when multiview is active. + */ + uint32_t pending_clear_views; }; /** State tracking for particular pipeline bind point diff --git a/src/intel/vulkan/genX_cmd_buffer.c b/src/intel/vulkan/genX_cmd_buffer.c index b5741fb8dc1..3c55cd964c6 100644 --- a/src/intel/vulkan/genX_cmd_buffer.c +++ b/src/intel/vulkan/genX_cmd_buffer.c @@ -1250,6 +1250,9 @@ genX(cmd_buffer_setup_attachments)(struct anv_cmd_buffer *cmd_buffer, anv_assert(iview->vk_format == att->format); anv_assert(iview->n_planes == 1); + const uint32_t num_layers = iview->planes[0].isl.array_len; + state->attachments[i].pending_clear_views = (1 << num_layers) - 1; + union isl_color_value clear_color = { .u32 = { 0, } }; if (att_aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV) { assert(att_aspects == VK_IMAGE_ASPECT_COLOR_BIT); @@ -3414,6 +3417,42 @@ cmd_buffer_emit_depth_stencil(struct anv_cmd_buffer *cmd_buffer) cmd_buffer->state.hiz_enabled = info.hiz_usage == ISL_AUX_USAGE_HIZ; } +/** + * This ANDs the view mask of the current subpass with the pending clear + * views in the attachment to get the mask of views active in the subpass + * that still need to be cleared. + */ +static inline uint32_t +get_multiview_subpass_clear_mask(const struct anv_cmd_state *cmd_state, + const struct anv_attachment_state *att_state) +{ + return cmd_state->subpass->view_mask & att_state->pending_clear_views; +} + +static inline bool +do_first_layer_clear(const struct anv_cmd_state *cmd_state, + const struct anv_attachment_state *att_state) +{ + if (!cmd_state->subpass->view_mask) + return true; + + uint32_t pending_clear_mask = + get_multiview_subpass_clear_mask(cmd_state, att_state); + + return pending_clear_mask & 1; +} + +static inline bool +current_subpass_is_last_for_attachment(const struct anv_cmd_state *cmd_state, + uint32_t att_idx) +{ + const uint32_t last_subpass_idx = + cmd_state->pass->attachments[att_idx].last_subpass_idx; + const struct anv_subpass *last_subpass = + &cmd_state->pass->subpasses[last_subpass_idx]; + return last_subpass == cmd_state->subpass; +} + static void cmd_buffer_begin_subpass(struct anv_cmd_buffer *cmd_buffer, uint32_t subpass_id) @@ -3452,6 +3491,8 @@ cmd_buffer_begin_subpass(struct anv_cmd_buffer *cmd_buffer, VkRect2D render_area = cmd_buffer->state.render_area; struct anv_framebuffer *fb = cmd_buffer->state.framebuffer; + bool is_multiview = subpass->view_mask != 0; + for (uint32_t i = 0; i < subpass->attachment_count; ++i) { const uint32_t a = subpass->attachments[i].attachment; if (a == VK_ATTACHMENT_UNUSED) @@ -3519,7 +3560,8 @@ cmd_buffer_begin_subpass(struct anv_cmd_buffer *cmd_buffer, uint32_t base_clear_layer = iview->planes[0].isl.base_array_layer; uint32_t clear_layer_count = fb->layers; - if (att_state->fast_clear) { + if (att_state->fast_clear && + do_first_layer_clear(cmd_state, att_state)) { /* We only support fast-clears on the first layer */ assert(iview->planes[0].isl.base_level == 0); assert(iview->planes[0].isl.base_array_layer == 0); @@ -3533,6 +3575,8 @@ cmd_buffer_begin_subpass(struct anv_cmd_buffer *cmd_buffer, } base_clear_layer++; clear_layer_count--; + if (is_multiview) + att_state->pending_clear_views &= ~1; genX(copy_fast_clear_dwords)(cmd_buffer, att_state->color.state, image, VK_IMAGE_ASPECT_COLOR_BIT, @@ -3554,7 +3598,39 @@ cmd_buffer_begin_subpass(struct anv_cmd_buffer *cmd_buffer, } } - if (clear_layer_count > 0) { + /* From the VkFramebufferCreateInfo spec: + * + * "If the render pass uses multiview, then layers must be one and each + * attachment requires a number of layers that is greater than the + * maximum bit index set in the view mask in the subpasses in which it + * is used." + * + * So if multiview is active we ignore the number of layers in the + * framebuffer and instead we honor the view mask from the subpass. + */ + if (is_multiview) { + assert(image->n_planes == 1); + uint32_t pending_clear_mask = + get_multiview_subpass_clear_mask(cmd_state, att_state); + + uint32_t layer_idx; + for_each_bit(layer_idx, pending_clear_mask) { + uint32_t layer = + iview->planes[0].isl.base_array_layer + layer_idx; + + anv_image_clear_color(cmd_buffer, image, + VK_IMAGE_ASPECT_COLOR_BIT, + att_state->aux_usage, + iview->planes[0].isl.format, + iview->planes[0].isl.swizzle, + iview->planes[0].isl.base_level, + layer, 1, + render_area, + vk_to_isl_color(att_state->clear_value.color)); + } + + att_state->pending_clear_views &= ~pending_clear_mask; + } else if (clear_layer_count > 0) { assert(image->n_planes == 1); anv_image_clear_color(cmd_buffer, image, VK_IMAGE_ASPECT_COLOR_BIT, att_state->aux_usage, @@ -3656,7 +3732,16 @@ cmd_buffer_begin_subpass(struct anv_cmd_buffer *cmd_buffer, } } - att_state->pending_clear_aspects = 0; + /* If multiview is enabled, then we are only done clearing when we no + * longer have pending layers to clear, or when we have processed the + * last subpass that uses this attachment. + */ + if (!is_multiview || + att_state->pending_clear_views == 0 || + current_subpass_is_last_for_attachment(cmd_state, a)) { + att_state->pending_clear_aspects = 0; + } + att_state->pending_load_aspects = 0; } |