zink: reapply resource/surface refs after app flushes
authorMike Blumenkrantz <michael.blumenkrantz@gmail.com>
Tue, 26 Jan 2021 14:37:17 +0000 (09:37 -0500)
committerMarge Bot <eric+marge@anholt.net>
Mon, 31 May 2021 14:39:57 +0000 (14:39 +0000)
instead of doing this during descriptor update, we can automatically handle
this rollover

Reviewed-by: Dave Airlie <airlied@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10997>

src/gallium/drivers/zink/zink_context.c
src/gallium/drivers/zink/zink_context.h
src/gallium/drivers/zink/zink_draw.c

index 70f297c..d7adcb2 100644 (file)
@@ -935,7 +935,8 @@ zink_set_constant_buffer(struct pipe_context *pctx,
          new_res->bind_stages |= 1 << shader;
          new_res->ubo_bind_count[shader == PIPE_SHADER_COMPUTE]++;
          new_res->bind_count[shader == PIPE_SHADER_COMPUTE]++;
-         zink_batch_reference_resource_rw(&ctx->batch, new_res, false);
+         if (!ctx->descriptor_refs_dirty[shader == PIPE_SHADER_COMPUTE])
+            zink_batch_reference_resource_rw(&ctx->batch, new_res, false);
          zink_resource_buffer_barrier(ctx, NULL, new_res, VK_ACCESS_UNIFORM_READ_BIT,
                                       zink_pipeline_flags_from_stage(zink_shader_stage(shader)));
       }
@@ -1013,9 +1014,9 @@ zink_set_shader_buffers(struct pipe_context *pctx,
          if (ctx->writable_ssbos[p_stage] & BITFIELD64_BIT(start_slot + i)) {
             res->write_bind_count[p_stage == PIPE_SHADER_COMPUTE]++;
             access |= VK_ACCESS_SHADER_WRITE_BIT;
-            zink_batch_reference_resource_rw(&ctx->batch, res, true);
-         } else
-            zink_batch_reference_resource_rw(&ctx->batch, res, false);
+         }
+         if (!ctx->descriptor_refs_dirty[p_stage == PIPE_SHADER_COMPUTE])
+            zink_batch_reference_resource_rw(&ctx->batch, res, access & VK_ACCESS_SHADER_WRITE_BIT);
          pipe_resource_reference(&ssbo->buffer, &res->base.b);
          ssbo->buffer_offset = buffers[i].buffer_offset;
          ssbo->buffer_size = MIN2(buffers[i].buffer_size, res->obj->size - ssbo->buffer_offset);
@@ -1130,11 +1131,8 @@ zink_set_shader_images(struct pipe_context *pctx,
          if (image_view->base.access & PIPE_IMAGE_ACCESS_WRITE) {
             zink_resource(image_view->base.resource)->write_bind_count[p_stage == PIPE_SHADER_COMPUTE]++;
             access |= VK_ACCESS_SHADER_WRITE_BIT;
-            zink_batch_reference_resource_rw(&ctx->batch, zink_resource(image_view->base.resource), true);
          }
          if (image_view->base.access & PIPE_IMAGE_ACCESS_READ) {
-            if (!access)
-               zink_batch_reference_resource_rw(&ctx->batch, zink_resource(image_view->base.resource), false);
             access |= VK_ACCESS_SHADER_READ_BIT;
          }
          if (images[i].resource->target == PIPE_BUFFER) {
@@ -1144,7 +1142,6 @@ zink_set_shader_images(struct pipe_context *pctx,
                            images[i].u.buf.offset + images[i].u.buf.size);
             zink_resource_buffer_barrier(ctx, NULL, res, access,
                                          zink_pipeline_flags_from_stage(zink_shader_stage(p_stage)));
-            zink_batch_reference_bufferview(&ctx->batch, image_view->buffer_view);
          } else {
             struct pipe_surface tmpl = {};
             tmpl.format = images[i].format;
@@ -1166,7 +1163,11 @@ zink_set_shader_images(struct pipe_context *pctx,
                                            zink_pipeline_flags_from_stage(zink_shader_stage(p_stage)));
             else
                _mesa_set_add(ctx->need_barriers[0], res);
-            zink_batch_reference_surface(&ctx->batch, image_view->surface);
+         }
+         if (!ctx->descriptor_refs_dirty[p_stage == PIPE_SHADER_COMPUTE]) {
+            zink_batch_reference_resource_rw(&ctx->batch, zink_resource(image_view->base.resource),
+                                             zink_resource_access_is_write(access));
+            zink_batch_reference_image_view(&ctx->batch, image_view);
          }
          update = true;
       } else if (image_view->base.resource) {
@@ -1226,7 +1227,6 @@ zink_set_sampler_views(struct pipe_context *pctx,
       unbind_samplerview(ctx, shader_type, start_slot + i);
       if (b && b->base.texture) {
          struct zink_resource *res = zink_resource(b->base.texture);
-         zink_batch_reference_resource_rw(&ctx->batch, res, false);
          if (res->base.b.target == PIPE_BUFFER) {
             if (res->bind_history & BITFIELD64_BIT(ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW)) {
                /* if this resource has been rebound while it wasn't set here,
@@ -1244,8 +1244,8 @@ zink_set_sampler_views(struct pipe_context *pctx,
             }
             zink_resource_buffer_barrier(ctx, NULL, res, VK_ACCESS_SHADER_READ_BIT,
                                          zink_pipeline_flags_from_stage(zink_shader_stage(shader_type)));
-            zink_batch_reference_bufferview(&ctx->batch, b->buffer_view);
-            update |= !a || a->buffer_view->buffer_view != b->buffer_view->buffer_view;
+            if (!a || a->buffer_view->buffer_view != b->buffer_view->buffer_view)
+               update = true;
          } else if (!res->obj->is_buffer) {
              if (res->obj != b->image_view->obj) {
                 struct pipe_surface *psurf = &b->image_view->base;
@@ -1253,20 +1253,22 @@ zink_set_sampler_views(struct pipe_context *pctx,
                 zink_rebind_surface(ctx, &psurf);
                 b->image_view = zink_surface(psurf);
                 update |= iv != b->image_view->image_view;
-             } else {
-                if (a != b)
-                   update = true;
-                if (shader_type == PIPE_SHADER_COMPUTE)
-                   zink_resource_image_barrier(ctx, NULL, res, get_layout_for_binding(res, ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW),
-                                               VK_ACCESS_SHADER_READ_BIT,
-                                               zink_pipeline_flags_from_stage(zink_shader_stage(shader_type)));
-                else
-                   _mesa_set_add(ctx->need_barriers[0], res);
-             }
+             } else  if (a != b)
+                update = true;
 
              res->sampler_binds[shader_type] |= BITFIELD_BIT(start_slot + i);
-             zink_batch_reference_surface(&ctx->batch, b->image_view);
-             update |= !a || a->image_view->image_view != b->image_view->image_view;
+             if (shader_type == PIPE_SHADER_COMPUTE)
+                zink_resource_image_barrier(ctx, NULL, res, get_layout_for_binding(res, ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW),
+                                            VK_ACCESS_SHADER_READ_BIT,
+                                            zink_pipeline_flags_from_stage(zink_shader_stage(shader_type)));
+             else
+                _mesa_set_add(ctx->need_barriers[0], res);
+             if (!a)
+                update = true;
+         }
+         if (!ctx->descriptor_refs_dirty[shader_type == PIPE_SHADER_COMPUTE]) {
+            zink_batch_reference_resource_rw(&ctx->batch, res, false);
+            zink_batch_reference_sampler_view(&ctx->batch, b);
          }
          res->bind_count[shader_type == PIPE_SHADER_COMPUTE]++;
          res->bind_history |= BITFIELD_BIT(ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW);
@@ -1583,6 +1585,100 @@ sync_flush(struct zink_context *ctx, struct zink_batch_state *bs)
       util_queue_fence_wait(&bs->flush_completed);
 }
 
+static inline VkAccessFlags
+get_access_flags_for_binding(struct zink_context *ctx, enum zink_descriptor_type type, enum pipe_shader_type stage, unsigned idx)
+{
+   VkAccessFlags flags = 0;
+   switch (type) {
+   case ZINK_DESCRIPTOR_TYPE_UBO:
+      return VK_ACCESS_UNIFORM_READ_BIT;
+   case ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW:
+      return VK_ACCESS_SHADER_READ_BIT;
+   case ZINK_DESCRIPTOR_TYPE_SSBO: {
+      flags = VK_ACCESS_SHADER_READ_BIT;
+      if (ctx->writable_ssbos[stage] & (1 << idx))
+         flags |= VK_ACCESS_SHADER_WRITE_BIT;
+      return flags;
+   }
+   case ZINK_DESCRIPTOR_TYPE_IMAGE: {
+      struct zink_image_view *image_view = &ctx->image_views[stage][idx];
+      if (image_view->base.access & PIPE_IMAGE_ACCESS_READ)
+         flags |= VK_ACCESS_SHADER_READ_BIT;
+      if (image_view->base.access & PIPE_IMAGE_ACCESS_WRITE)
+         flags |= VK_ACCESS_SHADER_WRITE_BIT;
+      return flags;
+   }
+   default:
+      break;
+   }
+   unreachable("ACK");
+   return 0;
+}
+
+static inline void
+add_surface_ref(struct zink_context *ctx, struct zink_resource *res, union zink_descriptor_surface *surface)
+{
+   if (!surface)
+      return;
+   if (res->obj->is_buffer) {
+      if (surface->bufferview)
+         zink_batch_reference_bufferview(&ctx->batch, surface->bufferview);
+   } else if (surface->surface)
+         zink_batch_reference_surface(&ctx->batch, surface->surface);
+}
+
+static void
+update_resource_refs_for_stage(struct zink_context *ctx, enum pipe_shader_type stage)
+{
+   struct zink_batch *batch = &ctx->batch;
+   unsigned max_slot[] = {
+      [ZINK_DESCRIPTOR_TYPE_UBO] = ctx->di.num_ubos[stage],
+      [ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW] = ctx->di.num_samplers[stage],
+      [ZINK_DESCRIPTOR_TYPE_SSBO] = ctx->di.num_ssbos[stage],
+      [ZINK_DESCRIPTOR_TYPE_IMAGE] = ctx->di.num_images[stage]
+   };
+   for (unsigned i = 0; i < ZINK_DESCRIPTOR_TYPES; i++) {
+      for (unsigned j = 0; j < max_slot[i]; j++) {
+         if (ctx->di.descriptor_res[i][stage][j]) {
+            struct zink_resource *res = ctx->di.descriptor_res[i][stage][j];
+            if (!res)
+               continue;
+            bool is_write = zink_resource_access_is_write(get_access_flags_for_binding(ctx, i, stage, j));
+            zink_batch_reference_resource_rw(batch, res, is_write);
+
+            struct zink_sampler_view *sv = zink_sampler_view(ctx->sampler_views[stage][j]);
+            struct zink_sampler_state *sampler_state = ctx->sampler_states[stage][j];
+            struct zink_image_view *iv = &ctx->image_views[stage][j];
+            if (sampler_state && i == ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW && j <= ctx->di.num_samplers[stage])
+               zink_batch_usage_set(&sampler_state->batch_uses, ctx->curr_batch);
+            if (sv && i == ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW && j <= ctx->di.num_sampler_views[stage])
+               zink_batch_reference_sampler_view(batch, sv);
+            else if (i == ZINK_DESCRIPTOR_TYPE_IMAGE && j <= ctx->di.num_images[stage])
+               zink_batch_reference_image_view(batch, iv);
+         }
+      }
+   }
+}
+
+void
+zink_update_descriptor_refs(struct zink_context *ctx, bool compute)
+{
+   struct zink_batch *batch = &ctx->batch;
+   if (compute)
+      update_resource_refs_for_stage(ctx, PIPE_SHADER_COMPUTE);
+   else {
+      for (unsigned i = 0; i < ZINK_SHADER_COUNT; i++)
+         update_resource_refs_for_stage(ctx, i);
+      unsigned vertex_buffers_enabled_mask = ctx->gfx_pipeline_state.vertex_buffers_enabled_mask;
+      unsigned last_vbo = util_last_bit(vertex_buffers_enabled_mask);
+      for (unsigned i = 0; i < last_vbo + 1; i++) {
+         if (ctx->vertex_buffers[i].buffer.resource)
+            zink_batch_reference_resource_rw(batch, zink_resource(ctx->vertex_buffers[i].buffer.resource), false);
+      }
+   }
+   ctx->descriptor_refs_dirty[compute] = false;
+}
+
 static void
 flush_batch(struct zink_context *ctx, bool sync)
 {
@@ -1604,6 +1700,7 @@ flush_batch(struct zink_context *ctx, bool sync)
       zink_start_batch(ctx, batch);
       if (zink_screen(ctx->base.screen)->info.have_EXT_transform_feedback && ctx->num_so_targets)
          ctx->dirty_so_targets = true;
+      ctx->descriptor_refs_dirty[0] = ctx->descriptor_refs_dirty[1] = true;
    }
 }
 
index edf2189..0196d3d 100644 (file)
@@ -251,6 +251,7 @@ struct zink_context {
       union zink_descriptor_surface sampler_surfaces[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS];
       union zink_descriptor_surface image_surfaces[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_IMAGES];
    } di;
+   bool descriptor_refs_dirty[2];
    struct set *need_barriers[2]; //gfx, compute
    struct set update_barriers[2][2]; //[gfx, compute][current, next]
    uint8_t barrier_set_idx[2];
@@ -397,4 +398,6 @@ zink_buffer_view_reference(struct zink_screen *screen,
    if (dst) *dst = src;
 }
 
+void
+zink_update_descriptor_refs(struct zink_context *ctx, bool compute);
 #endif
index efcb903..81761ea 100644 (file)
@@ -524,6 +524,9 @@ zink_draw_vbo(struct pipe_context *pctx,
    if (zink_program_has_descriptors(&gfx_program->base))
       screen->descriptors_update(ctx, false);
 
+   if (ctx->descriptor_refs_dirty[0])
+      zink_update_descriptor_refs(ctx, false);
+
    struct zink_batch *batch = zink_batch_rp(ctx);
    VkViewport viewports[PIPE_MAX_VIEWPORTS];
    for (unsigned i = 0; i < ctx->vp_state.num_viewports; i++) {
@@ -778,6 +781,8 @@ zink_launch_grid(struct pipe_context *pctx, const struct pipe_grid_info *info)
    if (zink_program_has_descriptors(&comp_program->base))
       screen->descriptors_update(ctx, true);
 
+   if (ctx->descriptor_refs_dirty[1])
+      zink_update_descriptor_refs(ctx, true);
 
    vkCmdBindPipeline(batch->state->cmdbuf, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);