Skip to content

anv: clamp per vertex input accesses to patchControlPoints

Lionel Landwerlin requested to merge llandwerlin/mesa:review/tcs-fix into main

In a tesselation control shader where an input array is accessed using the index gl_InvocationID, we can end up accessing elements beyond the number of input vertices specified in the shader key.

This happens because of the lowering in nir_lower_indirect_derefs(). This lowering will affect compact variables which happens in this case :

  in gl_PerVertex {
      vec4  gl_Position;
      float gl_ClipDistance[1];
  } gl_in[gl_MaxPatchVertices];

The lowered code produced by NIR is somewhat ineffecient (implements a binary seach) :

  if (gl_InvocationID < 16) {
     if (gl_InvocationID < 8) {
        if (gl_InvocationID < 4) {
          vec4 vals = load_at_offset(0);
          value = bcsel(vals, gl_InvocationID);
        } else {
          vec4 vals = load_at_offset(4);
          value = bcsel(vals, gl_InvocationID - 4);
        }
     } else {
        if (gl_InvocationID < 12) {
          vec4 vals = load_at_offset(8);
          value = bcsel(vals, gl_InvocationID - 8);
        } else {
          vec4 vals = load_at_offset(12);
          value = bcsel(vals, gl_InvocationID - 12);
        }
     }
  } else {
     if (gl_InvocationID < 24) {
        ...
     } else {
        ...
     }
  }

By default the gl_MaxPatchVertices must be set at 32 items and that's what the lowering code will use to divide the access into chunks of 4. But when running with 3 input vertices, this means we'll pull one more item than what was delivered in the shader payload.

This triggers issues further down the register scheduling where the g5UD (register for the 4th item) is overwritten by a previous SEND, leading the URB read to use an invalid handle.

Signed-off-by: Lionel Landwerlin lionel.g.landwerlin@intel.com

Edited by Lionel Landwerlin

Merge request reports