<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>