summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_state.c45
1 files 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 6cdc007a086..92161ec9e65 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;