diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c index f2bb4dd54bc..5ba9d59a27b 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.c +++ b/src/gallium/auxiliary/cso_cache/cso_context.c @@ -343,7 +343,7 @@ void cso_destroy_context( struct cso_context *ctx ) ctx->pipe->set_shader_buffers(ctx->pipe, sh, 0, maxssbo, ssbos, 0); } if (maximg > 0) { - ctx->pipe->set_shader_images(ctx->pipe, sh, 0, maximg, NULL); + ctx->pipe->set_shader_images(ctx->pipe, sh, 0, 0, maximg, NULL); } for (int i = 0; i < maxcb; i++) { ctx->pipe->set_constant_buffer(ctx->pipe, sh, i, false, NULL); diff --git a/src/gallium/auxiliary/driver_ddebug/dd_context.c b/src/gallium/auxiliary/driver_ddebug/dd_context.c index f96fe14e3f7..211133fd7e8 100644 --- a/src/gallium/auxiliary/driver_ddebug/dd_context.c +++ b/src/gallium/auxiliary/driver_ddebug/dd_context.c @@ -524,6 +524,7 @@ static void dd_context_set_shader_images(struct pipe_context *_pipe, enum pipe_shader_type shader, unsigned start, unsigned num, + unsigned unbind_num_trailing_slots, const struct pipe_image_view *views) { struct dd_context *dctx = dd_context(_pipe); @@ -531,7 +532,10 @@ dd_context_set_shader_images(struct pipe_context *_pipe, safe_memcpy(&dctx->draw_state.shader_images[shader][start], views, sizeof(views[0]) * num); - pipe->set_shader_images(pipe, shader, start, num, views); + safe_memcpy(&dctx->draw_state.shader_images[shader][start + num], NULL, + sizeof(views[0]) * unbind_num_trailing_slots); + pipe->set_shader_images(pipe, shader, start, num, + unbind_num_trailing_slots, views); } static void diff --git a/src/gallium/auxiliary/driver_trace/tr_context.c b/src/gallium/auxiliary/driver_trace/tr_context.c index a31da2ce13c..3b81b70289e 100644 --- a/src/gallium/auxiliary/driver_trace/tr_context.c +++ b/src/gallium/auxiliary/driver_trace/tr_context.c @@ -1772,6 +1772,7 @@ static void trace_context_set_shader_buffers(struct pipe_context *_context, static void trace_context_set_shader_images(struct pipe_context *_context, enum pipe_shader_type shader, unsigned start, unsigned nr, + unsigned unbind_num_trailing_slots, const struct pipe_image_view *images) { struct trace_context *tr_context = trace_context(_context); @@ -1784,9 +1785,11 @@ static void trace_context_set_shader_images(struct pipe_context *_context, trace_dump_arg_begin("images"); trace_dump_struct_array(image_view, images, nr); trace_dump_arg_end(); + trace_dump_arg(uint, unbind_num_trailing_slots); trace_dump_call_end(); - context->set_shader_images(context, shader, start, nr, images); + context->set_shader_images(context, shader, start, nr, + unbind_num_trailing_slots, images); } static void trace_context_launch_grid(struct pipe_context *_pipe, diff --git a/src/gallium/auxiliary/util/u_compute.c b/src/gallium/auxiliary/util/u_compute.c index 3da98ee3541..dcfc266f8c2 100644 --- a/src/gallium/auxiliary/util/u_compute.c +++ b/src/gallium/auxiliary/util/u_compute.c @@ -118,7 +118,7 @@ void util_compute_blit(struct pipe_context *ctx, struct pipe_blit_info *blit_inf image.u.tex.first_layer = 0; image.u.tex.last_layer = (unsigned)(dst->array_size - 1); - ctx->set_shader_images(ctx, PIPE_SHADER_COMPUTE, 0, 1, &image); + ctx->set_shader_images(ctx, PIPE_SHADER_COMPUTE, 0, 1, 0, &image); struct pipe_sampler_state sampler_state={0}; sampler_state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; @@ -157,7 +157,7 @@ void util_compute_blit(struct pipe_context *ctx, struct pipe_blit_info *blit_inf ctx->memory_barrier(ctx, PIPE_BARRIER_ALL); - ctx->set_shader_images(ctx, PIPE_SHADER_COMPUTE, 0, 1, NULL); + ctx->set_shader_images(ctx, PIPE_SHADER_COMPUTE, 0, 0, 1, NULL); ctx->set_constant_buffer(ctx, PIPE_SHADER_COMPUTE, 0, false, NULL); ctx->set_sampler_views(ctx, PIPE_SHADER_COMPUTE, 0, 1, NULL); pipe_sampler_view_reference(&src_view, NULL); diff --git a/src/gallium/auxiliary/util/u_tests.c b/src/gallium/auxiliary/util/u_tests.c index 52f1ab4c738..f73123b8ef2 100644 --- a/src/gallium/auxiliary/util/u_tests.c +++ b/src/gallium/auxiliary/util/u_tests.c @@ -834,7 +834,7 @@ test_compute_clear_image(struct pipe_context *ctx) image.shader_access = image.access = PIPE_IMAGE_ACCESS_READ_WRITE; image.format = cb->format; - ctx->set_shader_images(ctx, PIPE_SHADER_COMPUTE, 0, 1, &image); + ctx->set_shader_images(ctx, PIPE_SHADER_COMPUTE, 0, 1, 0, &image); /* Dispatch compute. */ struct pipe_grid_info info = {0}; diff --git a/src/gallium/auxiliary/util/u_threaded_context.c b/src/gallium/auxiliary/util/u_threaded_context.c index 3e8d0b8afd9..9c078886b20 100644 --- a/src/gallium/auxiliary/util/u_threaded_context.c +++ b/src/gallium/auxiliary/util/u_threaded_context.c @@ -985,7 +985,7 @@ tc_set_sampler_views(struct pipe_context *_pipe, struct tc_shader_images { ubyte shader, start, count; - bool unbind; + ubyte unbind_num_trailing_slots; struct pipe_image_view slot[0]; /* more will be allocated if needed */ }; @@ -995,12 +995,14 @@ tc_call_set_shader_images(struct pipe_context *pipe, union tc_payload *payload) struct tc_shader_images *p = (struct tc_shader_images *)payload; unsigned count = p->count; - if (p->unbind) { - pipe->set_shader_images(pipe, p->shader, p->start, p->count, NULL); + if (!p->count) { + pipe->set_shader_images(pipe, p->shader, p->start, 0, + p->unbind_num_trailing_slots, NULL); return; } - pipe->set_shader_images(pipe, p->shader, p->start, p->count, p->slot); + pipe->set_shader_images(pipe, p->shader, p->start, p->count, + p->unbind_num_trailing_slots, p->slot); for (unsigned i = 0; i < count; i++) pipe_resource_reference(&p->slot[i].resource, NULL); @@ -1010,9 +1012,10 @@ static void tc_set_shader_images(struct pipe_context *_pipe, enum pipe_shader_type shader, unsigned start, unsigned count, + unsigned unbind_num_trailing_slots, const struct pipe_image_view *images) { - if (!count) + if (!count && !unbind_num_trailing_slots) return; struct threaded_context *tc = threaded_context(_pipe); @@ -1022,10 +1025,11 @@ tc_set_shader_images(struct pipe_context *_pipe, p->shader = shader; p->start = start; - p->count = count; - p->unbind = images == NULL; if (images) { + p->count = count; + p->unbind_num_trailing_slots = unbind_num_trailing_slots; + for (unsigned i = 0; i < count; i++) { tc_set_resource_reference(&p->slot[i].resource, images[i].resource); @@ -1041,6 +1045,9 @@ tc_set_shader_images(struct pipe_context *_pipe, } } memcpy(p->slot, images, count * sizeof(images[0])); + } else { + p->count = 0; + p->unbind_num_trailing_slots = count + unbind_num_trailing_slots; } } diff --git a/src/gallium/auxiliary/vl/vl_compositor_cs.c b/src/gallium/auxiliary/vl/vl_compositor_cs.c index 111cf4f910b..c8a375cb9fd 100644 --- a/src/gallium/auxiliary/vl/vl_compositor_cs.c +++ b/src/gallium/auxiliary/vl/vl_compositor_cs.c @@ -597,7 +597,7 @@ cs_launch(struct vl_compositor *c, image.shader_access = image.access = PIPE_IMAGE_ACCESS_READ_WRITE; image.format = c->fb_state.cbufs[0]->texture->format; - ctx->set_shader_images(c->pipe, PIPE_SHADER_COMPUTE, 0, 1, &image); + ctx->set_shader_images(c->pipe, PIPE_SHADER_COMPUTE, 0, 1, 0, &image); /* Bind compute shader */ ctx->bind_compute_state(ctx, cs); @@ -732,7 +732,7 @@ draw_layers(struct vl_compositor *c, cs_launch(c, layer->cs, &(drawn.area)); /* Unbind. */ - c->pipe->set_shader_images(c->pipe, PIPE_SHADER_COMPUTE, 0, 1, NULL); + c->pipe->set_shader_images(c->pipe, PIPE_SHADER_COMPUTE, 0, 0, 1, NULL); c->pipe->set_constant_buffer(c->pipe, PIPE_SHADER_COMPUTE, 0, false, NULL); c->pipe->set_sampler_views(c->pipe, PIPE_SHADER_FRAGMENT, 0, num_sampler_views, NULL); diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_image.c b/src/gallium/drivers/freedreno/a6xx/fd6_image.c index 56824b3ff45..1fa6bd0c890 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_image.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_image.c @@ -316,12 +316,14 @@ fd6_build_ibo_state(struct fd_context *ctx, const struct ir3_shader_variant *v, static void fd6_set_shader_images(struct pipe_context *pctx, enum pipe_shader_type shader, unsigned start, unsigned count, + unsigned unbind_num_trailing_slots, const struct pipe_image_view *images) { struct fd_context *ctx = fd_context(pctx); struct fd_shaderimg_stateobj *so = &ctx->shaderimg[shader]; - fd_set_shader_images(pctx, shader, start, count, images); + fd_set_shader_images(pctx, shader, start, count, + unbind_num_trailing_slots, images); if (!images) return; diff --git a/src/gallium/drivers/freedreno/freedreno_state.c b/src/gallium/drivers/freedreno/freedreno_state.c index cc7fb180a1f..edbc8611636 100644 --- a/src/gallium/drivers/freedreno/freedreno_state.c +++ b/src/gallium/drivers/freedreno/freedreno_state.c @@ -165,6 +165,7 @@ void fd_set_shader_images(struct pipe_context *pctx, enum pipe_shader_type shader, unsigned start, unsigned count, + unsigned unbind_num_trailing_slots, const struct pipe_image_view *images) { struct fd_context *ctx = fd_context(pctx); @@ -206,6 +207,11 @@ fd_set_shader_images(struct pipe_context *pctx, so->enabled_mask &= ~mask; } + for (unsigned i = 0; i < unbind_num_trailing_slots; i++) + pipe_resource_reference(&so->si[i + start + count].resource, NULL); + + so->enabled_mask &= ~(BITFIELD_MASK(unbind_num_trailing_slots) << (start + count)); + ctx->dirty_shader[shader] |= FD_DIRTY_SHADER_IMAGE; ctx->dirty |= FD_DIRTY_IMAGE; } diff --git a/src/gallium/drivers/freedreno/freedreno_state.h b/src/gallium/drivers/freedreno/freedreno_state.h index b45a2daac32..dfa4a947711 100644 --- a/src/gallium/drivers/freedreno/freedreno_state.h +++ b/src/gallium/drivers/freedreno/freedreno_state.h @@ -53,6 +53,7 @@ static inline bool fd_depth_clamp_enabled(struct fd_context *ctx) void fd_set_shader_images(struct pipe_context *pctx, enum pipe_shader_type shader, unsigned start, unsigned count, + unsigned unbind_num_trailing_slots, const struct pipe_image_view *images); void fd_state_init(struct pipe_context *pctx); diff --git a/src/gallium/drivers/iris/iris_state.c b/src/gallium/drivers/iris/iris_state.c index 26bb12dd084..be9862a6565 100644 --- a/src/gallium/drivers/iris/iris_state.c +++ b/src/gallium/drivers/iris/iris_state.c @@ -2740,6 +2740,7 @@ static void iris_set_shader_images(struct pipe_context *ctx, enum pipe_shader_type p_stage, unsigned start_slot, unsigned count, + unsigned unbind_num_trailing_slots, const struct pipe_image_view *p_images) { struct iris_context *ice = (struct iris_context *) ctx; @@ -2840,6 +2841,11 @@ iris_set_shader_images(struct pipe_context *ctx, ice->state.stage_dirty |= IRIS_STAGE_DIRTY_CONSTANTS_VS << stage; shs->sysvals_need_upload = true; } + + if (unbind_num_trailing_slots) { + iris_set_shader_images(ctx, p_stage, start_slot + count, + unbind_num_trailing_slots, 0, NULL); + } } diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index b3673b40ae0..b151efcd798 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -3876,7 +3876,8 @@ llvmpipe_set_shader_buffers(struct pipe_context *pipe, static void llvmpipe_set_shader_images(struct pipe_context *pipe, enum pipe_shader_type shader, unsigned start_slot, - unsigned count, const struct pipe_image_view *images) + unsigned count, unsigned unbind_num_trailing_slots, + const struct pipe_image_view *images) { struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); unsigned i, idx; @@ -3901,6 +3902,11 @@ llvmpipe_set_shader_images(struct pipe_context *pipe, llvmpipe->cs_dirty |= LP_CSNEW_IMAGES; else llvmpipe->dirty |= LP_NEW_FS_IMAGES; + + if (unbind_num_trailing_slots) { + llvmpipe_set_shader_images(pipe, shader, start_slot + count, + unbind_num_trailing_slots, 0, NULL); + } } /** diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_state.c b/src/gallium/drivers/nouveau/nvc0/nvc0_state.c index e8afe654776..02942d52ee3 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_state.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_state.c @@ -1283,9 +1283,14 @@ static void nvc0_set_shader_images(struct pipe_context *pipe, enum pipe_shader_type shader, unsigned start, unsigned nr, + unsigned unbind_num_trailing_slots, const struct pipe_image_view *images) { const unsigned s = nvc0_shader_stage(shader); + + nvc0_bind_images_range(nvc0_context(pipe), s, start + nr, + unbind_num_trailing_slots, NULL); + if (!nvc0_bind_images_range(nvc0_context(pipe), s, start, nr, images)) return; diff --git a/src/gallium/drivers/panfrost/pan_context.c b/src/gallium/drivers/panfrost/pan_context.c index d8cba2d5438..1600e26fc99 100644 --- a/src/gallium/drivers/panfrost/pan_context.c +++ b/src/gallium/drivers/panfrost/pan_context.c @@ -642,14 +642,14 @@ static void panfrost_set_shader_images( struct pipe_context *pctx, enum pipe_shader_type shader, - unsigned start_slot, unsigned count, + unsigned start_slot, unsigned count, unsigned unbind_num_trailing_slots, const struct pipe_image_view *iviews) { struct panfrost_context *ctx = pan_context(pctx); /* Unbind start_slot...start_slot+count */ if (!iviews) { - for (int i = start_slot; i < start_slot + count; i++) { + for (int i = start_slot; i < start_slot + count + unbind_num_trailing_slots; i++) { pipe_resource_reference(&ctx->images[shader][i].resource, NULL); } @@ -677,6 +677,12 @@ panfrost_set_shader_images( util_copy_image_view(&ctx->images[shader][start_slot+i], image); } + + /* Unbind start_slot+count...start_slot+count+unbind_num_trailing_slots */ + for (int i = 0; i < unbind_num_trailing_slots; i++) { + SET_BIT(ctx->image_mask[shader], 1 << (start_slot + count + i), NULL); + util_copy_image_view(&ctx->images[shader][start_slot+count+i], NULL); + } } static void * diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c index c14052c3e2e..e7e91390846 100644 --- a/src/gallium/drivers/r600/evergreen_state.c +++ b/src/gallium/drivers/r600/evergreen_state.c @@ -4150,7 +4150,7 @@ static void evergreen_set_shader_buffers(struct pipe_context *ctx, static void evergreen_set_shader_images(struct pipe_context *ctx, enum pipe_shader_type shader, unsigned start_slot, - unsigned count, + unsigned count, unsigned unbind_num_trailing_slots, const struct pipe_image_view *images) { struct r600_context *rctx = (struct r600_context *)ctx; @@ -4164,7 +4164,9 @@ static void evergreen_set_shader_images(struct pipe_context *ctx, unsigned old_mask; struct r600_image_state *istate = NULL; int idx; - if (shader != PIPE_SHADER_FRAGMENT && shader != PIPE_SHADER_COMPUTE && count == 0) + if (shader != PIPE_SHADER_FRAGMENT && shader != PIPE_SHADER_COMPUTE) + return; + if (!count && !unbind_num_trailing_slots) return; if (shader == PIPE_SHADER_FRAGMENT) @@ -4307,6 +4309,16 @@ static void evergreen_set_shader_images(struct pipe_context *ctx, istate->enabled_mask |= (1 << i); } + for (i = start_slot + count, idx = 0; + i < start_slot + count + unbind_num_trailing_slots; i++, idx++) { + rview = &istate->views[i]; + + pipe_resource_reference((struct pipe_resource **)&rview->base.resource, NULL); + istate->enabled_mask &= ~(1 << i); + istate->compressed_colortex_mask &= ~(1 << i); + istate->compressed_depthtex_mask &= ~(1 << i); + } + istate->atom.num_dw = util_bitcount(istate->enabled_mask) * 46; istate->dirty_buffer_constants = TRUE; rctx->b.flags |= R600_CONTEXT_WAIT_3D_IDLE | R600_CONTEXT_FLUSH_AND_INV; diff --git a/src/gallium/drivers/radeonsi/si_compute_blit.c b/src/gallium/drivers/radeonsi/si_compute_blit.c index 9bc74b2c2ad..ca5fd5391c5 100644 --- a/src/gallium/drivers/radeonsi/si_compute_blit.c +++ b/src/gallium/drivers/radeonsi/si_compute_blit.c @@ -534,7 +534,7 @@ void si_compute_copy_image(struct si_context *sctx, struct pipe_resource *dst, u if (is_dcc_decompress) image[1].access |= SI_IMAGE_ACCESS_DCC_OFF; - ctx->set_shader_images(ctx, PIPE_SHADER_COMPUTE, 0, 2, image); + ctx->set_shader_images(ctx, PIPE_SHADER_COMPUTE, 0, 2, 0, image); struct pipe_grid_info info = {0}; @@ -603,7 +603,7 @@ void si_compute_copy_image(struct si_context *sctx, struct pipe_resource *dst, u si_launch_grid_internal(sctx, &info, saved_cs, SI_CS_WAIT_FOR_IDLE | SI_CS_IMAGE_OP); - ctx->set_shader_images(ctx, PIPE_SHADER_COMPUTE, 0, 2, saved_image); + ctx->set_shader_images(ctx, PIPE_SHADER_COMPUTE, 0, 2, 0, saved_image); for (int i = 0; i < 2; i++) pipe_resource_reference(&saved_image[i].resource, NULL); if (!is_dcc_decompress) { @@ -652,7 +652,7 @@ void si_retile_dcc(struct si_context *sctx, struct si_texture *tex) img[2].u.buf.offset = tex->surface.display_dcc_offset; img[2].u.buf.size = tex->surface.u.gfx9.display_dcc_size; - ctx->set_shader_images(ctx, PIPE_SHADER_COMPUTE, 0, 3, img); + ctx->set_shader_images(ctx, PIPE_SHADER_COMPUTE, 0, 3, 0, img); /* Bind the compute shader. */ if (!sctx->cs_dcc_retile) @@ -679,7 +679,7 @@ void si_retile_dcc(struct si_context *sctx, struct si_texture *tex) */ /* Restore states. */ - ctx->set_shader_images(ctx, PIPE_SHADER_COMPUTE, 0, 3, saved_img); + ctx->set_shader_images(ctx, PIPE_SHADER_COMPUTE, 0, 3, 0, saved_img); for (unsigned i = 0; i < 3; i++) { pipe_resource_reference(&saved_img[i].resource, NULL); @@ -717,7 +717,7 @@ void si_compute_expand_fmask(struct pipe_context *ctx, struct pipe_resource *tex if (is_array) image.u.tex.last_layer = tex->array_size - 1; - ctx->set_shader_images(ctx, PIPE_SHADER_COMPUTE, 0, 1, &image); + ctx->set_shader_images(ctx, PIPE_SHADER_COMPUTE, 0, 1, 0, &image); /* Bind the shader. */ void **shader = &sctx->cs_fmask_expand[log_samples - 1][is_array]; @@ -740,7 +740,7 @@ void si_compute_expand_fmask(struct pipe_context *ctx, struct pipe_resource *tex SI_CS_WAIT_FOR_IDLE | SI_CS_IMAGE_OP); /* Restore previous states. */ - ctx->set_shader_images(ctx, PIPE_SHADER_COMPUTE, 0, 1, &saved_image); + ctx->set_shader_images(ctx, PIPE_SHADER_COMPUTE, 0, 1, 0, &saved_image); pipe_resource_reference(&saved_image.resource, NULL); /* Array of fully expanded FMASK values, arranged by [log2(fragments)][log2(samples)-1]. */ @@ -819,7 +819,7 @@ void si_compute_clear_render_target(struct pipe_context *ctx, struct pipe_surfac image.u.tex.first_layer = 0; /* 3D images ignore first_layer (BASE_ARRAY) */ image.u.tex.last_layer = dstsurf->u.tex.last_layer; - ctx->set_shader_images(ctx, PIPE_SHADER_COMPUTE, 0, 1, &image); + ctx->set_shader_images(ctx, PIPE_SHADER_COMPUTE, 0, 1, 0, &image); struct pipe_grid_info info = {0}; @@ -852,7 +852,7 @@ void si_compute_clear_render_target(struct pipe_context *ctx, struct pipe_surfac SI_CS_WAIT_FOR_IDLE | SI_CS_IMAGE_OP | (render_condition_enabled ? SI_CS_RENDER_COND_ENABLE : 0)); - ctx->set_shader_images(ctx, PIPE_SHADER_COMPUTE, 0, 1, &saved_image); + ctx->set_shader_images(ctx, PIPE_SHADER_COMPUTE, 0, 1, 0, &saved_image); ctx->set_constant_buffer(ctx, PIPE_SHADER_COMPUTE, 0, true, &saved_cb); pipe_resource_reference(&saved_image.resource, NULL); } diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c index ccaa2800c2f..6139769c86a 100644 --- a/src/gallium/drivers/radeonsi/si_descriptors.c +++ b/src/gallium/drivers/radeonsi/si_descriptors.c @@ -803,6 +803,7 @@ static void si_set_shader_image(struct si_context *ctx, unsigned shader, unsigne static void si_set_shader_images(struct pipe_context *pipe, enum pipe_shader_type shader, unsigned start_slot, unsigned count, + unsigned unbind_num_trailing_slots, const struct pipe_image_view *views) { struct si_context *ctx = (struct si_context *)pipe; @@ -810,10 +811,10 @@ static void si_set_shader_images(struct pipe_context *pipe, enum pipe_shader_typ assert(shader < SI_NUM_SHADERS); - if (!count) + if (!count && !unbind_num_trailing_slots) return; - assert(start_slot + count <= SI_NUM_IMAGES); + assert(start_slot + count + unbind_num_trailing_slots <= SI_NUM_IMAGES); if (views) { for (i = 0, slot = start_slot; i < count; ++i, ++slot) @@ -823,6 +824,9 @@ static void si_set_shader_images(struct pipe_context *pipe, enum pipe_shader_typ si_set_shader_image(ctx, shader, slot, NULL, false); } + for (i = 0; i < unbind_num_trailing_slots; ++i, ++slot) + si_set_shader_image(ctx, shader, slot, NULL, false); + if (shader == PIPE_SHADER_COMPUTE && ctx->cs_shader_state.program && start_slot < ctx->cs_shader_state.program->sel.cs_num_images_in_user_sgprs) diff --git a/src/gallium/drivers/softpipe/sp_state_image.c b/src/gallium/drivers/softpipe/sp_state_image.c index 8e6757187da..bb2fb21c940 100644 --- a/src/gallium/drivers/softpipe/sp_state_image.c +++ b/src/gallium/drivers/softpipe/sp_state_image.c @@ -30,6 +30,7 @@ static void softpipe_set_shader_images(struct pipe_context *pipe, enum pipe_shader_type shader, unsigned start, unsigned num, + unsigned unbind_num_trailing_slots, const struct pipe_image_view *images) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -50,6 +51,13 @@ static void softpipe_set_shader_images(struct pipe_context *pipe, memset(&softpipe->tgsi.image[shader]->sp_iview[idx], 0, sizeof(struct pipe_image_view)); } } + + for (i = 0; i < unbind_num_trailing_slots; i++) { + int idx = start + num + i; + + pipe_resource_reference(&softpipe->tgsi.image[shader]->sp_iview[idx].resource, NULL); + memset(&softpipe->tgsi.image[shader]->sp_iview[idx], 0, sizeof(struct pipe_image_view)); + } } static void softpipe_set_shader_buffers(struct pipe_context *pipe, diff --git a/src/gallium/drivers/tegra/tegra_context.c b/src/gallium/drivers/tegra/tegra_context.c index 98e84a58ce0..aca256824ff 100644 --- a/src/gallium/drivers/tegra/tegra_context.c +++ b/src/gallium/drivers/tegra/tegra_context.c @@ -612,12 +612,13 @@ tegra_set_shader_buffers(struct pipe_context *pcontext, unsigned int shader, static void tegra_set_shader_images(struct pipe_context *pcontext, unsigned int shader, unsigned start, unsigned count, + unsigned unbind_num_trailing_slots, const struct pipe_image_view *images) { struct tegra_context *context = to_tegra_context(pcontext); context->gpu->set_shader_images(context->gpu, shader, start, count, - images); + unbind_num_trailing_slots, images); } static void diff --git a/src/gallium/drivers/v3d/v3dx_state.c b/src/gallium/drivers/v3d/v3dx_state.c index aa0315693aa..86fe97decfd 100644 --- a/src/gallium/drivers/v3d/v3dx_state.c +++ b/src/gallium/drivers/v3d/v3dx_state.c @@ -1347,6 +1347,7 @@ static void v3d_set_shader_images(struct pipe_context *pctx, enum pipe_shader_type shader, unsigned start, unsigned count, + unsigned unbind_num_trailing_slots, const struct pipe_image_view *images) { struct v3d_context *v3d = v3d_context(pctx); @@ -1392,6 +1393,11 @@ v3d_set_shader_images(struct pipe_context *pctx, } v3d->dirty |= VC5_DIRTY_SHADER_IMAGE; + + if (unbind_num_trailing_slots) { + v3d_set_shader_images(pctx, shader, start + count, + unbind_num_trailing_slots, 0, NULL); + } } void diff --git a/src/gallium/drivers/virgl/virgl_context.c b/src/gallium/drivers/virgl/virgl_context.c index 72c4a412975..2e42f1bfe92 100644 --- a/src/gallium/drivers/virgl/virgl_context.c +++ b/src/gallium/drivers/virgl/virgl_context.c @@ -1282,6 +1282,7 @@ static void virgl_fence_server_sync(struct pipe_context *ctx, static void virgl_set_shader_images(struct pipe_context *ctx, enum pipe_shader_type shader, unsigned start_slot, unsigned count, + unsigned unbind_num_trailing_slots, const struct pipe_image_view *images) { struct virgl_context *vctx = virgl_context(ctx); @@ -1311,6 +1312,11 @@ static void virgl_set_shader_images(struct pipe_context *ctx, if (!max_shader_images) return; virgl_encode_set_shader_images(vctx, shader, start_slot, count, images); + + if (unbind_num_trailing_slots) { + virgl_set_shader_images(ctx, shader, start_slot + count, + unbind_num_trailing_slots, 0, NULL); + } } static void virgl_memory_barrier(struct pipe_context *ctx, diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index 4ef04518804..eec6f16204b 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -621,6 +621,7 @@ static void zink_set_shader_images(struct pipe_context *pctx, enum pipe_shader_type p_stage, unsigned start_slot, unsigned count, + unsigned unbind_num_trailing_slots, const struct pipe_image_view *images) { struct zink_context *ctx = zink_context(pctx); @@ -653,6 +654,19 @@ zink_set_shader_images(struct pipe_context *pctx, image_view->surface = NULL; } } + + for (unsigned i = 0; i < unbind_num_trailing_slots; i++) { + struct zink_image_view *image_view = &ctx->image_views[p_stage][start_slot + count + i]; + if (image_view->base.resource) { + if (image_view->base.resource->target == PIPE_BUFFER) + vkDestroyBufferView(zink_screen(pctx->screen)->dev, image_view->buffer_view, NULL); + else + pipe_surface_reference((struct pipe_surface**)&image_view->surface, NULL); + pipe_resource_reference(&image_view->base.resource, NULL); + image_view->base.resource = NULL; + image_view->surface = NULL; + } + } } static void diff --git a/src/gallium/frontends/clover/core/kernel.cpp b/src/gallium/frontends/clover/core/kernel.cpp index 91873578e0f..fad6b7568ba 100644 --- a/src/gallium/frontends/clover/core/kernel.cpp +++ b/src/gallium/frontends/clover/core/kernel.cpp @@ -84,7 +84,7 @@ kernel::launch(command_queue &q, q.pipe->set_sampler_views(q.pipe, PIPE_SHADER_COMPUTE, 0, exec.sviews.size(), exec.sviews.data()); q.pipe->set_shader_images(q.pipe, PIPE_SHADER_COMPUTE, 0, - exec.iviews.size(), exec.iviews.data()); + exec.iviews.size(), 0, exec.iviews.data()); q.pipe->set_compute_resources(q.pipe, 0, exec.resources.size(), exec.resources.data()); q.pipe->set_global_binding(q.pipe, 0, exec.g_buffers.size(), @@ -102,7 +102,7 @@ kernel::launch(command_queue &q, q.pipe->set_global_binding(q.pipe, 0, exec.g_buffers.size(), NULL, NULL); q.pipe->set_compute_resources(q.pipe, 0, exec.resources.size(), NULL); q.pipe->set_shader_images(q.pipe, PIPE_SHADER_COMPUTE, 0, - exec.iviews.size(), NULL); + 0, exec.iviews.size(), NULL); q.pipe->set_sampler_views(q.pipe, PIPE_SHADER_COMPUTE, 0, exec.sviews.size(), NULL); q.pipe->bind_sampler_states(q.pipe, PIPE_SHADER_COMPUTE, 0, diff --git a/src/gallium/frontends/lavapipe/lvp_execute.c b/src/gallium/frontends/lavapipe/lvp_execute.c index 75a10c2d60d..be624c9fc0e 100644 --- a/src/gallium/frontends/lavapipe/lvp_execute.c +++ b/src/gallium/frontends/lavapipe/lvp_execute.c @@ -136,7 +136,7 @@ static void emit_compute_state(struct rendering_state *state) if (state->iv_dirty[PIPE_SHADER_COMPUTE]) { state->pctx->set_shader_images(state->pctx, PIPE_SHADER_COMPUTE, 0, state->num_shader_images[PIPE_SHADER_COMPUTE], - state->iv[PIPE_SHADER_COMPUTE]); + 0, state->iv[PIPE_SHADER_COMPUTE]); state->iv_dirty[PIPE_SHADER_COMPUTE] = false; } @@ -281,7 +281,7 @@ static void emit_state(struct rendering_state *state) for (sh = 0; sh < PIPE_SHADER_TYPES; sh++) { if (state->iv_dirty[sh]) { state->pctx->set_shader_images(state->pctx, sh, - 0, state->num_shader_images[sh], + 0, state->num_shader_images[sh], 0, state->iv[sh]); } } @@ -2792,7 +2792,7 @@ VkResult lvp_execute_cmds(struct lvp_device *device, } state.pctx->bind_sampler_states(state.pctx, s, 0, PIPE_MAX_SAMPLERS, state.ss_cso[s]); - state.pctx->set_shader_images(state.pctx, s, 0, device->physical_device->max_images, NULL); + state.pctx->set_shader_images(state.pctx, s, 0, 0, device->physical_device->max_images, NULL); } free(state.pending_clear_aspects); diff --git a/src/gallium/frontends/omx/vid_enc_common.c b/src/gallium/frontends/omx/vid_enc_common.c index aec01708812..6777bd53334 100644 --- a/src/gallium/frontends/omx/vid_enc_common.c +++ b/src/gallium/frontends/omx/vid_enc_common.c @@ -459,7 +459,7 @@ OMX_ERRORTYPE enc_LoadImage_common(vid_enc_PrivateType * priv, OMX_VIDEO_PORTDEF image[2].shader_access = image[1].access = PIPE_IMAGE_ACCESS_WRITE; image[2].format = PIPE_FORMAT_R8G8_UINT; - pipe->set_shader_images(pipe, PIPE_SHADER_COMPUTE, 0, 3, image); + pipe->set_shader_images(pipe, PIPE_SHADER_COMPUTE, 0, 3, 0, image); /* Set the constant buffer. */ uint32_t constants[4] = {def->nFrameHeight}; @@ -496,7 +496,7 @@ OMX_ERRORTYPE enc_LoadImage_common(vid_enc_PrivateType * priv, OMX_VIDEO_PORTDEF pipe->memory_barrier(pipe, PIPE_BARRIER_ALL); /* Unbind. */ - pipe->set_shader_images(pipe, PIPE_SHADER_COMPUTE, 0, 3, NULL); + pipe->set_shader_images(pipe, PIPE_SHADER_COMPUTE, 0, 0, 3, NULL); pipe->set_constant_buffer(pipe, PIPE_SHADER_COMPUTE, 0, false, NULL); pipe->bind_compute_state(pipe, NULL); } else { diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h index bea258b74bf..1f653e1df27 100644 --- a/src/gallium/include/pipe/p_context.h +++ b/src/gallium/include/pipe/p_context.h @@ -501,6 +501,8 @@ struct pipe_context { * \param shader selects shader stage * \param start_slot first image slot to bind. * \param count number of consecutive images to bind. + * \param unbind_num_trailing_slots number of images to unbind after + * the bound slot * \param buffers array of the images to bind, it * should contain at least \a count elements * unless it's NULL, in which case no images will @@ -509,6 +511,7 @@ struct pipe_context { void (*set_shader_images)(struct pipe_context *, enum pipe_shader_type shader, unsigned start_slot, unsigned count, + unsigned unbind_num_trailing_slots, const struct pipe_image_view *images); void (*set_vertex_buffers)( struct pipe_context *, diff --git a/src/mesa/state_tracker/st_atom_image.c b/src/mesa/state_tracker/st_atom_image.c index 37f12cf5989..0cf63db57ab 100644 --- a/src/mesa/state_tracker/st_atom_image.c +++ b/src/mesa/state_tracker/st_atom_image.c @@ -175,14 +175,11 @@ st_bind_images(struct st_context *st, struct gl_program *prog, } struct pipe_context *pipe = st->pipe; - pipe->set_shader_images(pipe, shader_type, 0, num_images, images); - - /* clear out any stale shader images */ unsigned last_num_images = st->state.num_images[shader_type]; - if (num_images < last_num_images) { - pipe->set_shader_images(pipe, shader_type, num_images, - last_num_images - num_images, NULL); - } + unsigned unbind_slots = last_num_images > num_images ? + last_num_images - num_images : 0; + pipe->set_shader_images(pipe, shader_type, 0, num_images, unbind_slots, + images); st->state.num_images[shader_type] = num_images; } diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c index cc346117ecb..44bc91f0d54 100644 --- a/src/mesa/state_tracker/st_cb_readpixels.c +++ b/src/mesa/state_tracker/st_cb_readpixels.c @@ -211,7 +211,7 @@ try_pbo_readpixels(struct st_context *st, struct st_renderbuffer *strb, image.u.buf.size = (addr.last_element - addr.first_element + 1) * addr.bytes_per_pixel; - pipe->set_shader_images(pipe, PIPE_SHADER_FRAGMENT, 0, 1, &image); + pipe->set_shader_images(pipe, PIPE_SHADER_FRAGMENT, 0, 1, 0, &image); } /* Set up no-attachment framebuffer */ @@ -263,7 +263,7 @@ fail: st->state.num_sampler_views[PIPE_SHADER_FRAGMENT], null); st->state.num_sampler_views[PIPE_SHADER_FRAGMENT] = 0; - pipe->set_shader_images(pipe, PIPE_SHADER_FRAGMENT, 0, 1, NULL); + pipe->set_shader_images(pipe, PIPE_SHADER_FRAGMENT, 0, 0, 1, NULL); st->dirty |= ST_NEW_FS_CONSTANTS | ST_NEW_FS_IMAGES |