Mesa (master): vtn: Handle ZeroExtend/SignExtend image operands

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Apr 13 18:05:25 UTC 2021


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

Author: Connor Abbott <cwabbott0 at gmail.com>
Date:   Mon Dec  7 14:54:25 2020 +0100

vtn: Handle ZeroExtend/SignExtend image operands

These decorations allow you to override the signedness of image
instructions. This means that we have to override the type we get from
the sampled image.

Apparently both Intel and AMD get the type from the descriptor rather
than the instruction, but this appears to not be the case with Adreno,
which is why this wasn't noticed until now. So this probably won't fix
any preexisting bugs, but it's required to fix
dEQP-VK.image.extend_operands_spirv1p4.* when exposing VK_KHR_spirv_1_4
on turnip.

Reviewed-by: Jason Ekstrand <jason at jlekstrand.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7968>

---

 src/compiler/spirv/spirv_to_nir.c | 47 +++++++++++++++++++++++++++++++--------
 1 file changed, 38 insertions(+), 9 deletions(-)

diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c
index d79582b16b2..b261a3e081e 100644
--- a/src/compiler/spirv/spirv_to_nir.c
+++ b/src/compiler/spirv/spirv_to_nir.c
@@ -2542,6 +2542,28 @@ non_uniform_decoration_cb(struct vtn_builder *b,
    }
 }
 
+/* Apply SignExtend/ZeroExtend operands to get the actual result type for
+ * image read/sample operations and source type for write operations.
+ */
+static nir_alu_type
+get_image_type(struct vtn_builder *b, nir_alu_type type, unsigned operands)
+{
+   unsigned extend_operands =
+      operands & (SpvImageOperandsSignExtendMask | SpvImageOperandsZeroExtendMask);
+   vtn_fail_if(nir_alu_type_get_base_type(type) == nir_type_float && extend_operands,
+               "SignExtend/ZeroExtend used on floating-point texel type");
+   vtn_fail_if(extend_operands ==
+               (SpvImageOperandsSignExtendMask | SpvImageOperandsZeroExtendMask),
+               "SignExtend and ZeroExtend both specified");
+
+   if (operands & SpvImageOperandsSignExtendMask)
+      return nir_type_int | nir_alu_type_get_type_size(type);
+   if (operands & SpvImageOperandsZeroExtendMask)
+      return nir_type_uint | nir_alu_type_get_type_size(type);
+
+   return type;
+}
+
 static void
 vtn_handle_texture(struct vtn_builder *b, SpvOp opcode,
                    const uint32_t *w, unsigned count)
@@ -2826,8 +2848,9 @@ vtn_handle_texture(struct vtn_builder *b, SpvOp opcode,
 
    /* Now we need to handle some number of optional arguments */
    struct vtn_value *gather_offsets = NULL;
+   uint32_t operands = SpvImageOperandsMaskNone;
    if (idx < count) {
-      uint32_t operands = w[idx];
+      operands = w[idx];
 
       if (operands & SpvImageOperandsBiasMask) {
          vtn_assert(texop == nir_texop_tex ||
@@ -2958,6 +2981,7 @@ vtn_handle_texture(struct vtn_builder *b, SpvOp opcode,
                   "SPIR-V return type mismatches image type. This is only valid "
                   "for untyped images (OpenCL).");
       dest_type = nir_get_nir_type_for_glsl_base_type(ret_base);
+      dest_type = get_image_type(b, dest_type, operands);
    }
 
    instr->dest_type = dest_type;
@@ -3104,6 +3128,7 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode,
    struct vtn_image_pointer image;
    SpvScope scope = SpvScopeInvocation;
    SpvMemorySemanticsMask semantics = 0;
+   SpvImageOperandsMask operands = SpvImageOperandsMaskNone;
 
    enum gl_access_qualifier access = 0;
 
@@ -3174,8 +3199,7 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode,
       image.image = vtn_get_image(b, w[3], &access);
       image.coord = get_image_coord(b, w[4]);
 
-      const SpvImageOperandsMask operands =
-         count > 5 ? w[5] : SpvImageOperandsMaskNone;
+      operands = count > 5 ? w[5] : SpvImageOperandsMaskNone;
 
       if (operands & SpvImageOperandsSampleMask) {
          uint32_t arg = image_operand_arg(b, w, count, 5,
@@ -3215,8 +3239,7 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode,
 
       /* texel = w[3] */
 
-      const SpvImageOperandsMask operands =
-         count > 4 ? w[4] : SpvImageOperandsMaskNone;
+      operands = count > 4 ? w[4] : SpvImageOperandsMaskNone;
 
       if (operands & SpvImageOperandsSampleMask) {
          uint32_t arg = image_operand_arg(b, w, count, 4,
@@ -3364,8 +3387,11 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode,
        */
       intrin->src[4] = nir_src_for_ssa(image.lod);
 
-      if (opcode == SpvOpImageWrite)
-         nir_intrinsic_set_src_type(intrin, nir_get_nir_type_for_glsl_type(value->type));
+      if (opcode == SpvOpImageWrite) {
+         nir_alu_type src_type =
+            get_image_type(b, nir_get_nir_type_for_glsl_type(value->type), operands);
+         nir_intrinsic_set_src_type(intrin, src_type);
+      }
       break;
    }
 
@@ -3442,8 +3468,11 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode,
          vtn_push_nir_ssa(b, w[2], result);
       }
 
-      if (opcode == SpvOpImageRead || opcode == SpvOpImageSparseRead)
-         nir_intrinsic_set_dest_type(intrin, nir_get_nir_type_for_glsl_type(type->type));
+      if (opcode == SpvOpImageRead || opcode == SpvOpImageSparseRead) {
+         nir_alu_type dest_type =
+            get_image_type(b, nir_get_nir_type_for_glsl_type(type->type), operands);
+         nir_intrinsic_set_dest_type(intrin, dest_type);
+      }
    } else {
       nir_builder_instr_insert(&b->nb, &intrin->instr);
    }



More information about the mesa-commit mailing list