Comparing Structs with Equality Operators in GLSL

In the OpenGL Shading Language (GLSL), two structure instances can be compared using the equality (==) and inequality (!=) operators, provided they satisfy specific type and member constraints. This article outlines the precise rules governing struct equality in GLSL, detailing the requirements for type matching, permissible member types, the prohibition of opaque types, and how the underlying component-wise evaluation operates.

Exact Type Equivalence

For two struct instances to be compared with == or !=, they must have the exact same structure type. GLSL uses nominal typing for structures, meaning that two structs are not considered equal in type simply because they share an identical layout or identical field names and types. They must be declared using the same struct type specifier. Implicit type conversion between different struct types does not occur.

Permissible Member Types

Struct equality operates recursively down to each individual field. Therefore, every member defined within the struct must itself support the equality operator. Valid member types include:

  • Scalar types (such as float, int, uint, and bool)
  • Vector types (such as vec2, vec3, vec4, ivec3, etc.)
  • Matrix types (such as mat3, mat4, etc.)
  • Other nested structure types that also meet equality requirements
  • Arrays of comparable types (in GLSL versions that support array equality, such as GLSL 1.30 and later)

Prohibition of Opaque Types

Two struct instances cannot be compared if the structure definition directly or indirectly contains opaque types. Opaque types do not support comparison operators. Members that invalidate a struct for equality comparison include:

  • Texture samplers (e.g., sampler2D, samplerCube)
  • Image types (e.g., image2D)
  • Atomic counters (atomic_uint)
  • Subpass inputs

If a struct definition contains any opaque type, attempting to evaluate structA == structB will result in a compile-time error.

Deep Component-Wise Evaluation

When two valid struct instances are compared using ==, the operator performs a deep component-wise comparison:

  1. Every corresponding pair of members is evaluated for equality.
  2. For vectors and matrices, the equality operator checks that every individual component matches.
  3. For nested structures and arrays, each sub-element is recursively tested.
  4. The expression evaluates to true if and only if all corresponding fields are equal. If any field differs, the result is false.

The inequality operator (!=) is logically equivalent to !(a == b), evaluating to true if any single field differs between the two instances.