Mesa (master): nir: add new VARYING_SLOTs and shader info for packed 16-bit varyings

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


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

Author: Marek Olšák <marek.olsak at amd.com>
Date:   Tue Feb  9 10:58:51 2021 -0500

nir: add new VARYING_SLOTs and shader info for packed 16-bit varyings

This allows mediump inputs and outputs to be trivially lowered into packed
16-bit varyings where 1 slot is occupied by 2 16-bit vec4s, without any
packing instructions in NIR and without any conflicts with 32-bit varyings.

The only thing that is changed is IO semantics in intrinsics to get packed
16-bit varyings.

This simplifies supporting 16-bit types for drivers that have 32-bit slots
everywhere except the fragment shader where they can do 16-bit interpolation
on either the low or high half of each slot.

Reviewed-by: Matt Turner <mattst88 at gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9050>

---

 src/compiler/nir/nir.h             |  3 +-
 src/compiler/nir/nir_gather_info.c | 36 +++++++++++++++++----
 src/compiler/nir/nir_print.c       |  6 ++--
 src/compiler/shader_enums.h        | 65 +++++++++++++++++++++++++++++++++++++-
 src/compiler/shader_info.h         |  9 ++++++
 5 files changed, 109 insertions(+), 10 deletions(-)

diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index 345bb25a1c9..2054fd761d6 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -1803,7 +1803,8 @@ typedef struct nir_io_semantics {
    unsigned gs_streams:8; /* xxyyzzww: 2-bit stream index for each component */
    unsigned medium_precision:1; /* GLSL mediump qualifier */
    unsigned per_view:1;
-   unsigned _pad:7;
+   unsigned high_16bits:1; /* whether accessing low or high half of the slot */
+   unsigned _pad:6;
 } nir_io_semantics;
 
 #define NIR_INTRINSIC_MAX_INPUTS 11
diff --git a/src/compiler/nir/nir_gather_info.c b/src/compiler/nir/nir_gather_info.c
index 5fbaecbf675..0b014411ce9 100644
--- a/src/compiler/nir/nir_gather_info.c
+++ b/src/compiler/nir/nir_gather_info.c
@@ -288,11 +288,13 @@ gather_intrinsic_info(nir_intrinsic_instr *instr, nir_shader *shader,
                       void *dead_ctx)
 {
    uint64_t slot_mask = 0;
+   uint16_t slot_mask_16bit = 0;
 
    if (nir_intrinsic_infos[instr->intrinsic].index_map[NIR_INTRINSIC_IO_SEMANTICS] > 0) {
       nir_io_semantics semantics = nir_intrinsic_io_semantics(instr);
 
-      if (semantics.location >= VARYING_SLOT_PATCH0) {
+      if (semantics.location >= VARYING_SLOT_PATCH0 &&
+          semantics.location <= VARYING_SLOT_PATCH31) {
          /* Generic per-patch I/O. */
          assert((shader->info.stage == MESA_SHADER_TESS_EVAL &&
                  instr->intrinsic == nir_intrinsic_load_input) ||
@@ -303,8 +305,16 @@ gather_intrinsic_info(nir_intrinsic_instr *instr, nir_shader *shader,
          semantics.location -= VARYING_SLOT_PATCH0;
       }
 
-      slot_mask = BITFIELD64_RANGE(semantics.location, semantics.num_slots);
-      assert(util_bitcount64(slot_mask) == semantics.num_slots);
+      if (semantics.location >= VARYING_SLOT_VAR0_16BIT &&
+          semantics.location <= VARYING_SLOT_VAR15_16BIT) {
+         /* Convert num_slots from the units of half vectors to full vectors. */
+         unsigned num_slots = (semantics.num_slots + semantics.high_16bits + 1) / 2;
+         slot_mask_16bit =
+            BITFIELD_RANGE(semantics.location - VARYING_SLOT_VAR0_16BIT, num_slots);
+      } else {
+         slot_mask = BITFIELD64_RANGE(semantics.location, semantics.num_slots);
+         assert(util_bitcount64(slot_mask) == semantics.num_slots);
+      }
    }
 
    switch (instr->intrinsic) {
@@ -373,8 +383,11 @@ gather_intrinsic_info(nir_intrinsic_instr *instr, nir_shader *shader,
             shader->info.patch_inputs_read_indirectly |= slot_mask;
       } else {
          shader->info.inputs_read |= slot_mask;
-         if (!nir_src_is_const(*nir_get_io_offset_src(instr)))
+         shader->info.inputs_read_16bit |= slot_mask_16bit;
+         if (!nir_src_is_const(*nir_get_io_offset_src(instr))) {
             shader->info.inputs_read_indirectly |= slot_mask;
+            shader->info.inputs_read_indirectly_16bit |= slot_mask_16bit;
+         }
       }
 
       if (shader->info.stage == MESA_SHADER_TESS_CTRL &&
@@ -392,8 +405,11 @@ gather_intrinsic_info(nir_intrinsic_instr *instr, nir_shader *shader,
             shader->info.patch_outputs_accessed_indirectly |= slot_mask;
       } else {
          shader->info.outputs_read |= slot_mask;
-         if (!nir_src_is_const(*nir_get_io_offset_src(instr)))
+         shader->info.outputs_read_16bit |= slot_mask_16bit;
+         if (!nir_src_is_const(*nir_get_io_offset_src(instr))) {
             shader->info.outputs_accessed_indirectly |= slot_mask;
+            shader->info.outputs_accessed_indirectly_16bit |= slot_mask_16bit;
+         }
       }
 
       if (shader->info.stage == MESA_SHADER_TESS_CTRL &&
@@ -415,8 +431,11 @@ gather_intrinsic_info(nir_intrinsic_instr *instr, nir_shader *shader,
             shader->info.patch_outputs_accessed_indirectly |= slot_mask;
       } else {
          shader->info.outputs_written |= slot_mask;
-         if (!nir_src_is_const(*nir_get_io_offset_src(instr)))
+         shader->info.outputs_written_16bit |= slot_mask_16bit;
+         if (!nir_src_is_const(*nir_get_io_offset_src(instr))) {
             shader->info.outputs_accessed_indirectly |= slot_mask;
+            shader->info.outputs_accessed_indirectly_16bit |= slot_mask_16bit;
+         }
       }
 
       if (shader->info.stage == MESA_SHADER_FRAGMENT &&
@@ -839,6 +858,11 @@ nir_shader_gather_info(nir_shader *shader, nir_function_impl *entrypoint)
    shader->info.inputs_read = 0;
    shader->info.outputs_written = 0;
    shader->info.outputs_read = 0;
+   shader->info.inputs_read_16bit = 0;
+   shader->info.outputs_written_16bit = 0;
+   shader->info.outputs_read_16bit = 0;
+   shader->info.inputs_read_indirectly_16bit = 0;
+   shader->info.outputs_accessed_indirectly_16bit = 0;
    shader->info.patch_outputs_read = 0;
    shader->info.patch_inputs_read = 0;
    shader->info.patch_outputs_written = 0;
diff --git a/src/compiler/nir/nir_print.c b/src/compiler/nir/nir_print.c
index af740daae5b..4ceac077da1 100644
--- a/src/compiler/nir/nir_print.c
+++ b/src/compiler/nir/nir_print.c
@@ -985,10 +985,12 @@ print_intrinsic_instr(nir_intrinsic_instr *instr, print_state *state)
                }
                fprintf(fp, ")");
             }
-            if (state->shader->info.stage == MESA_SHADER_FRAGMENT &&
-                nir_intrinsic_io_semantics(instr).medium_precision) {
+            if (nir_intrinsic_io_semantics(instr).medium_precision) {
                fprintf(fp, " mediump");
             }
+            if (nir_intrinsic_io_semantics(instr).high_16bits) {
+               fprintf(fp, " high_16bits");
+            }
          }
          break;
 
diff --git a/src/compiler/shader_enums.h b/src/compiler/shader_enums.h
index c44f4e32f62..8883e8d2aa7 100644
--- a/src/compiler/shader_enums.h
+++ b/src/compiler/shader_enums.h
@@ -333,11 +333,74 @@ typedef enum
    VARYING_SLOT_VAR29,
    VARYING_SLOT_VAR30,
    VARYING_SLOT_VAR31,
+   /* Per-patch varyings for tessellation. */
+   VARYING_SLOT_PATCH0,
+   VARYING_SLOT_PATCH1,
+   VARYING_SLOT_PATCH2,
+   VARYING_SLOT_PATCH3,
+   VARYING_SLOT_PATCH4,
+   VARYING_SLOT_PATCH5,
+   VARYING_SLOT_PATCH6,
+   VARYING_SLOT_PATCH7,
+   VARYING_SLOT_PATCH8,
+   VARYING_SLOT_PATCH9,
+   VARYING_SLOT_PATCH10,
+   VARYING_SLOT_PATCH11,
+   VARYING_SLOT_PATCH12,
+   VARYING_SLOT_PATCH13,
+   VARYING_SLOT_PATCH14,
+   VARYING_SLOT_PATCH15,
+   VARYING_SLOT_PATCH16,
+   VARYING_SLOT_PATCH17,
+   VARYING_SLOT_PATCH18,
+   VARYING_SLOT_PATCH19,
+   VARYING_SLOT_PATCH20,
+   VARYING_SLOT_PATCH21,
+   VARYING_SLOT_PATCH22,
+   VARYING_SLOT_PATCH23,
+   VARYING_SLOT_PATCH24,
+   VARYING_SLOT_PATCH25,
+   VARYING_SLOT_PATCH26,
+   VARYING_SLOT_PATCH27,
+   VARYING_SLOT_PATCH28,
+   VARYING_SLOT_PATCH29,
+   VARYING_SLOT_PATCH30,
+   VARYING_SLOT_PATCH31,
+   /* 32 16-bit vec4 slots packed in 16 32-bit vec4 slots for GLES/mediump.
+    * They are really just additional generic slots used for 16-bit data to
+    * prevent conflicts between neighboring mediump and non-mediump varyings
+    * that can't be packed without breaking one or the other, which is
+    * a limitation of separate shaders. This allows linking shaders in 32 bits
+    * and then get an optimally packed 16-bit varyings by remapping the IO
+    * locations to these slots. The remapping can also be undone trivially.
+    *
+    * nir_io_semantics::high_16bit determines which half of the slot is
+    * accessed. The low and high halves share the same IO "base" number.
+    * Drivers can treat these as 32-bit slots everywhere except for FP16
+    * interpolation.
+    */
+   VARYING_SLOT_VAR0_16BIT,
+   VARYING_SLOT_VAR1_16BIT,
+   VARYING_SLOT_VAR2_16BIT,
+   VARYING_SLOT_VAR3_16BIT,
+   VARYING_SLOT_VAR4_16BIT,
+   VARYING_SLOT_VAR5_16BIT,
+   VARYING_SLOT_VAR6_16BIT,
+   VARYING_SLOT_VAR7_16BIT,
+   VARYING_SLOT_VAR8_16BIT,
+   VARYING_SLOT_VAR9_16BIT,
+   VARYING_SLOT_VAR10_16BIT,
+   VARYING_SLOT_VAR11_16BIT,
+   VARYING_SLOT_VAR12_16BIT,
+   VARYING_SLOT_VAR13_16BIT,
+   VARYING_SLOT_VAR14_16BIT,
+   VARYING_SLOT_VAR15_16BIT,
+
+   NUM_TOTAL_VARYING_SLOTS,
 } gl_varying_slot;
 
 
 #define VARYING_SLOT_MAX	(VARYING_SLOT_VAR0 + MAX_VARYING)
-#define VARYING_SLOT_PATCH0	(VARYING_SLOT_MAX)
 #define VARYING_SLOT_TESS_MAX	(VARYING_SLOT_PATCH0 + MAX_VARYING)
 #define MAX_VARYINGS_INCL_PATCH (VARYING_SLOT_TESS_MAX - VARYING_SLOT_VAR0)
 
diff --git a/src/compiler/shader_info.h b/src/compiler/shader_info.h
index ebc2c43923f..d0c0dd28ddd 100644
--- a/src/compiler/shader_info.h
+++ b/src/compiler/shader_info.h
@@ -152,6 +152,15 @@ typedef struct shader_info {
    /* Which system values are actually read */
    BITSET_DECLARE(system_values_read, SYSTEM_VALUE_MAX);
 
+   /* Which 16-bit inputs and outputs are used corresponding to
+    * VARYING_SLOT_VARn_16BIT.
+    */
+   uint16_t inputs_read_16bit;
+   uint16_t outputs_written_16bit;
+   uint16_t outputs_read_16bit;
+   uint16_t inputs_read_indirectly_16bit;
+   uint16_t outputs_accessed_indirectly_16bit;
+
    /* Which patch inputs are actually read */
    uint32_t patch_inputs_read;
    /* Which patch outputs are actually written */



More information about the mesa-commit mailing list