Mesa (main): d3d12: Support setting SSBOs on the context and turning them into descriptors

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Dec 28 00:22:18 UTC 2021


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

Author: Jesse Natalie <jenatali at microsoft.com>
Date:   Tue Dec 21 16:24:55 2021 -0800

d3d12: Support setting SSBOs on the context and turning them into descriptors

Reviewed-by: Sil Vilerino <sivileri at microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14294>

---

 src/gallium/drivers/d3d12/d3d12_context.cpp | 61 ++++++++++++++++++++++++++++-
 src/gallium/drivers/d3d12/d3d12_context.h   |  5 ++-
 src/gallium/drivers/d3d12/d3d12_draw.cpp    | 50 ++++++++++++++++++++++-
 src/gallium/drivers/d3d12/d3d12_resource.h  |  1 +
 4 files changed, 114 insertions(+), 3 deletions(-)

diff --git a/src/gallium/drivers/d3d12/d3d12_context.cpp b/src/gallium/drivers/d3d12/d3d12_context.cpp
index 72aad42e34b..b208c5c3bf0 100644
--- a/src/gallium/drivers/d3d12/d3d12_context.cpp
+++ b/src/gallium/drivers/d3d12/d3d12_context.cpp
@@ -1460,9 +1460,62 @@ d3d12_set_stream_output_targets(struct pipe_context *pctx,
    ctx->state_dirty |= D3D12_DIRTY_STREAM_OUTPUT;
 }
 
+static void
+d3d12_decrement_uav_bind_count(struct d3d12_context *ctx,
+                               enum pipe_shader_type shader,
+                               struct d3d12_resource *res) {
+   assert(res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_UAV] > 0);
+   res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_UAV]--;
+}
+
+static void
+d3d12_increment_uav_bind_count(struct d3d12_context *ctx,
+                               enum pipe_shader_type shader,
+                               struct d3d12_resource *res) {
+   res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_UAV]++;
+}
+
+static void
+d3d12_set_shader_buffers(struct pipe_context *pctx,
+                         enum pipe_shader_type shader,
+                         unsigned start_slot, unsigned count,
+                         const struct pipe_shader_buffer *buffers,
+                         unsigned writable_bitmask)
+{
+   struct d3d12_context *ctx = d3d12_context(pctx);
+   for (unsigned i = 0; i < count; ++i) {
+      struct pipe_shader_buffer *slot = &ctx->ssbo_views[shader][i + start_slot];
+      if (slot->buffer) {
+         d3d12_decrement_uav_bind_count(ctx, shader, d3d12_resource(slot->buffer));
+         pipe_resource_reference(&slot->buffer, NULL);
+      }
+
+      if (buffers && buffers[i].buffer) {
+         pipe_resource_reference(&slot->buffer, buffers[i].buffer);
+         slot->buffer_offset = buffers[i].buffer_offset;
+         slot->buffer_size = buffers[i].buffer_size;
+         d3d12_increment_uav_bind_count(ctx, shader, d3d12_resource(buffers[i].buffer));
+      } else
+         memset(slot, 0, sizeof(*slot));
+   }
+
+   if (buffers) {
+      ctx->num_ssbo_views[shader] = MAX2(ctx->num_ssbo_views[shader], count + start_slot);
+   } else {
+      ctx->num_ssbo_views[shader] = 0;
+      for (int i = start_slot + count - 1; i >= (int)start_slot; --i) {
+         if (ctx->ssbo_views[shader][i].buffer) {
+            ctx->num_ssbo_views[shader] = i;
+            break;
+         }
+      }
+   }
+   ctx->shader_dirty[shader] |= D3D12_SHADER_DIRTY_UAVS;
+}
+
 static void
 d3d12_invalidate_context_bindings(struct d3d12_context *ctx, struct d3d12_resource *res) {
-   // For each shader type, if the resource is currently bound as CBV or SRV
+   // For each shader type, if the resource is currently bound as CBV, SRV, or UAV
    // set the context shader_dirty bit.
    for (uint i = 0; i < PIPE_SHADER_TYPES; ++i) {
       if (res->bind_counts[i][D3D12_RESOURCE_BINDING_TYPE_CBV] > 0) {
@@ -1472,6 +1525,10 @@ d3d12_invalidate_context_bindings(struct d3d12_context *ctx, struct d3d12_resour
       if (res->bind_counts[i][D3D12_RESOURCE_BINDING_TYPE_SRV] > 0) {
          ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_SAMPLER_VIEWS;
       }
+
+      if (res->bind_counts[i][D3D12_RESOURCE_BINDING_TYPE_UAV] > 0) {
+         ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_UAVS;
+      }
    }
 }
 
@@ -1966,6 +2023,8 @@ d3d12_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
    ctx->base.stream_output_target_destroy = d3d12_stream_output_target_destroy;
    ctx->base.set_stream_output_targets = d3d12_set_stream_output_targets;
 
+   ctx->base.set_shader_buffers = d3d12_set_shader_buffers;
+
    ctx->base.get_timestamp = d3d12_get_timestamp;
 
    ctx->base.clear = d3d12_clear;
diff --git a/src/gallium/drivers/d3d12/d3d12_context.h b/src/gallium/drivers/d3d12/d3d12_context.h
index 089e93b6fe8..5be0b06a9d6 100644
--- a/src/gallium/drivers/d3d12/d3d12_context.h
+++ b/src/gallium/drivers/d3d12/d3d12_context.h
@@ -69,6 +69,7 @@ enum d3d12_shader_dirty_flags
    D3D12_SHADER_DIRTY_CONSTBUF      = (1 << 0),
    D3D12_SHADER_DIRTY_SAMPLER_VIEWS = (1 << 1),
    D3D12_SHADER_DIRTY_SAMPLERS      = (1 << 2),
+   D3D12_SHADER_DIRTY_UAVS          = (1 << 3),
 };
 
 #define D3D12_DIRTY_PSO (D3D12_DIRTY_BLEND | D3D12_DIRTY_RASTERIZER | D3D12_DIRTY_ZSA | \
@@ -78,7 +79,7 @@ enum d3d12_shader_dirty_flags
                          D3D12_DIRTY_STRIP_CUT_VALUE)
 
 #define D3D12_SHADER_DIRTY_ALL (D3D12_SHADER_DIRTY_CONSTBUF | D3D12_SHADER_DIRTY_SAMPLER_VIEWS | \
-                                D3D12_SHADER_DIRTY_SAMPLERS)
+                                D3D12_SHADER_DIRTY_SAMPLERS | D3D12_SHADER_DIRTY_UAVS)
 
 enum d3d12_binding_type {
    D3D12_BINDING_CONSTANT_BUFFER,
@@ -181,6 +182,8 @@ struct d3d12_context {
    struct pipe_sampler_view *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_SAMPLER_VIEWS];
    unsigned num_sampler_views[PIPE_SHADER_TYPES];
    unsigned has_int_samplers;
+   struct pipe_shader_buffer ssbo_views[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_BUFFERS];
+   unsigned num_ssbo_views[PIPE_SHADER_TYPES];
    struct d3d12_sampler_state *samplers[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS];
    unsigned num_samplers[PIPE_SHADER_TYPES];
    D3D12_INDEX_BUFFER_VIEW ibv;
diff --git a/src/gallium/drivers/d3d12/d3d12_draw.cpp b/src/gallium/drivers/d3d12/d3d12_draw.cpp
index 77372b79cc0..5097c7536ab 100644
--- a/src/gallium/drivers/d3d12/d3d12_draw.cpp
+++ b/src/gallium/drivers/d3d12/d3d12_draw.cpp
@@ -138,6 +138,45 @@ fill_srv_descriptors(struct d3d12_context *ctx,
    return table_start.gpu_handle;
 }
 
+static D3D12_GPU_DESCRIPTOR_HANDLE
+fill_uav_descriptors(struct d3d12_context *ctx,
+                     const struct d3d12_shader *shader,
+                     int stage)
+{
+   struct d3d12_batch *batch = d3d12_current_batch(ctx);
+   struct d3d12_descriptor_handle table_start;
+
+   d2d12_descriptor_heap_get_next_handle(batch->view_heap, &table_start);
+
+   for (unsigned i = 0; i < shader->nir->info.num_ssbos; i++)
+   {
+      struct pipe_shader_buffer *view = &ctx->ssbo_views[stage][i];
+
+      D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc;
+      uav_desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
+      uav_desc.Format = DXGI_FORMAT_R32_TYPELESS;
+      uav_desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW;
+      uav_desc.Buffer.StructureByteStride = 0;
+      uav_desc.Buffer.CounterOffsetInBytes = 0;
+      ID3D12Resource *d3d12_res = nullptr;
+      if (view->buffer) {
+         struct d3d12_resource *res = d3d12_resource(view->buffer);
+         uint64_t res_offset = 0;
+         d3d12_res = d3d12_resource_underlying(res, &res_offset);
+         d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_BIND_INVALIDATE_NONE);
+         uav_desc.Buffer.FirstElement = (view->buffer_offset + res_offset) / 4;
+         uav_desc.Buffer.NumElements = DIV_ROUND_UP(view->buffer_size, 4);
+         d3d12_batch_reference_resource(batch, res, true);
+      }
+
+      struct d3d12_descriptor_handle handle;
+      d3d12_descriptor_heap_alloc_handle(batch->view_heap, &handle);
+      d3d12_screen(ctx->base.screen)->dev->CreateUnorderedAccessView(d3d12_res, nullptr, &uav_desc, handle.cpu_handle);
+   }
+
+   return table_start.gpu_handle;
+}
+
 static D3D12_GPU_DESCRIPTOR_HANDLE
 fill_sampler_descriptors(struct d3d12_context *ctx,
                          const struct d3d12_shader_selector *shader_sel,
@@ -229,6 +268,7 @@ check_descriptors_left(struct d3d12_context *ctx)
 
       needed_descs += shader->current->num_cb_bindings;
       needed_descs += shader->current->end_srv_binding - shader->current->begin_srv_binding;
+      needed_descs += shader->current->nir->info.num_ssbos;
    }
 
    if (d3d12_descriptor_heap_get_remaining_handles(batch->view_heap) < needed_descs)
@@ -250,7 +290,7 @@ check_descriptors_left(struct d3d12_context *ctx)
    return true;
 }
 
-#define MAX_DESCRIPTOR_TABLES (D3D12_GFX_SHADER_STAGES * 3)
+#define MAX_DESCRIPTOR_TABLES (D3D12_GFX_SHADER_STAGES * 4)
 
 static unsigned
 update_graphics_root_parameters(struct d3d12_context *ctx,
@@ -300,6 +340,14 @@ update_graphics_root_parameters(struct d3d12_context *ctx,
          ctx->cmdlist->SetGraphicsRoot32BitConstants(num_params, size, constants, 0);
          num_params++;
       }
+      if (shader->nir->info.num_ssbos > 0) {
+         if (dirty & D3D12_SHADER_DIRTY_UAVS) {
+            assert(num_root_desciptors < MAX_DESCRIPTOR_TABLES);
+            root_desc_tables[num_root_desciptors] = fill_uav_descriptors(ctx, shader, i);
+            root_desc_indices[num_root_desciptors++] = num_params;
+         }
+         num_params++;
+      }
    }
    return num_root_desciptors;
 }
diff --git a/src/gallium/drivers/d3d12/d3d12_resource.h b/src/gallium/drivers/d3d12/d3d12_resource.h
index 49b707739e7..e9532d1369f 100644
--- a/src/gallium/drivers/d3d12/d3d12_resource.h
+++ b/src/gallium/drivers/d3d12/d3d12_resource.h
@@ -35,6 +35,7 @@ struct pipe_screen;
 enum d3d12_resource_binding_type {
    D3D12_RESOURCE_BINDING_TYPE_SRV,
    D3D12_RESOURCE_BINDING_TYPE_CBV,
+   D3D12_RESOURCE_BINDING_TYPE_UAV,
    D3D12_RESOURCE_BINDING_TYPES
 };
 



More information about the mesa-commit mailing list