Also minify #defines in PLS shaders

There is lots of text and whitespace in these macros. We used to just
copy them straight. This PR starts minimizing them. This shaves about 5k
off the GLSL strings and helps obfuscate what we're doing, which is good
now that we will ship shader source strings in clear text.

Diffs=
fbd486cea Also minify #defines in PLS shaders (#5648)

Co-authored-by: Chris Dalton <99840794+csmartdalton@users.noreply.github.com>
diff --git a/.rive_head b/.rive_head
index 41811a2..41e96b8 100644
--- a/.rive_head
+++ b/.rive_head
@@ -1 +1 @@
-13863bf8f83c360422e9b8e924660a57e902b524
+fbd486cea70d209c96433b32a58f2ce57118ee4f
diff --git a/renderer/shaders/glsl.glsl b/renderer/shaders/glsl.glsl
index 109fb55..217f400 100644
--- a/renderer/shaders/glsl.glsl
+++ b/renderer/shaders/glsl.glsl
@@ -56,12 +56,6 @@
 #extension GL_ANGLE_base_vertex_base_instance_shader_builtin : require
 #endif
 
-#ifndef @BASE_INSTANCE_POLYFILL
-#define INSTANCE_ID (gl_BaseInstance + gl_InstanceID)
-#else
-#define INSTANCE_ID gl_InstanceID
-#endif
-
 #define UNIFORM_BLOCK_BEGIN(N)                                                                     \
     layout(std140) uniform N                                                                       \
     {
diff --git a/renderer/shaders/hlsl.glsl b/renderer/shaders/hlsl.glsl
index f31e58c..614b90f 100644
--- a/renderer/shaders/hlsl.glsl
+++ b/renderer/shaders/hlsl.glsl
@@ -12,55 +12,55 @@
 // #define native hlsl types if their names are being rewritten.
 #define _ARE_TOKEN_NAMES_PRESERVED
 #ifndef $_ARE_TOKEN_NAMES_PRESERVED
-#define half half
-#define half2 half2
-#define half3 half3
-#define half4 half4
-#define short short
-#define short2 short2
-#define short3 short3
-#define short4 short4
-#define ushort ushort
-#define ushort2 ushort2
-#define ushort3 ushort3
-#define ushort4 ushort4
-#define float2 float2
-#define float3 float3
-#define float4 float4
-#define bool2 bool2
-#define bool3 bool3
-#define bool4 bool4
-#define uint2 uint2
-#define uint3 uint3
-#define uint4 uint4
-#define int2 int2
-#define int3 int3
-#define int4 int4
-#define float4x2 float4x2
-#define ushort ushort
-#define float2x2 float2x2
-#define half3x4 half3x4
+#define half $half
+#define half2 $half2
+#define half3 $half3
+#define half4 $half4
+#define short $short
+#define short2 $short2
+#define short3 $short3
+#define short4 $short4
+#define ushort $ushort
+#define ushort2 $ushort2
+#define ushort3 $ushort3
+#define ushort4 $ushort4
+#define float2 $float2
+#define float3 $float3
+#define float4 $float4
+#define bool2 $bool2
+#define bool3 $bool3
+#define bool4 $bool4
+#define uint2 $uint2
+#define uint3 $uint3
+#define uint4 $uint4
+#define int2 $int2
+#define int3 $int3
+#define int4 $int4
+#define float4x2 $float4x2
+#define ushort $ushort
+#define float2x2 $float2x2
+#define half3x4 $half3x4
 #endif
 
-typedef float3 packed_float3;
+$typedef float3 packed_float3;
 #define make_half float
 #define make_half2 float2
 #define make_half3 float3
 #define make_half4 float4
 
-typedef min16int short;
-#define make_short min16int
-#define make_short2 min16int2
-#define make_short3 min16int3
-#define make_short4 min16int4
+$typedef $min16int short;
+#define make_short $min16int
+#define make_short2 $min16int2
+#define make_short3 $min16int3
+#define make_short4 $min16int4
 
-typedef min16uint ushort;
-#define make_ushort min16uint
-#define make_ushort2 min16uint2
-#define make_ushort3 min16uint3
-#define make_ushort4 min16uint4
+$typedef $min16uint ushort;
+#define make_ushort $min16uint
+#define make_ushort2 $min16uint2
+#define make_ushort3 $min16uint3
+#define make_ushort4 $min16uint4
 
-#define make_half3x4 float3x4
+#define make_half3x4 $half3x4
 
 #define ATTR_BLOCK_BEGIN(NAME)                                                                     \
     struct NAME                                                                                    \
@@ -73,7 +73,7 @@
 #define ATTR_UNPACK(ID, attrs, NAME, TYPE) TYPE NAME = attrs.NAME
 
 #define UNIFORM_BLOCK_BEGIN(NAME)                                                                  \
-    cbuffer NAME : register(b0)                                                                    \
+    $cbuffer NAME : $register($b0)                                                                 \
     {                                                                                              \
         struct                                                                                     \
         {
@@ -87,13 +87,13 @@
     struct NAME                                                                                    \
     {
 
-#define NO_PERSPECTIVE noperspective
-#define @OPTIONALLY_FLAT nointerpolation
-#define FLAT nointerpolation
-#define VARYING(IDX, TYPE, NAME) TYPE NAME : TEXCOORD##IDX
+#define NO_PERSPECTIVE $noperspective
+#define @OPTIONALLY_FLAT $nointerpolation
+#define FLAT $nointerpolation
+#define VARYING(IDX, TYPE, NAME) TYPE NAME : $TEXCOORD##IDX
 
 #define VARYING_BLOCK_END(_pos)                                                                    \
-    float4 _pos : SV_Position;                                                                     \
+    float4 _pos : $SV_Position;                                                                    \
     }                                                                                              \
     ;
 
@@ -111,29 +111,29 @@
 #define FRAG_TEXTURE_BLOCK_END
 #endif
 
-#define TEXTURE_RGBA32UI(IDX, NAME) uniform Texture2D<uint4> NAME : register(t##IDX)
-#define TEXTURE_RGBA32F(IDX, NAME) uniform Texture2D<float4> NAME : register(t##IDX)
-#define TEXTURE_RGBA8(IDX, NAME) uniform Texture2D<unorm float4> NAME : register(t##IDX)
+#define TEXTURE_RGBA32UI(IDX, NAME) uniform $Texture2D<uint4> NAME : $register($t##IDX)
+#define TEXTURE_RGBA32F(IDX, NAME) uniform $Texture2D<float4> NAME : $register($t##IDX)
+#define TEXTURE_RGBA8(IDX, NAME) uniform $Texture2D<$unorm float4> NAME : $register($t##IDX)
 
 #define TEXEL_FETCH(TEXTURE_BLOCK, NAME, COORD) NAME[COORD]
 
-#define GRADIENT_SAMPLER_DECL(IDX, NAME) SamplerState NAME : register(s##IDX);
+#define GRADIENT_SAMPLER_DECL(IDX, NAME) $SamplerState NAME : $register($s##IDX);
 
-#define TEXTURE_SAMPLE(TEXTURE_BLOCK, NAME, SAMPLER_NAME, COORD) NAME.Sample(SAMPLER_NAME, COORD)
+#define TEXTURE_SAMPLE(TEXTURE_BLOCK, NAME, SAMPLER_NAME, COORD) NAME.$Sample(SAMPLER_NAME, COORD)
 
 #define PLS_INTERLOCK_BEGIN
 #define PLS_INTERLOCK_END
 
 #ifdef @DRAW_INTERIOR_TRIANGLES
 // The interior triangles don't overlap, so therefore don't need rasterizer ordering.
-#define $PLS_TEX2D RWTexture2D
+#define PLS_TEX2D $RWTexture2D
 #else
-#define $PLS_TEX2D RasterizerOrderedTexture2D
+#define PLS_TEX2D $RasterizerOrderedTexture2D
 #endif
 
 #define PLS_BLOCK_BEGIN
-#define PLS_DECL4F(IDX, NAME) uniform PLS_TEX2D<unorm float4> NAME : register(u##IDX)
-#define PLS_DECL2F(IDX, NAME) uniform PLS_TEX2D<uint> NAME : register(u##IDX)
+#define PLS_DECL4F(IDX, NAME) uniform PLS_TEX2D<$unorm float4> NAME : $register($u##IDX)
+#define PLS_DECL2F(IDX, NAME) uniform PLS_TEX2D<uint> NAME : $register($u##IDX)
 #define PLS_BLOCK_END
 
 #define PLS_LOAD4F(P) P[_plsCoord]
@@ -145,7 +145,7 @@
 
 #ifdef @ENABLE_BASE_INSTANCE_POLYFILL
 #define BASE_INSTANCE_POLYFILL_DECL(NAME)                                                          \
-    cbuffer NAME##_cbuff : register(b1)                                                            \
+    $cbuffer NAME##_cbuff : $register($b1)                                                         \
     {                                                                                              \
         uint NAME;                                                                                 \
         uint NAME##_pad0;                                                                          \
@@ -167,7 +167,7 @@
                     _vertexID,                                                                     \
                     _instanceID,                                                                   \
                     _pos)                                                                          \
-    Varyings NAME(Attrs attrs, uint _vertexID : SV_VertexID, uint _instanceID : SV_InstanceID)     \
+    Varyings NAME(Attrs attrs, uint _vertexID : $SV_VertexID, uint _instanceID : $SV_InstanceID)   \
     {                                                                                              \
         Varyings varyings;                                                                         \
         float4 _pos;
@@ -178,7 +178,7 @@
     return varyings;
 
 #define FRAG_DATA_MAIN(DATA_TYPE, NAME, Varyings, varyings)                                        \
-    DATA_TYPE NAME(Varyings varyings) : SV_Target                                                  \
+    DATA_TYPE NAME(Varyings varyings) : $SV_Target                                                 \
     {
 
 #define EMIT_FRAG_DATA(VALUE)                                                                      \
@@ -186,45 +186,45 @@
     }
 
 #define PLS_MAIN(NAME, Varyings, varyings, FragmentTextures, textures, _pos)                       \
-    [earlydepthstencil] void NAME(Varyings varyings) {                                             \
+    [$earlydepthstencil] void NAME(Varyings varyings) {                                            \
         int2 _plsCoord = int2(floor(varyings._pos.xy));
 
 #define EMIT_PLS }
 
-#define INLINE inline
+#define INLINE $inline
 
-#define uintBitsToFloat asfloat
-#define intBitsToFloat asfloat
-#define floatBitsToInt asint
-#define floatBitsToUint asuint
-#define fract frac
-#define mix lerp
-#define inversesqrt rsqrt
+#define uintBitsToFloat $asfloat
+#define intBitsToFloat $asfloat
+#define floatBitsToInt $asint
+#define floatBitsToUint $asuint
+#define fract $frac
+#define mix $lerp
+#define inversesqrt $rsqrt
 #define notEqual(A, B) ((A) != (B))
 #define lessThanEqual(A, B) ((A) <= (B))
 #define greaterThanEqual(A, B) ((A) >= (B))
 
 // HLSL matrices are stored in row-major order, and therefore transposed from their counterparts
 // in GLSL and Metal. We can work around this entirely by reversing the arguments to mul().
-#define MUL(A, B) mul(B, A)
+#define MUL(A, B) $mul(B, A)
 
-inline half2 unpackHalf2x16(uint u)
+INLINE half2 unpackHalf2x16(uint u)
 {
     uint y = (u >> 16);
     uint x = u & 0xffffu;
-    return make_half2(f16tof32(x), f16tof32(y));
+    return make_half2($f16tof32(x), $f16tof32(y));
 }
 
-inline uint packHalf2x16(float2 v)
+INLINE uint packHalf2x16(float2 v)
 {
-    uint x = f32tof16(v.x);
-    uint y = f32tof16(v.y);
+    uint x = $f32tof16(v.x);
+    uint y = $f32tof16(v.y);
     return (y << 16) | x;
 }
 
-inline float atan(float y, float x) { return atan2(y, x); }
+INLINE float atan(float y, float x) { return $atan2(y, x); }
 
-inline float2x2 inverse(float2x2 m)
+INLINE float2x2 inverse(float2x2 m)
 {
     float2x2 adjoint = float2x2(m[1][1], -m[0][1], -m[1][0], m[0][0]);
     return adjoint * (1. / determinant(m));
diff --git a/renderer/shaders/metal.glsl b/renderer/shaders/metal.glsl
index 14f8b90..0569233 100644
--- a/renderer/shaders/metal.glsl
+++ b/renderer/shaders/metal.glsl
@@ -10,35 +10,35 @@
 // #define native metal types if their names are being rewritten.
 #define _ARE_TOKEN_NAMES_PRESERVED
 #ifndef $_ARE_TOKEN_NAMES_PRESERVED
-#define half half
-#define half2 half2
-#define half3 half3
-#define half4 half4
-#define short short
-#define short2 short2
-#define short3 short3
-#define short4 short4
-#define ushort ushort
-#define ushort2 ushort2
-#define ushort3 ushort3
-#define ushort4 ushort4
-#define float2 float2
-#define float3 float3
-#define packed_float3 packed_float3
-#define float4 float4
-#define bool2 bool2
-#define bool3 bool3
-#define bool4 bool4
-#define uint2 uint2
-#define uint3 uint3
-#define uint4 uint4
-#define int2 int2
-#define int3 int3
-#define int4 int4
-#define float4x2 float4x2
-#define ushort ushort
-#define float2x2 float2x2
-#define half3x4 half3x4
+#define half $half
+#define half2 $half2
+#define half3 $half3
+#define half4 $half4
+#define short $short
+#define short2 $short2
+#define short3 $short3
+#define short4 $short4
+#define ushort $ushort
+#define ushort2 $ushort2
+#define ushort3 $ushort3
+#define ushort4 $ushort4
+#define float2 $float2
+#define float3 $float3
+#define packed_float3 $packed_float3
+#define float4 $float4
+#define bool2 $bool2
+#define bool3 $bool3
+#define bool4 $bool4
+#define uint2 $uint2
+#define uint3 $uint3
+#define uint4 $uint4
+#define int2 $int2
+#define int3 $int3
+#define int4 $int4
+#define float4x2 $float4x2
+#define ushort $ushort
+#define float2x2 $float2x2
+#define half3x4 $half3x4
 #endif
 
 #define make_half4 half4
@@ -48,14 +48,14 @@
 
 #define make_ushort ushort
 
-#define INLINE inline
+#define INLINE $inline
 
 #define notEqual(A, B) ((A) != (B))
 #define lessThanEqual(A, B) ((A) <= (B))
 #define greaterThanEqual(A, B) ((A) >= (B))
 #define MUL(A, B) ((A) * (B))
-#define atan atan2
-#define inversesqrt rsqrt
+#define atan $atan2
+#define inversesqrt $rsqrt
 
 #define UNIFORM_BLOCK_BEGIN(N)                                                                     \
     struct N                                                                                       \
@@ -78,17 +78,17 @@
     {
 #define VARYING(IDX, TYPE, NAME) TYPE NAME
 #define FLAT [[flat]]
-#define NO_PERSPECTIVE [[center_no_perspective]]
+#define NO_PERSPECTIVE [[$center_no_perspective]]
 // No-persective interpolation appears to break the guarantee that a varying == "x" when all
 // barycentric values also == "x". Using default (perspective-correct) interpolation is also faster
 // than flat on M1.
 #define @OPTIONALLY_FLAT
 #define VARYING_BLOCK_END(_pos)                                                                    \
-    float4 _pos [[position]];                                                                      \
+    float4 _pos [[$position]];                                                                     \
     }                                                                                              \
     ;
 
-#define VARYING_INIT(varyings, NAME, TYPE) thread TYPE& NAME = varyings.NAME
+#define VARYING_INIT(varyings, NAME, TYPE) $thread TYPE& NAME = varyings.NAME
 #define VARYING_PACK(varyings, NAME)
 #define VARYING_UNPACK(varyings, NAME, TYPE) TYPE NAME = varyings.NAME
 
@@ -106,20 +106,20 @@
     }                                                                                              \
     ;
 
-#define TEXTURE_RGBA32UI(IDX, NAME) [[texture(IDX)]] texture2d<uint> NAME
-#define TEXTURE_RGBA32F(IDX, NAME) [[texture(IDX)]] texture2d<float> NAME
-#define TEXTURE_RGBA8(IDX, NAME) [[texture(IDX)]] texture2d<half> NAME
+#define TEXTURE_RGBA32UI(IDX, NAME) [[$texture(IDX)]] $texture2d<uint> NAME
+#define TEXTURE_RGBA32F(IDX, NAME) [[$texture(IDX)]] $texture2d<float> NAME
+#define TEXTURE_RGBA8(IDX, NAME) [[$texture(IDX)]] $texture2d<half> NAME
 
-#define TEXEL_FETCH(TEXTURE_BLOCK, NAME, COORD) TEXTURE_BLOCK.NAME.read(uint2(COORD))
+#define TEXEL_FETCH(TEXTURE_BLOCK, NAME, COORD) TEXTURE_BLOCK.NAME.$read(uint2(COORD))
 #define GRADIENT_SAMPLER_DECL(IDX, NAME)
 #define TEXTURE_SAMPLE(TEXTURE_BLOCK, NAME, SAMPLER_NAME, COORD)                                   \
-    TEXTURE_BLOCK.NAME.sample(sampler(mag_filter::linear, min_filter::linear), COORD)
+    TEXTURE_BLOCK.NAME.$sample($sampler($mag_filter::$linear, $min_filter::$linear), COORD)
 
 #define PLS_BLOCK_BEGIN                                                                            \
     struct PLS                                                                                     \
     {
-#define PLS_DECL4F(IDX, NAME) [[color(IDX)]] half4 NAME
-#define PLS_DECL2F(IDX, NAME) [[color(IDX)]] half2 NAME
+#define PLS_DECL4F(IDX, NAME) [[$color(IDX)]] half4 NAME
+#define PLS_DECL2F(IDX, NAME) [[$color(IDX)]] half2 NAME
 #define PLS_BLOCK_END                                                                              \
     }                                                                                              \
     ;
@@ -144,11 +144,11 @@
                     _vertexID,                                                                     \
                     _instanceID,                                                                   \
                     _pos)                                                                          \
-    __attribute__((visibility("default"))) Varyings vertex NAME(                                   \
-        uint _vertexID [[vertex_id]],                                                              \
-        uint _instanceID [[instance_id]],                                                          \
-        constant Uniforms& uniforms [[buffer(0)]],                                                 \
-        constant Attrs* attrs [[buffer(1)]],                                                       \
+    $__attribute__(($visibility("default"))) Varyings $vertex NAME(                                \
+        uint _vertexID [[$vertex_id]],                                                             \
+        uint _instanceID [[$instance_id]],                                                         \
+        $constant Uniforms& uniforms [[$buffer(0)]],                                               \
+        $constant Attrs* attrs [[$buffer(1)]],                                                     \
         VertexTextures textures)                                                                   \
     {                                                                                              \
         Varyings varyings;                                                                         \
@@ -160,7 +160,8 @@
     return varyings;
 
 #define FRAG_DATA_MAIN(DATA_TYPE, NAME, Varyings, varyings)                                        \
-    DATA_TYPE __attribute__((visibility("default"))) fragment NAME(Varyings varyings [[stage_in]]) \
+    DATA_TYPE $__attribute__(($visibility("default"))) $fragment NAME(Varyings varyings            \
+                                                                      [[$stage_in]])               \
     {
 
 #define EMIT_FRAG_DATA(VALUE)                                                                      \
@@ -168,9 +169,9 @@
     }
 
 #define PLS_MAIN(NAME, Varyings, varyings, FragmentTextures, textures, _pos)                       \
-    __attribute__((visibility("default"))) PLS fragment NAME(PLS _inpls,                           \
-                                                             Varyings varyings [[stage_in]],       \
-                                                             FragmentTextures textures)            \
+    $__attribute__(($visibility("default"))) PLS $fragment NAME(PLS _inpls,                        \
+                                                                Varyings varyings [[$stage_in]],   \
+                                                                FragmentTextures textures)         \
     {                                                                                              \
         PLS _pls;
 
@@ -178,39 +179,39 @@
     }                                                                                              \
     return _pls;
 
-using namespace metal;
+$using $namespace $metal;
 
-template <int N> inline vec<uint, N> floatBitsToUint(vec<float, N> x)
+$template<int N> INLINE $vec<uint, N> floatBitsToUint($vec<float, N> x)
 {
-    return as_type<vec<uint, N>>(x);
+    return $as_type<$vec<uint, N>>(x);
 }
 
-template <int N> inline vec<int, N> floatBitsToInt(vec<float, N> x)
+$template<int N> INLINE $vec<int, N> floatBitsToInt($vec<float, N> x)
 {
-    return as_type<vec<int, N>>(x);
+    return $as_type<$vec<int, N>>(x);
 }
 
-inline uint floatBitsToUint(float x) { return as_type<uint>(x); }
+INLINE uint floatBitsToUint(float x) { return $as_type<uint>(x); }
 
-inline int floatBitsToInt(float x) { return as_type<int>(x); }
+INLINE int floatBitsToInt(float x) { return $as_type<int>(x); }
 
-template <int N> inline vec<float, N> uintBitsToFloat(vec<uint, N> x)
+$template<int N> INLINE $vec<float, N> uintBitsToFloat($vec<uint, N> x)
 {
-    return as_type<vec<float, N>>(x);
+    return $as_type<$vec<float, N>>(x);
 }
 
-inline float uintBitsToFloat(uint x) { return as_type<float>(x); }
-inline half2 unpackHalf2x16(uint x) { return as_type<half2>(x); }
-inline uint packHalf2x16(half2 x) { return as_type<uint>(x); }
+INLINE float uintBitsToFloat(uint x) { return $as_type<float>(x); }
+INLINE half2 unpackHalf2x16(uint x) { return $as_type<half2>(x); }
+INLINE uint packHalf2x16(half2 x) { return $as_type<uint>(x); }
 
-inline float2x2 inverse(float2x2 m)
+INLINE float2x2 inverse(float2x2 m)
 {
     float2x2 m_ = float2x2(m[1][1], -m[0][1], -m[1][0], m[0][0]);
     float det = (m_[0][0] * m[0][0]) + (m_[0][1] * m[1][0]);
     return m_ * (1 / det);
 }
 
-inline half3 mix(half3 a, half3 b, bool3 c)
+INLINE half3 mix(half3 a, half3 b, bool3 c)
 {
     half3 result;
     for (int i = 0; i < 3; ++i)
@@ -218,7 +219,7 @@
     return result;
 }
 
-inline half3x4 make_half3x4(half3 a, half b, half3 c, half d, half3 e, half f)
+INLINE half3x4 make_half3x4(half3 a, half b, half3 c, half d, half3 e, half f)
 {
     return half3x4(a.x, a.y, a.z, b, c.x, c.y, c.z, d, e.x, e.y, e.z, f);
 }
diff --git a/renderer/shaders/minify.py b/renderer/shaders/minify.py
index 5445c5b..7eb49c0 100644
--- a/renderer/shaders/minify.py
+++ b/renderer/shaders/minify.py
@@ -42,16 +42,17 @@
 tokens = [
     "DEFINE",
     "IFDEF",
+    "TOKEN_PASTE",
     "DIRECTIVE",
     "LINE_COMMENT",
     "BLOCK_COMMENT",
     "WHITESPACE",
-    "ANNOTATION",
     "OP",
     "FLOAT",
     "HEX",
     "INT",
     "ID",
+    "UNKNOWN",
 ]
 
 # tracks which identifiers are declared via a #define macro
@@ -59,19 +60,25 @@
 
 # counts the number of times each ID is seen, to prioritize which IDs get the shortest names
 all_id_counts = defaultdict(int);
-def parse_id(name, exports):
+all_id_reference_counts = defaultdict(int);
+def parse_id(name, exports, *, is_reference):
     all_id_counts[name] += 1
+    if is_reference:
+        all_id_reference_counts[name] += 1
     # identifiers that begin with '@' get exported to C++ through #defines.
     if name[0] == '@':
         exports.add(name)
 
 # lexing functions used by PLY.
 def t_DEFINE(tok):
-    r"\#[ \t]*define[ \t]+(?P<id>[\@\$]?[A-Za-z_][A-Za-z0-9_]*)(?P<val>(((\\\n|.)(?!\/[\/\*]))*))"
+    r"\#[ \t]*define[ \t]+(?P<id>[\@\$]?[A-Za-z_][A-Za-z0-9_]*)(?P<arglist>\((\n|[^\)])*\))?(?P<val>(((\\\n|.)(?!\/[\/\*]))*))?"
     tok.define_id = re.match(t_DEFINE.__doc__, tok.value)['id']
-    tok.define_val = re.match(t_DEFINE.__doc__, tok.value)['val']
+    arglist = re.match(t_DEFINE.__doc__, tok.value)['arglist']
+    tok.define_arglist = Minifier(arglist, "", tok.lexer.exports) if arglist else None
+    val = re.match(t_DEFINE.__doc__, tok.value)['val']
+    tok.define_val = Minifier(val, "", tok.lexer.exports) if val else None
     defines.add(tok.define_id)
-    parse_id(tok.define_id, tok.lexer.exports)
+    parse_id(tok.define_id, tok.lexer.exports, is_reference=False)
     tok.lexer.lineno += tok.value.count('\n')
     return tok
 
@@ -79,7 +86,11 @@
     r"(?P<tag>\#[ \t]*ifn?def)[ \t]+(?P<id>[\@\$]?[A-Za-z_][A-Za-z0-9_]*)"
     tok.ifdef_tag = re.match(t_IFDEF.__doc__, tok.value)['tag']
     tok.ifdef_id = re.match(t_IFDEF.__doc__, tok.value)['id']
-    parse_id(tok.ifdef_id, tok.lexer.exports)
+    parse_id(tok.ifdef_id, tok.lexer.exports, is_reference=True)
+    return tok
+
+def t_TOKEN_PASTE(tok):
+    r"\#\#"
     return tok
 
 def t_DIRECTIVE(tok):
@@ -99,14 +110,10 @@
     return tok
 
 def t_WHITESPACE(tok):
-    r"\s+"
+    r"(\s|\\\r?\n)+"
     tok.lexer.lineno += tok.value.count('\n')
     return tok
 
-def t_ANNOTATION(tok):
-    r"\[\[.*\]\]"
-    return tok
-
 def t_OP(tok):
     r"[~!%^&\*\(\)\-=+\/\[\]{}\?:\<\>\.\,|;]"
     return tok
@@ -125,7 +132,11 @@
 
 def t_ID(tok):
     r"[\@\$]?[A-Za-z_][A-Za-z0-9_]*"
-    parse_id(tok.value, tok.lexer.exports)
+    parse_id(tok.value, tok.lexer.exports, is_reference=True)
+    return tok
+
+def t_UNKNOWN(tok):
+    r"."
     return tok
 
 def t_error(tok):
@@ -133,153 +144,147 @@
 
 # identifier names that cannot be renamed
 glsl_reserved = {
-    "const", "uniform", "layout", "location", "centroid", "flat", "smooth", "break", "continue",
-    "do", "for", "while", "switch", "case", "default", "if", "else", "in", "out", "inout", "float",
-    "int", "void", "bool", "true", "false", "invariant", "discard", "return", "mat2", "mat3",
-    "mat4", "mat2x2", "mat2x3", "mat2x4", "mat3x2", "mat3x3", "mat3x4", "mat4x2", "mat4x3",
-    "mat4x4", "vec2", "vec3", "vec4", "ivec2", "ivec3", "ivec4", "bvec2", "bvec3", "bvec4", "uint",
-    "uvec2", "uvec3", "uvec4", "lowp", "mediump", "highp", "precision", "sampler2D", "sampler3D",
-    "samplerCube", "sampler2DShadow", "samplerCubeShadow", "sampler2DArray", "sampler2DArrayShadow",
-    "isampler2D", "isampler3D", "isamplerCube", "isampler2DArray", "usampler2D", "usampler3D",
-    "usamplerCube", "usampler2DArray", "struct", "radians", "degrees", "sin", "cos", "tan", "asin",
-    "acos", "atan", "atan", "sinh", "cosh", "tanh", "asinh", "acosh", "atanh", "pow", "exp", "log",
-    "exp2", "log2", "sqrt", "sqrt", "inversesqrt", "inversesqrt", "abs", "abs", "abs", "sign",
-    "sign", "sign", "floor", "floor", "trunc", "trunc", "round", "round", "roundEven", "roundEven",
-    "ceil", "ceil", "fract", "fract", "mod", "mod", "mod", "mod", "min", "min", "min", "min", "min",
-    "min", "min", "min", "max", "max", "max", "max", "max", "max", "max", "max", "clamp", "clamp",
-    "clamp", "clamp", "clamp", "clamp", "clamp", "clamp", "mix", "mix", "mix", "mix", "mix", "mix",
-    "mix", "mix", "mix", "step", "step", "step", "step", "smoothstep", "smoothstep", "smoothstep",
-    "smoothstep", "modf", "modf", "isnan", "isnan", "isinf", "isinf", "floatBitsToInt",
-    "floatBitsToUint", "intBitsToFloat", "uintBitsToFloat", "fma", "fma", "fma", "frexp", "frexp",
-    "ldexp", "ldexp", "packSnorm2x16", "packHalf2x16", "unpackSnorm2x16", "unpackHalf2x16",
-    "packUnorm2x16", "unpackUnorm2x16", "packUnorm4x8", "packSnorm4x8", "unpackSnorm4x8",
-    "packDouble2x32", "unpackDouble2x32", "length", "length", "distance", "distance", "dot", "dot",
-    "cross", "cross", "normalize", "normalize", "faceforward", "faceforward", "reflect", "reflect",
-    "refract", "refract", "ftransform", "matrixCompMult", "matrixCompMult", "matrixCompMult",
-    "matrixCompMult", "matrixCompMult", "matrixCompMult", "matrixCompMult", "matrixCompMult",
-    "matrixCompMult", "outerProduct", "outerProduct", "outerProduct", "outerProduct",
-    "outerProduct", "outerProduct", "outerProduct", "outerProduct", "outerProduct", "transpose",
-    "transpose", "transpose", "transpose", "transpose", "transpose", "transpose", "transpose",
-    "transpose", "determinant", "determinant", "determinant", "inverse", "inverse", "inverse",
+    "EmitStreamVertex", "EmitVertex", "EmitVertex", "EndPrimitive", "EndPrimitive",
+    "EndStreamPrimitive", "abs", "abs", "abs", "acos", "acosh", "all", "allInvocations",
+    "allInvocationsEqual", "any", "anyInvocation", "asin", "asinh", "atan", "atan", "atanh",
+    "atomicAdd", "atomicAdd", "atomicAnd", "atomicAnd", "atomicCompSwap", "atomicCompSwap",
+    "atomicCounter", "atomicCounterAdd", "atomicCounterAnd", "atomicCounterCompSwap",
+    "atomicCounterDecrement", "atomicCounterExchange", "atomicCounterIncrement", "atomicCounterMax",
+    "atomicCounterMin", "atomicCounterOr", "atomicCounterSubtract", "atomicCounterXor",
+    "atomicExchange", "atomicExchange", "atomicMax", "atomicMax", "atomicMin", "atomicMin",
+    "atomicOr", "atomicOr", "atomicXor", "atomicXor", "barrier", "barrier",
+    "beginFragmentShaderOrderingINTEL", "beginInvocationInterlockARB", "beginInvocationInterlockNV",
+    "binding", "bitCount", "bitCount", "bitfieldExtract", "bitfieldExtract", "bitfieldInsert",
+    "bitfieldInsert", "bitfieldReverse", "bitfieldReverse", "bool", "break", "bvec2", "bvec3",
+    "bvec4", "case", "ceil", "ceil", "centroid", "clamp", "clamp", "clamp", "clamp", "clamp",
+    "clamp", "clamp", "clamp", "coherent", "const", "continue", "cos", "cosh", "cross", "cross",
+    "dFdx", "dFdx", "dFdxCoarse", "dFdxFine", "dFdy", "dFdy", "dFdyCoarse", "dFdyFine", "default",
+    "degrees", "determinant", "determinant", "determinant", "discard", "distance", "distance", "do",
+    "dot", "dot", "else", "endInvocationInterlockARB", "endInvocationInterlockNV", "equal", "equal",
+    "equal", "equal", "exp", "exp2", "faceforward", "faceforward", "false", "findLSB", "findLSB",
+    "findMSB", "findMSB", "flat", "float", "floatBitsToInt", "floatBitsToUint", "floor", "floor",
+    "fma", "fma", "fma", "for", "fract", "fract", "frexp", "frexp", "ftransform", "fwidth",
+    "fwidth", "fwidthCoarse", "fwidthFine", "greaterThan", "greaterThan", "greaterThan",
+    "greaterThanEqual", "greaterThanEqual", "greaterThanEqual", "groupMemoryBarrier", "highp", "if",
+    "iimage2D", "image2D", "imageAtomicAdd", "imageAtomicAdd", "imageAtomicAdd", "imageAtomicAdd",
+    "imageAtomicAnd", "imageAtomicAnd", "imageAtomicAnd", "imageAtomicAnd", "imageAtomicCompSwap",
+    "imageAtomicCompSwap", "imageAtomicCompSwap", "imageAtomicCompSwap", "imageAtomicExchange",
+    "imageAtomicExchange", "imageAtomicExchange", "imageAtomicExchange", "imageAtomicExchange",
+    "imageAtomicMax", "imageAtomicMax", "imageAtomicMax", "imageAtomicMax", "imageAtomicMin",
+    "imageAtomicMin", "imageAtomicMin", "imageAtomicMin", "imageAtomicOr", "imageAtomicOr",
+    "imageAtomicOr", "imageAtomicOr", "imageAtomicXor", "imageAtomicXor", "imageAtomicXor",
+    "imageAtomicXor", "imageLoad", "imageLoad", "imageLoad", "imageLoad", "imageLoad", "imageLoad",
+    "imageLoad", "imageLoad", "imageSamples", "imageSamples", "imageSize", "imageSize", "imageSize",
+    "imageSize", "imageSize", "imageSize", "imageSize", "imageSize", "imageSize", "imageSize",
+    "imageSize", "imageSize", "imageSize", "imageSize", "imageSize", "imageSize", "imageSize",
+    "imageSize", "imageSize", "imageStore", "imageStore", "imageStore", "imageStore", "imageStore",
+    "imageStore", "imageStore", "imageStore", "imageStore", "imulExtended", "in", "inout", "int",
+    "intBitsToFloat", "interpolateAtCentroid", "interpolateAtCentroid", "interpolateAtCentroid",
+    "interpolateAtCentroid", "interpolateAtCentroid", "interpolateAtCentroid",
+    "interpolateAtCentroid", "interpolateAtCentroid", "interpolateAtOffset", "interpolateAtOffset",
+    "interpolateAtOffset", "interpolateAtOffset", "interpolateAtOffset", "interpolateAtOffset",
+    "interpolateAtOffset", "interpolateAtSample", "interpolateAtSample", "interpolateAtSample",
+    "interpolateAtSample", "interpolateAtSample", "interpolateAtSample", "interpolateAtSample",
+    "interpolateAtSample", "invariant", "inverse", "inverse", "inverse", "inversesqrt",
+    "inversesqrt", "isampler2D", "isampler2DArray", "isampler3D", "isamplerCube", "isinf", "isinf",
+    "isnan", "isnan", "ivec2", "ivec3", "ivec4", "layout", "ldexp", "ldexp", "length", "length",
     "lessThan", "lessThan", "lessThan", "lessThanEqual", "lessThanEqual", "lessThanEqual",
-    "greaterThan", "greaterThan", "greaterThan", "greaterThanEqual", "greaterThanEqual",
-    "greaterThanEqual", "equal", "equal", "equal", "equal", "notEqual", "notEqual", "notEqual",
-    "notEqual", "any", "all", "not", "bitfieldExtract", "bitfieldExtract", "bitfieldInsert",
-    "bitfieldInsert", "bitfieldReverse", "bitfieldReverse", "bitCount", "bitCount", "findLSB",
-    "findLSB", "findMSB", "findMSB", "uaddCarry", "usubBorrow", "umulExtended", "imulExtended",
-    "texture2D", "texture2DProj", "texture2DProj", "textureCube", "texture1D", "texture1DProj",
-    "texture1DProj", "texture3D", "texture3DProj", "shadow1D", "shadow1DProj", "shadow2D",
-    "shadow2DProj", "texture3D", "texture3DProj", "shadow2DEXT", "shadow2DProjEXT", "texture2D",
-    "texture2DProj", "texture2DProj", "texture2DRect", "texture2DRectProj", "texture2DRectProj",
-    "texture2DGradEXT", "texture2DProjGradEXT", "texture2DProjGradEXT", "textureCubeGradEXT",
-    "textureVideoWEBGL", "texture2D", "texture2DProj", "texture2DProj", "textureCube", "texture3D",
-    "texture3DProj", "texture1D", "texture1DProj", "texture1DProj", "shadow1DProj", "shadow2D",
-    "shadow2DProj", "texture3D", "texture3DProj", "texture2DLod", "texture2DProjLod",
-    "texture2DProjLod", "textureCubeLod", "texture1DLod", "texture1DProjLod", "texture1DProjLod",
-    "shadow1DLod", "shadow1DProjLod", "shadow2DLod", "shadow2DProjLod", "texture3DLod",
-    "texture3DProjLod", "texture3DLod", "texture3DProjLod", "texture2DLod", "texture2DProjLod",
-    "texture2DProjLod", "textureCubeLod", "texture2DLodEXT", "texture2DProjLodEXT",
-    "texture2DProjLodEXT", "textureCubeLodEXT", "texture", "texture", "texture", "texture",
+    "location", "log", "log2", "lowp", "main", "mat2", "mat2x2", "mat2x3", "mat2x4", "mat3",
+    "mat3x2", "mat3x3", "mat3x4", "mat4", "mat4x2", "mat4x3", "mat4x4", "matrixCompMult",
+    "matrixCompMult", "matrixCompMult", "matrixCompMult", "matrixCompMult", "matrixCompMult",
+    "matrixCompMult", "matrixCompMult", "matrixCompMult", "max", "max", "max", "max", "max", "max",
+    "max", "max", "mediump", "memoryBarrier", "memoryBarrierAtomicCounter", "memoryBarrierBuffer",
+    "memoryBarrierImage", "memoryBarrierShared", "min", "min", "min", "min", "min", "min", "min",
+    "min", "mix", "mix", "mix", "mix", "mix", "mix", "mix", "mix", "mix", "mod", "mod", "mod",
+    "mod", "modf", "modf", "noise1", "noise2", "noise3", "noise4", "noperspective", "normalize",
+    "normalize", "not", "notEqual", "notEqual", "notEqual", "notEqual", "out", "outerProduct",
+    "outerProduct", "outerProduct", "outerProduct", "outerProduct", "outerProduct", "outerProduct",
+    "outerProduct", "outerProduct", "packDouble2x32", "packHalf2x16", "packSnorm2x16",
+    "packSnorm4x8", "packUnorm2x16", "packUnorm4x8", "pixelLocalLoadANGLE", "pixelLocalStoreANGLE",
+    "pow", "precision", "r16f", "r32f", "r32ui", "radians", "reflect", "reflect", "refract",
+    "refract", "return", "rg16f", "rgb_2_yuv", "rgba8", "rgba8i", "rgba8ui", "round", "round",
+    "roundEven", "roundEven", "sampler2D", "sampler2DArray", "sampler2DArrayShadow",
+    "sampler2DShadow", "sampler3D", "samplerCube", "samplerCubeShadow", "shadow1D", "shadow1DLod",
+    "shadow1DProj", "shadow1DProj", "shadow1DProjLod", "shadow2D", "shadow2D", "shadow2DEXT",
+    "shadow2DLod", "shadow2DProj", "shadow2DProj", "shadow2DProjEXT", "shadow2DProjLod", "sign",
+    "sign", "sign", "sin", "sinh", "smooth", "smoothstep", "smoothstep", "smoothstep", "smoothstep",
+    "sqrt", "sqrt", "std140", "step", "step", "step", "step", "struct", "subpassLoad",
+    "subpassLoad", "switch", "tan", "tanh", "texelFetch", "texelFetch", "texelFetch", "texelFetch",
+    "texelFetch", "texelFetch", "texelFetch", "texelFetch", "texelFetch", "texelFetch",
+    "texelFetch", "texelFetch", "texelFetch", "texelFetchOffset", "texelFetchOffset",
+    "texelFetchOffset", "texelFetchOffset", "texelFetchOffset", "texelFetchOffset", "texture",
     "texture", "texture", "texture", "texture", "texture", "texture", "texture", "texture",
     "texture", "texture", "texture", "texture", "texture", "texture", "texture", "texture",
-    "texture", "textureProj", "textureProj", "textureProj", "textureProj", "textureProj",
-    "textureProj", "textureProj", "textureProj", "textureProj", "textureProj", "textureProj",
-    "textureProj", "textureProj", "textureProj", "textureProj", "textureLod", "textureLod",
-    "textureLod", "textureLod", "textureLod", "textureLod", "textureLod", "textureLod",
-    "textureLod", "textureLod", "textureLod", "textureSize", "textureSize", "textureSize",
-    "textureSize", "textureSize", "textureSize", "textureSize", "textureSize", "textureSize",
-    "textureSize", "textureSize", "textureSize", "textureSize", "textureSize", "textureSize",
-    "textureSize", "textureSize", "textureSize", "textureSize", "textureSize", "textureSize",
-    "textureSize", "textureSize", "textureSize", "textureProjLod", "textureProjLod",
-    "textureProjLod", "textureProjLod", "textureProjLod", "textureProjLod", "textureProjLod",
-    "texelFetch", "texelFetch", "texelFetch", "texelFetch", "texelFetch", "texelFetch",
-    "texelFetch", "texelFetch", "texelFetch", "texelFetch", "texelFetch", "texelFetch",
-    "texelFetch", "textureGrad", "textureGrad", "textureGrad", "textureGrad", "textureGrad",
+    "texture", "texture", "texture", "texture", "texture", "texture", "texture", "texture",
+    "texture", "texture", "texture", "texture", "texture", "texture", "texture", "texture",
+    "texture", "texture", "texture", "texture1D", "texture1D", "texture1DLod", "texture1DProj",
+    "texture1DProj", "texture1DProj", "texture1DProj", "texture1DProjLod", "texture1DProjLod",
+    "texture2D", "texture2D", "texture2D", "texture2DGradEXT", "texture2DLod", "texture2DLod",
+    "texture2DLodEXT", "texture2DProj", "texture2DProj", "texture2DProj", "texture2DProj",
+    "texture2DProj", "texture2DProj", "texture2DProjGradEXT", "texture2DProjGradEXT",
+    "texture2DProjLod", "texture2DProjLod", "texture2DProjLod", "texture2DProjLod",
+    "texture2DProjLodEXT", "texture2DProjLodEXT", "texture2DRect", "texture2DRectProj",
+    "texture2DRectProj", "texture3D", "texture3D", "texture3D", "texture3D", "texture3DLod",
+    "texture3DLod", "texture3DProj", "texture3DProj", "texture3DProj", "texture3DProj",
+    "texture3DProjLod", "texture3DProjLod", "textureCube", "textureCube", "textureCubeGradEXT",
+    "textureCubeLod", "textureCubeLod", "textureCubeLodEXT", "textureGather", "textureGather",
+    "textureGather", "textureGather", "textureGather", "textureGather", "textureGather",
+    "textureGather", "textureGather", "textureGather", "textureGather", "textureGather",
+    "textureGather", "textureGather", "textureGather", "textureGather", "textureGather",
+    "textureGather", "textureGather", "textureGather", "textureGather", "textureGatherOffset",
+    "textureGatherOffset", "textureGatherOffset", "textureGatherOffset", "textureGatherOffset",
+    "textureGatherOffset", "textureGatherOffset", "textureGatherOffset", "textureGatherOffset",
+    "textureGatherOffsets", "textureGatherOffsets", "textureGatherOffsets", "textureGatherOffsets",
+    "textureGatherOffsets", "textureGatherOffsets", "textureGatherOffsets", "textureGatherOffsets",
+    "textureGatherOffsets", "textureGatherOffsets", "textureGatherOffsets", "textureGatherOffsets",
+    "textureGatherOffsets", "textureGatherOffsets", "textureGatherOffsets", "textureGrad",
     "textureGrad", "textureGrad", "textureGrad", "textureGrad", "textureGrad", "textureGrad",
-    "textureGrad", "textureGrad", "textureGrad", "textureGrad", "textureProjGrad",
+    "textureGrad", "textureGrad", "textureGrad", "textureGrad", "textureGrad", "textureGrad",
+    "textureGrad", "textureGrad", "textureGradOffset", "textureGradOffset", "textureGradOffset",
+    "textureGradOffset", "textureGradOffset", "textureGradOffset", "textureGradOffset",
+    "textureGradOffset", "textureGradOffset", "textureGradOffset", "textureGradOffset",
+    "textureLod", "textureLod", "textureLod", "textureLod", "textureLod", "textureLod",
+    "textureLod", "textureLod", "textureLod", "textureLod", "textureLod", "textureLodOffset",
+    "textureLodOffset", "textureLodOffset", "textureLodOffset", "textureLodOffset",
+    "textureLodOffset", "textureLodOffset", "textureLodOffset", "textureOffset", "textureOffset",
+    "textureOffset", "textureOffset", "textureOffset", "textureOffset", "textureOffset",
+    "textureOffset", "textureOffset", "textureOffset", "textureOffset", "textureOffset",
+    "textureOffset", "textureOffset", "textureOffset", "textureOffset", "textureOffset",
+    "textureOffset", "textureOffset", "textureProj", "textureProj", "textureProj", "textureProj",
+    "textureProj", "textureProj", "textureProj", "textureProj", "textureProj", "textureProj",
+    "textureProj", "textureProj", "textureProj", "textureProj", "textureProj", "textureProj",
+    "textureProj", "textureProj", "textureProj", "textureProj", "textureProj", "textureProj",
+    "textureProj", "textureProj", "textureProj", "textureProj", "textureProjGrad",
     "textureProjGrad", "textureProjGrad", "textureProjGrad", "textureProjGrad", "textureProjGrad",
     "textureProjGrad", "textureProjGrad", "textureProjGrad", "textureProjGrad",
-    "textureQueryLevels", "textureQueryLevels", "textureQueryLevels", "textureQueryLevels",
-    "textureQueryLevels", "textureQueryLevels", "textureQueryLevels", "textureQueryLevels",
-    "textureQueryLevels", "textureQueryLevels", "textureQueryLevels", "textureQueryLevels",
-    "textureQueryLevels", "textureSamples", "textureSamples", "texture", "texture", "texture",
-    "texture", "textureProj", "textureProj", "textureProj", "texture", "texture", "textureProj",
-    "texture", "texture", "texture", "texture", "texture", "textureProj", "textureProj",
-    "textureProj", "texture", "texture", "texture", "textureProj", "textureProj", "texture",
-    "textureProj", "textureProj", "textureQueryLod", "textureQueryLod", "textureQueryLod",
-    "textureQueryLod", "textureQueryLod", "textureQueryLod", "textureQueryLod", "textureQueryLod",
-    "textureQueryLod", "textureQueryLod", "textureQueryLod", "textureQueryLod", "textureQueryLod",
-    "textureOffset", "textureOffset", "textureOffset", "textureOffset", "textureOffset",
-    "textureOffset", "textureOffset", "textureOffset", "textureOffset", "textureOffset",
-    "textureOffset", "textureProjOffset", "textureProjOffset", "textureProjOffset",
-    "textureProjOffset", "textureProjOffset", "textureProjOffset", "textureProjOffset",
-    "textureProjOffset", "textureProjOffset", "textureProjOffset", "textureLodOffset",
-    "textureLodOffset", "textureLodOffset", "textureLodOffset", "textureLodOffset",
-    "textureLodOffset", "textureLodOffset", "textureLodOffset", "textureProjLodOffset",
+    "textureProjGradOffset", "textureProjGradOffset", "textureProjGradOffset",
+    "textureProjGradOffset", "textureProjGradOffset", "textureProjGradOffset",
+    "textureProjGradOffset", "textureProjGradOffset", "textureProjGradOffset",
+    "textureProjGradOffset", "textureProjLod", "textureProjLod", "textureProjLod", "textureProjLod",
+    "textureProjLod", "textureProjLod", "textureProjLod", "textureProjLodOffset",
     "textureProjLodOffset", "textureProjLodOffset", "textureProjLodOffset", "textureProjLodOffset",
-    "textureProjLodOffset", "textureProjLodOffset", "texelFetchOffset", "texelFetchOffset",
-    "texelFetchOffset", "texelFetchOffset", "texelFetchOffset", "texelFetchOffset",
-    "textureGradOffset", "textureGradOffset", "textureGradOffset", "textureGradOffset",
-    "textureGradOffset", "textureGradOffset", "textureGradOffset", "textureGradOffset",
-    "textureGradOffset", "textureGradOffset", "textureGradOffset", "textureProjGradOffset",
-    "textureProjGradOffset", "textureProjGradOffset", "textureProjGradOffset",
-    "textureProjGradOffset", "textureProjGradOffset", "textureProjGradOffset",
-    "textureProjGradOffset", "textureProjGradOffset", "textureProjGradOffset", "textureOffset",
-    "textureOffset", "textureOffset", "textureOffset", "textureOffset", "textureOffset",
-    "textureOffset", "textureOffset", "textureProjOffset", "textureProjOffset", "textureProjOffset",
+    "textureProjLodOffset", "textureProjLodOffset", "textureProjOffset", "textureProjOffset",
     "textureProjOffset", "textureProjOffset", "textureProjOffset", "textureProjOffset",
-    "textureGather", "textureGather", "textureGather", "textureGather", "textureGather",
-    "textureGather", "textureGather", "textureGather", "textureGather", "textureGather",
-    "textureGather", "textureGather", "textureGather", "textureGather", "textureGather",
-    "textureGather", "textureGather", "textureGather", "textureGather", "textureGather",
-    "textureGather", "textureGatherOffset", "textureGatherOffset", "textureGatherOffset",
-    "textureGatherOffset", "textureGatherOffset", "textureGatherOffset", "textureGatherOffset",
-    "textureGatherOffset", "textureGatherOffset", "textureGatherOffsets", "textureGatherOffsets",
-    "textureGatherOffsets", "textureGatherOffsets", "textureGatherOffsets", "textureGatherOffsets",
-    "textureGatherOffsets", "textureGatherOffsets", "textureGatherOffsets", "textureGatherOffsets",
-    "textureGatherOffsets", "textureGatherOffsets", "textureGatherOffsets", "textureGatherOffsets",
-    "textureGatherOffsets", "rgb_2_yuv", "yuv_2_rgb", "dFdx", "dFdy", "fwidth", "dFdx", "dFdy",
-    "fwidth", "dFdxFine", "dFdyFine", "dFdxCoarse", "dFdyCoarse", "fwidthFine", "fwidthCoarse",
-    "interpolateAtCentroid", "interpolateAtCentroid", "interpolateAtCentroid",
-    "interpolateAtCentroid", "interpolateAtSample", "interpolateAtSample", "interpolateAtSample",
-    "interpolateAtSample", "interpolateAtOffset", "interpolateAtOffset", "interpolateAtOffset",
-    "interpolateAtOffset", "interpolateAtCentroid", "interpolateAtCentroid",
-    "interpolateAtCentroid", "interpolateAtCentroid", "interpolateAtSample", "interpolateAtSample",
-    "interpolateAtSample", "interpolateAtSample", "interpolateAtOffset", "interpolateAtOffset",
-    "interpolateAtOffset", "atomicCounter", "atomicCounterIncrement", "atomicCounterDecrement",
-    "atomicCounterAdd", "atomicCounterSubtract", "atomicCounterMin", "atomicCounterMax",
-    "atomicCounterAnd", "atomicCounterOr", "atomicCounterXor", "atomicCounterExchange",
-    "atomicCounterCompSwap", "atomicAdd", "atomicAdd", "atomicMin", "atomicMin", "atomicMax",
-    "atomicMax", "atomicAnd", "atomicAnd", "atomicOr", "atomicOr", "atomicXor", "atomicXor",
-    "atomicExchange", "atomicExchange", "atomicCompSwap", "atomicCompSwap", "imageStore",
-    "imageStore", "imageStore", "imageStore", "imageStore", "imageStore", "imageStore",
-    "imageStore", "imageStore", "imageLoad", "imageLoad", "imageLoad", "imageLoad", "imageLoad",
-    "imageLoad", "imageLoad", "imageLoad", "imageSize", "imageSize", "imageSize", "imageSize",
-    "imageSize", "imageSize", "imageSize", "imageSize", "imageSize", "imageSize", "imageSize",
-    "imageSize", "imageSize", "imageSize", "imageSize", "imageSize", "imageSize", "imageSize",
-    "imageSize", "imageSamples", "imageSamples", "imageAtomicAdd", "imageAtomicAdd",
-    "imageAtomicMin", "imageAtomicMin", "imageAtomicMax", "imageAtomicMax", "imageAtomicAnd",
-    "imageAtomicAnd", "imageAtomicOr", "imageAtomicOr", "imageAtomicXor", "imageAtomicXor",
-    "imageAtomicExchange", "imageAtomicExchange", "imageAtomicExchange", "imageAtomicCompSwap",
-    "imageAtomicCompSwap", "imageAtomicAdd", "imageAtomicAdd", "imageAtomicMin", "imageAtomicMin",
-    "imageAtomicMax", "imageAtomicMax", "imageAtomicAnd", "imageAtomicAnd", "imageAtomicOr",
-    "imageAtomicOr", "imageAtomicXor", "imageAtomicXor", "imageAtomicExchange",
-    "imageAtomicExchange", "imageAtomicCompSwap", "imageAtomicCompSwap", "pixelLocalLoadANGLE",
-    "pixelLocalStoreANGLE", "beginInvocationInterlockNV", "endInvocationInterlockNV",
-    "beginFragmentShaderOrderingINTEL", "beginInvocationInterlockARB", "endInvocationInterlockARB",
-    "noise1", "noise2", "noise3", "noise4", "memoryBarrier", "memoryBarrierAtomicCounter",
-    "memoryBarrierBuffer", "memoryBarrierImage", "barrier", "memoryBarrierShared",
-    "groupMemoryBarrier", "barrier", "EmitVertex", "EndPrimitive", "EmitVertex", "EndPrimitive",
-    "EmitStreamVertex", "EndStreamPrimitive", "subpassLoad", "subpassLoad", "anyInvocation",
-    "allInvocations", "allInvocationsEqual", "r32ui", "rg16f", "rgba8", "rgba8ui", "rgba8i", "r32f",
-    "main",
-
-    # keywords borrowed from metal, used by metal.glsl
-    "using", "namespace", "metal", "inline", "template", "vec", "as_type", "constant",
-
-    # keywords borrowed from hlsl, used by hlsl.glsl
-    "f16tof32", "f32tof16", "atan2", "asfloat", "asint", "asuint", "frac", "lerp", "rsqrt",
-    "typedef", "min16int", "min16uint"
+    "textureProjOffset", "textureProjOffset", "textureProjOffset", "textureProjOffset",
+    "textureProjOffset", "textureProjOffset", "textureProjOffset", "textureProjOffset",
+    "textureProjOffset", "textureProjOffset", "textureProjOffset", "textureQueryLevels",
+    "textureQueryLevels", "textureQueryLevels", "textureQueryLevels", "textureQueryLevels",
+    "textureQueryLevels", "textureQueryLevels", "textureQueryLevels", "textureQueryLevels",
+    "textureQueryLevels", "textureQueryLevels", "textureQueryLevels", "textureQueryLevels",
+    "textureQueryLod", "textureQueryLod", "textureQueryLod", "textureQueryLod", "textureQueryLod",
+    "textureQueryLod", "textureQueryLod", "textureQueryLod", "textureQueryLod", "textureQueryLod",
+    "textureQueryLod", "textureQueryLod", "textureQueryLod", "textureSamples", "textureSamples",
+    "textureSize", "textureSize", "textureSize", "textureSize", "textureSize", "textureSize",
+    "textureSize", "textureSize", "textureSize", "textureSize", "textureSize", "textureSize",
+    "textureSize", "textureSize", "textureSize", "textureSize", "textureSize", "textureSize",
+    "textureSize", "textureSize", "textureSize", "textureSize", "textureSize", "textureSize",
+    "textureVideoWEBGL", "transpose", "transpose", "transpose", "transpose", "transpose",
+    "transpose", "transpose", "transpose", "transpose", "true", "trunc", "trunc", "uaddCarry",
+    "uimage2D", "uint", "uintBitsToFloat", "umulExtended", "uniform", "unpackDouble2x32",
+    "unpackHalf2x16", "unpackSnorm2x16", "unpackSnorm4x8", "unpackUnorm2x16", "usampler2D",
+    "usampler2DArray", "usampler3D", "usamplerCube", "usubBorrow", "uvec2", "uvec3", "uvec4",
+    "vec2", "vec3", "vec4", "void", "volatile", "while", "yuv_2_rgb", "__pixel_localEXT",
+    "__pixel_local_inEXT", "__pixel_local_outEXT",
 }
 
 # rgba and stpq get rewritten to xyzw, so we only need to check xyzw here. This way we can keep
@@ -337,7 +342,6 @@
 used_new_names = set()
 
 def generate_new_name(*, force_upper_case):
-    global upper_case_name_generator, general_name_generator, used_new_names;
     name_generator = upper_case_name_generator if force_upper_case else general_name_generator
     while True:
         name = name_generator.next_name()
@@ -364,14 +368,14 @@
 
 # minifies a single GLSL file.
 class Minifier:
-    def __init__(self, in_filename):
+    def __init__(self, code, basename, exports=set()):
         # parse tokens.
         lexer = lex.lex()
-        lexer.exports = set()
-        lexer.input(open(in_filename).read())
+        lexer.exports = exports
+        lexer.input(code)
         self.tokens = [tok for tok in lexer];
-        self.exports = lexer.exports
-        self.basename = os.path.basename(in_filename)
+        self.exports = exports
+        self.basename = basename
 
 
     # Strips unneeded code from the tokens. Called after all Minifiers have been parsed.
@@ -380,19 +384,26 @@
 
         # strip comments.
         self.tokens = \
-            [t for t in self.tokens if "COMMENT" not in t.type]
+            [tok for tok in self.tokens if "COMMENT" not in tok.type]
 
         # strip unused defines.
-        self.tokens = \
-            [t for t in self.tokens if t.type != "DEFINE" or all_id_counts[t.define_id] > 1]
+        self.tokens = [tok for tok in self.tokens if tok.type != "DEFINE"\
+                                                  or all_id_reference_counts[tok.define_id] > 0]
 
         # merge whitespace.
         unmerged,self.tokens = self.tokens,[]
-        for t in unmerged:
-            if t.type == "WHITESPACE" and len(self.tokens) > 0 and self.tokens[-1].type == "WHITESPACE":
-                self.tokens[-1].value += t.value
+        for tok in unmerged:
+            if tok.type == "DEFINE":
+                if tok.define_arglist != None:
+                    tok.define_arglist.strip_tokens()
+                if tok.define_val != None:
+                    tok.define_val.strip_tokens()
+            if (tok.type == "WHITESPACE"
+                and len(self.tokens) > 0
+                and self.tokens[-1].type == "WHITESPACE"):
+                self.tokens[-1].value += tok.value
             else:
-                self.tokens.append(t)
+                self.tokens.append(tok)
 
 
     # generates rewritten glsl from our tokens.
@@ -420,6 +431,10 @@
             elif needs_whitespace and lasttoken_needs_whitespace:
                 out.write(' ')
 
+            # is_newline will be false once we output the token (unless this value otherwise gets
+            # updated).
+            is_newline = False
+
             if tok.type == "ID":
                 if (rgba_stpq_pattern.match(tok.value)
                     and lasttoken.type == "OP"
@@ -436,8 +451,16 @@
                 out.write(new_names[tok.define_id]
                           if rename_exported_defines or tok.define_id[0] != '@'
                           else tok.define_id[1:])
+                if tok.define_arglist != None:
+                    is_newline = tok.define_arglist.emit_tokens_to_rewritten_glsl(\
+                        out,\
+                        rename_exported_defines=rename_exported_defines)
+                    assert(not is_newline)
                 if tok.define_val != None:
-                    out.write(tok.define_val)
+                    out.write(' ')
+                    is_newline = tok.define_val.emit_tokens_to_rewritten_glsl(\
+                        out,\
+                        rename_exported_defines=rename_exported_defines)
 
             elif tok.type == "IFDEF":
                 out.write(tok.ifdef_tag)
@@ -454,19 +477,17 @@
             else:
                 out.write(tok.value)
 
-            if is_directive and not args.human_readable:
+            # Since we preserve whitespace in 'human_readable' mode, the newline after a
+            # preprocessor directive will happen for us automatically unless 'human_readable' is
+            # false.
+            if not args.human_readable and is_directive and not is_newline:
                 out.write('\n')
                 is_newline = True
-            else:
-                # Since we preserve whitespace in 'human_readable' mode, the newline after a
-                # preprocessor directive will happen automatically.
-                is_newline = False
 
             lasttoken = tok
             lasttoken_needs_whitespace = needs_whitespace
 
-        if not is_newline:
-            out.write('\n')
+        return is_newline
 
 
     def write_exports(self, outdir):
@@ -493,7 +514,9 @@
         out.write("namespace glsl {\n")
         out.write('const char %s[] = R"===(' % os.path.splitext(self.basename)[0])
 
-        self.emit_tokens_to_rewritten_glsl(out, rename_exported_defines=True)
+        is_newline = self.emit_tokens_to_rewritten_glsl(out, rename_exported_defines=True)
+        if not is_newline:
+            out.write('\n')
 
         out.write(')===";\n')
         out.write("} // namespace glsl\n")
@@ -511,7 +534,7 @@
 
 
 # parse all GLSL files before renaming. This keeps the renaming consistent across files.
-minifiers = [Minifier(f) for f in args.files]
+minifiers = [Minifier(open(f).read(), os.path.basename(f)) for f in args.files]
 generate_new_names()
 
 # minify all GLSL files.