diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index 55ed0c09e37..2799a3eed66 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -960,6 +960,13 @@ zink_set_shader_images(struct pipe_context *pctx, invalidate_descriptor_state(ctx, p_stage, ZINK_DESCRIPTOR_TYPE_IMAGE); } +static void +sampler_view_buffer_clear(struct zink_context *ctx, struct zink_sampler_view *sampler_view) +{ + zink_descriptor_set_refs_clear(&sampler_view->desc_set_refs, sampler_view); + zink_buffer_view_reference(zink_screen(ctx->base.screen), &sampler_view->buffer_view, NULL); +} + static void zink_set_sampler_views(struct pipe_context *pctx, enum pipe_shader_type shader_type, @@ -978,6 +985,20 @@ zink_set_sampler_views(struct pipe_context *pctx, struct zink_sampler_view *b = zink_sampler_view(pview); if (b && b->base.texture) { struct zink_resource *res = zink_resource(b->base.texture); + if (res->base.target == PIPE_BUFFER && + res->bind_history & BITFIELD64_BIT(ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW)) { + /* if this resource has been rebound while it wasn't set here, + * its backing resource will have changed and thus we need to update + * the bufferview + */ + struct zink_buffer_view *buffer_view = get_buffer_view(ctx, res, b->base.format, b->base.u.buf.offset, b->base.u.buf.size); + if (buffer_view == b->buffer_view) + p_atomic_dec(&buffer_view->reference.count); + else { + sampler_view_buffer_clear(ctx, b); + b->buffer_view = buffer_view; + } + } res->bind_history |= BITFIELD_BIT(ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW); res->bind_stages |= 1 << shader_type; } @@ -2148,6 +2169,60 @@ zink_set_stream_output_targets(struct pipe_context *pctx, } } +void +zink_resource_rebind(struct zink_context *ctx, struct zink_resource *res) +{ + assert(res->base.target == PIPE_BUFFER); + + for (unsigned shader = 0; shader < PIPE_SHADER_TYPES; shader++) { + if (!(res->bind_stages & (1 << shader))) + continue; + for (enum zink_descriptor_type type = 0; type < ZINK_DESCRIPTOR_TYPES; type++) { + if (!(res->bind_history & BITFIELD64_BIT(type))) + continue; + + uint32_t usage = zink_program_get_descriptor_usage(ctx, shader, type); + while (usage) { + const int i = u_bit_scan(&usage); + struct zink_resource *cres = get_resource_for_descriptor(ctx, type, shader, i); + if (res != cres) + continue; + + switch (type) { + case ZINK_DESCRIPTOR_TYPE_SSBO: { + struct pipe_shader_buffer *ssbo = &ctx->ssbos[shader][i]; + util_range_add(&res->base, &res->valid_buffer_range, ssbo->buffer_offset, + ssbo->buffer_offset + ssbo->buffer_size); + break; + } + case ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW: { + struct zink_sampler_view *sampler_view = zink_sampler_view(ctx->sampler_views[shader][i]); + sampler_view_buffer_clear(ctx, sampler_view); + sampler_view->buffer_view = get_buffer_view(ctx, res, sampler_view->base.format, + sampler_view->base.u.buf.offset, sampler_view->base.u.buf.size); + break; + } + case ZINK_DESCRIPTOR_TYPE_IMAGE: { + struct zink_image_view *image_view = &ctx->image_views[shader][i]; + zink_descriptor_set_refs_clear(&image_view->desc_set_refs, image_view); + zink_buffer_view_reference(zink_screen(ctx->base.screen), &image_view->buffer_view, NULL); + image_view->buffer_view = get_buffer_view(ctx, res, image_view->base.format, + image_view->base.u.buf.offset, image_view->base.u.buf.size); + assert(image_view->buffer_view); + util_range_add(&res->base, &res->valid_buffer_range, image_view->base.u.buf.offset, + image_view->base.u.buf.offset + image_view->base.u.buf.size); + break; + } + default: + break; + } + + invalidate_descriptor_state(ctx, shader, type); + } + } + } +} + static bool init_batch(struct zink_context *ctx, struct zink_batch *batch, unsigned idx) { diff --git a/src/gallium/drivers/zink/zink_context.h b/src/gallium/drivers/zink/zink_context.h index 161dce031e5..5f30030fa61 100644 --- a/src/gallium/drivers/zink/zink_context.h +++ b/src/gallium/drivers/zink/zink_context.h @@ -322,6 +322,9 @@ zink_rect_from_box(const struct pipe_box *box) return (struct u_rect){box->x, box->x + box->width, box->y, box->y + box->height}; } +void +zink_resource_rebind(struct zink_context *ctx, struct zink_resource *res); + void zink_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *dinfo, diff --git a/src/gallium/drivers/zink/zink_resource.c b/src/gallium/drivers/zink/zink_resource.c index 4d1d8735762..b0f73b006df 100644 --- a/src/gallium/drivers/zink/zink_resource.c +++ b/src/gallium/drivers/zink/zink_resource.c @@ -573,6 +573,37 @@ zink_resource_from_handle(struct pipe_screen *pscreen, #endif } +static void +zink_resource_invalidate(struct pipe_context *pctx, struct pipe_resource *pres) +{ + struct zink_context *ctx = zink_context(pctx); + struct zink_resource *res = zink_resource(pres); + struct zink_screen *screen = zink_screen(pctx->screen); + + if (pres->target != PIPE_BUFFER) + return; + + if (res->valid_buffer_range.start > res->valid_buffer_range.end) + return; + + util_range_set_empty(&res->valid_buffer_range); + if (!zink_get_resource_usage(res)) + return; + + struct zink_resource_object *old_obj = res->obj; + struct zink_resource_object *new_obj = resource_object_create(screen, pres, NULL, NULL); + if (!new_obj) { + debug_printf("new backing resource alloc failed!"); + return; + } + res->obj = new_obj; + res->access_stage = 0; + res->access = 0; + zink_resource_rebind(ctx, res); + zink_descriptor_set_refs_clear(&old_obj->desc_set_refs, old_obj); + zink_resource_object_reference(screen, &old_obj, NULL); +} + static void zink_transfer_copy_bufimage(struct zink_context *ctx, struct zink_resource *dst, @@ -946,4 +977,5 @@ zink_context_resource_init(struct pipe_context *pctx) pctx->transfer_flush_region = u_transfer_helper_transfer_flush_region; pctx->buffer_subdata = u_default_buffer_subdata; pctx->texture_subdata = u_default_texture_subdata; + pctx->invalidate_resource = zink_resource_invalidate; }