zink: rework input/output location emission
authorMike Blumenkrantz <michael.blumenkrantz@gmail.com>
Wed, 10 Jun 2020 19:26:07 +0000 (15:26 -0400)
committerMarge Bot <eric+marge@anholt.net>
Mon, 15 Jun 2020 15:36:06 +0000 (15:36 +0000)
glsl builtins that have no analog in spirv are emitted as regular varyings,
which means they take up a slot.

we need to ensure that there's no conflict between these regular varying
slots (from user-defined varyings) and the glsl translated builtins, so
we do that by "reserving" the max number of varying slots that can be used
by a given stage, then remapping all glsl builtins with no spirv builtin
to a packed layout location that can be consistent across stages

sort of addresses mesa/mesa#3113 except now there's 10 fewer varying slots

Reviewed-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5432>

src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c

index 881103c1432a6b71ad035fc4654cc171677f0995..cabc83b70220394cc2e4524aaf1be7be070fa4a3 100644 (file)
 #include "util/u_memory.h"
 #include "util/hash_table.h"
 
+/* this consistently maps slots to a zero-indexed value to avoid wasting slots */
+static unsigned slot_pack_map[] = {
+   /* Position is builtin */
+   [VARYING_SLOT_POS] = UINT_MAX,
+   [VARYING_SLOT_COL0] = 0, /* input/output */
+   [VARYING_SLOT_COL1] = 1, /* input/output */
+   [VARYING_SLOT_FOGC] = 2, /* input/output */
+   /* TEX0-7 are translated to VAR0-7 by nir, so we don't need to reserve */
+   [VARYING_SLOT_TEX0] = UINT_MAX, /* input/output */
+   [VARYING_SLOT_TEX1] = UINT_MAX,
+   [VARYING_SLOT_TEX2] = UINT_MAX,
+   [VARYING_SLOT_TEX3] = UINT_MAX,
+   [VARYING_SLOT_TEX4] = UINT_MAX,
+   [VARYING_SLOT_TEX5] = UINT_MAX,
+   [VARYING_SLOT_TEX6] = UINT_MAX,
+   [VARYING_SLOT_TEX7] = UINT_MAX,
+
+   /* PointSize is builtin */
+   [VARYING_SLOT_PSIZ] = UINT_MAX,
+
+   [VARYING_SLOT_BFC0] = 3, /* output only */
+   [VARYING_SLOT_BFC1] = 4, /* output only */
+   [VARYING_SLOT_EDGE] = 5, /* output only */
+   [VARYING_SLOT_CLIP_VERTEX] = 6, /* output only */
+
+   /* ClipDistance is builtin */
+   [VARYING_SLOT_CLIP_DIST0] = UINT_MAX,
+   [VARYING_SLOT_CLIP_DIST1] = UINT_MAX,
+
+   /* CullDistance is builtin */
+   [VARYING_SLOT_CULL_DIST0] = UINT_MAX, /* input/output */
+   [VARYING_SLOT_CULL_DIST1] = UINT_MAX, /* never actually used */
+
+   /* PrimitiveId is builtin */
+   [VARYING_SLOT_PRIMITIVE_ID] = UINT_MAX,
+
+   /* Layer is builtin */
+   [VARYING_SLOT_LAYER] = UINT_MAX, /* input/output */
+
+   /* ViewportIndex is builtin */
+   [VARYING_SLOT_VIEWPORT] =  UINT_MAX, /* input/output */
+
+   /* FrontFacing is builtin */
+   [VARYING_SLOT_FACE] = UINT_MAX,
+
+   /* PointCoord is builtin */
+   [VARYING_SLOT_PNTC] = UINT_MAX, /* input only */
+
+   /* TessLevelOuter is builtin */
+   [VARYING_SLOT_TESS_LEVEL_OUTER] = UINT_MAX,
+   /* TessLevelInner is builtin */
+   [VARYING_SLOT_TESS_LEVEL_INNER] = UINT_MAX,
+
+   [VARYING_SLOT_BOUNDING_BOX0] = 7, /* Only appears as TCS output. */
+   [VARYING_SLOT_BOUNDING_BOX1] = 8, /* Only appears as TCS output. */
+   [VARYING_SLOT_VIEW_INDEX] = 9, /* input/output */
+   [VARYING_SLOT_VIEWPORT_MASK] = 10, /* output only */
+};
+#define NTV_MIN_RESERVED_SLOTS 10
+
 struct ntv_context {
    struct spirv_builder builder;
 
@@ -240,32 +300,26 @@ emit_input(struct ntv_context *ctx, struct nir_variable *var)
       spirv_builder_emit_name(&ctx->builder, var_id, var->name);
 
    if (ctx->stage == MESA_SHADER_FRAGMENT) {
-      if (var->data.location >= VARYING_SLOT_VAR0)
-         spirv_builder_emit_location(&ctx->builder, var_id,
-                                     var->data.location -
-                                     VARYING_SLOT_VAR0 +
-                                     VARYING_SLOT_TEX0);
-      else if ((var->data.location >= VARYING_SLOT_COL0 &&
-                var->data.location <= VARYING_SLOT_TEX7) ||
-               var->data.location == VARYING_SLOT_BFC0 ||
-               var->data.location == VARYING_SLOT_BFC1) {
-         spirv_builder_emit_location(&ctx->builder, var_id,
-                                     var->data.location);
-      } else {
-         switch (var->data.location) {
-         HANDLE_EMIT_BUILTIN(POS, FragCoord);
-         HANDLE_EMIT_BUILTIN(PNTC, PointCoord);
-         HANDLE_EMIT_BUILTIN(LAYER, Layer);
-         HANDLE_EMIT_BUILTIN(PRIMITIVE_ID, PrimitiveId);
-         HANDLE_EMIT_BUILTIN(CLIP_DIST0, ClipDistance);
-         HANDLE_EMIT_BUILTIN(CULL_DIST0, CullDistance);
-         HANDLE_EMIT_BUILTIN(VIEWPORT, ViewportIndex);
-         HANDLE_EMIT_BUILTIN(FACE, FrontFacing);
+      unsigned slot = var->data.location;
+      switch (slot) {
+      HANDLE_EMIT_BUILTIN(POS, FragCoord);
+      HANDLE_EMIT_BUILTIN(PNTC, PointCoord);
+      HANDLE_EMIT_BUILTIN(LAYER, Layer);
+      HANDLE_EMIT_BUILTIN(PRIMITIVE_ID, PrimitiveId);
+      HANDLE_EMIT_BUILTIN(CLIP_DIST0, ClipDistance);
+      HANDLE_EMIT_BUILTIN(CULL_DIST0, CullDistance);
+      HANDLE_EMIT_BUILTIN(VIEWPORT, ViewportIndex);
+      HANDLE_EMIT_BUILTIN(FACE, FrontFacing);
 
-         default:
-            debug_printf("unknown varying slot: %s\n", gl_varying_slot_name(var->data.location));
-            unreachable("unexpected varying slot");
-         }
+      default:
+         if (slot < VARYING_SLOT_VAR0) {
+            slot = slot_pack_map[slot];
+            if (slot == UINT_MAX)
+               debug_printf("unhandled varying slot: %s\n", gl_varying_slot_name(var->data.location));
+         } else
+            slot -= VARYING_SLOT_VAR0 - NTV_MIN_RESERVED_SLOTS;
+         assert(slot < VARYING_SLOT_VAR0);
+         spirv_builder_emit_location(&ctx->builder, var_id, slot);
       }
    } else {
       spirv_builder_emit_location(&ctx->builder, var_id,
@@ -299,37 +353,35 @@ emit_output(struct ntv_context *ctx, struct nir_variable *var)
 
 
    if (ctx->stage == MESA_SHADER_VERTEX) {
-      if (var->data.location >= VARYING_SLOT_VAR0)
-         spirv_builder_emit_location(&ctx->builder, var_id,
-                                     var->data.location -
-                                     VARYING_SLOT_VAR0 +
-                                     VARYING_SLOT_TEX0);
-      else if ((var->data.location >= VARYING_SLOT_COL0 &&
-                var->data.location <= VARYING_SLOT_TEX7) ||
-               var->data.location == VARYING_SLOT_BFC0 ||
-               var->data.location == VARYING_SLOT_BFC1) {
-         spirv_builder_emit_location(&ctx->builder, var_id,
-                                     var->data.location);
-      } else {
-         switch (var->data.location) {
-         HANDLE_EMIT_BUILTIN(POS, Position);
-         HANDLE_EMIT_BUILTIN(PSIZ, PointSize);
-         HANDLE_EMIT_BUILTIN(LAYER, Layer);
-         HANDLE_EMIT_BUILTIN(PRIMITIVE_ID, PrimitiveId);
-         HANDLE_EMIT_BUILTIN(CULL_DIST0, CullDistance);
-         HANDLE_EMIT_BUILTIN(VIEWPORT, ViewportIndex);
-         HANDLE_EMIT_BUILTIN(TESS_LEVEL_OUTER, TessLevelOuter);
-         HANDLE_EMIT_BUILTIN(TESS_LEVEL_INNER, TessLevelInner);
-
-         case VARYING_SLOT_CLIP_DIST0:
-            assert(glsl_type_is_array(var->type));
-            spirv_builder_emit_builtin(&ctx->builder, var_id, SpvBuiltInClipDistance);
-            break;
 
-         default:
-            debug_printf("unknown varying slot: %s\n", gl_varying_slot_name(var->data.location));
-            unreachable("unexpected varying slot");
-         }
+      unsigned slot = var->data.location;
+      switch (slot) {
+      HANDLE_EMIT_BUILTIN(POS, Position);
+      HANDLE_EMIT_BUILTIN(PSIZ, PointSize);
+      HANDLE_EMIT_BUILTIN(LAYER, Layer);
+      HANDLE_EMIT_BUILTIN(PRIMITIVE_ID, PrimitiveId);
+      HANDLE_EMIT_BUILTIN(CULL_DIST0, CullDistance);
+      HANDLE_EMIT_BUILTIN(VIEWPORT, ViewportIndex);
+      HANDLE_EMIT_BUILTIN(TESS_LEVEL_OUTER, TessLevelOuter);
+      HANDLE_EMIT_BUILTIN(TESS_LEVEL_INNER, TessLevelInner);
+
+      case VARYING_SLOT_CLIP_DIST0:
+         assert(glsl_type_is_array(var->type));
+         spirv_builder_emit_builtin(&ctx->builder, var_id, SpvBuiltInClipDistance);
+         break;
+
+      default:
+         if (slot < VARYING_SLOT_VAR0) {
+            slot = slot_pack_map[slot];
+            if (slot == UINT_MAX)
+               debug_printf("unhandled varying slot: %s\n", gl_varying_slot_name(var->data.location));
+         } else
+            slot -= VARYING_SLOT_VAR0 - NTV_MIN_RESERVED_SLOTS;
+         assert(slot < VARYING_SLOT_VAR0);
+         spirv_builder_emit_location(&ctx->builder, var_id, slot);
+         /* non-builtins get location incremented by VARYING_SLOT_VAR0 in vtn, so
+          * use driver_location for non-builtins with defined slots to avoid overlap
+          */
       }
    } else if (ctx->stage == MESA_SHADER_FRAGMENT) {
       if (var->data.location >= FRAG_RESULT_DATA0)