-static bool
-subpass_needs_clear(const struct anv_cmd_buffer *cmd_buffer)
-{
- const struct anv_cmd_state *cmd_state = &cmd_buffer->state;
- uint32_t ds = cmd_state->subpass->depth_stencil_attachment.attachment;
-
- for (uint32_t i = 0; i < cmd_state->subpass->color_count; ++i) {
- uint32_t a = cmd_state->subpass->color_attachments[i].attachment;
- if (a == VK_ATTACHMENT_UNUSED)
- continue;
-
- assert(a < cmd_state->pass->attachment_count);
- if (cmd_state->attachments[a].pending_clear_aspects) {
- return true;
- }
- }
-
- if (ds != VK_ATTACHMENT_UNUSED) {
- assert(ds < cmd_state->pass->attachment_count);
- if (cmd_state->attachments[ds].pending_clear_aspects)
- return true;
- }
-
- return false;
-}
-
-void
-anv_cmd_buffer_clear_subpass(struct anv_cmd_buffer *cmd_buffer)
-{
- const struct anv_cmd_state *cmd_state = &cmd_buffer->state;
- const VkRect2D render_area = cmd_buffer->state.render_area;
-
-
- if (!subpass_needs_clear(cmd_buffer))
- return;
-
- /* Because this gets called within a render pass, we tell blorp not to
- * trash our depth and stencil buffers.
- */
- struct blorp_batch batch;
- blorp_batch_init(&cmd_buffer->device->blorp, &batch, cmd_buffer,
- BLORP_BATCH_NO_EMIT_DEPTH_STENCIL);
-
- VkClearRect clear_rect = {
- .rect = cmd_buffer->state.render_area,
- .baseArrayLayer = 0,
- .layerCount = cmd_buffer->state.framebuffer->layers,
- };
-
- struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
- for (uint32_t i = 0; i < cmd_state->subpass->color_count; ++i) {
- const uint32_t a = cmd_state->subpass->color_attachments[i].attachment;
- if (a == VK_ATTACHMENT_UNUSED)
- continue;
-
- assert(a < cmd_state->pass->attachment_count);
- struct anv_attachment_state *att_state = &cmd_state->attachments[a];
-
- if (!att_state->pending_clear_aspects)
- continue;
-
- assert(att_state->pending_clear_aspects == VK_IMAGE_ASPECT_COLOR_BIT);
-
- struct anv_image_view *iview = fb->attachments[a];
- const struct anv_image *image = iview->image;
- struct blorp_surf surf;
- get_blorp_surf_for_anv_image(cmd_buffer->device,
- image, VK_IMAGE_ASPECT_COLOR_BIT,
- att_state->aux_usage, &surf);
-
- if (att_state->fast_clear) {
- surf.clear_color = vk_to_isl_color(att_state->clear_value.color);
-
- /* From the Sky Lake PRM Vol. 7, "Render Target Fast Clear":
- *
- * "After Render target fast clear, pipe-control with color cache
- * write-flush must be issued before sending any DRAW commands on
- * that render target."
- *
- * This comment is a bit cryptic and doesn't really tell you what's
- * going or what's really needed. It appears that fast clear ops are
- * not properly synchronized with other drawing. This means that we
- * cannot have a fast clear operation in the pipe at the same time as
- * other regular drawing operations. We need to use a PIPE_CONTROL
- * to ensure that the contents of the previous draw hit the render
- * target before we resolve and then use a second PIPE_CONTROL after
- * the resolve to ensure that it is completed before any additional
- * drawing occurs.
- */
- cmd_buffer->state.pending_pipe_bits |=
- ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | ANV_PIPE_CS_STALL_BIT;
-
- assert(image->n_planes == 1);
- blorp_fast_clear(&batch, &surf, iview->planes[0].isl.format,
- iview->planes[0].isl.base_level,
- iview->planes[0].isl.base_array_layer, fb->layers,
- render_area.offset.x, render_area.offset.y,
- render_area.offset.x + render_area.extent.width,
- render_area.offset.y + render_area.extent.height);
-
- cmd_buffer->state.pending_pipe_bits |=
- ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | ANV_PIPE_CS_STALL_BIT;
- } else {
- assert(image->n_planes == 1);
- anv_cmd_buffer_mark_image_written(cmd_buffer, image,
- VK_IMAGE_ASPECT_COLOR_BIT,
- att_state->aux_usage,
- iview->planes[0].isl.base_level,
- iview->planes[0].isl.base_array_layer,
- fb->layers);
-
- blorp_clear(&batch, &surf, iview->planes[0].isl.format,
- anv_swizzle_for_render(iview->planes[0].isl.swizzle),
- iview->planes[0].isl.base_level,
- iview->planes[0].isl.base_array_layer, fb->layers,
- render_area.offset.x, render_area.offset.y,
- render_area.offset.x + render_area.extent.width,
- render_area.offset.y + render_area.extent.height,
- vk_to_isl_color(att_state->clear_value.color), NULL);
- }
-
- att_state->pending_clear_aspects = 0;
- }
-
- const uint32_t ds = cmd_state->subpass->depth_stencil_attachment.attachment;
- assert(ds == VK_ATTACHMENT_UNUSED || ds < cmd_state->pass->attachment_count);
-
- if (ds != VK_ATTACHMENT_UNUSED &&
- cmd_state->attachments[ds].pending_clear_aspects) {
-
- VkClearAttachment clear_att = {
- .aspectMask = cmd_state->attachments[ds].pending_clear_aspects,
- .clearValue = cmd_state->attachments[ds].clear_value,
- };
-
-
- const uint8_t gen = cmd_buffer->device->info.gen;
- bool clear_with_hiz = gen >= 8 && cmd_state->attachments[ds].aux_usage ==
- ISL_AUX_USAGE_HIZ;
- const struct anv_image_view *iview = fb->attachments[ds];
-
- if (clear_with_hiz) {
- const bool clear_depth = clear_att.aspectMask &
- VK_IMAGE_ASPECT_DEPTH_BIT;
- const bool clear_stencil = clear_att.aspectMask &
- VK_IMAGE_ASPECT_STENCIL_BIT;
-
- /* Check against restrictions for depth buffer clearing. A great GPU
- * performance benefit isn't expected when using the HZ sequence for
- * stencil-only clears. Therefore, we don't emit a HZ op sequence for
- * a stencil clear in addition to using the BLORP-fallback for depth.
- */
- if (clear_depth) {
- if (!blorp_can_hiz_clear_depth(gen, iview->planes[0].isl.format,
- iview->image->samples,
- render_area.offset.x,
- render_area.offset.y,
- render_area.offset.x +
- render_area.extent.width,
- render_area.offset.y +
- render_area.extent.height)) {
- clear_with_hiz = false;
- } else if (clear_att.clearValue.depthStencil.depth !=
- ANV_HZ_FC_VAL) {
- /* Don't enable fast depth clears for any color not equal to
- * ANV_HZ_FC_VAL.
- */
- clear_with_hiz = false;
- } else if (gen == 8 &&
- anv_can_sample_with_hiz(&cmd_buffer->device->info,
- iview->image)) {
- /* Only gen9+ supports returning ANV_HZ_FC_VAL when sampling a
- * fast-cleared portion of a HiZ buffer. Testing has revealed
- * that Gen8 only supports returning 0.0f. Gens prior to gen8 do
- * not support this feature at all.
- */
- clear_with_hiz = false;
- }
- }
-
- if (clear_with_hiz) {
- blorp_gen8_hiz_clear_attachments(&batch, iview->image->samples,
- render_area.offset.x,
- render_area.offset.y,
- render_area.offset.x +
- render_area.extent.width,
- render_area.offset.y +
- render_area.extent.height,
- clear_depth, clear_stencil,
- clear_att.clearValue.
- depthStencil.stencil);
-
- /* From the SKL PRM, Depth Buffer Clear:
- *
- * Depth Buffer Clear Workaround
- * Depth buffer clear pass using any of the methods (WM_STATE,
- * 3DSTATE_WM or 3DSTATE_WM_HZ_OP) must be followed by a
- * PIPE_CONTROL command with DEPTH_STALL bit and Depth FLUSH bits
- * “set” before starting to render. DepthStall and DepthFlush are
- * not needed between consecutive depth clear passes nor is it
- * required if the depth-clear pass was done with “full_surf_clear”
- * bit set in the 3DSTATE_WM_HZ_OP.
- */
- if (clear_depth) {
- cmd_buffer->state.pending_pipe_bits |=
- ANV_PIPE_DEPTH_CACHE_FLUSH_BIT | ANV_PIPE_DEPTH_STALL_BIT;
- }
- }
- }
-
- if (!clear_with_hiz) {
- clear_depth_stencil_attachment(cmd_buffer, &batch,
- &clear_att, 1, &clear_rect);
- }
-
- cmd_state->attachments[ds].pending_clear_aspects = 0;
- }
-
- blorp_batch_finish(&batch);
-}
-