[Mesa-dev] [PATCH] glsl: Fix cross-version linking between VS and GS.
Paul Berry
stereotype441 at gmail.com
Wed Nov 20 14:15:25 PST 2013
On 20 November 2013 11:35, Ian Romanick <idr at freedesktop.org> wrote:
> On 11/19/2013 06:11 PM, Paul Berry wrote:
> > Previously, when attempting to link a vertex shader and a geometry
> > shader that use different GLSL versions, we would sometimes generate a
> > link error due to the implicit declaration of gl_PerVertex being
> > different between the two GLSL versions.
> >
> > This patch fixes that problem by only requiring interface block
> > definitions to match when they are explicitly declared.
> >
> > Fixes piglit test "shaders/version-mixing vs-gs".
>
> Which type do you get? What happens when the linked shader runs?
>
The interface blocks get lowered to individual variable declarations by
lower_named_interface_blocks.cpp, and then since these are built-ins, the
linker isn't actually responsible for matching them up--they get matched up
automatically by virtue of the ir_variable->location values that were
preassigned by builtin_variables.cpp.
So what happens when the shader runs is that the mismatch really has no
consequence. For example, if we link a 1.10 VS with a 1.50 GS, and the GS
tries to access gl_in[...].gl_ClipDistance, it gets undefined results,
because the VS didn't write to gl_ClipDistance (it couldn't, because
gl_ClipDistance didn't exist in 1.10). But that's no different from what
would have happened if we had linked a 1.50 VS that didn't write
gl_ClipDistance to a 1.50 GS that tried to read from gl_ClipDistance.
>
> Do we know what other implementations do for mixed VS / GS versions?
>
My Nvidia system allows arbitrary mixing of VS / GS versions.
>
> > Cc: "10.0" <mesa-stable at lists.freedesktop.org>
> > ---
> >
> > This patch depends on "[PATCH v2] glsl: Prohibit illegal mixing of
> > redeclarations inside/outside gl_PerVertex.", which was sent out for
> > review earlier today.
> >
> > src/glsl/link_interface_blocks.cpp | 29 +++++++++++++++++++++++++----
> > 1 file changed, 25 insertions(+), 4 deletions(-)
> >
> > diff --git a/src/glsl/link_interface_blocks.cpp
> b/src/glsl/link_interface_blocks.cpp
> > index a7fceb9..b4379b0 100644
> > --- a/src/glsl/link_interface_blocks.cpp
> > +++ b/src/glsl/link_interface_blocks.cpp
> > @@ -59,6 +59,9 @@ struct interface_block_definition
> > instance_name = var->name;
> > if (var->type->is_array())
> > array_size = var->type->length;
> > + explicitly_declared = (var->how_declared ==
> ir_var_declared_normally);
> > + } else {
> > + explicitly_declared = (var->how_declared ==
> ir_var_declared_in_block);
>
> Would it be easier to just have
>
> explicitly_declared = (var->how_declared != ir_var_declared_implicitly);
>
> after the existing if-block?
>
Ok, sure. I don't have a strong feeling about this, so I'm happy to change
it.
> > }
> > }
> >
> > @@ -77,6 +80,12 @@ struct interface_block_definition
> > * Otherwise -1.
> > */
> > int array_size;
> > +
> > + /**
> > + * True if this interface block was explicitly declared in the
> shader;
> > + * false if it was an implicitly declared built-in interface block.
> > + */
> > + bool explicitly_declared;
> > };
> >
> >
> > @@ -91,8 +100,14 @@ intrastage_match(interface_block_definition *a,
> > ir_variable_mode mode)
> > {
> > /* Types must match. */
> > - if (a->type != b->type)
> > - return false;
> > + if (a->type != b->type) {
> > + /* Exception: if both the interface blocks are implicitly
> declared,
> > + * don't force their types to match. They might mismatch due to
> the two
> > + * shaders using different GLSL versions, and that's ok.
> > + */
> > + if (a->explicitly_declared || b->explicitly_declared)
> > + return false;
> > + }
> >
> > /* Presence/absence of interface names must match. */
> > if ((a->instance_name == NULL) != (b->instance_name == NULL))
> > @@ -144,8 +159,14 @@ interstage_match(const interface_block_definition
> *producer,
> > assert(producer->array_size != 0);
> >
> > /* Types must match. */
> > - if (consumer->type != producer->type)
> > - return false;
> > + if (consumer->type != producer->type) {
> > + /* Exception: if both the interface blocks are implicitly
> declared,
> > + * don't force their types to match. They might mismatch due to
> the two
> > + * shaders using different GLSL versions, and that's ok.
> > + */
> > + if (consumer->explicitly_declared ||
> producer->explicitly_declared)
> > + return false;
> > + }
> > if (extra_array_level) {
> > /* Consumer must be an array, and producer must not. */
> > if (consumer->array_size == -1)
> >
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20131120/9c77482f/attachment.html>
More information about the mesa-dev
mailing list