lavapipe: use clear interface for renderpass clears

For llvmpipe this means clears happen in the raster threads
rather than in the single cpu thread.

This path can't be used for scissored or clears with different
clear colors per mrt.

Reviewed-by: Eric Anholt <eric@anholt.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9041>
This commit is contained in:
Dave Airlie 2021-02-15 08:33:08 +10:00 committed by Marge Bot
parent 2ecb47abda
commit b4f7535ba2
1 changed files with 91 additions and 9 deletions

View File

@ -1159,9 +1159,6 @@ static void render_subpass_clear(struct rendering_state *state)
{
const struct lvp_subpass *subpass = &state->pass->subpasses[state->subpass];
if (!subpass_needs_clear(state))
return;
for (unsigned i = 0; i < subpass->color_count; i++) {
uint32_t a = subpass->color_attachments[i].attachment;
@ -1206,13 +1203,17 @@ static void render_subpass_clear(struct rendering_state *state)
uint32_t sclear_val = 0;
uint32_t ds_clear_flags = 0;
if (util_format_has_stencil(desc) && att->stencil_load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
if ((util_format_has_stencil(desc) && att->stencil_load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) ||
(util_format_is_depth_and_stencil(imgv->surface->format) && att->stencil_load_op == VK_ATTACHMENT_LOAD_OP_DONT_CARE)) {
ds_clear_flags |= PIPE_CLEAR_STENCIL;
sclear_val = state->attachments[ds].clear_value.depthStencil.stencil;
if (att->stencil_load_op == VK_ATTACHMENT_LOAD_OP_CLEAR)
sclear_val = state->attachments[ds].clear_value.depthStencil.stencil;
}
if (util_format_has_depth(desc) && att->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
if ((util_format_has_depth(desc) && att->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) ||
(util_format_is_depth_and_stencil(imgv->surface->format) && att->load_op == VK_ATTACHMENT_LOAD_OP_DONT_CARE)) {
ds_clear_flags |= PIPE_CLEAR_DEPTH;
dclear_val = state->attachments[ds].clear_value.depthStencil.depth;
if (att->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR)
dclear_val = state->attachments[ds].clear_value.depthStencil.depth;
}
if (ds_clear_flags)
@ -1229,6 +1230,86 @@ static void render_subpass_clear(struct rendering_state *state)
}
static void render_subpass_clear_fast(struct rendering_state *state)
{
/* attempt to use the clear interface first, then fallback to per-attchment clears */
const struct lvp_subpass *subpass = &state->pass->subpasses[state->subpass];
bool has_color_value = false;
uint32_t buffers = 0;
VkClearValue color_value = {};
double dclear_val = 0;
uint32_t sclear_val = 0;
/*
* the state tracker clear interface only works if all the attachments have the same
* clear color.
*/
/* llvmpipe doesn't support scissored clears yet */
if (state->render_area.offset.x || state->render_area.offset.y)
goto slow_clear;
if (state->render_area.extent.width != state->framebuffer.width ||
state->render_area.extent.height != state->framebuffer.height)
goto slow_clear;
for (unsigned i = 0; i < subpass->color_count; i++) {
uint32_t a = subpass->color_attachments[i].attachment;
if (!attachment_needs_clear(state, a))
continue;
if (has_color_value) {
if (memcmp(&color_value, &state->attachments[a].clear_value, sizeof(VkClearValue)))
goto slow_clear;
} else {
memcpy(&color_value, &state->attachments[a].clear_value, sizeof(VkClearValue));
has_color_value = true;
}
}
for (unsigned i = 0; i < subpass->color_count; i++) {
uint32_t a = subpass->color_attachments[i].attachment;
if (!attachment_needs_clear(state, a))
continue;
buffers |= (PIPE_CLEAR_COLOR0 << i);
state->pending_clear_aspects[a] = 0;
}
if (subpass->depth_stencil_attachment) {
uint32_t ds = subpass->depth_stencil_attachment->attachment;
if (!attachment_needs_clear(state, ds))
return;
struct lvp_render_pass_attachment *att = &state->pass->attachments[ds];
struct lvp_image_view *imgv = state->vk_framebuffer->attachments[ds];
const struct util_format_description *desc = util_format_description(imgv->surface->format);
/* also clear stencil for don't care to avoid RMW */
if ((util_format_has_stencil(desc) && att->stencil_load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) ||
(util_format_is_depth_and_stencil(imgv->surface->format) && att->stencil_load_op == VK_ATTACHMENT_LOAD_OP_DONT_CARE))
buffers |= PIPE_CLEAR_STENCIL;
if (util_format_has_depth(desc) && att->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR)
buffers |= PIPE_CLEAR_DEPTH;
dclear_val = state->attachments[ds].clear_value.depthStencil.depth;
sclear_val = state->attachments[ds].clear_value.depthStencil.stencil;
state->pending_clear_aspects[ds] = 0;
}
union pipe_color_union col_val;
for (unsigned i = 0; i < 4; i++)
col_val.ui[i] = color_value.color.uint32[i];
state->pctx->clear(state->pctx, buffers,
NULL, &col_val,
dclear_val, sclear_val);
return;
slow_clear:
render_subpass_clear(state);
}
static void render_pass_resolve(struct rendering_state *state)
{
const struct lvp_subpass *subpass = &state->pass->subpasses[state->subpass];
@ -1270,8 +1351,6 @@ static void begin_render_subpass(struct rendering_state *state,
{
state->subpass = subpass_idx;
render_subpass_clear(state);
state->framebuffer.nr_cbufs = 0;
const struct lvp_subpass *subpass = &state->pass->subpasses[subpass_idx];
@ -1299,6 +1378,9 @@ static void begin_render_subpass(struct rendering_state *state,
state->pctx->set_framebuffer_state(state->pctx,
&state->framebuffer);
if (subpass_needs_clear(state))
render_subpass_clear_fast(state);
}
static void handle_begin_render_pass(struct lvp_cmd_buffer_entry *cmd,