anv/cmd_buffer: Move the rest of clear_subpass into begin_subpass
Reviewed-by: Nanley Chery <nanley.g.chery@intel.com>
This commit is contained in:
parent
7991838973
commit
6fc8555610
|
@ -1139,143 +1139,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,
|
||||
|
@ -1563,6 +1426,50 @@ anv_image_clear_color(struct anv_cmd_buffer *cmd_buffer,
|
|||
blorp_batch_finish(&batch);
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -1589,6 +1496,65 @@ anv_image_hiz_op(struct anv_cmd_buffer *cmd_buffer,
|
|||
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,
|
||||
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,
|
||||
|
|
|
@ -1934,7 +1934,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 *
|
||||
|
@ -2628,12 +2627,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,
|
||||
|
|
|
@ -3547,9 +3547,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;
|
||||
|
||||
anv_cmd_buffer_clear_subpass(cmd_buffer);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
att_state->pending_clear_aspects = 0;
|
||||
}
|
||||
|
||||
cmd_buffer_emit_depth_stencil(cmd_buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
Loading…
Reference in New Issue