[Mesa-dev] [PATCH v3 10/18] anv/cmd_buffer: Move the rest of clear_subpass into begin_subpass
Jason Ekstrand
jason at jlekstrand.net
Wed Feb 14 20:16:25 UTC 2018
---
src/intel/vulkan/anv_blorp.c | 242 ++++++++++++++++---------------------
src/intel/vulkan/anv_private.h | 17 ++-
src/intel/vulkan/genX_cmd_buffer.c | 68 ++++++++++-
3 files changed, 186 insertions(+), 141 deletions(-)
diff --git a/src/intel/vulkan/anv_blorp.c b/src/intel/vulkan/anv_blorp.c
index fd32227..6c0c858 100644
--- a/src/intel/vulkan/anv_blorp.c
+++ b/src/intel/vulkan/anv_blorp.c
@@ -1136,143 +1136,6 @@ enum subpass_stage {
SUBPASS_STAGE_RESOLVE,
};
-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;
-
- 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;
-
- 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);
-}
-
static void
resolve_surface(struct blorp_batch *batch,
struct blorp_surf *src_surf,
@@ -1561,13 +1424,57 @@ anv_image_clear_color(struct anv_cmd_buffer *cmd_buffer,
}
void
+anv_image_clear_depth_stencil(struct anv_cmd_buffer *cmd_buffer,
+ const struct anv_image *image,
+ VkImageAspectFlags aspects,
+ enum isl_aux_usage depth_aux_usage,
+ uint32_t level,
+ uint32_t base_layer, uint32_t layer_count,
+ VkRect2D area,
+ float depth_value, 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) {
+ get_blorp_surf_for_anv_image(cmd_buffer->device,
+ image, VK_IMAGE_ASPECT_DEPTH_BIT,
+ depth_aux_usage, &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,
+ ISL_AUX_USAGE_NONE, &stencil);
+ }
+
+ blorp_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,
+ depth_value,
+ (aspects & VK_IMAGE_ASPECT_STENCIL_BIT) ? 0xff : 0,
+ stencil_value);
+
+ blorp_batch_finish(&batch);
+}
+
+void
anv_image_hiz_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 hiz_op)
{
- assert(aspect == VK_IMAGE_ASPECT_DEPTH_BIT);
+ assert(image->aspects & VK_IMAGE_ASPECT_DEPTH_BIT);
assert(base_layer + layer_count <= anv_image_aux_layers(image, aspect, level));
assert(anv_image_aspect_to_plane(image->aspects,
VK_IMAGE_ASPECT_DEPTH_BIT) == 0);
@@ -1587,6 +1494,65 @@ anv_image_hiz_op(struct anv_cmd_buffer *cmd_buffer,
}
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, 0));
+ get_blorp_surf_for_anv_image(cmd_buffer->device,
+ image, VK_IMAGE_ASPECT_DEPTH_BIT,
+ 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,
+ ISL_AUX_USAGE_NONE, &stencil);
+ }
+
+ 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.
+ */
+ if (aspects & VK_IMAGE_ASPECT_DEPTH_BIT) {
+ 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,
diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h
index 73004a3..906c6f3 100644
--- a/src/intel/vulkan/anv_private.h
+++ b/src/intel/vulkan/anv_private.h
@@ -1923,7 +1923,6 @@ anv_cmd_buffer_push_constants(struct anv_cmd_buffer *cmd_buffer,
struct anv_state
anv_cmd_buffer_cs_push_constants(struct anv_cmd_buffer *cmd_buffer);
-void anv_cmd_buffer_clear_subpass(struct anv_cmd_buffer *cmd_buffer);
void anv_cmd_buffer_resolve_subpass(struct anv_cmd_buffer *cmd_buffer);
const struct anv_image_view *
@@ -2617,12 +2616,28 @@ anv_image_clear_color(struct anv_cmd_buffer *cmd_buffer,
uint32_t level, uint32_t base_layer, uint32_t layer_count,
VkRect2D area, union isl_color_value clear_color);
void
+anv_image_clear_depth_stencil(struct anv_cmd_buffer *cmd_buffer,
+ const struct anv_image *image,
+ VkImageAspectFlags aspects,
+ enum isl_aux_usage depth_aux_usage,
+ uint32_t level,
+ uint32_t base_layer, uint32_t layer_count,
+ VkRect2D area,
+ float depth_value, uint8_t stencil_value);
+void
anv_image_hiz_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 hiz_op);
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);
+void
anv_image_mcs_op(struct anv_cmd_buffer *cmd_buffer,
const struct anv_image *image,
VkImageAspectFlagBits aspect,
diff --git a/src/intel/vulkan/genX_cmd_buffer.c b/src/intel/vulkan/genX_cmd_buffer.c
index badb423..93894c1 100644
--- a/src/intel/vulkan/genX_cmd_buffer.c
+++ b/src/intel/vulkan/genX_cmd_buffer.c
@@ -3527,9 +3527,73 @@ cmd_buffer_begin_subpass(struct anv_cmd_buffer *cmd_buffer,
att_state->pending_clear_aspects = 0;
}
- cmd_buffer_emit_depth_stencil(cmd_buffer);
+ if (subpass->depth_stencil_attachment.attachment != VK_ATTACHMENT_UNUSED) {
+ const uint32_t a = subpass->depth_stencil_attachment.attachment;
+
+ assert(a < cmd_state->pass->attachment_count);
+ struct anv_attachment_state *att_state = &cmd_state->attachments[a];
+ struct anv_image_view *iview = fb->attachments[a];
+ const struct anv_image *image = iview->image;
+
+ assert(image->aspects & (VK_IMAGE_ASPECT_DEPTH_BIT |
+ VK_IMAGE_ASPECT_STENCIL_BIT));
+
+ if (att_state->pending_clear_aspects) {
+ bool clear_with_hiz = att_state->aux_usage == ISL_AUX_USAGE_HIZ;
+ if (clear_with_hiz &&
+ (att_state->pending_clear_aspects & VK_IMAGE_ASPECT_DEPTH_BIT)) {
+ if (!blorp_can_hiz_clear_depth(GEN_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 (att_state->clear_value.depthStencil.depth != ANV_HZ_FC_VAL) {
+ clear_with_hiz = false;
+ } else if (GEN_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) {
+ /* We currently only support HiZ for single-slice images */
+ assert(iview->planes[0].isl.base_level == 0);
+ assert(iview->planes[0].isl.base_array_layer == 0);
+ assert(fb->layers == 1);
+
+ anv_image_hiz_clear(cmd_buffer, image,
+ att_state->pending_clear_aspects,
+ iview->planes[0].isl.base_level,
+ iview->planes[0].isl.base_array_layer,
+ fb->layers, render_area,
+ att_state->clear_value.depthStencil.stencil);
+ } else {
+ anv_image_clear_depth_stencil(cmd_buffer, image,
+ att_state->pending_clear_aspects,
+ att_state->aux_usage,
+ iview->planes[0].isl.base_level,
+ iview->planes[0].isl.base_array_layer,
+ fb->layers, render_area,
+ att_state->clear_value.depthStencil.depth,
+ att_state->clear_value.depthStencil.stencil);
+ }
+ }
- anv_cmd_buffer_clear_subpass(cmd_buffer);
+ att_state->pending_clear_aspects = 0;
+ }
+
+ cmd_buffer_emit_depth_stencil(cmd_buffer);
}
static void
--
2.5.0.400.gff86faf
More information about the mesa-dev
mailing list