<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Wed, Jan 4, 2017 at 3:07 AM, Kenneth Graunke <span dir="ltr"><<a href="mailto:kenneth@whitecape.org" target="_blank">kenneth@whitecape.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Treating everything as scalar arrays allows us to drop a bunch of<br>
special case input/output munging all throughout the backend.<br>
Instead, we just need to remap the TessLevel components to the<br>
appropriate patch URB header locations in remap_patch_urb_offsets().<br>
<br>
We also switch to treating the TES input versions of these as ordinary<br>
shader inputs rather than system values, as remap_patch_urb_offsets()<br>
just makes everything work out without special handling.<br>
<br>
This regresses one Piglit test:<br>
arb_tessellation_shader-large-<wbr>uniforms/GL_TESS_CONTROL_<wbr>SHADER-array-at-limit<br>
<br>
The compiler starts promoting the constant arrays assigned to gl_TessLevel*<br>
to uniform arrays.  Since the shader also has a uniform array that uses<br>
the maximum number of uniform components, this puts it over the uniform<br>
component limit enforced by the linker.  This is arguably a bug in the<br>
constant array promotion code (it should avoid pushing us over limits),<br>
but is unlikely to penalize any real application.<br>
<br>
Signed-off-by: Kenneth Graunke <<a href="mailto:kenneth@whitecape.org">kenneth@whitecape.org</a>><br>
---<br>
 src/mesa/drivers/dri/i965/brw_<wbr>context.c            |   2 +-<br>
 src/mesa/drivers/dri/i965/brw_<wbr>fs_nir.cpp           | 164 +--------------------<br>
 src/mesa/drivers/dri/i965/brw_<wbr>nir.c                |  74 +++++++++-<br>
 src/mesa/drivers/dri/i965/brw_<wbr>nir.h                |   3 +-<br>
 .../drivers/dri/i965/brw_nir_<wbr>tcs_workarounds.c     |   8 +-<br>
 src/mesa/drivers/dri/i965/brw_<wbr>shader.cpp           |  61 +-------<br>
 src/mesa/drivers/dri/i965/brw_<wbr>shader.h             |   5 -<br>
 src/mesa/drivers/dri/i965/brw_<wbr>tcs.c                |   5 +-<br>
 src/mesa/drivers/dri/i965/brw_<wbr>tes.c                |  17 +--<br>
 src/mesa/drivers/dri/i965/brw_<wbr>vec4_tcs.cpp         | 117 +--------------<br>
 10 files changed, 92 insertions(+), 364 deletions(-)<br>
<br>
diff --git a/src/mesa/drivers/dri/i965/<wbr>brw_context.c b/src/mesa/drivers/dri/i965/<wbr>brw_context.c<br>
index 45490a0f5cf..22f872fe782 100644<br>
--- a/src/mesa/drivers/dri/i965/<wbr>brw_context.c<br>
+++ b/src/mesa/drivers/dri/i965/<wbr>brw_context.c<br>
@@ -672,7 +672,7 @@ brw_initialize_context_<wbr>constants(struct brw_context *brw)<br>
    if (brw->gen >= 5 || brw->is_g4x)<br>
       ctx->Const.MaxClipPlanes = 8;<br>
<br>
-   ctx->Const.LowerTessLevel = true;<br>
+   ctx->Const.<wbr>GLSLTessLevelsAsInputs = true;<br>
    ctx->Const.<wbr>LowerTCSPatchVerticesIn = brw->gen >= 8;<br>
    ctx->Const.<wbr>LowerTESPatchVerticesIn = true;<br>
    ctx->Const.<wbr>PrimitiveRestartForPatches = true;<br>
diff --git a/src/mesa/drivers/dri/i965/<wbr>brw_fs_nir.cpp b/src/mesa/drivers/dri/i965/<wbr>brw_fs_nir.cpp<br>
index 2ed843bd03d..8f745dff440 100644<br>
--- a/src/mesa/drivers/dri/i965/<wbr>brw_fs_nir.cpp<br>
+++ b/src/mesa/drivers/dri/i965/<wbr>brw_fs_nir.cpp<br>
@@ -2520,78 +2520,7 @@ fs_visitor::nir_emit_tcs_<wbr>intrinsic(const fs_builder &bld,<br>
          bld.MOV(patch_handle,<br>
                  retype(brw_vec1_grf(0, 0), BRW_REGISTER_TYPE_UD));<br>
<br>
-         if (imm_offset == 0) {<br>
-            /* This is a read of gl_TessLevelInner[], which lives in the<br>
-             * Patch URB header.  The layout depends on the domain.<br>
-             */<br>
-            dst.type = BRW_REGISTER_TYPE_F;<br>
-            switch (tcs_key->tes_primitive_mode) {<br>
-            case GL_QUADS: {<br>
-               /* DWords 3-2 (reversed) */<br>
-               fs_reg tmp = bld.vgrf(BRW_REGISTER_TYPE_F, 4);<br>
-<br>
-               inst = bld.emit(SHADER_OPCODE_URB_<wbr>READ_SIMD8, tmp, patch_handle);<br>
-               inst->offset = 0;<br>
-               inst->mlen = 1;<br>
-               inst->size_written = 4 * REG_SIZE;<br>
-<br>
-               /* dst.xy = tmp.wz */<br>
-               bld.MOV(dst,                 offset(tmp, bld, 3));<br>
-               bld.MOV(offset(dst, bld, 1), offset(tmp, bld, 2));<br>
-               break;<br>
-            }<br>
-            case GL_TRIANGLES:<br>
-               /* DWord 4; hardcode offset = 1 and size_written = REG_SIZE */<br>
-               inst = bld.emit(SHADER_OPCODE_URB_<wbr>READ_SIMD8, dst, patch_handle);<br>
-               inst->offset = 1;<br>
-               inst->mlen = 1;<br>
-               inst->size_written = REG_SIZE;<br>
-               break;<br>
-            case GL_ISOLINES:<br>
-               /* All channels are undefined. */<br>
-               break;<br>
-            default:<br>
-               unreachable("Bogus tessellation domain");<br>
-            }<br>
-         } else if (imm_offset == 1) {<br>
-            /* This is a read of gl_TessLevelOuter[], which lives in the<br>
-             * Patch URB header.  The layout depends on the domain.<br>
-             */<br>
-            dst.type = BRW_REGISTER_TYPE_F;<br>
-<br>
-            fs_reg tmp = bld.vgrf(BRW_REGISTER_TYPE_F, 4);<br>
-            inst = bld.emit(SHADER_OPCODE_URB_<wbr>READ_SIMD8, tmp, patch_handle);<br>
-            inst->offset = 1;<br>
-            inst->mlen = 1;<br>
-            inst->size_written = 4 * REG_SIZE;<br>
-<br>
-            /* Reswizzle: WZYX */<br>
-            fs_reg srcs[4] = {<br>
-               offset(tmp, bld, 3),<br>
-               offset(tmp, bld, 2),<br>
-               offset(tmp, bld, 1),<br>
-               offset(tmp, bld, 0),<br>
-            };<br>
-<br>
-            unsigned num_components;<br>
-            switch (tcs_key->tes_primitive_mode) {<br>
-            case GL_QUADS:<br>
-               num_components = 4;<br>
-               break;<br>
-            case GL_TRIANGLES:<br>
-               num_components = 3;<br>
-               break;<br>
-            case GL_ISOLINES:<br>
-               /* Isolines are not reversed; swizzle .zw -> .xy */<br>
-               srcs[0] = offset(tmp, bld, 2);<br>
-               srcs[1] = offset(tmp, bld, 3);<br>
-               num_components = 2;<br>
-               break;<br>
-            default:<br>
-               unreachable("Bogus tessellation domain");<br>
-            }<br>
-            bld.LOAD_PAYLOAD(dst, srcs, num_components, 0);<br>
-         } else {<br>
+         {<br>
             if (first_component != 0) {<br>
                unsigned read_components =<br>
                   instr->num_components + first_component;<br>
@@ -2656,55 +2585,6 @@ fs_visitor::nir_emit_tcs_<wbr>intrinsic(const fs_builder &bld,<br>
<br>
       if (indirect_offset.file != BAD_FILE) {<br>
          srcs[header_regs++] = indirect_offset;<br>
-      } else if (!is_passthrough_shader) {<br>
-         if (imm_offset == 0) {<br>
-            value.type = BRW_REGISTER_TYPE_F;<br>
-<br>
-            mask &= (1 << tesslevel_inner_components(<wbr>tcs_key->tes_primitive_mode)) - 1;<br>
-<br>
-            /* This is a write to gl_TessLevelInner[], which lives in the<br>
-             * Patch URB header.  The layout depends on the domain.<br>
-             */<br>
-            switch (tcs_key->tes_primitive_mode) {<br>
-            case GL_QUADS:<br>
-               /* gl_TessLevelInner[].xy lives at DWords 3-2 (reversed).<br>
-                * We use an XXYX swizzle to reverse put .xy in the .wz<br>
-                * channels, and use a .zw writemask.<br>
-                */<br>
-               mask = writemask_for_backwards_<wbr>vector(mask);<br>
-               swiz = BRW_SWIZZLE4(0, 0, 1, 0);<br>
-               break;<br>
-            case GL_TRIANGLES:<br>
-               /* gl_TessLevelInner[].x lives at DWord 4, so we set the<br>
-                * writemask to X and bump the URB offset by 1.<br>
-                */<br>
-               imm_offset = 1;<br>
-               break;<br>
-            case GL_ISOLINES:<br>
-               /* Skip; gl_TessLevelInner[] doesn't exist for isolines. */<br>
-               return;<br>
-            default:<br>
-               unreachable("Bogus tessellation domain");<br>
-            }<br>
-         } else if (imm_offset == 1) {<br>
-            /* This is a write to gl_TessLevelOuter[] which lives in the<br>
-             * Patch URB Header at DWords 4-7.  However, it's reversed, so<br>
-             * instead of .xyzw we have .wzyx.<br>
-             */<br>
-            value.type = BRW_REGISTER_TYPE_F;<br>
-<br>
-            mask &= (1 << tesslevel_outer_components(<wbr>tcs_key->tes_primitive_mode)) - 1;<br>
-<br>
-            if (tcs_key->tes_primitive_mode == GL_ISOLINES) {<br>
-               /* Isolines .xy should be stored in .zw, in order. */<br>
-               swiz = BRW_SWIZZLE4(0, 0, 0, 1);<br>
-               mask <<= 2;<br>
-            } else {<br>
-               /* Other domains are reversed; store .wzyx instead of .xyzw */<br>
-               swiz = BRW_SWIZZLE_WZYX;<br>
-               mask = writemask_for_backwards_<wbr>vector(mask);<br>
-            }<br>
-         }<br>
       }<br>
<br>
       if (mask == 0)<br>
@@ -2851,48 +2731,6 @@ fs_visitor::nir_emit_tes_<wbr>intrinsic(const fs_builder &bld,<br>
       }<br>
       break;<br>
<br>
-   case nir_intrinsic_load_tess_level_<wbr>outer:<br>
-      /* When the TES reads gl_TessLevelOuter, we ensure that the patch header<br>
-       * appears as a push-model input.  So, we can simply use the ATTR file<br>
-       * rather than issuing URB read messages.  The data is stored in the<br>
-       * high DWords in reverse order - DWord 7 contains .x, DWord 6 contains<br>
-       * .y, and so on.<br>
-       */<br>
-      switch (tes_prog_data->domain) {<br>
-      case BRW_TESS_DOMAIN_QUAD:<br>
-         for (unsigned i = 0; i < 4; i++)<br>
-            bld.MOV(offset(dest, bld, i), component(fs_reg(ATTR, 0), 7 - i));<br>
-         break;<br>
-      case BRW_TESS_DOMAIN_TRI:<br>
-         for (unsigned i = 0; i < 3; i++)<br>
-            bld.MOV(offset(dest, bld, i), component(fs_reg(ATTR, 0), 7 - i));<br>
-         break;<br>
-      case BRW_TESS_DOMAIN_ISOLINE:<br>
-         for (unsigned i = 0; i < 2; i++)<br>
-            bld.MOV(offset(dest, bld, i), component(fs_reg(ATTR, 0), 6 + i));<br>
-         break;<br>
-      }<br>
-      break;<br>
-<br>
-   case nir_intrinsic_load_tess_level_<wbr>inner:<br>
-      /* When the TES reads gl_TessLevelInner, we ensure that the patch header<br>
-       * appears as a push-model input.  So, we can simply use the ATTR file<br>
-       * rather than issuing URB read messages.<br>
-       */<br>
-      switch (tes_prog_data->domain) {<br>
-      case BRW_TESS_DOMAIN_QUAD:<br>
-         bld.MOV(dest, component(fs_reg(ATTR, 0), 3));<br>
-         bld.MOV(offset(dest, bld, 1), component(fs_reg(ATTR, 0), 2));<br>
-         break;<br>
-      case BRW_TESS_DOMAIN_TRI:<br>
-         bld.MOV(dest, component(fs_reg(ATTR, 0), 4));<br>
-         break;<br>
-      case BRW_TESS_DOMAIN_ISOLINE:<br>
-         /* ignore - value is undefined */<br>
-         break;<br>
-      }<br>
-      break;<br>
-<br>
    case nir_intrinsic_load_input:<br>
    case nir_intrinsic_load_per_vertex_<wbr>input: {<br>
       fs_reg indirect_offset = get_indirect_offset(instr);<br>
diff --git a/src/mesa/drivers/dri/i965/<wbr>brw_nir.c b/src/mesa/drivers/dri/i965/<wbr>brw_nir.c<br>
index 6f37e97a86f..46eeb1723b4 100644<br>
--- a/src/mesa/drivers/dri/i965/<wbr>brw_nir.c<br>
+++ b/src/mesa/drivers/dri/i965/<wbr>brw_nir.c<br>
@@ -141,9 +141,68 @@ remap_inputs_with_vue_map(nir_<wbr>block *block, const struct brw_vue_map *vue_map)<br>
 }<br>
<br>
 static bool<br>
+remap_tess_levels(nir_builder *b, nir_intrinsic_instr *intr,<br>
+                  GLenum primitive_mode)<br>
+{<br>
+   const int location = nir_intrinsic_base(intr);<br>
+   const unsigned component = nir_intrinsic_component(intr);<br>
+   bool out_of_bounds;<br>
+<br>
+   if (location == VARYING_SLOT_TESS_LEVEL_INNER) {<br>
+      switch (primitive_mode) {<br>
+      case GL_QUADS:<br>
+         /* gl_TessLevelInner[0..1] lives at DWords 3-2 (reversed). */<br>
+         nir_intrinsic_set_base(intr, 0);<br>
+         nir_intrinsic_set_component(<wbr>intr, 3 - component);<br>
+         out_of_bounds = false;<br></blockquote><div><br></div><div>What if component > 1?  I guess that's not really a problem but it is out-of-bounds...<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+         break;<br>
+      case GL_TRIANGLES:<br>
+         /* gl_TessLevelInner[0] lives at DWord 4. */<br>
+         nir_intrinsic_set_base(intr, 1);<br>
+         out_of_bounds = component > 0;<br>
+         break;<br>
+      case GL_ISOLINES:<br>
+         out_of_bounds = true;<br>
+         break;<br>
+      default:<br>
+         unreachable("Bogus tessellation domain");<br>
+      }<br>
+   } else if (location == VARYING_SLOT_TESS_LEVEL_OUTER) {<br>
+      if (primitive_mode == GL_ISOLINES) {<br>
+         /* gl_TessLevelOuter[0..1] lives at DWords 6-7 (in order). */<br>
+         nir_intrinsic_set_base(intr, 1);<br>
+         nir_intrinsic_set_component(<wbr>intr, 2 + nir_intrinsic_component(intr))<wbr>;<br>
+         out_of_bounds = component > 1;<br>
+      } else {<br>
+         /* Triangles use DWords 7-5 (reversed); Quads use 7-4 (reversed) */<br>
+         nir_intrinsic_set_base(intr, 1);<br>
+         nir_intrinsic_set_component(<wbr>intr, 3 - nir_intrinsic_component(intr))<wbr>;<br>
+         out_of_bounds = component == 3 && primitive_mode == GL_TRIANGLES;<br></blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+      }<br>
+   } else {<br>
+      return false;<br>
+   }<br>
+<br>
+   if (out_of_bounds) {<br>
+      if (nir_intrinsic_infos[intr-><wbr>intrinsic].has_dest) {<br>
+         b->cursor = nir_before_instr(&intr->instr)<wbr>;<br>
+         nir_ssa_def *undef = nir_ssa_undef(b, 1, 32);<br>
+         nir_ssa_def_rewrite_uses(&<wbr>intr->dest.ssa, nir_src_for_ssa(undef));<br>
+      }<br>
+      nir_instr_remove(&intr->instr)<wbr>;<br>
+   }<br>
+<br>
+   return true;<br>
+}<br>
+<br>
+static bool<br>
 remap_patch_urb_offsets(nir_<wbr>block *block, nir_builder *b,<br>
-                        const struct brw_vue_map *vue_map)<br>
+                        const struct brw_vue_map *vue_map,<br>
+                        GLenum tes_primitive_mode)<br>
 {<br>
+   const bool is_passthrough_tcs = b->shader->info->name &&<br>
+      strcmp(b->shader->info->name, "passthrough") == 0;<br></blockquote><div><br></div><div>This is gross...<br><br></div><div>Also... Why?  What's so special about the passthrough that it doesn't need tess level remaps?  I have a feeling there's some more general thing we could be doing here.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
    nir_foreach_instr_safe(instr, block) {<br>
       if (instr->type != nir_instr_type_intrinsic)<br>
          continue;<br>
@@ -154,6 +213,11 @@ remap_patch_urb_offsets(nir_<wbr>block *block, nir_builder *b,<br>
<br>
       if ((stage == MESA_SHADER_TESS_CTRL && is_output(intrin)) ||<br>
           (stage == MESA_SHADER_TESS_EVAL && is_input(intrin))) {<br>
+<br>
+         if (!is_passthrough_tcs &&<br>
+             remap_tess_levels(b, intrin, tes_primitive_mode))<br>
+            continue;<br></blockquote><div><br></div><div>Let's make sure I've got this right...<br><br></div><div>We map everything from the varying identifiers to VUE slots.  For the case of tesslevel, they will be assigned VUE slots 0 and 1 so the code below will hever cause any other output to alias.  Then we rework stuff in remap_tess_levels so that they map to the right locaion in 8-dword chunk at the begining of the VUE.<br><br></div><div>This function (remap_patch_urb_offsets) could really use a comment at the top saying what it's doing.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
          int vue_slot = vue_map->varying_to_slot[<wbr>intrin->const_index[0]];<br>
          assert(vue_slot != -1);<br>
          intrin->const_index[0] = vue_slot;<br>
@@ -273,7 +337,8 @@ brw_nir_lower_tes_inputs(nir_<wbr>shader *nir, const struct brw_vue_map *vue_map)<br>
          nir_builder b;<br>
          nir_builder_init(&b, function->impl);<br>
          nir_foreach_block(block, function->impl) {<br>
-            remap_patch_urb_offsets(block, &b, vue_map);<br>
+            remap_patch_urb_offsets(block, &b, vue_map,<br>
+                                    nir->info->tes.primitive_mode)<wbr>;<br>
          }<br>
       }<br>
    }<br>
@@ -341,7 +406,8 @@ brw_nir_lower_vue_outputs(nir_<wbr>shader *nir,<br>
 }<br>
<br>
 void<br>
-brw_nir_lower_tcs_outputs(<wbr>nir_shader *nir, const struct brw_vue_map *vue_map)<br>
+brw_nir_lower_tcs_outputs(<wbr>nir_shader *nir, const struct brw_vue_map *vue_map,<br>
+                          GLenum tes_primitive_mode)<br>
 {<br>
    nir_foreach_variable(var, &nir->outputs) {<br>
       var->data.driver_location = var->data.location;<br>
@@ -359,7 +425,7 @@ brw_nir_lower_tcs_outputs(nir_<wbr>shader *nir, const struct brw_vue_map *vue_map)<br>
          nir_builder b;<br>
          nir_builder_init(&b, function->impl);<br>
          nir_foreach_block(block, function->impl) {<br>
-            remap_patch_urb_offsets(block, &b, vue_map);<br>
+            remap_patch_urb_offsets(block, &b, vue_map, tes_primitive_mode);<br>
          }<br>
       }<br>
    }<br>
diff --git a/src/mesa/drivers/dri/i965/<wbr>brw_nir.h b/src/mesa/drivers/dri/i965/<wbr>brw_nir.h<br>
index 8cfb6c1be68..c6ef437d4f9 100644<br>
--- a/src/mesa/drivers/dri/i965/<wbr>brw_nir.h<br>
+++ b/src/mesa/drivers/dri/i965/<wbr>brw_nir.h<br>
@@ -109,7 +109,8 @@ void brw_nir_lower_fs_inputs(nir_<wbr>shader *nir, struct brw_vue_map *vue_map,<br>
                              const struct gen_device_info *devinfo,<br>
                              const struct brw_wm_prog_key *key);<br>
 void brw_nir_lower_vue_outputs(nir_<wbr>shader *nir, bool is_scalar);<br>
-void brw_nir_lower_tcs_outputs(nir_<wbr>shader *nir, const struct brw_vue_map *vue);<br>
+void brw_nir_lower_tcs_outputs(nir_<wbr>shader *nir, const struct brw_vue_map *vue,<br>
+                               GLenum tes_primitive_mode);<br>
 void brw_nir_lower_fs_outputs(nir_<wbr>shader *nir);<br>
 void brw_nir_lower_cs_shared(nir_<wbr>shader *nir);<br>
<br>
diff --git a/src/mesa/drivers/dri/i965/<wbr>brw_nir_tcs_workarounds.c b/src/mesa/drivers/dri/i965/<wbr>brw_nir_tcs_workarounds.c<br>
index caf5c393a5e..e130c8c9c1a 100644<br>
--- a/src/mesa/drivers/dri/i965/<wbr>brw_nir_tcs_workarounds.c<br>
+++ b/src/mesa/drivers/dri/i965/<wbr>brw_nir_tcs_workarounds.c<br>
@@ -73,7 +73,7 @@<br>
  */<br>
<br>
 static inline nir_ssa_def *<br>
-load_output(nir_builder *b, int num_components, int offset)<br>
+load_output(nir_builder *b, int num_components, int offset, int component)<br>
 {<br>
    nir_intrinsic_instr *load =<br>
       nir_intrinsic_instr_create(b-><wbr>shader, nir_intrinsic_load_output);<br>
@@ -81,6 +81,7 @@ load_output(nir_builder *b, int num_components, int offset)<br>
    load->num_components = num_components;<br>
    load->src[0] = nir_src_for_ssa(nir_imm_int(b, 0));<br>
    nir_intrinsic_set_base(load, offset);<br>
+   nir_intrinsic_set_component(<wbr>load, component);<br>
<br>
    nir_builder_instr_insert(b, &load->instr);<br>
<br>
@@ -92,8 +93,8 @@ emit_quads_workaround(nir_<wbr>builder *b, nir_block *block)<br>
 {<br>
    b->cursor = nir_after_block_before_jump(<wbr>block);<br>
<br>
-   nir_ssa_def *inner = load_output(b, 2, 0);<br>
-   nir_ssa_def *outer = load_output(b, 4, 1);<br>
+   nir_ssa_def *inner = load_output(b, 2, 0, 2);<br>
+   nir_ssa_def *outer = load_output(b, 4, 1, 0);<br>
<br>
    nir_ssa_def *any_greater_than_1 =<br>
        nir_ior(b, nir_bany(b, nir_flt(b, nir_imm_float(b, 1.0f), outer)),<br>
@@ -113,6 +114,7 @@ emit_quads_workaround(nir_<wbr>builder *b, nir_block *block)<br>
       nir_intrinsic_instr_create(b-><wbr>shader, nir_intrinsic_store_output);<br>
    store->num_components = 2;<br>
    nir_intrinsic_set_write_mask(<wbr>store, WRITEMASK_XY);<br>
+   nir_intrinsic_set_component(<wbr>store, 2);<br>
    store->src[0] = nir_src_for_ssa(inner);<br>
    store->src[1] = nir_src_for_ssa(nir_imm_int(b, 0));<br>
    nir_builder_instr_insert(b, &store->instr);<br>
diff --git a/src/mesa/drivers/dri/i965/<wbr>brw_shader.cpp b/src/mesa/drivers/dri/i965/<wbr>brw_shader.cpp<br>
index dfc7407ea5b..7dbe3a502ec 100644<br>
--- a/src/mesa/drivers/dri/i965/<wbr>brw_shader.cpp<br>
+++ b/src/mesa/drivers/dri/i965/<wbr>brw_shader.cpp<br>
@@ -648,53 +648,6 @@ get_atomic_counter_op(nir_<wbr>intrinsic_op op)<br>
    }<br>
 }<br>
<br>
-unsigned<br>
-tesslevel_outer_components(<wbr>GLenum tes_primitive_mode)<br>
-{<br>
-   switch (tes_primitive_mode) {<br>
-   case GL_QUADS:<br>
-      return 4;<br>
-   case GL_TRIANGLES:<br>
-      return 3;<br>
-   case GL_ISOLINES:<br>
-      return 2;<br>
-   default:<br>
-      unreachable("Bogus tessellation domain");<br>
-   }<br>
-   return 0;<br>
-}<br>
-<br>
-unsigned<br>
-tesslevel_inner_components(<wbr>GLenum tes_primitive_mode)<br>
-{<br>
-   switch (tes_primitive_mode) {<br>
-   case GL_QUADS:<br>
-      return 2;<br>
-   case GL_TRIANGLES:<br>
-      return 1;<br>
-   case GL_ISOLINES:<br>
-      return 0;<br>
-   default:<br>
-      unreachable("Bogus tessellation domain");<br>
-   }<br>
-   return 0;<br>
-}<br>
-<br>
-/**<br>
- * Given a normal .xyzw writemask, convert it to a writemask for a vector<br>
- * that's stored backwards, i.e. .wzyx.<br>
- */<br>
-unsigned<br>
-writemask_for_backwards_<wbr>vector(unsigned mask)<br>
-{<br>
-   unsigned new_mask = 0;<br>
-<br>
-   for (int i = 0; i < 4; i++)<br>
-      new_mask |= ((mask >> i) & 1) << (3 - i);<br>
-<br>
-   return new_mask;<br>
-}<br>
-<br>
 backend_shader::backend_<wbr>shader(const struct brw_compiler *compiler,<br>
                                void *log_data,<br>
                                void *mem_ctx,<br>
@@ -712,8 +665,6 @@ backend_shader::backend_<wbr>shader(const struct brw_compiler *compiler,<br>
    debug_enabled = INTEL_DEBUG & intel_debug_flag_for_shader_<wbr>stage(stage);<br>
    stage_name = _mesa_shader_stage_to_string(<wbr>stage);<br>
    stage_abbrev = _mesa_shader_stage_to_abbrev(<wbr>stage);<br>
-   is_passthrough_shader =<br>
-      nir->info->name && strcmp(nir->info->name, "passthrough") == 0;<br>
 }<br>
<br>
 bool<br>
@@ -1399,17 +1350,7 @@ brw_compile_tes(const struct brw_compiler *compiler,<br>
<br>
    /* URB entry sizes are stored as a multiple of 64 bytes. */<br>
    prog_data->base.urb_entry_size = ALIGN(output_size_bytes, 64) / 64;<br>
-<br>
-   bool need_patch_header = nir->info->system_values_read &<br>
-      (BITFIELD64_BIT(SYSTEM_VALUE_<wbr>TESS_LEVEL_OUTER) |<br>
-       BITFIELD64_BIT(SYSTEM_VALUE_<wbr>TESS_LEVEL_INNER));<br>
-<br>
-   /* The TES will pull most inputs using URB read messages.<br>
-    *<br>
-    * However, we push the patch header for TessLevel factors when required,<br>
-    * as it's a tiny amount of extra data.<br>
-    */<br>
-   prog_data->base.urb_read_<wbr>length = need_patch_header ? 1 : 0;<br>
+   prog_data->base.urb_read_<wbr>length = 0;<br>
<br>
    if (unlikely(INTEL_DEBUG & DEBUG_TES)) {<br>
       fprintf(stderr, "TES Input ");<br>
diff --git a/src/mesa/drivers/dri/i965/<wbr>brw_shader.h b/src/mesa/drivers/dri/i965/<wbr>brw_shader.h<br>
index 6b5ee3719a9..13f271db8c1 100644<br>
--- a/src/mesa/drivers/dri/i965/<wbr>brw_shader.h<br>
+++ b/src/mesa/drivers/dri/i965/<wbr>brw_shader.h<br>
@@ -217,7 +217,6 @@ public:<br>
    bool debug_enabled;<br>
    const char *stage_name;<br>
    const char *stage_abbrev;<br>
-   bool is_passthrough_shader;<br>
<br>
    brw::simple_allocator alloc;<br>
<br>
@@ -301,10 +300,6 @@ bool brw_cs_precompile(struct gl_context *ctx,<br>
 GLboolean brw_link_shader(struct gl_context *ctx, struct gl_shader_program *prog);<br>
 struct gl_linked_shader *brw_new_shader(gl_shader_<wbr>stage stage);<br>
<br>
-unsigned tesslevel_outer_components(<wbr>GLenum tes_primitive_mode);<br>
-unsigned tesslevel_inner_components(<wbr>GLenum tes_primitive_mode);<br>
-unsigned writemask_for_backwards_<wbr>vector(unsigned mask);<br>
-<br>
 unsigned get_atomic_counter_op(nir_<wbr>intrinsic_op op);<br>
<br>
 #ifdef __cplusplus<br>
diff --git a/src/mesa/drivers/dri/i965/<wbr>brw_tcs.c b/src/mesa/drivers/dri/i965/<wbr>brw_tcs.c<br>
index f890ccf0296..567ae792dcd 100644<br>
--- a/src/mesa/drivers/dri/i965/<wbr>brw_tcs.c<br>
+++ b/src/mesa/drivers/dri/i965/<wbr>brw_tcs.c<br>
@@ -51,7 +51,8 @@ create_passthrough_tcs(void *mem_ctx, const struct brw_compiler *compiler,<br>
    nir_ssa_def *invoc_id =<br>
       nir_load_system_value(&b, nir_intrinsic_load_invocation_<wbr>id, 0);<br>
<br>
-   nir->info->inputs_read = key->outputs_written;<br>
+   nir->info->inputs_read = key->outputs_written &<br>
+      ~(VARYING_BIT_TESS_LEVEL_INNER | VARYING_BIT_TESS_LEVEL_OUTER);<br>
    nir->info->outputs_written = key->outputs_written;<br>
    nir->info->tcs.vertices_out = key->input_vertices;<br>
    nir->info->name = ralloc_strdup(nir, "passthrough");<br>
@@ -81,7 +82,7 @@ create_passthrough_tcs(void *mem_ctx, const struct brw_compiler *compiler,<br>
    }<br>
<br>
    /* Copy inputs to outputs. */<br>
-   uint64_t varyings = key->outputs_written;<br>
+   uint64_t varyings = nir->info->inputs_read;<br>
<br>
    while (varyings != 0) {<br>
       const int varying = ffsll(varyings) - 1;<br>
diff --git a/src/mesa/drivers/dri/i965/<wbr>brw_tes.c b/src/mesa/drivers/dri/i965/<wbr>brw_tes.c<br>
index 20313660734..56d75c28447 100644<br>
--- a/src/mesa/drivers/dri/i965/<wbr>brw_tes.c<br>
+++ b/src/mesa/drivers/dri/i965/<wbr>brw_tes.c<br>
@@ -239,16 +239,12 @@ brw_tes_populate_key(struct brw_context *brw,<br>
     */<br>
    if (tcp) {<br>
       struct gl_program *tcp_prog = &tcp->program;<br>
-      per_vertex_slots |= tcp_prog->info.outputs_<wbr>written;<br>
+      per_vertex_slots |= tcp_prog->info.outputs_written &<br>
+         ~(VARYING_BIT_TESS_LEVEL_INNER | VARYING_BIT_TESS_LEVEL_OUTER);<br>
       per_patch_slots |= tcp_prog->info.patch_outputs_<wbr>written;<br>
    }<br>
<br>
-   /* Ignore gl_TessLevelInner/Outer - we treat them as system values,<br>
-    * not inputs, and they're always present in the URB entry regardless<br>
-    * of whether or not we read them.<br>
-    */<br>
-   key->inputs_read = per_vertex_slots &<br>
-      ~(VARYING_BIT_TESS_LEVEL_INNER | VARYING_BIT_TESS_LEVEL_OUTER);<br>
+   key->inputs_read = per_vertex_slots;<br>
    key->patch_inputs_read = per_patch_slots;<br>
<br>
    /* _NEW_TEXTURE */<br>
@@ -305,14 +301,11 @@ brw_tes_precompile(struct gl_context *ctx,<br>
    if (shader_prog->_LinkedShaders[<wbr>MESA_SHADER_TESS_CTRL]) {<br>
       struct gl_program *tcp =<br>
          shader_prog->_LinkedShaders[<wbr>MESA_SHADER_TESS_CTRL]-><wbr>Program;<br>
-      key.inputs_read |= tcp->nir->info->outputs_<wbr>written;<br>
+      key.inputs_read |= tcp->nir->info->outputs_<wbr>written &<br>
+         ~(VARYING_BIT_TESS_LEVEL_INNER | VARYING_BIT_TESS_LEVEL_OUTER);<br>
       key.patch_inputs_read |= tcp->nir->info->patch_outputs_<wbr>written;<br>
    }<br>
<br>
-   /* Ignore gl_TessLevelInner/Outer - they're system values. */<br>
-   key.inputs_read &= ~(VARYING_BIT_TESS_LEVEL_INNER |<br>
-                        VARYING_BIT_TESS_LEVEL_OUTER);<br>
-<br>
    brw_setup_tex_for_precompile(<wbr>brw, &key.tex, prog);<br>
<br>
    success = brw_codegen_tes_prog(brw, shader_prog, btep, &key);<br>
diff --git a/src/mesa/drivers/dri/i965/<wbr>brw_vec4_tcs.cpp b/src/mesa/drivers/dri/i965/<wbr>brw_vec4_tcs.cpp<br>
index bfa22458f0e..9ef3dc04665 100644<br>
--- a/src/mesa/drivers/dri/i965/<wbr>brw_vec4_tcs.cpp<br>
+++ b/src/mesa/drivers/dri/i965/<wbr>brw_vec4_tcs.cpp<br>
@@ -319,62 +319,8 @@ vec4_tcs_visitor::nir_emit_<wbr>intrinsic(nir_intrinsic_instr *instr)<br>
       dst_reg dst = get_nir_dest(instr->dest, BRW_REGISTER_TYPE_D);<br>
       dst.writemask = brw_writemask_for_size(instr-><wbr>num_components);<br>
<br>
-      if (imm_offset == 0 && indirect_offset.file == BAD_FILE) {<br>
-         dst.type = BRW_REGISTER_TYPE_F;<br>
-<br>
-         /* This is a read of gl_TessLevelInner[], which lives in the<br>
-          * Patch URB header.  The layout depends on the domain.<br>
-          */<br>
-         switch (key->tes_primitive_mode) {<br>
-         case GL_QUADS: {<br>
-            /* DWords 3-2 (reversed); use offset 0 and WZYX swizzle. */<br>
-            dst_reg tmp(this, glsl_type::vec4_type);<br>
-            emit_output_urb_read(tmp, 0, 0, src_reg());<br>
-            emit(MOV(writemask(dst, WRITEMASK_XY),<br>
-                     swizzle(src_reg(tmp), BRW_SWIZZLE_WZYX)));<br>
-            break;<br>
-         }<br>
-         case GL_TRIANGLES:<br>
-            /* DWord 4; use offset 1 but normal swizzle/writemask. */<br>
-            emit_output_urb_read(<wbr>writemask(dst, WRITEMASK_X), 1, 0,<br>
-                                 src_reg());<br>
-            break;<br>
-         case GL_ISOLINES:<br>
-            /* All channels are undefined. */<br>
-            return;<br>
-         default:<br>
-            unreachable("Bogus tessellation domain");<br>
-         }<br>
-      } else if (imm_offset == 1 && indirect_offset.file == BAD_FILE) {<br>
-         dst.type = BRW_REGISTER_TYPE_F;<br>
-         unsigned swiz = BRW_SWIZZLE_WZYX;<br>
-<br>
-         /* This is a read of gl_TessLevelOuter[], which lives in the<br>
-          * high 4 DWords of the Patch URB header, in reverse order.<br>
-          */<br>
-         switch (key->tes_primitive_mode) {<br>
-         case GL_QUADS:<br>
-            dst.writemask = WRITEMASK_XYZW;<br>
-            break;<br>
-         case GL_TRIANGLES:<br>
-            dst.writemask = WRITEMASK_XYZ;<br>
-            break;<br>
-         case GL_ISOLINES:<br>
-            /* Isolines are not reversed; swizzle .zw -> .xy */<br>
-            swiz = BRW_SWIZZLE_ZWZW;<br>
-            dst.writemask = WRITEMASK_XY;<br>
-            return;<br>
-         default:<br>
-            unreachable("Bogus tessellation domain");<br>
-         }<br>
-<br>
-         dst_reg tmp(this, glsl_type::vec4_type);<br>
-         emit_output_urb_read(tmp, 1, 0, src_reg());<br>
-         emit(MOV(dst, swizzle(src_reg(tmp), swiz)));<br>
-      } else {<br>
-         emit_output_urb_read(dst, imm_offset, nir_intrinsic_component(instr)<wbr>,<br>
-                              indirect_offset);<br>
-      }<br>
+      emit_output_urb_read(dst, imm_offset, nir_intrinsic_component(instr)<wbr>,<br>
+                           indirect_offset);<br>
       break;<br>
    }<br>
    case nir_intrinsic_store_output:<br>
@@ -386,62 +332,6 @@ vec4_tcs_visitor::nir_emit_<wbr>intrinsic(nir_intrinsic_instr *instr)<br>
       src_reg indirect_offset = get_indirect_offset(instr);<br>
       unsigned imm_offset = instr->const_index[0];<br>
<br>
-      /* The passthrough shader writes the whole patch header as two vec4s;<br>
-       * skip all the gl_TessLevelInner/Outer swizzling.<br>
-       */<br>
-      if (indirect_offset.file == BAD_FILE && !is_passthrough_shader) {<br>
-         if (imm_offset == 0) {<br>
-            value.type = BRW_REGISTER_TYPE_F;<br>
-<br>
-            mask &=<br>
-               (1 << tesslevel_inner_components(<wbr>key->tes_primitive_mode)) - 1;<br>
-<br>
-            /* This is a write to gl_TessLevelInner[], which lives in the<br>
-             * Patch URB header.  The layout depends on the domain.<br>
-             */<br>
-            switch (key->tes_primitive_mode) {<br>
-            case GL_QUADS:<br>
-               /* gl_TessLevelInner[].xy lives at DWords 3-2 (reversed).<br>
-                * We use an XXYX swizzle to reverse put .xy in the .wz<br>
-                * channels, and use a .zw writemask.<br>
-                */<br>
-               swiz = BRW_SWIZZLE4(0, 0, 1, 0);<br>
-               mask = writemask_for_backwards_<wbr>vector(mask);<br>
-               break;<br>
-            case GL_TRIANGLES:<br>
-               /* gl_TessLevelInner[].x lives at DWord 4, so we set the<br>
-                * writemask to X and bump the URB offset by 1.<br>
-                */<br>
-               imm_offset = 1;<br>
-               break;<br>
-            case GL_ISOLINES:<br>
-               /* Skip; gl_TessLevelInner[] doesn't exist for isolines. */<br>
-               return;<br>
-            default:<br>
-               unreachable("Bogus tessellation domain");<br>
-            }<br>
-         } else if (imm_offset == 1) {<br>
-            value.type = BRW_REGISTER_TYPE_F;<br>
-<br>
-            mask &=<br>
-               (1 << tesslevel_outer_components(<wbr>key->tes_primitive_mode)) - 1;<br>
-<br>
-            /* This is a write to gl_TessLevelOuter[] which lives in the<br>
-             * Patch URB Header at DWords 4-7.  However, it's reversed, so<br>
-             * instead of .xyzw we have .wzyx.<br>
-             */<br>
-            if (key->tes_primitive_mode == GL_ISOLINES) {<br>
-               /* Isolines .xy should be stored in .zw, in order. */<br>
-               swiz = BRW_SWIZZLE4(0, 0, 0, 1);<br>
-               mask <<= 2;<br>
-            } else {<br>
-               /* Other domains are reversed; store .wzyx instead of .xyzw. */<br>
-               swiz = BRW_SWIZZLE_WZYX;<br>
-               mask = writemask_for_backwards_<wbr>vector(mask);<br>
-            }<br>
-         }<br>
-      }<br>
-<br>
       unsigned first_component = nir_intrinsic_component(instr)<wbr>;<br>
       if (first_component) {<br>
          if (nir_src_bit_size(instr->src[<wbr>0]) == 64)<br>
@@ -522,7 +412,8 @@ brw_compile_tcs(const struct brw_compiler *compiler,<br>
<br>
    nir = brw_nir_apply_sampler_key(nir, compiler, &key->tex, is_scalar);<br>
    brw_nir_lower_vue_inputs(nir, is_scalar, &input_vue_map);<br>
-   brw_nir_lower_tcs_outputs(nir, &vue_prog_data->vue_map);<br>
+   brw_nir_lower_tcs_outputs(nir, &vue_prog_data->vue_map,<br>
+                             key->tes_primitive_mode);<br>
    if (key->quads_workaround)<br>
       brw_nir_apply_tcs_quads_<wbr>workaround(nir);<br>
<span class="HOEnZb"><font color="#888888"><br>
--<br>
2.11.0<br>
<br>
______________________________<wbr>_________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br></div></div>