[Mesa-dev] [PATCH v2] anv: fix bug when using component qualifier in FS outputs
Jason Ekstrand
jason at jlekstrand.net
Tue Nov 28 20:59:43 UTC 2017
On Tue, Nov 14, 2017 at 10:39 PM, Samuel Iglesias Gonsálvez <
siglesias at igalia.com> wrote:
> We can write to the same output but in different components, like
> in this example:
>
> layout(location = 0, component = 0) out ivec2 dEQP_FragColor_0;
> layout(location = 0, component = 2) out ivec2 dEQP_FragColor_1;
>
> Therefore, they are not two different outputs but only one.
>
> Fixes:
>
> dEQP-VK.glsl.440.linkage.varying.component.frag_out.*
>
> Signed-off-by: Samuel Iglesias Gonsálvez <siglesias at igalia.com>
> ---
> src/compiler/shader_enums.h | 1 +
> src/intel/vulkan/anv_pipeline.c | 46 +++++++++++++++++++++++++++---
> -----------
> 2 files changed, 32 insertions(+), 15 deletions(-)
>
> diff --git a/src/compiler/shader_enums.h b/src/compiler/shader_enums.h
> index 9d229d4199e..90729dbfd96 100644
> --- a/src/compiler/shader_enums.h
> +++ b/src/compiler/shader_enums.h
> @@ -603,6 +603,7 @@ typedef enum
> FRAG_RESULT_DATA5,
> FRAG_RESULT_DATA6,
> FRAG_RESULT_DATA7,
> + FRAG_RESULT_MAX, /**< Number of fragment program results */
> } gl_frag_result;
>
> const char *gl_frag_result_name(gl_frag_result result);
> diff --git a/src/intel/vulkan/anv_pipeline.c b/src/intel/vulkan/anv_
> pipeline.c
> index 907b24a758d..92cfc2898f5 100644
> --- a/src/intel/vulkan/anv_pipeline.c
> +++ b/src/intel/vulkan/anv_pipeline.c
> @@ -870,30 +870,28 @@ anv_pipeline_compile_fs(struct anv_pipeline
> *pipeline,
> }
>
> unsigned num_rts = 0;
> - struct anv_pipeline_binding rt_bindings[8];
> + const int max_rt = FRAG_RESULT_MAX - FRAG_RESULT_DATA0;
> + struct anv_pipeline_binding rt_bindings[max_rt];
> nir_function_impl *impl = nir_shader_get_entrypoint(nir);
> + int rt_to_bindings[max_rt];
> + memset(rt_to_bindings, -1, sizeof(int) * max_rt);
> +
> + /* Set new, compacted, location */
> nir_foreach_variable_safe(var, &nir->outputs) {
> if (var->data.location < FRAG_RESULT_DATA0)
> continue;
>
> unsigned rt = var->data.location - FRAG_RESULT_DATA0;
> - if (rt >= key.nr_color_regions) {
> - /* Out-of-bounds, throw it away */
> - var->data.mode = nir_var_local;
> - exec_node_remove(&var->node);
> - exec_list_push_tail(&impl->locals, &var->node);
> + if (rt_to_bindings[rt] != -1 || rt >= key.nr_color_regions)
> continue;
> - }
> -
> - /* Give it a new, compacted, location */
> - var->data.location = FRAG_RESULT_DATA0 + num_rts;
> -
> - unsigned array_len =
> + const unsigned array_len =
> glsl_type_is_array(var->type) ? glsl_get_length(var->type) :
> 1;
> - assert(num_rts + array_len <= 8);
> + assert(num_rts + array_len <= max_rt);
> +
> + rt_to_bindings[rt] = num_rts;
>
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.
As a side-note, it's abundantly obvious that we need more tests for this.
--Jason
>
> for (unsigned i = 0; i < array_len; i++) {
> - rt_bindings[num_rts + i] = (struct anv_pipeline_binding) {
> + rt_bindings[rt_to_bindings[rt] + i] = (struct
> anv_pipeline_binding) {
> .set = ANV_DESCRIPTOR_SET_COLOR_ATTACHMENTS,
> .binding = 0,
> .index = rt + i,
> @@ -903,6 +901,24 @@ anv_pipeline_compile_fs(struct anv_pipeline *pipeline,
> num_rts += array_len;
> }
>
> + nir_foreach_variable_safe(var, &nir->outputs) {
> + if (var->data.location < FRAG_RESULT_DATA0)
> + continue;
> +
> + unsigned rt = var->data.location - FRAG_RESULT_DATA0;
> + if (rt >= key.nr_color_regions) {
> + /* Out-of-bounds, throw it away */
> + var->data.mode = nir_var_local;
> + exec_node_remove(&var->node);
> + exec_list_push_tail(&impl->locals, &var->node);
> + continue;
> + }
> +
> + /* Give it the new location */
> + assert(rt_to_bindings[rt] != -1);
> + var->data.location = rt_to_bindings[rt] + FRAG_RESULT_DATA0;
> + }
> +
> if (num_rts == 0) {
> /* If we have no render targets, we need a null render target */
> rt_bindings[0] = (struct anv_pipeline_binding) {
> @@ -913,7 +929,7 @@ anv_pipeline_compile_fs(struct anv_pipeline *pipeline,
> num_rts = 1;
> }
>
> - assert(num_rts <= 8);
> + assert(num_rts <= max_rt);
> map.surface_to_descriptor -= num_rts;
> map.surface_count += num_rts;
> assert(map.surface_count <= 256);
> --
> 2.14.3
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20171128/d044733e/attachment-0001.html>
More information about the mesa-dev
mailing list