Mesa (main): zink: implement sparse shader instructions in ntv

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Jan 20 16:08:02 UTC 2022


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

Author: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Date:   Thu Jan 13 12:25:58 2022 -0500

zink: implement sparse shader instructions in ntv

this automatically wraps the results into the required struct(int, result) type,
handling will come next

note that there is no cts coverage for sparseImageLoadARB, so this is purely
hypothetical

Acked-by: Dave Airlie <airlied at redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14381>

---

 .../drivers/zink/nir_to_spirv/nir_to_spirv.c       | 13 +++--
 .../drivers/zink/nir_to_spirv/spirv_builder.c      | 65 ++++++++++++++++------
 .../drivers/zink/nir_to_spirv/spirv_builder.h      | 12 ++--
 3 files changed, 65 insertions(+), 25 deletions(-)

diff --git a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c
index ccd5a338abd..f98a667ffaa 100644
--- a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c
+++ b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c
@@ -2394,6 +2394,7 @@ emit_image_deref_store(struct ntv_context *ctx, nir_intrinsic_instr *intr)
 static void
 emit_image_deref_load(struct ntv_context *ctx, nir_intrinsic_instr *intr)
 {
+   bool sparse = intr->intrinsic == nir_intrinsic_image_deref_sparse_load;
    SpvId img_var = get_src(ctx, &intr->src[0]);
    nir_deref_instr *deref = nir_src_as_deref(intr->src[0]);
    nir_variable *var = deref->deref_type == nir_deref_type_var ? deref->var : get_var_from_image(ctx, img_var);
@@ -2403,9 +2404,10 @@ emit_image_deref_load(struct ntv_context *ctx, nir_intrinsic_instr *intr)
    SpvId img = spirv_builder_emit_load(&ctx->builder, img_type, img_var);
    SpvId coord = get_image_coords(ctx, type, &intr->src[1]);
    SpvId sample = glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_MS ? get_src(ctx, &intr->src[2]) : 0;
+   SpvId dest_type = spirv_builder_type_vector(&ctx->builder, base_type, nir_dest_num_components(intr->dest));
    SpvId result = spirv_builder_emit_image_read(&ctx->builder,
-                                 spirv_builder_type_vector(&ctx->builder, base_type, nir_dest_num_components(intr->dest)),
-                                 img, coord, 0, sample, 0);
+                                 dest_type,
+                                 img, coord, 0, sample, 0, sparse);
    store_dest(ctx, &intr->dest, result, nir_type_float);
 }
 
@@ -2703,6 +2705,7 @@ emit_intrinsic(struct ntv_context *ctx, nir_intrinsic_instr *intr)
       emit_image_deref_store(ctx, intr);
       break;
 
+   case nir_intrinsic_image_deref_sparse_load:
    case nir_intrinsic_image_deref_load:
       emit_image_deref_load(ctx, intr);
       break;
@@ -3101,17 +3104,17 @@ emit_tex(struct ntv_context *ctx, nir_tex_instr *tex)
             spirv_builder_emit_cap(&ctx->builder, SpvCapabilityImageGatherExtended);
          result = spirv_builder_emit_image_gather(&ctx->builder, dest_type,
                                                  load, coord, emit_uint_const(ctx, 32, tex->component),
-                                                 lod, sample, const_offset, offset, dref);
+                                                 lod, sample, const_offset, offset, dref, tex->is_sparse);
       } else
          result = spirv_builder_emit_image_fetch(&ctx->builder, actual_dest_type,
-                                                 image, coord, lod, sample, const_offset, offset);
+                                                 image, coord, lod, sample, const_offset, offset, tex->is_sparse);
    } else {
       result = spirv_builder_emit_image_sample(&ctx->builder,
                                                actual_dest_type, load,
                                                coord,
                                                proj != 0,
                                                lod, bias, dref, dx, dy,
-                                               const_offset, offset);
+                                               const_offset, offset, tex->is_sparse);
    }
 
    spirv_builder_emit_decoration(&ctx->builder, result,
diff --git a/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c b/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c
index d93d47d11e4..0a02476c4a9 100644
--- a/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c
+++ b/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c
@@ -742,6 +742,15 @@ spirv_builder_emit_vote(struct spirv_builder *b, SpvOp op, SpvId src)
                                    spirv_builder_const_uint(b, 32, SpvScopeWorkgroup), src);
 }
 
+static SpvId
+sparse_wrap_result_type(struct spirv_builder *b, SpvId result_type)
+{
+   SpvId types[2];
+   types[0] = spirv_builder_type_uint(b, 32);
+   types[1] = result_type;
+   return spirv_builder_type_struct(b, types, 2);
+}
+
 SpvId
 spirv_builder_emit_image_sample(struct spirv_builder *b,
                                 SpvId result_type,
@@ -754,19 +763,34 @@ spirv_builder_emit_image_sample(struct spirv_builder *b,
                                 SpvId dx,
                                 SpvId dy,
                                 SpvId const_offset,
-                                SpvId offset)
+                                SpvId offset,
+                                bool sparse)
 {
    SpvId result = spirv_builder_new_id(b);
 
-   int opcode = SpvOpImageSampleImplicitLod;
    int operands = 5;
-   if (proj)
-      opcode += SpvOpImageSampleProjImplicitLod - SpvOpImageSampleImplicitLod;
-   if (lod || (dx && dy))
-      opcode += SpvOpImageSampleExplicitLod - SpvOpImageSampleImplicitLod;
-   if (dref) {
-      opcode += SpvOpImageSampleDrefImplicitLod - SpvOpImageSampleImplicitLod;
-      operands++;
+   int opcode;
+   if (sparse) {
+      opcode = SpvOpImageSparseSampleImplicitLod;
+      if (proj)
+         opcode += SpvOpImageSparseSampleProjImplicitLod - SpvOpImageSparseSampleImplicitLod;
+      if (lod || (dx && dy))
+         opcode += SpvOpImageSparseSampleExplicitLod - SpvOpImageSparseSampleImplicitLod;
+      if (dref) {
+         opcode += SpvOpImageSparseSampleDrefImplicitLod - SpvOpImageSparseSampleImplicitLod;
+         operands++;
+      }
+      result_type = sparse_wrap_result_type(b, result_type);
+   } else {
+      opcode = SpvOpImageSampleImplicitLod;
+      if (proj)
+         opcode += SpvOpImageSampleProjImplicitLod - SpvOpImageSampleImplicitLod;
+      if (lod || (dx && dy))
+         opcode += SpvOpImageSampleExplicitLod - SpvOpImageSampleImplicitLod;
+      if (dref) {
+         opcode += SpvOpImageSampleDrefImplicitLod - SpvOpImageSampleImplicitLod;
+         operands++;
+      }
    }
 
    SpvImageOperandsMask operand_mask = SpvImageOperandsMaskNone;
@@ -842,13 +866,16 @@ spirv_builder_emit_image_read(struct spirv_builder *b,
                               SpvId coordinate,
                               SpvId lod,
                               SpvId sample,
-                              SpvId offset)
+                              SpvId offset,
+                              bool sparse)
 {
    SpvId result = spirv_builder_new_id(b);
 
    SpvImageOperandsMask operand_mask = SpvImageOperandsMaskNone;
    SpvId extra_operands[5];
    int num_extra_operands = 1;
+   if (sparse)
+      result_type = sparse_wrap_result_type(b, result_type);
    if (lod) {
       extra_operands[num_extra_operands++] = lod;
       operand_mask |= SpvImageOperandsLodMask;
@@ -865,7 +892,7 @@ spirv_builder_emit_image_read(struct spirv_builder *b,
    extra_operands[0] = operand_mask;
 
    spirv_buffer_prepare(&b->instructions, b->mem_ctx, 5 + num_extra_operands);
-   spirv_buffer_emit_word(&b->instructions, SpvOpImageRead |
+   spirv_buffer_emit_word(&b->instructions, (sparse ? SpvOpImageSparseRead : SpvOpImageRead) |
                           ((5 + num_extra_operands) << 16));
    spirv_buffer_emit_word(&b->instructions, result_type);
    spirv_buffer_emit_word(&b->instructions, result);
@@ -923,10 +950,11 @@ spirv_builder_emit_image_gather(struct spirv_builder *b,
                                SpvId sample,
                                SpvId const_offset,
                                SpvId offset,
-                               SpvId dref)
+                               SpvId dref,
+                               bool sparse)
 {
    SpvId result = spirv_builder_new_id(b);
-   SpvId op = SpvOpImageGather;
+   SpvId op = sparse ? SpvOpImageSparseGather : SpvOpImageGather;
 
    SpvImageOperandsMask operand_mask = SpvImageOperandsMaskNone;
    SpvId extra_operands[4];
@@ -948,7 +976,9 @@ spirv_builder_emit_image_gather(struct spirv_builder *b,
       operand_mask |= SpvImageOperandsOffsetMask;
    }
    if (dref)
-      op = SpvOpImageDrefGather;
+      op = sparse ? SpvOpImageSparseDrefGather : SpvOpImageDrefGather;
+   if (sparse)
+      result_type = sparse_wrap_result_type(b, result_type);
    /* finalize num_extra_operands / extra_operands */
    extra_operands[0] = operand_mask;
 
@@ -976,7 +1006,8 @@ spirv_builder_emit_image_fetch(struct spirv_builder *b,
                                SpvId lod,
                                SpvId sample,
                                SpvId const_offset,
-                               SpvId offset)
+                               SpvId offset,
+                               bool sparse)
 {
    SpvId result = spirv_builder_new_id(b);
 
@@ -999,12 +1030,14 @@ spirv_builder_emit_image_fetch(struct spirv_builder *b,
       extra_operands[num_extra_operands++] = offset;
       operand_mask |= SpvImageOperandsOffsetMask;
    }
+   if (sparse)
+      result_type = sparse_wrap_result_type(b, result_type);
 
    /* finalize num_extra_operands / extra_operands */
    extra_operands[0] = operand_mask;
 
    spirv_buffer_prepare(&b->instructions, b->mem_ctx, 5 + num_extra_operands);
-   spirv_buffer_emit_word(&b->instructions, SpvOpImageFetch |
+   spirv_buffer_emit_word(&b->instructions, (sparse ? SpvOpImageSparseFetch : SpvOpImageFetch) |
                           ((5 + num_extra_operands) << 16));
    spirv_buffer_emit_word(&b->instructions, result_type);
    spirv_buffer_emit_word(&b->instructions, result);
diff --git a/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.h b/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.h
index d18c101b394..15a27a17f44 100644
--- a/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.h
+++ b/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.h
@@ -283,7 +283,8 @@ spirv_builder_emit_image_sample(struct spirv_builder *b,
                                 SpvId dx,
                                 SpvId dy,
                                 SpvId const_offset,
-                                SpvId offset);
+                                SpvId offset,
+                                bool sparse);
 
 SpvId
 spirv_builder_emit_image(struct spirv_builder *b, SpvId result_type,
@@ -303,7 +304,8 @@ spirv_builder_emit_image_read(struct spirv_builder *b,
                               SpvId coordinate,
                               SpvId lod,
                               SpvId sample,
-                              SpvId offset);
+                              SpvId offset,
+                              bool sparse);
 
 void
 spirv_builder_emit_image_write(struct spirv_builder *b,
@@ -322,7 +324,8 @@ spirv_builder_emit_image_fetch(struct spirv_builder *b,
                                SpvId lod,
                                SpvId sample,
                                SpvId const_offset,
-                               SpvId offset);
+                               SpvId offset,
+                               bool sparse);
 SpvId
 spirv_builder_emit_image_gather(struct spirv_builder *b,
                                SpvId result_type,
@@ -333,7 +336,8 @@ spirv_builder_emit_image_gather(struct spirv_builder *b,
                                SpvId sample,
                                SpvId const_offset,
                                SpvId offset,
-                               SpvId dref);
+                               SpvId dref,
+                               bool sparse);
 
 SpvId
 spirv_builder_emit_image_query_size(struct spirv_builder *b,



More information about the mesa-commit mailing list