glsl/linker: add xfb workaround for modified built-in variables
authorLouis-Francis Ratté-Boulianne <lfrb@collabora.com>
Sat, 12 Oct 2019 05:13:54 +0000 (01:13 -0400)
committerMarge Bot <eric+marge@anholt.net>
Tue, 3 Mar 2020 12:28:23 +0000 (12:28 +0000)
Some lowering passes modify the value of built-in variables in
order for drivers to work properly. However, modifying such values
will also break transform feedback as the captured value won't
match what's expected.

For example, on some hardware, the vertex shaders are expected to
output gl_Position in screen space. However, the transform
feedback captured value is still supposed to be the world-space
coordinates (see nir_lower_viewport_transform).

To fix that, we create a new variable that contains the
pre-transformation value and use it for transform feedback instead
of the built-in one.

Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb@collabora.com>
Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Acked-by: Daniel Stone <daniels@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/2433>

src/compiler/glsl/link_varyings.cpp
src/mesa/main/mtypes.h

index 4757825c244ff4e32c7a914189cf53dab8abb53e..5219294ad7bf90cf7c38dc42b5554e22c6cd0242 100644 (file)
@@ -2794,15 +2794,26 @@ assign_varying_locations(struct gl_context *ctx,
          return false;
       }
 
-      /* A new output varying is needed, and the matched candidate should be
-       * replaced, if varying packing is disabled for xfb and the current
-       * declaration is not aligned within the top level varying
-       * (e.g. vec3_arr[1]).
+      /* There are two situations where a new output varying is needed:
+       *
+       *  - If varying packing is disabled for xfb and the current declaration
+       *    is not aligned within the top level varying (e.g. vec3_arr[1]).
+       *
+       *  - If a builtin variable needs to be copied to a new variable
+       *    before its content is modified by another lowering pass (e.g.
+       *    \c gl_Position is transformed by \c nir_lower_viewport_transform).
        */
       const unsigned dmul =
          matched_candidate->type->without_array()->is_64bit() ? 2 : 1;
-      if (disable_xfb_packing &&
-          !tfeedback_decls[i].is_aligned(dmul, matched_candidate->offset)) {
+      const bool lowered =
+         (disable_xfb_packing &&
+          !tfeedback_decls[i].is_aligned(dmul, matched_candidate->offset)) ||
+         (matched_candidate->toplevel_var->data.explicit_location &&
+          matched_candidate->toplevel_var->data.location < VARYING_SLOT_VAR0 &&
+          (ctx->Const.ShaderCompilerOptions[producer->Stage].LowerBuiltinVariablesXfb &
+              BITFIELD_BIT(matched_candidate->toplevel_var->data.location)));
+
+      if (lowered) {
          ir_variable *new_var;
          tfeedback_candidate *new_candidate = NULL;
 
index 91fc71cfcfdbf9993692912903f3ebc536eb7826..7396de5b5d003e606152f5ca31284d2f6a251e2f 100644 (file)
@@ -3174,6 +3174,9 @@ struct gl_shader_compiler_options
                                               * gl_CullDistance together from
                                               * float[8] to vec4[2]
                                               **/
+   GLbitfield LowerBuiltinVariablesXfb;   /**< Which builtin variables should
+                                           * be lowered for transform feedback
+                                           **/
 
    /**
     * \name Forms of indirect addressing the driver cannot do.