From d823f92970447859c4891728da4e48f0c9bc0044 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Fri, 7 Oct 2016 17:29:36 -0700 Subject: [PATCH] anv: Use blorp for subpass clears Signed-off-by: Jason Ekstrand Reviewed-by: Topi Pohjolainen --- src/intel/vulkan/anv_blorp.c | 81 ++++++++ src/intel/vulkan/anv_meta_clear.c | 298 ------------------------------ 2 files changed, 81 insertions(+), 298 deletions(-) diff --git a/src/intel/vulkan/anv_blorp.c b/src/intel/vulkan/anv_blorp.c index 8577e5f39b2..5361c4b2deb 100644 --- a/src/intel/vulkan/anv_blorp.c +++ b/src/intel/vulkan/anv_blorp.c @@ -981,6 +981,87 @@ void anv_CmdClearAttachments( blorp_batch_finish(&batch); } +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; + + for (uint32_t i = 0; i < cmd_state->subpass->color_count; ++i) { + uint32_t a = cmd_state->subpass->color_attachments[i]; + if (cmd_state->attachments[a].pending_clear_aspects) { + return true; + } + } + + if (ds != VK_ATTACHMENT_UNUSED && + 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; + + 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, + }; + + for (uint32_t i = 0; i < cmd_state->subpass->color_count; ++i) { + const uint32_t a = cmd_state->subpass->color_attachments[i]; + + if (!cmd_state->attachments[a].pending_clear_aspects) + continue; + + assert(cmd_state->attachments[a].pending_clear_aspects == + VK_IMAGE_ASPECT_COLOR_BIT); + + VkClearAttachment clear_att = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .colorAttachment = i, /* Use attachment index relative to subpass */ + .clearValue = cmd_state->attachments[a].clear_value, + }; + + clear_color_attachment(cmd_buffer, &batch, &clear_att, 1, &clear_rect); + + cmd_state->attachments[a].pending_clear_aspects = 0; + } + + const uint32_t ds = cmd_state->subpass->depth_stencil_attachment; + + 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, + }; + + 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_image(struct blorp_batch *batch, const struct anv_image *src_image, diff --git a/src/intel/vulkan/anv_meta_clear.c b/src/intel/vulkan/anv_meta_clear.c index 6802229a9ac..2bc718babd0 100644 --- a/src/intel/vulkan/anv_meta_clear.c +++ b/src/intel/vulkan/anv_meta_clear.c @@ -40,26 +40,6 @@ struct depthstencil_clear_vattrs { float position[2]; /*<< 3DPRIM_RECTLIST */ }; -static void -meta_clear_begin(struct anv_meta_saved_state *saved_state, - struct anv_cmd_buffer *cmd_buffer) -{ - anv_meta_save(saved_state, cmd_buffer, - (1 << VK_DYNAMIC_STATE_VIEWPORT) | - (1 << VK_DYNAMIC_STATE_STENCIL_REFERENCE) | - (1 << VK_DYNAMIC_STATE_STENCIL_WRITE_MASK)); - - /* Avoid uploading more viewport states than necessary */ - cmd_buffer->state.dynamic.viewport.count = 0; -} - -static void -meta_clear_end(struct anv_meta_saved_state *saved_state, - struct anv_cmd_buffer *cmd_buffer) -{ - anv_meta_restore(saved_state, cmd_buffer); -} - static void build_color_shaders(struct nir_shader **out_vs, struct nir_shader **out_fs, @@ -336,80 +316,6 @@ anv_device_finish_meta_clear_state(struct anv_device *device) } } -static void -emit_color_clear(struct anv_cmd_buffer *cmd_buffer, - const VkClearAttachment *clear_att, - const VkClearRect *clear_rect) -{ - struct anv_device *device = cmd_buffer->device; - const struct anv_subpass *subpass = cmd_buffer->state.subpass; - const struct anv_framebuffer *fb = cmd_buffer->state.framebuffer; - const uint32_t subpass_att = clear_att->colorAttachment; - const uint32_t pass_att = subpass->color_attachments[subpass_att]; - const struct anv_image_view *iview = fb->attachments[pass_att]; - const uint32_t samples = iview->image->samples; - const uint32_t samples_log2 = ffs(samples) - 1; - struct anv_pipeline *pipeline = - device->meta_state.clear[samples_log2].color_pipelines[subpass_att]; - VkClearColorValue clear_value = clear_att->clearValue.color; - - VkCommandBuffer cmd_buffer_h = anv_cmd_buffer_to_handle(cmd_buffer); - VkPipeline pipeline_h = anv_pipeline_to_handle(pipeline); - - assert(samples_log2 < ARRAY_SIZE(device->meta_state.clear)); - assert(clear_att->aspectMask == VK_IMAGE_ASPECT_COLOR_BIT); - assert(clear_att->colorAttachment < subpass->color_count); - - const struct color_clear_vattrs vertex_data[3] = { - { - .vue_header = { 0 }, - .position = { - clear_rect->rect.offset.x, - clear_rect->rect.offset.y, - }, - .color = clear_value, - }, - { - .vue_header = { 0 }, - .position = { - clear_rect->rect.offset.x + clear_rect->rect.extent.width, - clear_rect->rect.offset.y, - }, - .color = clear_value, - }, - { - .vue_header = { 0 }, - .position = { - clear_rect->rect.offset.x + clear_rect->rect.extent.width, - clear_rect->rect.offset.y + clear_rect->rect.extent.height, - }, - .color = clear_value, - }, - }; - - struct anv_state state = - anv_cmd_buffer_emit_dynamic(cmd_buffer, vertex_data, sizeof(vertex_data), 16); - - struct anv_buffer vertex_buffer = { - .device = device, - .size = sizeof(vertex_data), - .bo = &device->dynamic_state_block_pool.bo, - .offset = state.offset, - }; - - ANV_CALL(CmdBindVertexBuffers)(cmd_buffer_h, 0, 1, - (VkBuffer[]) { anv_buffer_to_handle(&vertex_buffer) }, - (VkDeviceSize[]) { 0 }); - - if (cmd_buffer->state.pipeline != pipeline) { - ANV_CALL(CmdBindPipeline)(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS, - pipeline_h); - } - - ANV_CALL(CmdDraw)(cmd_buffer_h, 3, 1, 0, 0); -} - - static void build_depthstencil_shader(struct nir_shader **out_vs) { @@ -503,111 +409,6 @@ create_depthstencil_pipeline(struct anv_device *device, /*use_repclear*/ true, pipeline); } -static void -emit_depthstencil_clear(struct anv_cmd_buffer *cmd_buffer, - const VkClearAttachment *clear_att, - const VkClearRect *clear_rect) -{ - struct anv_device *device = cmd_buffer->device; - struct anv_meta_state *meta_state = &device->meta_state; - const struct anv_subpass *subpass = cmd_buffer->state.subpass; - const struct anv_framebuffer *fb = cmd_buffer->state.framebuffer; - const uint32_t pass_att = subpass->depth_stencil_attachment; - const struct anv_image_view *iview = fb->attachments[pass_att]; - const uint32_t samples = iview->image->samples; - const uint32_t samples_log2 = ffs(samples) - 1; - VkClearDepthStencilValue clear_value = clear_att->clearValue.depthStencil; - VkImageAspectFlags aspects = clear_att->aspectMask; - - VkCommandBuffer cmd_buffer_h = anv_cmd_buffer_to_handle(cmd_buffer); - - assert(samples_log2 < ARRAY_SIZE(meta_state->clear)); - assert(aspects == VK_IMAGE_ASPECT_DEPTH_BIT || - aspects == VK_IMAGE_ASPECT_STENCIL_BIT || - aspects == (VK_IMAGE_ASPECT_DEPTH_BIT | - VK_IMAGE_ASPECT_STENCIL_BIT)); - assert(pass_att != VK_ATTACHMENT_UNUSED); - - const struct depthstencil_clear_vattrs vertex_data[3] = { - { - .vue_header = { 0 }, - .position = { - clear_rect->rect.offset.x, - clear_rect->rect.offset.y, - }, - }, - { - .vue_header = { 0 }, - .position = { - clear_rect->rect.offset.x + clear_rect->rect.extent.width, - clear_rect->rect.offset.y, - }, - }, - { - .vue_header = { 0 }, - .position = { - clear_rect->rect.offset.x + clear_rect->rect.extent.width, - clear_rect->rect.offset.y + clear_rect->rect.extent.height, - }, - }, - }; - - struct anv_state state = - anv_cmd_buffer_emit_dynamic(cmd_buffer, vertex_data, sizeof(vertex_data), 16); - - struct anv_buffer vertex_buffer = { - .device = device, - .size = sizeof(vertex_data), - .bo = &device->dynamic_state_block_pool.bo, - .offset = state.offset, - }; - - ANV_CALL(CmdSetViewport)(cmd_buffer_h, 0, 1, - (VkViewport[]) { - { - .x = 0, - .y = 0, - .width = fb->width, - .height = fb->height, - - /* Ignored when clearing only stencil. */ - .minDepth = clear_value.depth, - .maxDepth = clear_value.depth, - }, - }); - - if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT) { - ANV_CALL(CmdSetStencilReference)(cmd_buffer_h, VK_STENCIL_FACE_FRONT_BIT, - clear_value.stencil); - } - - ANV_CALL(CmdBindVertexBuffers)(cmd_buffer_h, 0, 1, - (VkBuffer[]) { anv_buffer_to_handle(&vertex_buffer) }, - (VkDeviceSize[]) { 0 }); - - struct anv_pipeline *pipeline; - switch (aspects) { - case VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT: - pipeline = meta_state->clear[samples_log2].depthstencil_pipeline; - break; - case VK_IMAGE_ASPECT_DEPTH_BIT: - pipeline = meta_state->clear[samples_log2].depth_only_pipeline; - break; - case VK_IMAGE_ASPECT_STENCIL_BIT: - pipeline = meta_state->clear[samples_log2].stencil_only_pipeline; - break; - default: - unreachable("expected depth or stencil aspect"); - } - - if (cmd_buffer->state.pipeline != pipeline) { - ANV_CALL(CmdBindPipeline)(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS, - anv_pipeline_to_handle(pipeline)); - } - - ANV_CALL(CmdDraw)(cmd_buffer_h, 3, 1, 0, 0); -} - VkResult anv_device_init_meta_clear_state(struct anv_device *device) { @@ -652,102 +453,3 @@ fail: anv_device_finish_meta_clear_state(device); return res; } - -/** - * The parameters mean that same as those in vkCmdClearAttachments. - */ -static void -emit_clear(struct anv_cmd_buffer *cmd_buffer, - const VkClearAttachment *clear_att, - const VkClearRect *clear_rect) -{ - if (clear_att->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) { - emit_color_clear(cmd_buffer, clear_att, clear_rect); - } else { - assert(clear_att->aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | - VK_IMAGE_ASPECT_STENCIL_BIT)); - emit_depthstencil_clear(cmd_buffer, clear_att, clear_rect); - } -} - -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; - - for (uint32_t i = 0; i < cmd_state->subpass->color_count; ++i) { - uint32_t a = cmd_state->subpass->color_attachments[i]; - if (cmd_state->attachments[a].pending_clear_aspects) { - return true; - } - } - - if (ds != VK_ATTACHMENT_UNUSED && - cmd_state->attachments[ds].pending_clear_aspects) { - return true; - } - - return false; -} - -/** - * Emit any pending attachment clears for the current subpass. - * - * @see anv_attachment_state::pending_clear_aspects - */ -void -anv_cmd_buffer_clear_subpass(struct anv_cmd_buffer *cmd_buffer) -{ - struct anv_cmd_state *cmd_state = &cmd_buffer->state; - struct anv_meta_saved_state saved_state; - - if (!subpass_needs_clear(cmd_buffer)) - return; - - meta_clear_begin(&saved_state, cmd_buffer); - - if (cmd_state->framebuffer->layers > 1) - anv_finishme("clearing multi-layer framebuffer"); - - VkClearRect clear_rect = { - .rect = cmd_state->render_area, - .baseArrayLayer = 0, - .layerCount = 1, /* FINISHME: clear multi-layer framebuffer */ - }; - - for (uint32_t i = 0; i < cmd_state->subpass->color_count; ++i) { - uint32_t a = cmd_state->subpass->color_attachments[i]; - - if (!cmd_state->attachments[a].pending_clear_aspects) - continue; - - assert(cmd_state->attachments[a].pending_clear_aspects == - VK_IMAGE_ASPECT_COLOR_BIT); - - VkClearAttachment clear_att = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .colorAttachment = i, /* Use attachment index relative to subpass */ - .clearValue = cmd_state->attachments[a].clear_value, - }; - - emit_clear(cmd_buffer, &clear_att, &clear_rect); - cmd_state->attachments[a].pending_clear_aspects = 0; - } - - uint32_t ds = cmd_state->subpass->depth_stencil_attachment; - - 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, - }; - - emit_clear(cmd_buffer, &clear_att, &clear_rect); - cmd_state->attachments[ds].pending_clear_aspects = 0; - } - - meta_clear_end(&saved_state, cmd_buffer); -} -- 2.30.2