+ blorp_batch_finish(&batch);
+}
+
+void
+anv_image_hiz_clear(struct anv_cmd_buffer *cmd_buffer,
+ const struct anv_image *image,
+ VkImageAspectFlags aspects,
+ uint32_t level,
+ uint32_t base_layer, uint32_t layer_count,
+ VkRect2D area, uint8_t stencil_value)
+{
+ assert(image->aspects & (VK_IMAGE_ASPECT_DEPTH_BIT |
+ VK_IMAGE_ASPECT_STENCIL_BIT));
+
+ struct blorp_batch batch;
+ blorp_batch_init(&cmd_buffer->device->blorp, &batch, cmd_buffer, 0);
+
+ struct blorp_surf depth = {};
+ if (aspects & VK_IMAGE_ASPECT_DEPTH_BIT) {
+ assert(base_layer + layer_count <=
+ anv_image_aux_layers(image, VK_IMAGE_ASPECT_DEPTH_BIT, level));
+ get_blorp_surf_for_anv_image(cmd_buffer->device,
+ image, VK_IMAGE_ASPECT_DEPTH_BIT,
+ ANV_IMAGE_LAYOUT_EXPLICIT_AUX,
+ ISL_AUX_USAGE_HIZ, &depth);
+ depth.clear_color.f32[0] = ANV_HZ_FC_VAL;
+ }
+
+ struct blorp_surf stencil = {};
+ if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
+ get_blorp_surf_for_anv_image(cmd_buffer->device,
+ image, VK_IMAGE_ASPECT_STENCIL_BIT,
+ ANV_IMAGE_LAYOUT_EXPLICIT_AUX,
+ ISL_AUX_USAGE_NONE, &stencil);
+ }
+
+ /* From the Sky Lake PRM Volume 7, "Depth Buffer Clear":
+ *
+ * "The following is required when performing a depth buffer clear with
+ * using the WM_STATE or 3DSTATE_WM:
+ *
+ * * If other rendering operations have preceded this clear, a
+ * PIPE_CONTROL with depth cache flush enabled, Depth Stall bit
+ * enabled must be issued before the rectangle primitive used for
+ * the depth buffer clear operation.
+ * * [...]"
+ *
+ * Even though the PRM only says that this is required if using 3DSTATE_WM
+ * and a 3DPRIMITIVE, the GPU appears to also need this to avoid occasional
+ * hangs when doing a clear with WM_HZ_OP.
+ */
+ cmd_buffer->state.pending_pipe_bits |=
+ ANV_PIPE_DEPTH_CACHE_FLUSH_BIT | ANV_PIPE_DEPTH_STALL_BIT;
+
+ blorp_hiz_clear_depth_stencil(&batch, &depth, &stencil,
+ level, base_layer, layer_count,
+ area.offset.x, area.offset.y,
+ area.offset.x + area.extent.width,
+ area.offset.y + area.extent.height,
+ aspects & VK_IMAGE_ASPECT_DEPTH_BIT,
+ ANV_HZ_FC_VAL,
+ aspects & VK_IMAGE_ASPECT_STENCIL_BIT,
+ stencil_value);
+
+ blorp_batch_finish(&batch);
+
+ /* 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."
+ *
+ * Even though the PRM provides a bunch of conditions under which this is
+ * supposedly unnecessary, we choose to perform the flush unconditionally
+ * just to be safe.
+ */
+ cmd_buffer->state.pending_pipe_bits |=
+ ANV_PIPE_DEPTH_CACHE_FLUSH_BIT | ANV_PIPE_DEPTH_STALL_BIT;
+}
+
+void
+anv_image_mcs_op(struct anv_cmd_buffer *cmd_buffer,
+ const struct anv_image *image,
+ VkImageAspectFlagBits aspect,
+ uint32_t base_layer, uint32_t layer_count,
+ enum isl_aux_op mcs_op, union isl_color_value *clear_value,
+ bool predicate)
+{
+ assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
+ assert(image->samples > 1);
+ assert(base_layer + layer_count <= anv_image_aux_layers(image, aspect, 0));
+
+ /* Multisampling with multi-planar formats is not supported */
+ assert(image->n_planes == 1);
+
+ struct blorp_batch batch;
+ blorp_batch_init(&cmd_buffer->device->blorp, &batch, cmd_buffer,
+ predicate ? BLORP_BATCH_PREDICATE_ENABLE : 0);
+
+ struct blorp_surf surf;
+ get_blorp_surf_for_anv_image(cmd_buffer->device, image, aspect,
+ ANV_IMAGE_LAYOUT_EXPLICIT_AUX,
+ ISL_AUX_USAGE_MCS, &surf);
+
+ /* Blorp will store the clear color for us if we provide the clear color
+ * address and we are doing a fast clear. So we save the clear value into
+ * the blorp surface. However, in some situations we want to do a fast clear
+ * without changing the clear value stored in the state buffer. For those
+ * cases, we set the clear color address pointer to NULL, so blorp will not
+ * try to store a garbage color.
+ */
+ if (mcs_op == ISL_AUX_OP_FAST_CLEAR) {
+ if (clear_value)
+ surf.clear_color = *clear_value;
+ else
+ surf.clear_color_addr.buffer = NULL;
+ }
+
+ /* 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;
+
+ switch (mcs_op) {
+ case ISL_AUX_OP_FAST_CLEAR:
+ blorp_fast_clear(&batch, &surf, surf.surf->format,
+ 0, base_layer, layer_count,
+ 0, 0, image->extent.width, image->extent.height);
+ break;
+ case ISL_AUX_OP_PARTIAL_RESOLVE:
+ blorp_mcs_partial_resolve(&batch, &surf, surf.surf->format,
+ base_layer, layer_count);
+ break;
+ case ISL_AUX_OP_FULL_RESOLVE:
+ case ISL_AUX_OP_AMBIGUATE:
+ default:
+ unreachable("Unsupported MCS operation");
+ }
+
+ cmd_buffer->state.pending_pipe_bits |=
+ ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | ANV_PIPE_CS_STALL_BIT;
+
+ blorp_batch_finish(&batch);
+}
+
+void
+anv_image_ccs_op(struct anv_cmd_buffer *cmd_buffer,
+ const struct anv_image *image,
+ VkImageAspectFlagBits aspect, uint32_t level,
+ uint32_t base_layer, uint32_t layer_count,
+ enum isl_aux_op ccs_op, union isl_color_value *clear_value,
+ bool predicate)
+{
+ assert(image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV);
+ assert(image->samples == 1);
+ assert(level < anv_image_aux_levels(image, aspect));
+ /* Multi-LOD YcBcR is not allowed */
+ assert(image->n_planes == 1 || level == 0);
+ assert(base_layer + layer_count <=
+ anv_image_aux_layers(image, aspect, level));
+
+ uint32_t plane = anv_image_aspect_to_plane(image->aspects, aspect);
+ uint32_t width_div = image->format->planes[plane].denominator_scales[0];
+ uint32_t height_div = image->format->planes[plane].denominator_scales[1];
+ uint32_t level_width = anv_minify(image->extent.width, level) / width_div;
+ uint32_t level_height = anv_minify(image->extent.height, level) / height_div;
+
+ struct blorp_batch batch;
+ blorp_batch_init(&cmd_buffer->device->blorp, &batch, cmd_buffer,
+ predicate ? BLORP_BATCH_PREDICATE_ENABLE : 0);
+
+ struct blorp_surf surf;
+ get_blorp_surf_for_anv_image(cmd_buffer->device, image, aspect,
+ ANV_IMAGE_LAYOUT_EXPLICIT_AUX,
+ fast_clear_aux_usage(image, aspect),
+ &surf);
+
+ /* Blorp will store the clear color for us if we provide the clear color
+ * address and we are doing a fast clear. So we save the clear value into
+ * the blorp surface. However, in some situations we want to do a fast clear
+ * without changing the clear value stored in the state buffer. For those
+ * cases, we set the clear color address pointer to NULL, so blorp will not
+ * try to store a garbage color.
+ */
+ if (ccs_op == ISL_AUX_OP_FAST_CLEAR) {
+ if (clear_value)
+ surf.clear_color = *clear_value;
+ else
+ surf.clear_color_addr.buffer = NULL;
+ }
+
+ /* 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;
+
+ switch (ccs_op) {
+ case ISL_AUX_OP_FAST_CLEAR:
+ blorp_fast_clear(&batch, &surf, surf.surf->format,
+ level, base_layer, layer_count,
+ 0, 0, level_width, level_height);
+ break;
+ case ISL_AUX_OP_FULL_RESOLVE:
+ case ISL_AUX_OP_PARTIAL_RESOLVE:
+ blorp_ccs_resolve(&batch, &surf, level, base_layer, layer_count,
+ surf.surf->format, ccs_op);
+ break;
+ case ISL_AUX_OP_AMBIGUATE:
+ for (uint32_t a = 0; a < layer_count; a++) {
+ const uint32_t layer = base_layer + a;
+ blorp_ccs_ambiguate(&batch, &surf, level, layer);
+ }
+ break;
+ default:
+ unreachable("Unsupported CCS operation");
+ }
+
+ cmd_buffer->state.pending_pipe_bits |=
+ ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | ANV_PIPE_CS_STALL_BIT;