Module: Mesa
Branch: main
Commit: b385fa85db020a73c58ad92db50444abcf436e60
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=b385fa85db020a73c58ad92db50444abcf436e60

Author: Mike Blumenkrantz <[email protected]>
Date:   Wed Oct  4 10:04:40 2023 -0400

tc: add batch usage tagging to threaded_resource

this allows the tc recorder thread to tag resources to determine if
a resource has been previously seen by the current batch

Acked-by: Marek Olšák <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25624>

---

 src/gallium/auxiliary/util/u_threaded_context.c | 87 ++++++++++++++++++++-----
 src/gallium/auxiliary/util/u_threaded_context.h |  8 ++-
 2 files changed, 79 insertions(+), 16 deletions(-)

diff --git a/src/gallium/auxiliary/util/u_threaded_context.c 
b/src/gallium/auxiliary/util/u_threaded_context.c
index 05c0c4ffe25..268a02cf4bc 100644
--- a/src/gallium/auxiliary/util/u_threaded_context.c
+++ b/src/gallium/auxiliary/util/u_threaded_context.c
@@ -305,6 +305,25 @@ to_call_check(void *ptr, unsigned num_slots)
    sizeof(struct type) + sizeof(((struct type*)NULL)->slot[0]) * (num_slots))
 #define get_next_call(ptr, type) ((struct type*)((uint64_t*)ptr + 
call_size(type)))
 
+ALWAYS_INLINE static void
+tc_set_resource_batch_usage(struct threaded_context *tc, struct pipe_resource 
*pres)
+{
+   /* ignore batch usage when persistent */
+   if (threaded_resource(pres)->last_batch_usage != INT8_MAX)
+      threaded_resource(pres)->last_batch_usage = tc->next;
+   threaded_resource(pres)->batch_generation = tc->batch_generation;
+}
+
+ALWAYS_INLINE static void
+tc_set_resource_batch_usage_persistent(struct threaded_context *tc, struct 
pipe_resource *pres, bool enable)
+{
+   if (!pres)
+      return;
+   /* mark with special value to block any unsynchronized access */
+   threaded_resource(pres)->last_batch_usage = enable ? INT8_MAX : tc->next;
+   threaded_resource(pres)->batch_generation = tc->batch_generation;
+}
+
 /* Assign src to dst while dst is uninitialized. */
 static inline void
 tc_set_resource_reference(struct pipe_resource **dst, struct pipe_resource 
*src)
@@ -525,6 +544,8 @@ tc_batch_flush(struct threaded_context *tc, bool full_copy)
                       NULL, 0);
    tc->last = tc->next;
    tc->next = next_id;
+   if (next_id == 0)
+      tc->batch_generation++;
    tc_begin_next_buffer_list(tc);
 
 }
@@ -1018,6 +1039,7 @@ threaded_resource_init(struct pipe_resource *res, bool 
allow_cpu_storage)
    tres->is_user_ptr = false;
    tres->buffer_id_unique = 0;
    tres->pending_staging_uploads = 0;
+   tres->last_batch_usage = -1;
    util_range_init(&tres->pending_staging_uploads_range);
 
    if (allow_cpu_storage &&
@@ -1460,12 +1482,20 @@ tc_set_framebuffer_state(struct pipe_context *_pipe,
    p->state.layers = fb->layers;
    p->state.nr_cbufs = nr_cbufs;
 
+   /* when unbinding, mark attachments as used for the current batch */
+   for (unsigned i = 0; i < tc->nr_cbufs; i++)
+      tc_set_resource_batch_usage_persistent(tc, tc->fb_resources[i], false);
+   tc_set_resource_batch_usage_persistent(tc, 
tc->fb_resources[PIPE_MAX_COLOR_BUFS], false);
+   tc_set_resource_batch_usage_persistent(tc, tc->fb_resolve, false);
+
    for (unsigned i = 0; i < nr_cbufs; i++) {
       p->state.cbufs[i] = NULL;
       pipe_surface_reference(&p->state.cbufs[i], fb->cbufs[i]);
       /* full tracking requires storing the fb attachment resources */
       tc->fb_resources[i] = fb->cbufs[i] ? fb->cbufs[i]->texture : NULL;
+      tc_set_resource_batch_usage_persistent(tc, tc->fb_resources[i], true);
    }
+   tc->nr_cbufs = nr_cbufs;
    memset(&tc->fb_resources[nr_cbufs], 0,
             sizeof(void*) * (PIPE_MAX_COLOR_BUFS - nr_cbufs));
    if (tc->options.parse_renderpass_info) {
@@ -1502,6 +1532,8 @@ tc_set_framebuffer_state(struct pipe_context *_pipe,
    }
    tc->fb_resources[PIPE_MAX_COLOR_BUFS] = fb->zsbuf ? fb->zsbuf->texture : 
NULL;
    tc->fb_resolve = fb->resolve;
+   tc_set_resource_batch_usage_persistent(tc, 
tc->fb_resources[PIPE_MAX_COLOR_BUFS], true);
+   tc_set_resource_batch_usage_persistent(tc, tc->fb_resolve, true);
    tc->in_renderpass = false;
    p->state.zsbuf = NULL;
    pipe_surface_reference(&p->state.zsbuf, fb->zsbuf);
@@ -1833,9 +1865,12 @@ tc_set_sampler_views(struct pipe_context *_pipe,
          memcpy(p->slot, views, sizeof(*views) * count);
 
          for (unsigned i = 0; i < count; i++) {
-            if (views[i] && views[i]->target == PIPE_BUFFER) {
-               tc_bind_buffer(tc, &tc->sampler_buffers[shader][start + i], 
next,
-                              views[i]->texture);
+            if (views[i]) {
+               if (views[i]->target == PIPE_BUFFER)
+                  tc_bind_buffer(tc, &tc->sampler_buffers[shader][start + i], 
next,
+                                 views[i]->texture);
+               else
+                  tc_set_resource_batch_usage(tc, views[i]->texture);
             } else {
                tc_unbind_buffer(&tc->sampler_buffers[shader][start + i]);
             }
@@ -1845,9 +1880,12 @@ tc_set_sampler_views(struct pipe_context *_pipe,
             p->slot[i] = NULL;
             pipe_sampler_view_reference(&p->slot[i], views[i]);
 
-            if (views[i] && views[i]->target == PIPE_BUFFER) {
-               tc_bind_buffer(tc, &tc->sampler_buffers[shader][start + i], 
next,
-                              views[i]->texture);
+            if (views[i]) {
+               if (views[i]->target == PIPE_BUFFER)
+                  tc_bind_buffer(tc, &tc->sampler_buffers[shader][start + i], 
next,
+                                 views[i]->texture);
+               else
+                  tc_set_resource_batch_usage(tc, views[i]->texture);
             } else {
                tc_unbind_buffer(&tc->sampler_buffers[shader][start + i]);
             }
@@ -1924,17 +1962,21 @@ tc_set_shader_images(struct pipe_context *_pipe,
 
          tc_set_resource_reference(&p->slot[i].resource, resource);
 
-         if (resource && resource->target == PIPE_BUFFER) {
-            tc_bind_buffer(tc, &tc->image_buffers[shader][start + i], next, 
resource);
+         if (resource) {
+            if (resource->target == PIPE_BUFFER) {
+               tc_bind_buffer(tc, &tc->image_buffers[shader][start + i], next, 
resource);
 
-            if (images[i].access & PIPE_IMAGE_ACCESS_WRITE) {
-               struct threaded_resource *tres = threaded_resource(resource);
+               if (images[i].access & PIPE_IMAGE_ACCESS_WRITE) {
+                  struct threaded_resource *tres = threaded_resource(resource);
 
-               tc_buffer_disable_cpu_storage(resource);
-               util_range_add(&tres->b, &tres->valid_buffer_range,
-                              images[i].u.buf.offset,
-                              images[i].u.buf.offset + images[i].u.buf.size);
-               writable_buffers |= BITFIELD_BIT(start + i);
+                  tc_buffer_disable_cpu_storage(resource);
+                  util_range_add(&tres->b, &tres->valid_buffer_range,
+                                 images[i].u.buf.offset,
+                                 images[i].u.buf.offset + 
images[i].u.buf.size);
+                  writable_buffers |= BITFIELD_BIT(start + i);
+               }
+            } else {
+               tc_set_resource_batch_usage(tc, resource);
             }
          } else {
             tc_unbind_buffer(&tc->image_buffers[shader][start + i]);
@@ -2705,6 +2747,8 @@ tc_texture_map(struct pipe_context *_pipe,
 
    tc_sync_msg(tc, "texture");
    tc_set_driver_thread(tc);
+   /* block all unsync texture subdata during map */
+   tc_set_resource_batch_usage_persistent(tc, resource, true);
 
    tc->bytes_mapped_estimate += box->width;
 
@@ -2953,6 +2997,9 @@ tc_texture_unmap(struct pipe_context *_pipe, struct 
pipe_transfer *transfer)
    struct threaded_context *tc = threaded_context(_pipe);
    struct threaded_transfer *ttrans = threaded_transfer(transfer);
 
+   /* enable subdata again once resource is no longer mapped */
+   tc_set_resource_batch_usage_persistent(tc, transfer->resource, false);
+
    tc_add_call(tc, TC_CALL_texture_unmap, tc_texture_unmap)->transfer = 
transfer;
 
    /* tc_texture_map directly maps the textures, but tc_texture_unmap
@@ -3135,6 +3182,7 @@ tc_texture_subdata(struct pipe_context *_pipe,
       struct tc_texture_subdata *p =
          tc_add_slot_based_call(tc, TC_CALL_texture_subdata, 
tc_texture_subdata, size);
 
+      tc_set_resource_batch_usage(tc, resource);
       tc_set_resource_reference(&p->resource, resource);
       p->level = level;
       p->usage = usage;
@@ -4252,11 +4300,13 @@ tc_resource_copy_region(struct pipe_context *_pipe,
    if (dst->target == PIPE_BUFFER)
       tc_buffer_disable_cpu_storage(dst);
 
+   tc_set_resource_batch_usage(tc, dst);
    tc_set_resource_reference(&p->dst, dst);
    p->dst_level = dst_level;
    p->dstx = dstx;
    p->dsty = dsty;
    p->dstz = dstz;
+   tc_set_resource_batch_usage(tc, src);
    tc_set_resource_reference(&p->src, src);
    p->src_level = src_level;
    p->src_box = *src_box;
@@ -4294,7 +4344,9 @@ tc_blit(struct pipe_context *_pipe, const struct 
pipe_blit_info *info)
    struct threaded_context *tc = threaded_context(_pipe);
    struct tc_blit_call *blit = tc_add_call(tc, TC_CALL_blit, tc_blit_call);
 
+   tc_set_resource_batch_usage(tc, info->dst.resource);
    tc_set_resource_reference(&blit->info.dst.resource, info->dst.resource);
+   tc_set_resource_batch_usage(tc, info->src.resource);
    tc_set_resource_reference(&blit->info.src.resource, info->src.resource);
    memcpy(&blit->info, info, sizeof(*info));
    if (tc->options.parse_renderpass_info) {
@@ -4355,6 +4407,7 @@ tc_generate_mipmap(struct pipe_context *_pipe,
    struct tc_generate_mipmap *p =
       tc_add_call(tc, TC_CALL_generate_mipmap, tc_generate_mipmap);
 
+   tc_set_resource_batch_usage(tc, res);
    tc_set_resource_reference(&p->res, res);
    p->format = format;
    p->base_level = base_level;
@@ -4386,6 +4439,7 @@ tc_flush_resource(struct pipe_context *_pipe, struct 
pipe_resource *resource)
    struct tc_resource_call *call = tc_add_call(tc, TC_CALL_flush_resource,
                                                tc_resource_call);
 
+   tc_set_resource_batch_usage(tc, resource);
    tc_set_resource_reference(&call->resource, resource);
 }
 
@@ -4412,6 +4466,7 @@ tc_invalidate_resource(struct pipe_context *_pipe,
 
    struct tc_resource_call *call = tc_add_call(tc, TC_CALL_invalidate_resource,
                                                tc_resource_call);
+   tc_set_resource_batch_usage(tc, resource);
    tc_set_resource_reference(&call->resource, resource);
 
    struct tc_renderpass_info *info = tc_get_renderpass_info(tc);
@@ -4641,6 +4696,7 @@ tc_clear_texture(struct pipe_context *_pipe, struct 
pipe_resource *res,
    struct tc_clear_texture *p =
       tc_add_call(tc, TC_CALL_clear_texture, tc_clear_texture);
 
+   tc_set_resource_batch_usage(tc, res);
    tc_set_resource_reference(&p->res, res);
    p->level = level;
    p->box = *box;
@@ -4675,6 +4731,7 @@ tc_resource_commit(struct pipe_context *_pipe, struct 
pipe_resource *res,
       tc_add_call(tc, TC_CALL_resource_commit, tc_resource_commit);
 
    tc_set_resource_reference(&p->res, res);
+   tc_set_resource_batch_usage(tc, res);
    p->level = level;
    p->box = *box;
    p->commit = commit;
diff --git a/src/gallium/auxiliary/util/u_threaded_context.h 
b/src/gallium/auxiliary/util/u_threaded_context.h
index fe988195813..42b649c2381 100644
--- a/src/gallium/auxiliary/util/u_threaded_context.h
+++ b/src/gallium/auxiliary/util/u_threaded_context.h
@@ -350,6 +350,11 @@ struct threaded_resource {
    bool is_user_ptr;
    bool allow_cpu_storage;
 
+   /* internal tag for tc indicating which batch last touched this resource */
+   int8_t last_batch_usage;
+   /* for disambiguating last_batch_usage across batch cycles */
+   uint32_t batch_generation;
+
    /* Unique buffer ID. Drivers must set it to non-zero for buffers and it must
     * be unique. Textures must set 0. Low bits are used as a hash of the ID.
     * Use util_idalloc_mt to generate these IDs.
@@ -608,8 +613,9 @@ struct threaded_context {
    unsigned max_shader_buffers;
    unsigned max_images;
    unsigned max_samplers;
+   unsigned nr_cbufs;
 
-   unsigned last, next, next_buf_list;
+   unsigned last, next, next_buf_list, batch_generation;
 
    /* The list fences that the driver should signal after the next flush.
     * If this is empty, all driver command buffers have been flushed.

Reply via email to