From fd6bbc2ee205ed02f66a8d8ef5b2adf4005d588c Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Sat, 4 Jun 2016 14:13:38 -0400 Subject: [PATCH] nvc0: reduce overhead from always marking images dirty We would revalidate images when anything was touched at all. Which is unfortunate, since the state tracker does not use CSO's to reduce the workload. So instead implement a protocol to ensure that something has changed before revalidating all the images. Signed-off-by: Ilia Mirkin Cc: "12.0" --- src/gallium/drivers/nouveau/nvc0/nvc0_state.c | 45 +++++++++++++++++++++------ 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_state.c b/src/gallium/drivers/nouveau/nvc0/nvc0_state.c index 6cdc007..92161ec 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_state.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_state.c @@ -1231,36 +1231,60 @@ nvc0_set_compute_resources(struct pipe_context *pipe, nvc0_context(pipe)->dirty_cp |= NVC0_NEW_CP_SURFACES; } -static void +static bool nvc0_bind_images_range(struct nvc0_context *nvc0, const unsigned s, unsigned start, unsigned nr, struct pipe_image_view *pimages) { const unsigned end = start + nr; - const unsigned mask = ((1 << nr) - 1) << start; + unsigned mask = 0; unsigned i; assert(s < 6); if (pimages) { for (i = start; i < end; ++i) { + struct pipe_image_view *img = &nvc0->images[s][i]; const unsigned p = i - start; + + if (img->resource == pimages[p].resource && + img->format == pimages[p].format && + img->access == pimages[p].access) { + if (img->resource == NULL) + continue; + if (img->resource->target == PIPE_BUFFER && + img->u.buf.first_element == pimages[p].u.buf.first_element && + img->u.buf.last_element == pimages[p].u.buf.last_element) + continue; + if (img->resource->target != PIPE_BUFFER && + img->u.tex.first_layer == pimages[p].u.tex.first_layer && + img->u.tex.last_layer == pimages[p].u.tex.last_layer && + img->u.tex.level == pimages[p].u.tex.level) + continue; + } + + mask |= (1 << i); if (pimages[p].resource) nvc0->images_valid[s] |= (1 << i); else nvc0->images_valid[s] &= ~(1 << i); - nvc0->images[s][i].format = pimages[p].format; - nvc0->images[s][i].access = pimages[p].access; - if (pimages[p].resource->target == PIPE_BUFFER) - nvc0->images[s][i].u.buf = pimages[p].u.buf; + img->format = pimages[p].format; + img->access = pimages[p].access; + if (pimages[p].resource && pimages[p].resource->target == PIPE_BUFFER) + img->u.buf = pimages[p].u.buf; else - nvc0->images[s][i].u.tex = pimages[p].u.tex; + img->u.tex = pimages[p].u.tex; pipe_resource_reference( - &nvc0->images[s][i].resource, pimages[p].resource); + &img->resource, pimages[p].resource); } + if (!mask) + return false; } else { + mask = ((1 << nr) - 1) << start; + if (!(nvc0->images_valid[s] & mask)) + return false; for (i = start; i < end; ++i) pipe_resource_reference(&nvc0->images[s][i].resource, NULL); nvc0->images_valid[s] &= ~mask; @@ -1271,6 +1295,8 @@ nvc0_bind_images_range(struct nvc0_context *nvc0, const unsigned s, nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_SUF); else nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_SUF); + + return true; } static void @@ -1279,7 +1305,8 @@ nvc0_set_shader_images(struct pipe_context *pipe, unsigned shader, struct pipe_image_view *images) { const unsigned s = nvc0_shader_stage(shader); - nvc0_bind_images_range(nvc0_context(pipe), s, start, nr, images); + if (!nvc0_bind_images_range(nvc0_context(pipe), s, start, nr, images)) + return; if (s == 5) nvc0_context(pipe)->dirty_cp |= NVC0_NEW_CP_SURFACES; -- 2.7.4