[Mesa-dev] [PATCH v4 16/17] glsl linker: compare interface blocks during intrastage linking

Kenneth Graunke kenneth at whitecape.org
Wed May 22 11:00:52 PDT 2013


On 05/16/2013 05:44 PM, Jordan Justen wrote:
> Verify that interface blocks match when combining compilation
> units at the same stage. (For example, when merging all vertex
> shaders.)
>
> Fixes piglit glsl-1.50 test:
> * linker/interface-blocks-multiple-vs-member-count-mismatch.shader_test
>
> Signed-off-by: Jordan Justen <jordan.l.justen at intel.com>

I will be sending out a revised version of this patch that incorporates 
my suggestions.

> ---
>   src/glsl/Makefile.sources     |    1 +
>   src/glsl/interface_blocks.cpp |   86 +++++++++++++++++++++++++++++++++++++++++
>   src/glsl/interface_blocks.h   |   32 +++++++++++++++
>   src/glsl/linker.cpp           |    7 ++++
>   4 files changed, 126 insertions(+)
>   create mode 100644 src/glsl/interface_blocks.cpp
>   create mode 100644 src/glsl/interface_blocks.h
>
> diff --git a/src/glsl/Makefile.sources b/src/glsl/Makefile.sources
> index b9fd283..e39cb1a 100644
> --- a/src/glsl/Makefile.sources
> +++ b/src/glsl/Makefile.sources
> @@ -26,6 +26,7 @@ LIBGLSL_FILES = \
>   	$(GLSL_SRCDIR)/glsl_types.cpp \
>   	$(GLSL_SRCDIR)/glsl_symbol_table.cpp \
>   	$(GLSL_SRCDIR)/hir_field_selection.cpp \
> +	$(GLSL_SRCDIR)/interface_blocks.cpp \
>   	$(GLSL_SRCDIR)/ir_basic_block.cpp \
>   	$(GLSL_SRCDIR)/ir_builder.cpp \
>   	$(GLSL_SRCDIR)/ir_clone.cpp \
> diff --git a/src/glsl/interface_blocks.cpp b/src/glsl/interface_blocks.cpp
> new file mode 100644
> index 0000000..6dfd0c4
> --- /dev/null
> +++ b/src/glsl/interface_blocks.cpp

I would call this link_interface_blocks.cpp.  All the other linker code 
is named link*.cpp.

> @@ -0,0 +1,86 @@
> +/*
> + * Copyright (c) 2013 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + */
> +
> +/**
> + * \file interface_blocks.cpp
> + * GLSL interface blocks support
> + */
> +
> +#include "ir.h"
> +#include "glsl_symbol_table.h"
> +#include "main/macros.h"
> +#include "program/hash_table.h"
> +
> +static bool
> +cross_validate_interface_blocks(const gl_shader **shader_list,
> +                                unsigned num_shaders)
> +{
> +   bool ok = true;
> +   glsl_symbol_table interfaces;
> +
> +   for (unsigned int i = 0; ok && i < num_shaders; i++) {
> +      if (shader_list[i] == NULL)
> +         continue;
> +
> +      foreach_list(node, shader_list[i]->ir) {
> +         ir_variable *var = ((ir_instruction *) node)->as_variable();
> +         if (!var)
> +            continue;
> +
> +         const glsl_type *iface_type = var->interface_type;
> +
> +         if (iface_type == NULL)
> +            continue;
> +
> +         const char *iface_name = iface_type->name;
> +
> +         const glsl_type *old_iface_type =
> +            interfaces.get_interface(iface_name,
> +                                     (enum ir_variable_mode) var->mode);
> +
> +         /* This is the first time we've seen the interface, so save
> +          * it into our symbol table.
> +          */
> +         if (old_iface_type == NULL) {
> +            interfaces.add_interface(iface_name, iface_type,
> +                                     (enum ir_variable_mode) var->mode);
> +            old_iface_type = iface_type;
> +         }
> +
> +         ok &= old_iface_type == iface_type;

I guess C++ booleans are guaranteed to be 0 or 1, so this ought to work, 
but using bitwise operators on bools is still a bit odd.

> +         if (!ok)
> +            break;

You could actually just drop the "ok" variable altogether and change 
this code to:

if (old_iface_type != iface_type)
    return false;

and then "return true" at the bottom.  Seems simpler.

> +      }
> +   }
> +
> +   return ok;
> +}
> +
> +bool
> +validate_intrastage_interface_blocks(const gl_shader **shader_list,
> +                                     unsigned num_shaders)
> +{
> +   return cross_validate_interface_blocks(shader_list,
> +                                          num_shaders);
> +}
> +
> diff --git a/src/glsl/interface_blocks.h b/src/glsl/interface_blocks.h
> new file mode 100644
> index 0000000..4c37c02
> --- /dev/null
> +++ b/src/glsl/interface_blocks.h

I would just stuff this in linker.h.  Two prototypes is probably not 
worth the extra header file.

> @@ -0,0 +1,32 @@
> +/*
> + * Copyright (c) 2013 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + */
> +
> +#pragma once
> +#ifndef GLSL_INTERFACE_BLOCKS_H
> +#define GLSL_INTERFACE_BLOCKS_H
> +
> +bool
> +validate_intrastage_interface_blocks(const gl_shader **shader_list,
> +                                     unsigned num_shaders);
> +
> +#endif /* GLSL_INTERFACE_BLOCKS_H */
> diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
> index c8d430c..4f2cab2 100644
> --- a/src/glsl/linker.cpp
> +++ b/src/glsl/linker.cpp
> @@ -66,6 +66,7 @@
>
>   #include "main/core.h"
>   #include "glsl_symbol_table.h"
> +#include "interface_blocks.h"
>   #include "ir.h"
>   #include "program.h"
>   #include "program/hash_table.h"
> @@ -938,6 +939,12 @@ link_intrastage_shaders(void *mem_ctx,
>      if (!cross_validate_globals(prog, shader_list, num_shaders, false))
>         return NULL;
>
> +   /* Check that interface blocks defined in multiple shaders are consistent.
> +    */
> +   if (!validate_intrastage_interface_blocks((const gl_shader **)shader_list,
> +                                             num_shaders))
> +      return NULL;
> +
>      /* Check that uniform blocks between shaders for a stage agree. */
>      const int num_uniform_blocks =
>         link_uniform_blocks(mem_ctx, prog, shader_list, num_shaders,
>



More information about the mesa-dev mailing list