<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Tue, Nov 14, 2017 at 10:39 PM, Samuel Iglesias Gonsálvez <span dir="ltr"><<a href="mailto:siglesias@igalia.com" target="_blank">siglesias@igalia.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">We can write to the same output but in different components, like<br>
in this example:<br>
<br>
layout(location = 0, component = 0) out ivec2 dEQP_FragColor_0;<br>
layout(location = 0, component = 2) out ivec2 dEQP_FragColor_1;<br>
<br>
Therefore, they are not two different outputs but only one.<br>
<br>
Fixes:<br>
<br>
dEQP-VK.glsl.440.linkage.<wbr>varying.component.frag_out.*<br>
<br>
Signed-off-by: Samuel Iglesias Gonsálvez <<a href="mailto:siglesias@igalia.com">siglesias@igalia.com</a>><br>
---<br>
 src/compiler/shader_enums.h     |  1 +<br>
</span> src/intel/vulkan/anv_pipeline.<wbr>c | 46 +++++++++++++++++++++++++++---<wbr>-----------<br>
 2 files changed, 32 insertions(+), 15 deletions(-)<br>
<span class=""><br>
diff --git a/src/compiler/shader_enums.h b/src/compiler/shader_enums.h<br>
index 9d229d4199e..90729dbfd96 100644<br>
--- a/src/compiler/shader_enums.h<br>
+++ b/src/compiler/shader_enums.h<br>
@@ -603,6 +603,7 @@ typedef enum<br>
    FRAG_RESULT_DATA5,<br>
    FRAG_RESULT_DATA6,<br>
    FRAG_RESULT_DATA7,<br>
+   FRAG_RESULT_MAX, /**< Number of fragment program results */<br>
 } gl_frag_result;<br>
<br>
 const char *gl_frag_result_name(gl_frag_<wbr>result result);<br>
diff --git a/src/intel/vulkan/anv_<wbr>pipeline.c b/src/intel/vulkan/anv_<wbr>pipeline.c<br>
</span>index 907b24a758d..92cfc2898f5 100644<br>
--- a/src/intel/vulkan/anv_<wbr>pipeline.c<br>
+++ b/src/intel/vulkan/anv_<wbr>pipeline.c<br>
@@ -870,30 +870,28 @@ anv_pipeline_compile_fs(struct anv_pipeline *pipeline,<br>
       }<br>
<br>
       unsigned num_rts = 0;<br>
-      struct anv_pipeline_binding rt_bindings[8];<br>
+      const int max_rt = FRAG_RESULT_MAX - FRAG_RESULT_DATA0;<br>
+      struct anv_pipeline_binding rt_bindings[max_rt];<br>
       nir_function_impl *impl = nir_shader_get_entrypoint(nir)<wbr>;<br>
+      int rt_to_bindings[max_rt];<br>
+      memset(rt_to_bindings, -1, sizeof(int) * max_rt);<br>
+<br>
+      /* Set new, compacted, location */<br>
<span class="">       nir_foreach_variable_safe(var, &nir->outputs) {<br>
          if (var->data.location < FRAG_RESULT_DATA0)<br>
             continue;<br>
<br>
</span>          unsigned rt = var->data.location - FRAG_RESULT_DATA0;<br>
-         if (rt >= key.nr_color_regions) {<br>
-            /* Out-of-bounds, throw it away */<br>
-            var->data.mode = nir_var_local;<br>
-            exec_node_remove(&var->node);<br>
-            exec_list_push_tail(&impl-><wbr>locals, &var->node);<br>
+         if (rt_to_bindings[rt] != -1 || rt >= key.nr_color_regions)<br>
             continue;<br>
-         }<br>
-<br>
-         /* Give it a new, compacted, location */<br>
<span class="">-         var->data.location = FRAG_RESULT_DATA0 + num_rts;<br>
</span>-<br>
-         unsigned array_len =<br>
+         const unsigned array_len =<br>
<span class="">             glsl_type_is_array(var->type) ? glsl_get_length(var->type) : 1;<br>
</span>-         assert(num_rts + array_len <= 8);<br>
+         assert(num_rts + array_len <= max_rt);<br>
+<br>
+         rt_to_bindings[rt] = num_rts;<br></blockquote><div><br></div><div>But what about arrays?  I'm pretty sure that in order to get this 100% correct in all cases, we need to do the three-pass I suggested above.  In particular, we need rt_to_bindings to have an entry for each array element.  Also, if we want to handle crazy cases such as a vec2[2] at location 0 and a vec2 at location 1 channel 2, we basically have to do a pre-pass to figure out what all bindings are live before we can start assigning anything.</div><div><br></div><div>As a side-note, it's abundantly obvious that we need more tests for this.</div><div><br></div><div>--Jason<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
          for (unsigned i = 0; i < array_len; i++) {<br>
-            rt_bindings[num_rts + i] = (struct anv_pipeline_binding) {<br>
+            rt_bindings[rt_to_bindings[rt] + i] = (struct anv_pipeline_binding) {<br>
                .set = ANV_DESCRIPTOR_SET_COLOR_<wbr>ATTACHMENTS,<br>
                .binding = 0,<br>
                .index = rt + i,<br>
@@ -903,6 +901,24 @@ anv_pipeline_compile_fs(struct anv_pipeline *pipeline,<br>
          num_rts += array_len;<br>
       }<br>
<br>
+      nir_foreach_variable_safe(var, &nir->outputs) {<br>
+         if (var->data.location < FRAG_RESULT_DATA0)<br>
+            continue;<br>
+<br>
+         unsigned rt = var->data.location - FRAG_RESULT_DATA0;<br>
+         if (rt >= key.nr_color_regions) {<br>
+            /* Out-of-bounds, throw it away */<br>
+            var->data.mode = nir_var_local;<br>
+            exec_node_remove(&var->node);<br>
+            exec_list_push_tail(&impl-><wbr>locals, &var->node);<br>
+            continue;<br>
+         }<br>
+<br>
+         /* Give it the new location */<br>
+         assert(rt_to_bindings[rt] != -1);<br>
+         var->data.location = rt_to_bindings[rt] + FRAG_RESULT_DATA0;<br>
+      }<br>
+<br>
       if (num_rts == 0) {<br>
          /* If we have no render targets, we need a null render target */<br>
          rt_bindings[0] = (struct anv_pipeline_binding) {<br>
@@ -913,7 +929,7 @@ anv_pipeline_compile_fs(struct anv_pipeline *pipeline,<br>
          num_rts = 1;<br>
       }<br>
<br>
-      assert(num_rts <= 8);<br>
+      assert(num_rts <= max_rt);<br>
       map.surface_to_descriptor -= num_rts;<br>
       map.surface_count += num_rts;<br>
       assert(map.surface_count <= 256);<br>
<span class="HOEnZb"><font color="#888888">--<br>
2.14.3<br>
<br>
</font></span></blockquote></div><br></div></div>