glsl: Write a new built-in function module.
authorKenneth Graunke <kenneth@whitecape.org>
Fri, 30 Aug 2013 06:06:39 +0000 (23:06 -0700)
committerKenneth Graunke <kenneth@whitecape.org>
Mon, 9 Sep 2013 21:42:18 +0000 (14:42 -0700)
This creates a new replacement for the existing built-in function code.
The new module lives in builtin_functions.cpp (not builtin_function.cpp)
and exists in parallel with the existing system.  It isn't used yet.

The new built-in function code takes a significantly different approach:

Instead of implementing built-ins via printed IR, build time scripts,
and run time parsing, we now implement them directly in C++, using
ir_builder.  This translates to faster load times, and a much less
complex build system.

It also takes a different approach to built-in availability: each
signature now stores a boolean predicate, which makes it easy to
construct arbitrary expressions based on _mesa_glsl_parse_state's
fields.  This is much more flexible than the old system, and also
easier to use.

Built-ins are also now stored in a single gl_shader object, rather
than being spread out across a number of shaders that need to be linked.
When searching for a matching prototype, we simply consult the
availability predicate.  This also simplifies the code.

v2: Incorporate Matt Turner's feedback: use the new fma() function rather
    than expr().  Don't expose textureQueryLOD() in GLSL 4.00 (since it
    was renamed to textureQueryLod()).  Also correct some #undefs.
v3: Incorporate Paul Berry's feedback: rename legacy to compatibility;
    add comments to explain a few things; fix uvec availability; include
    shaderobj.h instead of repeating the _mesa_new_shader prototype.
v4: Fix lack of TEX_PROJECT on textureProjGrad[Offset] (caught by oglc).
    Add an out_var convenience function (more feedback by Matt Turner).
v5: Rework availability predicates for Lod functions.  They were broken.

Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Matt Turner <mattst88@gmail.com>
Enthusiastically-acked-by: Paul Berry <stereotype441@gmail.com>
src/glsl/Makefile.sources
src/glsl/builtin_functions.cpp [new file with mode: 0644]
src/glsl/ir.h

index 979c4165f501eea24ba14e56d7afb83c4799229b..3e706efeaa93f19cf6ac5f41ab1dc6a89acf497e 100644 (file)
@@ -21,6 +21,7 @@ LIBGLSL_FILES = \
        $(GLSL_SRCDIR)/ast_function.cpp \
        $(GLSL_SRCDIR)/ast_to_hir.cpp \
        $(GLSL_SRCDIR)/ast_type.cpp \
+       $(GLSL_SRCDIR)/builtin_functions.cpp \
        $(GLSL_SRCDIR)/builtin_types.cpp \
        $(GLSL_SRCDIR)/builtin_variables.cpp \
        $(GLSL_SRCDIR)/glsl_parser_extras.cpp \
diff --git a/src/glsl/builtin_functions.cpp b/src/glsl/builtin_functions.cpp
new file mode 100644 (file)
index 0000000..662fc1e
--- /dev/null
@@ -0,0 +1,3517 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file builtin_functions.cpp
+ *
+ * Support for GLSL built-in functions.
+ *
+ * This file is split into several main components:
+ *
+ * 1. Availability predicates
+ *
+ *    A series of small functions that check whether the current shader
+ *    supports the version/extensions required to expose a built-in.
+ *
+ * 2. Core builtin_builder class functionality
+ *
+ * 3. Lists of built-in functions
+ *
+ *    The builtin_builder::create_builtins() function contains lists of all
+ *    built-in function signatures, where they're available, what types they
+ *    take, and so on.
+ *
+ * 4. Implementations of built-in function signatures
+ *
+ *    A series of functions which create ir_function_signatures and emit IR
+ *    via ir_builder to implement them.
+ *
+ * 5. External API
+ *
+ *    A few functions the rest of the compiler can use to interact with the
+ *    built-in function module.  For example, searching for a built-in by
+ *    name and parameters.
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "main/core.h" /* for struct gl_shader */
+#include "main/shaderobj.h"
+#include "ir_builder.h"
+#include "glsl_parser_extras.h"
+#include "program/prog_instruction.h"
+#include <limits>
+
+using namespace ir_builder;
+
+/**
+ * Availability predicates:
+ *  @{
+ */
+static bool
+always_available(const _mesa_glsl_parse_state *state)
+{
+   return true;
+}
+
+static bool
+compatibility_vs_only(const _mesa_glsl_parse_state *state)
+{
+   return state->target == vertex_shader &&
+          state->language_version <= 130 &&
+          !state->es_shader;
+}
+
+static bool
+fs_only(const _mesa_glsl_parse_state *state)
+{
+   return state->target == fragment_shader;
+}
+
+static bool
+gs_only(const _mesa_glsl_parse_state *state)
+{
+   return state->target == geometry_shader;
+}
+
+static bool
+v110(const _mesa_glsl_parse_state *state)
+{
+   return !state->es_shader;
+}
+
+static bool
+v110_fs_only(const _mesa_glsl_parse_state *state)
+{
+   return !state->es_shader && state->target == fragment_shader;
+}
+
+static bool
+v120(const _mesa_glsl_parse_state *state)
+{
+   return state->is_version(120, 300);
+}
+
+static bool
+v130(const _mesa_glsl_parse_state *state)
+{
+   return state->is_version(130, 300);
+}
+
+static bool
+v130_fs_only(const _mesa_glsl_parse_state *state)
+{
+   return state->is_version(130, 300) &&
+          state->target == fragment_shader;
+}
+
+static bool
+v140(const _mesa_glsl_parse_state *state)
+{
+   return state->is_version(140, 0);
+}
+
+static bool
+texture_rectangle(const _mesa_glsl_parse_state *state)
+{
+   return state->ARB_texture_rectangle_enable;
+}
+
+static bool
+texture_external(const _mesa_glsl_parse_state *state)
+{
+   return state->OES_EGL_image_external_enable;
+}
+
+/** True if texturing functions with explicit LOD are allowed. */
+static bool
+lod_exists_in_stage(const _mesa_glsl_parse_state *state)
+{
+   /* Texturing functions with "Lod" in their name exist:
+    * - In the vertex shader stage (for all languages)
+    * - In any stage for GLSL 1.30+ or GLSL ES 3.00
+    * - In any stage for desktop GLSL with ARB_shader_texture_lod enabled.
+    *
+    * Since ARB_shader_texture_lod can only be enabled on desktop GLSL, we
+    * don't need to explicitly check state->es_shader.
+    */
+   return state->target == vertex_shader ||
+          state->is_version(130, 300) ||
+          state->ARB_shader_texture_lod_enable;
+}
+
+static bool
+v110_lod(const _mesa_glsl_parse_state *state)
+{
+   return !state->es_shader && lod_exists_in_stage(state);
+}
+
+static bool
+shader_texture_lod(const _mesa_glsl_parse_state *state)
+{
+   return state->ARB_shader_texture_lod_enable;
+}
+
+static bool
+shader_texture_lod_and_rect(const _mesa_glsl_parse_state *state)
+{
+   return state->ARB_shader_texture_lod_enable &&
+          state->ARB_texture_rectangle_enable;
+}
+
+static bool
+shader_bit_encoding(const _mesa_glsl_parse_state *state)
+{
+   return state->is_version(330, 300) ||
+          state->ARB_shader_bit_encoding_enable ||
+          state->ARB_gpu_shader5_enable;
+}
+
+static bool
+shader_packing(const _mesa_glsl_parse_state *state)
+{
+   return state->ARB_shading_language_packing_enable ||
+          state->is_version(400, 0);
+}
+
+static bool
+shader_packing_or_es3(const _mesa_glsl_parse_state *state)
+{
+   return state->ARB_shading_language_packing_enable ||
+          state->is_version(400, 300);
+}
+
+static bool
+gpu_shader5(const _mesa_glsl_parse_state *state)
+{
+   return state->is_version(400, 0) || state->ARB_gpu_shader5_enable;
+}
+
+static bool
+vs_texture_array(const _mesa_glsl_parse_state *state)
+{
+   return state->target == vertex_shader &&
+          state->EXT_texture_array_enable;
+}
+
+static bool
+fs_texture_array(const _mesa_glsl_parse_state *state)
+{
+   return state->target == fragment_shader &&
+          state->EXT_texture_array_enable;
+}
+
+static bool
+texture_array(const _mesa_glsl_parse_state *state)
+{
+   return state->EXT_texture_array_enable;
+}
+
+static bool
+texture_multisample(const _mesa_glsl_parse_state *state)
+{
+   return state->is_version(150, 0) ||
+          state->ARB_texture_multisample_enable;
+}
+
+static bool
+fs_texture_cube_map_array(const _mesa_glsl_parse_state *state)
+{
+   return state->target == fragment_shader &&
+          (state->is_version(400, 0) ||
+           state->ARB_texture_cube_map_array_enable);
+}
+
+static bool
+texture_cube_map_array(const _mesa_glsl_parse_state *state)
+{
+   return state->is_version(400, 0) ||
+          state->ARB_texture_cube_map_array_enable;
+}
+
+static bool
+texture_query_lod(const _mesa_glsl_parse_state *state)
+{
+   return state->target == fragment_shader &&
+          state->ARB_texture_query_lod_enable;
+}
+
+/* Desktop GL or OES_standard_derivatives + fragment shader only */
+static bool
+fs_oes_derivatives(const _mesa_glsl_parse_state *state)
+{
+   return state->target == fragment_shader &&
+          (!state->es_shader || state->OES_standard_derivatives_enable);
+}
+
+static bool
+tex1d_lod(const _mesa_glsl_parse_state *state)
+{
+   return !state->es_shader && lod_exists_in_stage(state);
+}
+
+/** True if sampler3D exists */
+static bool
+tex3d(const _mesa_glsl_parse_state *state)
+{
+   /* sampler3D exists in all desktop GLSL versions, GLSL ES 1.00 with the
+    * OES_texture_3D extension, and in GLSL ES 3.00.
+    */
+   return !state->es_shader ||
+          state->OES_texture_3D_enable ||
+          state->language_version >= 300;
+}
+
+static bool
+fs_tex3d(const _mesa_glsl_parse_state *state)
+{
+   return state->target == fragment_shader &&
+          (!state->es_shader || state->OES_texture_3D_enable);
+}
+
+static bool
+tex3d_lod(const _mesa_glsl_parse_state *state)
+{
+   return tex3d(state) && lod_exists_in_stage(state);
+}
+/** @} */
+
+/******************************************************************************/
+
+/**
+ * builtin_builder: A singleton object representing the core of the built-in
+ * function module.
+ *
+ * It generates IR for every built-in function signature, and organizes them
+ * into functions.
+ */
+class builtin_builder {
+public:
+   builtin_builder();
+   ~builtin_builder();
+
+   void initialize();
+   void release();
+   ir_function_signature *find(_mesa_glsl_parse_state *state,
+                               const char *name, exec_list *actual_parameters);
+
+private:
+   void *mem_ctx;
+   /**
+    * A shader to hold all the built-in signatures; created by this module.
+    *
+    * This includes signatures for every built-in, regardless of version or
+    * enabled extensions.  The availability predicate associated with each
+    * signature allows matching_signature() to filter out the irrelevant ones.
+    */
+   gl_shader *shader;
+
+   /** Global variables used by built-in functions. */
+   ir_variable *gl_ModelViewProjectionMatrix;
+   ir_variable *gl_Vertex;
+
+   void create_shader();
+   void create_builtins();
+
+   /**
+    * IR builder helpers:
+    *
+    * These convenience functions assist in emitting IR, but don't necessarily
+    * fit in ir_builder itself.  Many of them rely on having a mem_ctx class
+    * member available.
+    */
+   ir_variable *in_var(const glsl_type *type, const char *name);
+   ir_variable *out_var(const glsl_type *type, const char *name);
+   ir_constant *imm(float f);
+   ir_constant *imm(int i);
+   ir_constant *imm(unsigned u);
+   ir_constant *imm(const glsl_type *type, const ir_constant_data &);
+   ir_dereference_variable *var_ref(ir_variable *var);
+   ir_dereference_array *array_ref(ir_variable *var, int i);
+   ir_swizzle *matrix_elt(ir_variable *var, int col, int row);
+
+   ir_expression *asin_expr(ir_variable *x);
+
+   /** Create a new function and add the given signatures. */
+   void add_function(const char *name, ...);
+
+   ir_function_signature *new_sig(const glsl_type *return_type,
+                                  builtin_available_predicate avail,
+                                  int num_params, ...);
+
+   /**
+    * Function signature generators:
+    *  @{
+    */
+   ir_function_signature *unop(builtin_available_predicate avail,
+                               ir_expression_operation opcode,
+                               const glsl_type *return_type,
+                               const glsl_type *param_type);
+   ir_function_signature *binop(ir_expression_operation opcode,
+                                builtin_available_predicate avail,
+                                const glsl_type *return_type,
+                                const glsl_type *param0_type,
+                                const glsl_type *param1_type);
+
+#define B0(X) ir_function_signature *_##X();
+#define B1(X) ir_function_signature *_##X(const glsl_type *);
+#define B2(X) ir_function_signature *_##X(const glsl_type *, const glsl_type *);
+#define B3(X) ir_function_signature *_##X(const glsl_type *, const glsl_type *, const glsl_type *);
+#define BA1(X) ir_function_signature *_##X(builtin_available_predicate, const glsl_type *);
+#define BA2(X) ir_function_signature *_##X(builtin_available_predicate, const glsl_type *, const glsl_type *);
+   B1(radians)
+   B1(degrees)
+   B1(sin)
+   B1(cos)
+   B1(tan)
+   B1(asin)
+   B1(acos)
+   B1(atan2)
+   B1(atan)
+   B1(sinh)
+   B1(cosh)
+   B1(tanh)
+   B1(asinh)
+   B1(acosh)
+   B1(atanh)
+   B1(pow)
+   B1(exp)
+   B1(log)
+   B1(exp2)
+   B1(log2)
+   B1(sqrt)
+   B1(inversesqrt)
+   B1(abs)
+   B1(sign)
+   B1(floor)
+   B1(trunc)
+   B1(round)
+   B1(roundEven)
+   B1(ceil)
+   B1(fract)
+   B2(mod)
+   B1(modf)
+   BA2(min)
+   BA2(max)
+   BA2(clamp)
+   B2(mix_lrp)
+   B2(mix_sel)
+   B2(step)
+   B2(smoothstep)
+   B1(isnan)
+   B1(isinf)
+   B1(floatBitsToInt)
+   B1(floatBitsToUint)
+   B1(intBitsToFloat)
+   B1(uintBitsToFloat)
+   ir_function_signature *_packUnorm2x16(builtin_available_predicate avail);
+   ir_function_signature *_packSnorm2x16(builtin_available_predicate avail);
+   ir_function_signature *_packUnorm4x8(builtin_available_predicate avail);
+   ir_function_signature *_packSnorm4x8(builtin_available_predicate avail);
+   ir_function_signature *_unpackUnorm2x16(builtin_available_predicate avail);
+   ir_function_signature *_unpackSnorm2x16(builtin_available_predicate avail);
+   ir_function_signature *_unpackUnorm4x8(builtin_available_predicate avail);
+   ir_function_signature *_unpackSnorm4x8(builtin_available_predicate avail);
+   ir_function_signature *_packHalf2x16(builtin_available_predicate avail);
+   ir_function_signature *_unpackHalf2x16(builtin_available_predicate avail);
+   B1(length)
+   B1(distance);
+   B1(dot);
+   B1(cross);
+   B1(normalize);
+   B0(ftransform);
+   B1(faceforward);
+   B1(reflect);
+   B1(refract);
+   B1(matrixCompMult);
+   B1(outerProduct);
+   B0(determinant_mat2);
+   B0(determinant_mat3);
+   B0(determinant_mat4);
+   B0(inverse_mat2);
+   B0(inverse_mat3);
+   B0(inverse_mat4);
+   B1(transpose);
+   BA1(lessThan);
+   BA1(lessThanEqual);
+   BA1(greaterThan);
+   BA1(greaterThanEqual);
+   BA1(equal);
+   BA1(notEqual);
+   B1(any);
+   B1(all);
+   B1(not);
+   B2(textureSize);
+   ir_function_signature *_textureSize(builtin_available_predicate avail,
+                                       const glsl_type *return_type,
+                                       const glsl_type *sampler_type);
+
+/** Flags to _texture() */
+#define TEX_PROJECT 1
+#define TEX_OFFSET  2
+
+   ir_function_signature *_texture(ir_texture_opcode opcode,
+                                   builtin_available_predicate avail,
+                                   const glsl_type *return_type,
+                                   const glsl_type *sampler_type,
+                                   int coord_size,
+                                   const glsl_type *coord_type,
+                                   int flags = 0);
+   B0(textureCubeArrayShadow);
+   ir_function_signature *_texelFetch(builtin_available_predicate avail,
+                                      const glsl_type *return_type,
+                                      const glsl_type *sampler_type,
+                                      const glsl_type *coord_type,
+                                      const glsl_type *offset_type = NULL);
+
+   B0(EmitVertex)
+   B0(EndPrimitive)
+
+   B2(textureQueryLod);
+   B1(dFdx);
+   B1(dFdy);
+   B1(fwidth);
+   B1(noise1);
+   B1(noise2);
+   B1(noise3);
+   B1(noise4);
+
+   B1(bitfieldExtract)
+   B1(bitfieldInsert)
+   B1(bitfieldReverse)
+   B1(bitCount)
+   B1(findLSB)
+   B1(findMSB)
+   B1(fma)
+#undef B0
+#undef B1
+#undef B2
+#undef B3
+#undef BA1
+#undef BA2
+   /** @} */
+};
+
+/**
+ * Core builtin_builder functionality:
+ *  @{
+ */
+builtin_builder::builtin_builder()
+{
+   mem_ctx = NULL;
+}
+
+builtin_builder::~builtin_builder()
+{
+   ralloc_free(mem_ctx);
+}
+
+ir_function_signature *
+builtin_builder::find(_mesa_glsl_parse_state *state,
+                      const char *name, exec_list *actual_parameters)
+{
+   /* The shader currently being compiled requested a built-in function;
+    * it needs to link against builtin_builder::shader in order to get them.
+    *
+    * Even if we don't find a matching signature, we still need to do this so
+    * that the "no matching signature" error will list potential candidates
+    * from the available built-ins.
+    */
+   state->builtins_to_link[0] = shader;
+   state->num_builtins_to_link = 1;
+
+   ir_function *f = shader->symbols->get_function(name);
+   if (f == NULL)
+      return NULL;
+
+   ir_function_signature *sig = f->matching_signature(state, actual_parameters);
+   if (sig == NULL)
+      return NULL;
+
+   return sig;
+}
+
+void
+builtin_builder::initialize()
+{
+   /* If already initialized, don't do it again. */
+   if (mem_ctx != NULL)
+      return;
+
+   mem_ctx = ralloc_context(NULL);
+   create_shader();
+   create_builtins();
+}
+
+void
+builtin_builder::release()
+{
+   ralloc_free(mem_ctx);
+   mem_ctx = NULL;
+}
+
+void
+builtin_builder::create_shader()
+{
+   /* The target doesn't actually matter.  There's no target for generic
+    * GLSL utility code that could be linked against any stage, so just
+    * arbitrarily pick GL_VERTEX_SHADER.
+    */
+   shader = _mesa_new_shader(NULL, 0, GL_VERTEX_SHADER);
+   shader->symbols = new(mem_ctx) glsl_symbol_table;
+
+   gl_ModelViewProjectionMatrix =
+      new(mem_ctx) ir_variable(glsl_type::mat4_type,
+                               "gl_ModelViewProjectionMatrix",
+                               ir_var_uniform);
+
+   shader->symbols->add_variable(gl_ModelViewProjectionMatrix);
+
+   gl_Vertex = in_var(glsl_type::vec4_type, "gl_Vertex");
+   shader->symbols->add_variable(gl_Vertex);
+}
+
+/** @} */
+
+/**
+ * Create ir_function and ir_function_signature objects for each built-in.
+ *
+ * Contains a list of every available built-in.
+ */
+void
+builtin_builder::create_builtins()
+{
+#define F(NAME)                                 \
+   add_function(#NAME,                          \
+                _##NAME(glsl_type::float_type), \
+                _##NAME(glsl_type::vec2_type),  \
+                _##NAME(glsl_type::vec3_type),  \
+                _##NAME(glsl_type::vec4_type),  \
+                NULL);
+
+#define FI(NAME)                                \
+   add_function(#NAME,                          \
+                _##NAME(glsl_type::float_type), \
+                _##NAME(glsl_type::vec2_type),  \
+                _##NAME(glsl_type::vec3_type),  \
+                _##NAME(glsl_type::vec4_type),  \
+                _##NAME(glsl_type::int_type),   \
+                _##NAME(glsl_type::ivec2_type), \
+                _##NAME(glsl_type::ivec3_type), \
+                _##NAME(glsl_type::ivec4_type), \
+                NULL);
+
+#define FIU(NAME)                                                 \
+   add_function(#NAME,                                            \
+                _##NAME(always_available, glsl_type::float_type), \
+                _##NAME(always_available, glsl_type::vec2_type),  \
+                _##NAME(always_available, glsl_type::vec3_type),  \
+                _##NAME(always_available, glsl_type::vec4_type),  \
+                                                                  \
+                _##NAME(always_available, glsl_type::int_type),   \
+                _##NAME(always_available, glsl_type::ivec2_type), \
+                _##NAME(always_available, glsl_type::ivec3_type), \
+                _##NAME(always_available, glsl_type::ivec4_type), \
+                                                                  \
+                _##NAME(v130, glsl_type::uint_type),              \
+                _##NAME(v130, glsl_type::uvec2_type),             \
+                _##NAME(v130, glsl_type::uvec3_type),             \
+                _##NAME(v130, glsl_type::uvec4_type),             \
+                NULL);
+
+#define IU(NAME)                                \
+   add_function(#NAME,                          \
+                _##NAME(glsl_type::int_type),   \
+                _##NAME(glsl_type::ivec2_type), \
+                _##NAME(glsl_type::ivec3_type), \
+                _##NAME(glsl_type::ivec4_type), \
+                                                \
+                _##NAME(glsl_type::uint_type),  \
+                _##NAME(glsl_type::uvec2_type), \
+                _##NAME(glsl_type::uvec3_type), \
+                _##NAME(glsl_type::uvec4_type), \
+                NULL);
+
+#define FIUB(NAME)                                                \
+   add_function(#NAME,                                            \
+                _##NAME(always_available, glsl_type::float_type), \
+                _##NAME(always_available, glsl_type::vec2_type),  \
+                _##NAME(always_available, glsl_type::vec3_type),  \
+                _##NAME(always_available, glsl_type::vec4_type),  \
+                                                                  \
+                _##NAME(always_available, glsl_type::int_type),   \
+                _##NAME(always_available, glsl_type::ivec2_type), \
+                _##NAME(always_available, glsl_type::ivec3_type), \
+                _##NAME(always_available, glsl_type::ivec4_type), \
+                                                                  \
+                _##NAME(v130, glsl_type::uint_type),              \
+                _##NAME(v130, glsl_type::uvec2_type),             \
+                _##NAME(v130, glsl_type::uvec3_type),             \
+                _##NAME(v130, glsl_type::uvec4_type),             \
+                                                                  \
+                _##NAME(always_available, glsl_type::bool_type),  \
+                _##NAME(always_available, glsl_type::bvec2_type), \
+                _##NAME(always_available, glsl_type::bvec3_type), \
+                _##NAME(always_available, glsl_type::bvec4_type), \
+                NULL);
+
+#define FIU2_MIXED(NAME)                                                                 \
+   add_function(#NAME,                                                                   \
+                _##NAME(always_available, glsl_type::float_type, glsl_type::float_type), \
+                _##NAME(always_available, glsl_type::vec2_type,  glsl_type::float_type), \
+                _##NAME(always_available, glsl_type::vec3_type,  glsl_type::float_type), \
+                _##NAME(always_available, glsl_type::vec4_type,  glsl_type::float_type), \
+                                                                                         \
+                _##NAME(always_available, glsl_type::vec2_type,  glsl_type::vec2_type),  \
+                _##NAME(always_available, glsl_type::vec3_type,  glsl_type::vec3_type),  \
+                _##NAME(always_available, glsl_type::vec4_type,  glsl_type::vec4_type),  \
+                                                                                         \
+                _##NAME(always_available, glsl_type::int_type,   glsl_type::int_type),   \
+                _##NAME(always_available, glsl_type::ivec2_type, glsl_type::int_type),   \
+                _##NAME(always_available, glsl_type::ivec3_type, glsl_type::int_type),   \
+                _##NAME(always_available, glsl_type::ivec4_type, glsl_type::int_type),   \
+                                                                                         \
+                _##NAME(always_available, glsl_type::ivec2_type, glsl_type::ivec2_type), \
+                _##NAME(always_available, glsl_type::ivec3_type, glsl_type::ivec3_type), \
+                _##NAME(always_available, glsl_type::ivec4_type, glsl_type::ivec4_type), \
+                                                                                         \
+                _##NAME(v130, glsl_type::uint_type,  glsl_type::uint_type),              \
+                _##NAME(v130, glsl_type::uvec2_type, glsl_type::uint_type),              \
+                _##NAME(v130, glsl_type::uvec3_type, glsl_type::uint_type),              \
+                _##NAME(v130, glsl_type::uvec4_type, glsl_type::uint_type),              \
+                                                                                         \
+                _##NAME(v130, glsl_type::uvec2_type, glsl_type::uvec2_type),             \
+                _##NAME(v130, glsl_type::uvec3_type, glsl_type::uvec3_type),             \
+                _##NAME(v130, glsl_type::uvec4_type, glsl_type::uvec4_type),             \
+                NULL);
+
+   F(radians)
+   F(degrees)
+   F(sin)
+   F(cos)
+   F(tan)
+   F(asin)
+   F(acos)
+
+   add_function("atan",
+                _atan(glsl_type::float_type),
+                _atan(glsl_type::vec2_type),
+                _atan(glsl_type::vec3_type),
+                _atan(glsl_type::vec4_type),
+                _atan2(glsl_type::float_type),
+                _atan2(glsl_type::vec2_type),
+                _atan2(glsl_type::vec3_type),
+                _atan2(glsl_type::vec4_type),
+                NULL);
+
+   F(sinh)
+   F(cosh)
+   F(tanh)
+   F(asinh)
+   F(acosh)
+   F(atanh)
+   F(pow)
+   F(exp)
+   F(log)
+   F(exp2)
+   F(log2)
+   F(sqrt)
+   F(inversesqrt)
+   FI(abs)
+   FI(sign)
+   F(floor)
+   F(trunc)
+   F(round)
+   F(roundEven)
+   F(ceil)
+   F(fract)
+
+   add_function("mod",
+                _mod(glsl_type::float_type, glsl_type::float_type),
+                _mod(glsl_type::vec2_type,  glsl_type::float_type),
+                _mod(glsl_type::vec3_type,  glsl_type::float_type),
+                _mod(glsl_type::vec4_type,  glsl_type::float_type),
+
+                _mod(glsl_type::vec2_type,  glsl_type::vec2_type),
+                _mod(glsl_type::vec3_type,  glsl_type::vec3_type),
+                _mod(glsl_type::vec4_type,  glsl_type::vec4_type),
+                NULL);
+
+   F(modf)
+
+   FIU2_MIXED(min)
+   FIU2_MIXED(max)
+   FIU2_MIXED(clamp)
+
+   add_function("mix",
+                _mix_lrp(glsl_type::float_type, glsl_type::float_type),
+                _mix_lrp(glsl_type::vec2_type,  glsl_type::float_type),
+                _mix_lrp(glsl_type::vec3_type,  glsl_type::float_type),
+                _mix_lrp(glsl_type::vec4_type,  glsl_type::float_type),
+
+                _mix_lrp(glsl_type::vec2_type,  glsl_type::vec2_type),
+                _mix_lrp(glsl_type::vec3_type,  glsl_type::vec3_type),
+                _mix_lrp(glsl_type::vec4_type,  glsl_type::vec4_type),
+
+                _mix_sel(glsl_type::float_type, glsl_type::bool_type),
+                _mix_sel(glsl_type::vec2_type,  glsl_type::bvec2_type),
+                _mix_sel(glsl_type::vec3_type,  glsl_type::bvec3_type),
+                _mix_sel(glsl_type::vec4_type,  glsl_type::bvec4_type),
+                NULL);
+
+   add_function("step",
+                _step(glsl_type::float_type, glsl_type::float_type),
+                _step(glsl_type::float_type, glsl_type::vec2_type),
+                _step(glsl_type::float_type, glsl_type::vec3_type),
+                _step(glsl_type::float_type, glsl_type::vec4_type),
+
+                _step(glsl_type::vec2_type,  glsl_type::vec2_type),
+                _step(glsl_type::vec3_type,  glsl_type::vec3_type),
+                _step(glsl_type::vec4_type,  glsl_type::vec4_type),
+                NULL);
+
+   add_function("smoothstep",
+                _smoothstep(glsl_type::float_type, glsl_type::float_type),
+                _smoothstep(glsl_type::float_type, glsl_type::vec2_type),
+                _smoothstep(glsl_type::float_type, glsl_type::vec3_type),
+                _smoothstep(glsl_type::float_type, glsl_type::vec4_type),
+
+                _smoothstep(glsl_type::vec2_type,  glsl_type::vec2_type),
+                _smoothstep(glsl_type::vec3_type,  glsl_type::vec3_type),
+                _smoothstep(glsl_type::vec4_type,  glsl_type::vec4_type),
+                NULL);
+   F(isnan)
+   F(isinf)
+
+   F(floatBitsToInt)
+   F(floatBitsToUint)
+   add_function("intBitsToFloat",
+                _intBitsToFloat(glsl_type::int_type),
+                _intBitsToFloat(glsl_type::ivec2_type),
+                _intBitsToFloat(glsl_type::ivec3_type),
+                _intBitsToFloat(glsl_type::ivec4_type),
+                NULL);
+   add_function("uintBitsToFloat",
+                _uintBitsToFloat(glsl_type::uint_type),
+                _uintBitsToFloat(glsl_type::uvec2_type),
+                _uintBitsToFloat(glsl_type::uvec3_type),
+                _uintBitsToFloat(glsl_type::uvec4_type),
+                NULL);
+
+   add_function("packUnorm2x16",   _packUnorm2x16(shader_packing_or_es3),   NULL);
+   add_function("packSnorm2x16",   _packSnorm2x16(shader_packing_or_es3),   NULL);
+   add_function("packUnorm4x8",    _packUnorm4x8(shader_packing),           NULL);
+   add_function("packSnorm4x8",    _packSnorm4x8(shader_packing),           NULL);
+   add_function("unpackUnorm2x16", _unpackUnorm2x16(shader_packing_or_es3), NULL);
+   add_function("unpackSnorm2x16", _unpackSnorm2x16(shader_packing_or_es3), NULL);
+   add_function("unpackUnorm4x8",  _unpackUnorm4x8(shader_packing),         NULL);
+   add_function("unpackSnorm4x8",  _unpackSnorm4x8(shader_packing),         NULL);
+   add_function("packHalf2x16",    _packHalf2x16(shader_packing_or_es3),    NULL);
+   add_function("unpackHalf2x16",  _unpackHalf2x16(shader_packing_or_es3),  NULL);
+
+   F(length)
+   F(distance)
+   F(dot)
+
+   add_function("cross", _cross(glsl_type::vec3_type), NULL);
+
+   F(normalize)
+   add_function("ftransform", _ftransform(), NULL);
+   F(faceforward)
+   F(reflect)
+   F(refract)
+   // ...
+   add_function("matrixCompMult",
+                _matrixCompMult(glsl_type::mat2_type),
+                _matrixCompMult(glsl_type::mat3_type),
+                _matrixCompMult(glsl_type::mat4_type),
+                _matrixCompMult(glsl_type::mat2x3_type),
+                _matrixCompMult(glsl_type::mat2x4_type),
+                _matrixCompMult(glsl_type::mat3x2_type),
+                _matrixCompMult(glsl_type::mat3x4_type),
+                _matrixCompMult(glsl_type::mat4x2_type),
+                _matrixCompMult(glsl_type::mat4x3_type),
+                NULL);
+   add_function("outerProduct",
+                _outerProduct(glsl_type::mat2_type),
+                _outerProduct(glsl_type::mat3_type),
+                _outerProduct(glsl_type::mat4_type),
+                _outerProduct(glsl_type::mat2x3_type),
+                _outerProduct(glsl_type::mat2x4_type),
+                _outerProduct(glsl_type::mat3x2_type),
+                _outerProduct(glsl_type::mat3x4_type),
+                _outerProduct(glsl_type::mat4x2_type),
+                _outerProduct(glsl_type::mat4x3_type),
+                NULL);
+   add_function("determinant",
+                _determinant_mat2(),
+                _determinant_mat3(),
+                _determinant_mat4(),
+                NULL);
+   add_function("inverse",
+                _inverse_mat2(),
+                _inverse_mat3(),
+                _inverse_mat4(),
+                NULL);
+   add_function("transpose",
+                _transpose(glsl_type::mat2_type),
+                _transpose(glsl_type::mat3_type),
+                _transpose(glsl_type::mat4_type),
+                _transpose(glsl_type::mat2x3_type),
+                _transpose(glsl_type::mat2x4_type),
+                _transpose(glsl_type::mat3x2_type),
+                _transpose(glsl_type::mat3x4_type),
+                _transpose(glsl_type::mat4x2_type),
+                _transpose(glsl_type::mat4x3_type),
+                NULL);
+   FIU(lessThan)
+   FIU(lessThanEqual)
+   FIU(greaterThan)
+   FIU(greaterThanEqual)
+   FIUB(notEqual)
+   FIUB(equal)
+
+   add_function("any",
+                _any(glsl_type::bvec2_type),
+                _any(glsl_type::bvec3_type),
+                _any(glsl_type::bvec4_type),
+                NULL);
+
+   add_function("all",
+                _all(glsl_type::bvec2_type),
+                _all(glsl_type::bvec3_type),
+                _all(glsl_type::bvec4_type),
+                NULL);
+
+   add_function("not",
+                _not(glsl_type::bvec2_type),
+                _not(glsl_type::bvec3_type),
+                _not(glsl_type::bvec4_type),
+                NULL);
+
+   add_function("textureSize",
+                _textureSize(v130, glsl_type::int_type,   glsl_type::sampler1D_type),
+                _textureSize(v130, glsl_type::int_type,   glsl_type::isampler1D_type),
+                _textureSize(v130, glsl_type::int_type,   glsl_type::usampler1D_type),
+
+                _textureSize(v130, glsl_type::ivec2_type, glsl_type::sampler2D_type),
+                _textureSize(v130, glsl_type::ivec2_type, glsl_type::isampler2D_type),
+                _textureSize(v130, glsl_type::ivec2_type, glsl_type::usampler2D_type),
+
+                _textureSize(v130, glsl_type::ivec3_type, glsl_type::sampler3D_type),
+                _textureSize(v130, glsl_type::ivec3_type, glsl_type::isampler3D_type),
+                _textureSize(v130, glsl_type::ivec3_type, glsl_type::usampler3D_type),
+
+                _textureSize(v130, glsl_type::ivec2_type, glsl_type::samplerCube_type),
+                _textureSize(v130, glsl_type::ivec2_type, glsl_type::isamplerCube_type),
+                _textureSize(v130, glsl_type::ivec2_type, glsl_type::usamplerCube_type),
+
+                _textureSize(v130, glsl_type::int_type,   glsl_type::sampler1DShadow_type),
+                _textureSize(v130, glsl_type::ivec2_type, glsl_type::sampler2DShadow_type),
+                _textureSize(v130, glsl_type::ivec2_type, glsl_type::samplerCubeShadow_type),
+
+                _textureSize(v130, glsl_type::ivec2_type, glsl_type::sampler1DArray_type),
+                _textureSize(v130, glsl_type::ivec2_type, glsl_type::isampler1DArray_type),
+                _textureSize(v130, glsl_type::ivec2_type, glsl_type::usampler1DArray_type),
+                _textureSize(v130, glsl_type::ivec3_type, glsl_type::sampler2DArray_type),
+                _textureSize(v130, glsl_type::ivec3_type, glsl_type::isampler2DArray_type),
+                _textureSize(v130, glsl_type::ivec3_type, glsl_type::usampler2DArray_type),
+
+                _textureSize(v130, glsl_type::ivec2_type, glsl_type::sampler1DArrayShadow_type),
+                _textureSize(v130, glsl_type::ivec3_type, glsl_type::sampler2DArrayShadow_type),
+
+                _textureSize(texture_cube_map_array, glsl_type::ivec3_type, glsl_type::samplerCubeArray_type),
+                _textureSize(texture_cube_map_array, glsl_type::ivec3_type, glsl_type::isamplerCubeArray_type),
+                _textureSize(texture_cube_map_array, glsl_type::ivec3_type, glsl_type::usamplerCubeArray_type),
+                _textureSize(texture_cube_map_array, glsl_type::ivec3_type, glsl_type::samplerCubeArrayShadow_type),
+
+                _textureSize(v130, glsl_type::ivec2_type, glsl_type::sampler2DRect_type),
+                _textureSize(v130, glsl_type::ivec2_type, glsl_type::isampler2DRect_type),
+                _textureSize(v130, glsl_type::ivec2_type, glsl_type::usampler2DRect_type),
+                _textureSize(v130, glsl_type::ivec2_type, glsl_type::sampler2DRectShadow_type),
+
+                _textureSize(v140, glsl_type::int_type,   glsl_type::samplerBuffer_type),
+                _textureSize(v140, glsl_type::int_type,   glsl_type::isamplerBuffer_type),
+                _textureSize(v140, glsl_type::int_type,   glsl_type::usamplerBuffer_type),
+                _textureSize(texture_multisample, glsl_type::ivec2_type, glsl_type::sampler2DMS_type),
+                _textureSize(texture_multisample, glsl_type::ivec2_type, glsl_type::isampler2DMS_type),
+                _textureSize(texture_multisample, glsl_type::ivec2_type, glsl_type::usampler2DMS_type),
+
+                _textureSize(texture_multisample, glsl_type::ivec3_type, glsl_type::sampler2DMSArray_type),
+                _textureSize(texture_multisample, glsl_type::ivec3_type, glsl_type::isampler2DMSArray_type),
+                _textureSize(texture_multisample, glsl_type::ivec3_type, glsl_type::usampler2DMSArray_type),
+                NULL);
+
+   add_function("texture",
+                _texture(ir_tex, v130, glsl_type::vec4_type,  glsl_type::sampler1D_type,  1, glsl_type::float_type),
+                _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, 1, glsl_type::float_type),
+                _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, 1, glsl_type::float_type),
+
+                _texture(ir_tex, v130, glsl_type::vec4_type,  glsl_type::sampler2D_type,  2, glsl_type::vec2_type),
+                _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, 2, glsl_type::vec2_type),
+                _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, 2, glsl_type::vec2_type),
+
+                _texture(ir_tex, v130, glsl_type::vec4_type,  glsl_type::sampler3D_type,  3, glsl_type::vec3_type),
+                _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, 3, glsl_type::vec3_type),
+                _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, 3, glsl_type::vec3_type),
+
+                _texture(ir_tex, v130, glsl_type::vec4_type,  glsl_type::samplerCube_type,  3, glsl_type::vec3_type),
+                _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isamplerCube_type, 3, glsl_type::vec3_type),
+                _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usamplerCube_type, 3, glsl_type::vec3_type),
+
+                _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type,   1, glsl_type::vec3_type),
+                _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type,   2, glsl_type::vec3_type),
+                _texture(ir_tex, v130, glsl_type::float_type, glsl_type::samplerCubeShadow_type, 3, glsl_type::vec4_type),
+
+                _texture(ir_tex, v130, glsl_type::vec4_type,  glsl_type::sampler1DArray_type,  2, glsl_type::vec2_type),
+                _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler1DArray_type, 2, glsl_type::vec2_type),
+                _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler1DArray_type, 2, glsl_type::vec2_type),
+
+                _texture(ir_tex, v130, glsl_type::vec4_type,  glsl_type::sampler2DArray_type,  3, glsl_type::vec3_type),
+                _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, 3, glsl_type::vec3_type),
+                _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, 3, glsl_type::vec3_type),
+
+                _texture(ir_tex, texture_cube_map_array, glsl_type::vec4_type,  glsl_type::samplerCubeArray_type,  4, glsl_type::vec4_type),
+                _texture(ir_tex, texture_cube_map_array, glsl_type::ivec4_type, glsl_type::isamplerCubeArray_type, 4, glsl_type::vec4_type),
+                _texture(ir_tex, texture_cube_map_array, glsl_type::uvec4_type, glsl_type::usamplerCubeArray_type, 4, glsl_type::vec4_type),
+
+                _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler1DArrayShadow_type, 2, glsl_type::vec3_type),
+                _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler2DArrayShadow_type, 3, glsl_type::vec4_type),
+                /* samplerCubeArrayShadow is special; it has an extra parameter
+                 * for the shadow comparitor since there is no vec5 type.
+                 */
+                _textureCubeArrayShadow(),
+
+                _texture(ir_tex, v130, glsl_type::vec4_type,  glsl_type::sampler2DRect_type,  2, glsl_type::vec2_type),
+                _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, 2, glsl_type::vec2_type),
+                _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, 2, glsl_type::vec2_type),
+
+                _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler2DRectShadow_type, 2, glsl_type::vec3_type),
+
+                _texture(ir_txb, v130_fs_only, glsl_type::vec4_type,  glsl_type::sampler1D_type,  1, glsl_type::float_type),
+                _texture(ir_txb, v130_fs_only, glsl_type::ivec4_type, glsl_type::isampler1D_type, 1, glsl_type::float_type),
+                _texture(ir_txb, v130_fs_only, glsl_type::uvec4_type, glsl_type::usampler1D_type, 1, glsl_type::float_type),
+
+                _texture(ir_txb, v130_fs_only, glsl_type::vec4_type,  glsl_type::sampler2D_type,  2, glsl_type::vec2_type),
+                _texture(ir_txb, v130_fs_only, glsl_type::ivec4_type, glsl_type::isampler2D_type, 2, glsl_type::vec2_type),
+                _texture(ir_txb, v130_fs_only, glsl_type::uvec4_type, glsl_type::usampler2D_type, 2, glsl_type::vec2_type),
+
+                _texture(ir_txb, v130_fs_only, glsl_type::vec4_type,  glsl_type::sampler3D_type,  3, glsl_type::vec3_type),
+                _texture(ir_txb, v130_fs_only, glsl_type::ivec4_type, glsl_type::isampler3D_type, 3, glsl_type::vec3_type),
+                _texture(ir_txb, v130_fs_only, glsl_type::uvec4_type, glsl_type::usampler3D_type, 3, glsl_type::vec3_type),
+
+                _texture(ir_txb, v130_fs_only, glsl_type::vec4_type,  glsl_type::samplerCube_type,  3, glsl_type::vec3_type),
+                _texture(ir_txb, v130_fs_only, glsl_type::ivec4_type, glsl_type::isamplerCube_type, 3, glsl_type::vec3_type),
+                _texture(ir_txb, v130_fs_only, glsl_type::uvec4_type, glsl_type::usamplerCube_type, 3, glsl_type::vec3_type),
+
+                _texture(ir_txb, v130_fs_only, glsl_type::float_type, glsl_type::sampler1DShadow_type,   1, glsl_type::vec3_type),
+                _texture(ir_txb, v130_fs_only, glsl_type::float_type, glsl_type::sampler2DShadow_type,   2, glsl_type::vec3_type),
+                _texture(ir_txb, v130_fs_only, glsl_type::float_type, glsl_type::samplerCubeShadow_type, 3, glsl_type::vec4_type),
+
+                _texture(ir_txb, v130_fs_only, glsl_type::vec4_type,  glsl_type::sampler1DArray_type,  2, glsl_type::vec2_type),
+                _texture(ir_txb, v130_fs_only, glsl_type::ivec4_type, glsl_type::isampler1DArray_type, 2, glsl_type::vec2_type),
+                _texture(ir_txb, v130_fs_only, glsl_type::uvec4_type, glsl_type::usampler1DArray_type, 2, glsl_type::vec2_type),
+
+                _texture(ir_txb, v130_fs_only, glsl_type::vec4_type,  glsl_type::sampler2DArray_type,  3, glsl_type::vec3_type),
+                _texture(ir_txb, v130_fs_only, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, 3, glsl_type::vec3_type),
+                _texture(ir_txb, v130_fs_only, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, 3, glsl_type::vec3_type),
+
+                _texture(ir_txb, fs_texture_cube_map_array, glsl_type::vec4_type,  glsl_type::samplerCubeArray_type,  4, glsl_type::vec4_type),
+                _texture(ir_txb, fs_texture_cube_map_array, glsl_type::ivec4_type, glsl_type::isamplerCubeArray_type, 4, glsl_type::vec4_type),
+                _texture(ir_txb, fs_texture_cube_map_array, glsl_type::uvec4_type, glsl_type::usamplerCubeArray_type, 4, glsl_type::vec4_type),
+
+                _texture(ir_txb, v130_fs_only, glsl_type::float_type, glsl_type::sampler1DArrayShadow_type, 2, glsl_type::vec3_type),
+                NULL);
+
+   add_function("textureLod",
+                _texture(ir_txl, v130, glsl_type::vec4_type,  glsl_type::sampler1D_type,  1, glsl_type::float_type),
+                _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, 1, glsl_type::float_type),
+                _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, 1, glsl_type::float_type),
+
+                _texture(ir_txl, v130, glsl_type::vec4_type,  glsl_type::sampler2D_type,  2, glsl_type::vec2_type),
+                _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, 2, glsl_type::vec2_type),
+                _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, 2, glsl_type::vec2_type),
+
+                _texture(ir_txl, v130, glsl_type::vec4_type,  glsl_type::sampler3D_type,  3, glsl_type::vec3_type),
+                _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, 3, glsl_type::vec3_type),
+                _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, 3, glsl_type::vec3_type),
+
+                _texture(ir_txl, v130, glsl_type::vec4_type,  glsl_type::samplerCube_type,  3, glsl_type::vec3_type),
+                _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isamplerCube_type, 3, glsl_type::vec3_type),
+                _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usamplerCube_type, 3, glsl_type::vec3_type),
+
+                _texture(ir_txl, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type, 1, glsl_type::vec3_type),
+                _texture(ir_txl, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type, 2, glsl_type::vec3_type),
+
+                _texture(ir_txl, v130, glsl_type::vec4_type,  glsl_type::sampler1DArray_type,  2, glsl_type::vec2_type),
+                _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler1DArray_type, 2, glsl_type::vec2_type),
+                _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler1DArray_type, 2, glsl_type::vec2_type),
+
+                _texture(ir_txl, v130, glsl_type::vec4_type,  glsl_type::sampler2DArray_type,  3, glsl_type::vec3_type),
+                _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, 3, glsl_type::vec3_type),
+                _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, 3, glsl_type::vec3_type),
+
+                _texture(ir_txl, texture_cube_map_array, glsl_type::vec4_type,  glsl_type::samplerCubeArray_type,  4, glsl_type::vec4_type),
+                _texture(ir_txl, texture_cube_map_array, glsl_type::ivec4_type, glsl_type::isamplerCubeArray_type, 4, glsl_type::vec4_type),
+                _texture(ir_txl, texture_cube_map_array, glsl_type::uvec4_type, glsl_type::usamplerCubeArray_type, 4, glsl_type::vec4_type),
+
+                _texture(ir_txl, v130, glsl_type::float_type, glsl_type::sampler1DArrayShadow_type, 2, glsl_type::vec3_type),
+                NULL);
+
+   add_function("textureOffset",
+                _texture(ir_tex, v130, glsl_type::vec4_type,  glsl_type::sampler1D_type,  1, glsl_type::float_type, TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, 1, glsl_type::float_type, TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, 1, glsl_type::float_type, TEX_OFFSET),
+
+                _texture(ir_tex, v130, glsl_type::vec4_type,  glsl_type::sampler2D_type,  2, glsl_type::vec2_type, TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, 2, glsl_type::vec2_type, TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, 2, glsl_type::vec2_type, TEX_OFFSET),
+
+                _texture(ir_tex, v130, glsl_type::vec4_type,  glsl_type::sampler3D_type,  3, glsl_type::vec3_type, TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, 3, glsl_type::vec3_type, TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, 3, glsl_type::vec3_type, TEX_OFFSET),
+
+                _texture(ir_tex, v130, glsl_type::vec4_type,  glsl_type::sampler2DRect_type,  2, glsl_type::vec2_type, TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, 2, glsl_type::vec2_type, TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, 2, glsl_type::vec2_type, TEX_OFFSET),
+
+                _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler2DRectShadow_type, 2, glsl_type::vec3_type, TEX_OFFSET),
+
+                _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type, 1, glsl_type::vec3_type, TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type, 2, glsl_type::vec3_type, TEX_OFFSET),
+
+                _texture(ir_tex, v130, glsl_type::vec4_type,  glsl_type::sampler1DArray_type,  2, glsl_type::vec2_type, TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler1DArray_type, 2, glsl_type::vec2_type, TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler1DArray_type, 2, glsl_type::vec2_type, TEX_OFFSET),
+
+                _texture(ir_tex, v130, glsl_type::vec4_type,  glsl_type::sampler2DArray_type,  3, glsl_type::vec3_type, TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, 3, glsl_type::vec3_type, TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, 3, glsl_type::vec3_type, TEX_OFFSET),
+
+                _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler1DArrayShadow_type, 2, glsl_type::vec3_type, TEX_OFFSET),
+
+                _texture(ir_txb, v130_fs_only, glsl_type::vec4_type,  glsl_type::sampler1D_type,  1, glsl_type::float_type, TEX_OFFSET),
+                _texture(ir_txb, v130_fs_only, glsl_type::ivec4_type, glsl_type::isampler1D_type, 1, glsl_type::float_type, TEX_OFFSET),
+                _texture(ir_txb, v130_fs_only, glsl_type::uvec4_type, glsl_type::usampler1D_type, 1, glsl_type::float_type, TEX_OFFSET),
+
+                _texture(ir_txb, v130_fs_only, glsl_type::vec4_type,  glsl_type::sampler2D_type,  2, glsl_type::vec2_type, TEX_OFFSET),
+                _texture(ir_txb, v130_fs_only, glsl_type::ivec4_type, glsl_type::isampler2D_type, 2, glsl_type::vec2_type, TEX_OFFSET),
+                _texture(ir_txb, v130_fs_only, glsl_type::uvec4_type, glsl_type::usampler2D_type, 2, glsl_type::vec2_type, TEX_OFFSET),
+
+                _texture(ir_txb, v130_fs_only, glsl_type::vec4_type,  glsl_type::sampler3D_type,  3, glsl_type::vec3_type, TEX_OFFSET),
+                _texture(ir_txb, v130_fs_only, glsl_type::ivec4_type, glsl_type::isampler3D_type, 3, glsl_type::vec3_type, TEX_OFFSET),
+                _texture(ir_txb, v130_fs_only, glsl_type::uvec4_type, glsl_type::usampler3D_type, 3, glsl_type::vec3_type, TEX_OFFSET),
+
+                _texture(ir_txb, v130_fs_only, glsl_type::float_type, glsl_type::sampler1DShadow_type, 1, glsl_type::vec3_type, TEX_OFFSET),
+                _texture(ir_txb, v130_fs_only, glsl_type::float_type, glsl_type::sampler2DShadow_type, 2, glsl_type::vec3_type, TEX_OFFSET),
+
+                _texture(ir_txb, v130_fs_only, glsl_type::vec4_type,  glsl_type::sampler1DArray_type,  2, glsl_type::vec2_type, TEX_OFFSET),
+                _texture(ir_txb, v130_fs_only, glsl_type::ivec4_type, glsl_type::isampler1DArray_type, 2, glsl_type::vec2_type, TEX_OFFSET),
+                _texture(ir_txb, v130_fs_only, glsl_type::uvec4_type, glsl_type::usampler1DArray_type, 2, glsl_type::vec2_type, TEX_OFFSET),
+
+                _texture(ir_txb, v130_fs_only, glsl_type::vec4_type,  glsl_type::sampler2DArray_type,  3, glsl_type::vec3_type, TEX_OFFSET),
+                _texture(ir_txb, v130_fs_only, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, 3, glsl_type::vec3_type, TEX_OFFSET),
+                _texture(ir_txb, v130_fs_only, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, 3, glsl_type::vec3_type, TEX_OFFSET),
+
+                _texture(ir_txb, v130_fs_only, glsl_type::float_type, glsl_type::sampler1DArrayShadow_type, 2, glsl_type::vec3_type, TEX_OFFSET),
+                NULL);
+
+   add_function("textureProj",
+                _texture(ir_tex, v130, glsl_type::vec4_type,  glsl_type::sampler1D_type,  1, glsl_type::vec2_type, TEX_PROJECT),
+                _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, 1, glsl_type::vec2_type, TEX_PROJECT),
+                _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, 1, glsl_type::vec2_type, TEX_PROJECT),
+                _texture(ir_tex, v130, glsl_type::vec4_type,  glsl_type::sampler1D_type,  1, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, 1, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, 1, glsl_type::vec4_type, TEX_PROJECT),
+
+                _texture(ir_tex, v130, glsl_type::vec4_type,  glsl_type::sampler2D_type,  2, glsl_type::vec3_type, TEX_PROJECT),
+                _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, 2, glsl_type::vec3_type, TEX_PROJECT),
+                _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, 2, glsl_type::vec3_type, TEX_PROJECT),
+                _texture(ir_tex, v130, glsl_type::vec4_type,  glsl_type::sampler2D_type,  2, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+
+                _texture(ir_tex, v130, glsl_type::vec4_type,  glsl_type::sampler3D_type,  3, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, 3, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, 3, glsl_type::vec4_type, TEX_PROJECT),
+
+                _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type, 1, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+
+                _texture(ir_tex, v130, glsl_type::vec4_type,  glsl_type::sampler2DRect_type,  2, glsl_type::vec3_type, TEX_PROJECT),
+                _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, 2, glsl_type::vec3_type, TEX_PROJECT),
+                _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, 2, glsl_type::vec3_type, TEX_PROJECT),
+                _texture(ir_tex, v130, glsl_type::vec4_type,  glsl_type::sampler2DRect_type,  2, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+
+                _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler2DRectShadow_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+
+                _texture(ir_txb, v130, glsl_type::vec4_type,  glsl_type::sampler1D_type,  1, glsl_type::vec2_type, TEX_PROJECT),
+                _texture(ir_txb, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, 1, glsl_type::vec2_type, TEX_PROJECT),
+                _texture(ir_txb, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, 1, glsl_type::vec2_type, TEX_PROJECT),
+                _texture(ir_txb, v130, glsl_type::vec4_type,  glsl_type::sampler1D_type,  1, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txb, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, 1, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txb, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, 1, glsl_type::vec4_type, TEX_PROJECT),
+
+                _texture(ir_txb, v130, glsl_type::vec4_type,  glsl_type::sampler2D_type,  2, glsl_type::vec3_type, TEX_PROJECT),
+                _texture(ir_txb, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, 2, glsl_type::vec3_type, TEX_PROJECT),
+                _texture(ir_txb, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, 2, glsl_type::vec3_type, TEX_PROJECT),
+                _texture(ir_txb, v130, glsl_type::vec4_type,  glsl_type::sampler2D_type,  2, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txb, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txb, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+
+                _texture(ir_txb, v130, glsl_type::vec4_type,  glsl_type::sampler3D_type,  3, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txb, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, 3, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txb, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, 3, glsl_type::vec4_type, TEX_PROJECT),
+
+                _texture(ir_txb, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type, 1, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txb, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+                NULL);
+
+   add_function("texelFetch",
+                _texelFetch(v130, glsl_type::vec4_type,  glsl_type::sampler1D_type,  glsl_type::int_type),
+                _texelFetch(v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::int_type),
+                _texelFetch(v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::int_type),
+
+                _texelFetch(v130, glsl_type::vec4_type,  glsl_type::sampler2D_type,  glsl_type::ivec2_type),
+                _texelFetch(v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::ivec2_type),
+                _texelFetch(v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::ivec2_type),
+
+                _texelFetch(v130, glsl_type::vec4_type,  glsl_type::sampler3D_type,  glsl_type::ivec3_type),
+                _texelFetch(v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, glsl_type::ivec3_type),
+                _texelFetch(v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, glsl_type::ivec3_type),
+
+                _texelFetch(v130, glsl_type::vec4_type,  glsl_type::sampler2DRect_type,  glsl_type::ivec2_type),
+                _texelFetch(v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::ivec2_type),
+                _texelFetch(v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::ivec2_type),
+
+                _texelFetch(v130, glsl_type::vec4_type,  glsl_type::sampler1DArray_type,  glsl_type::ivec2_type),
+                _texelFetch(v130, glsl_type::ivec4_type, glsl_type::isampler1DArray_type, glsl_type::ivec2_type),
+                _texelFetch(v130, glsl_type::uvec4_type, glsl_type::usampler1DArray_type, glsl_type::ivec2_type),
+
+                _texelFetch(v130, glsl_type::vec4_type,  glsl_type::sampler2DArray_type,  glsl_type::ivec3_type),
+                _texelFetch(v130, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::ivec3_type),
+                _texelFetch(v130, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::ivec3_type),
+
+                _texelFetch(v140, glsl_type::vec4_type,  glsl_type::samplerBuffer_type,  glsl_type::int_type),
+                _texelFetch(v140, glsl_type::ivec4_type, glsl_type::isamplerBuffer_type, glsl_type::int_type),
+                _texelFetch(v140, glsl_type::uvec4_type, glsl_type::usamplerBuffer_type, glsl_type::int_type),
+
+                _texelFetch(texture_multisample, glsl_type::vec4_type,  glsl_type::sampler2DMS_type,  glsl_type::ivec2_type),
+                _texelFetch(texture_multisample, glsl_type::ivec4_type, glsl_type::isampler2DMS_type, glsl_type::ivec2_type),
+                _texelFetch(texture_multisample, glsl_type::uvec4_type, glsl_type::usampler2DMS_type, glsl_type::ivec2_type),
+
+                _texelFetch(texture_multisample, glsl_type::vec4_type,  glsl_type::sampler2DMSArray_type,  glsl_type::ivec3_type),
+                _texelFetch(texture_multisample, glsl_type::ivec4_type, glsl_type::isampler2DMSArray_type, glsl_type::ivec3_type),
+                _texelFetch(texture_multisample, glsl_type::uvec4_type, glsl_type::usampler2DMSArray_type, glsl_type::ivec3_type),
+                NULL);
+
+   add_function("texelFetchOffset",
+                _texelFetch(v130, glsl_type::vec4_type,  glsl_type::sampler1D_type,  glsl_type::int_type, glsl_type::int_type),
+                _texelFetch(v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::int_type, glsl_type::int_type),
+                _texelFetch(v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::int_type, glsl_type::int_type),
+
+                _texelFetch(v130, glsl_type::vec4_type,  glsl_type::sampler2D_type,  glsl_type::ivec2_type, glsl_type::ivec2_type),
+                _texelFetch(v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::ivec2_type, glsl_type::ivec2_type),
+                _texelFetch(v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::ivec2_type, glsl_type::ivec2_type),
+
+                _texelFetch(v130, glsl_type::vec4_type,  glsl_type::sampler3D_type,  glsl_type::ivec3_type, glsl_type::ivec3_type),
+                _texelFetch(v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, glsl_type::ivec3_type, glsl_type::ivec3_type),
+                _texelFetch(v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, glsl_type::ivec3_type, glsl_type::ivec3_type),
+
+                _texelFetch(v130, glsl_type::vec4_type,  glsl_type::sampler2DRect_type,  glsl_type::ivec2_type, glsl_type::ivec2_type),
+                _texelFetch(v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::ivec2_type, glsl_type::ivec2_type),
+                _texelFetch(v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::ivec2_type, glsl_type::ivec2_type),
+
+                _texelFetch(v130, glsl_type::vec4_type,  glsl_type::sampler1DArray_type,  glsl_type::ivec2_type, glsl_type::int_type),
+                _texelFetch(v130, glsl_type::ivec4_type, glsl_type::isampler1DArray_type, glsl_type::ivec2_type, glsl_type::int_type),
+                _texelFetch(v130, glsl_type::uvec4_type, glsl_type::usampler1DArray_type, glsl_type::ivec2_type, glsl_type::int_type),
+
+                _texelFetch(v130, glsl_type::vec4_type,  glsl_type::sampler2DArray_type,  glsl_type::ivec3_type, glsl_type::ivec2_type),
+                _texelFetch(v130, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::ivec3_type, glsl_type::ivec2_type),
+                _texelFetch(v130, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::ivec3_type, glsl_type::ivec2_type),
+
+                NULL);
+
+   add_function("textureProjOffset",
+                _texture(ir_tex, v130, glsl_type::vec4_type,  glsl_type::sampler1D_type,  1, glsl_type::vec2_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, 1, glsl_type::vec2_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, 1, glsl_type::vec2_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::vec4_type,  glsl_type::sampler1D_type,  1, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, 1, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, 1, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+
+                _texture(ir_tex, v130, glsl_type::vec4_type,  glsl_type::sampler2D_type,  2, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, 2, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, 2, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::vec4_type,  glsl_type::sampler2D_type,  2, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, 2, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, 2, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+
+                _texture(ir_tex, v130, glsl_type::vec4_type,  glsl_type::sampler3D_type,  3, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, 3, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, 3, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+
+                _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type, 1, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type, 2, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+
+                _texture(ir_tex, v130, glsl_type::vec4_type,  glsl_type::sampler2DRect_type,  2, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, 2, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, 2, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::vec4_type,  glsl_type::sampler2DRect_type,  2, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, 2, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, 2, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+
+                _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler2DRectShadow_type, 2, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+
+                _texture(ir_txb, v130, glsl_type::vec4_type,  glsl_type::sampler1D_type,  1, glsl_type::vec2_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txb, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, 1, glsl_type::vec2_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txb, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, 1, glsl_type::vec2_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txb, v130, glsl_type::vec4_type,  glsl_type::sampler1D_type,  1, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txb, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, 1, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txb, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, 1, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+
+                _texture(ir_txb, v130, glsl_type::vec4_type,  glsl_type::sampler2D_type,  2, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txb, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, 2, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txb, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, 2, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txb, v130, glsl_type::vec4_type,  glsl_type::sampler2D_type,  2, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txb, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, 2, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txb, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, 2, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+
+                _texture(ir_txb, v130, glsl_type::vec4_type,  glsl_type::sampler3D_type,  3, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txb, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, 3, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txb, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, 3, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+
+                _texture(ir_txb, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type, 1, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txb, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type, 2, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                NULL);
+
+   add_function("textureLodOffset",
+                _texture(ir_txl, v130, glsl_type::vec4_type,  glsl_type::sampler1D_type,  1, glsl_type::float_type, TEX_OFFSET),
+                _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, 1, glsl_type::float_type, TEX_OFFSET),
+                _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, 1, glsl_type::float_type, TEX_OFFSET),
+
+                _texture(ir_txl, v130, glsl_type::vec4_type,  glsl_type::sampler2D_type,  2, glsl_type::vec2_type, TEX_OFFSET),
+                _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, 2, glsl_type::vec2_type, TEX_OFFSET),
+                _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, 2, glsl_type::vec2_type, TEX_OFFSET),
+
+                _texture(ir_txl, v130, glsl_type::vec4_type,  glsl_type::sampler3D_type,  3, glsl_type::vec3_type, TEX_OFFSET),
+                _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, 3, glsl_type::vec3_type, TEX_OFFSET),
+                _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, 3, glsl_type::vec3_type, TEX_OFFSET),
+
+                _texture(ir_txl, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type, 1, glsl_type::vec3_type, TEX_OFFSET),
+                _texture(ir_txl, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type, 2, glsl_type::vec3_type, TEX_OFFSET),
+
+                _texture(ir_txl, v130, glsl_type::vec4_type,  glsl_type::sampler1DArray_type,  2, glsl_type::vec2_type, TEX_OFFSET),
+                _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler1DArray_type, 2, glsl_type::vec2_type, TEX_OFFSET),
+                _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler1DArray_type, 2, glsl_type::vec2_type, TEX_OFFSET),
+
+                _texture(ir_txl, v130, glsl_type::vec4_type,  glsl_type::sampler2DArray_type,  3, glsl_type::vec3_type, TEX_OFFSET),
+                _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, 3, glsl_type::vec3_type, TEX_OFFSET),
+                _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, 3, glsl_type::vec3_type, TEX_OFFSET),
+
+                _texture(ir_txl, v130, glsl_type::float_type, glsl_type::sampler1DArrayShadow_type, 2, glsl_type::vec3_type, TEX_OFFSET),
+                NULL);
+
+   add_function("textureProjLod",
+                _texture(ir_txl, v130, glsl_type::vec4_type,  glsl_type::sampler1D_type,  1, glsl_type::vec2_type, TEX_PROJECT),
+                _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, 1, glsl_type::vec2_type, TEX_PROJECT),
+                _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, 1, glsl_type::vec2_type, TEX_PROJECT),
+                _texture(ir_txl, v130, glsl_type::vec4_type,  glsl_type::sampler1D_type,  1, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, 1, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, 1, glsl_type::vec4_type, TEX_PROJECT),
+
+                _texture(ir_txl, v130, glsl_type::vec4_type,  glsl_type::sampler2D_type,  2, glsl_type::vec3_type, TEX_PROJECT),
+                _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, 2, glsl_type::vec3_type, TEX_PROJECT),
+                _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, 2, glsl_type::vec3_type, TEX_PROJECT),
+                _texture(ir_txl, v130, glsl_type::vec4_type,  glsl_type::sampler2D_type,  2, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+
+                _texture(ir_txl, v130, glsl_type::vec4_type,  glsl_type::sampler3D_type,  3, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, 3, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, 3, glsl_type::vec4_type, TEX_PROJECT),
+
+                _texture(ir_txl, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type, 1, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txl, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+                NULL);
+
+   add_function("textureProjLodOffset",
+                _texture(ir_txl, v130, glsl_type::vec4_type,  glsl_type::sampler1D_type,  1, glsl_type::vec2_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, 1, glsl_type::vec2_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, 1, glsl_type::vec2_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txl, v130, glsl_type::vec4_type,  glsl_type::sampler1D_type,  1, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, 1, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, 1, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+
+                _texture(ir_txl, v130, glsl_type::vec4_type,  glsl_type::sampler2D_type,  2, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, 2, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, 2, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txl, v130, glsl_type::vec4_type,  glsl_type::sampler2D_type,  2, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, 2, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, 2, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+
+                _texture(ir_txl, v130, glsl_type::vec4_type,  glsl_type::sampler3D_type,  3, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, 3, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, 3, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+
+                _texture(ir_txl, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type, 1, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txl, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type, 2, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                NULL);
+
+   add_function("textureGrad",
+                _texture(ir_txd, v130, glsl_type::vec4_type,  glsl_type::sampler1D_type,  1, glsl_type::float_type),
+                _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, 1, glsl_type::float_type),
+                _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, 1, glsl_type::float_type),
+
+                _texture(ir_txd, v130, glsl_type::vec4_type,  glsl_type::sampler2D_type,  2, glsl_type::vec2_type),
+                _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, 2, glsl_type::vec2_type),
+                _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, 2, glsl_type::vec2_type),
+
+                _texture(ir_txd, v130, glsl_type::vec4_type,  glsl_type::sampler3D_type,  3, glsl_type::vec3_type),
+                _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, 3, glsl_type::vec3_type),
+                _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, 3, glsl_type::vec3_type),
+
+                _texture(ir_txd, v130, glsl_type::vec4_type,  glsl_type::samplerCube_type,  3, glsl_type::vec3_type),
+                _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isamplerCube_type, 3, glsl_type::vec3_type),
+                _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usamplerCube_type, 3, glsl_type::vec3_type),
+
+                _texture(ir_txd, v130, glsl_type::vec4_type,  glsl_type::sampler2DRect_type,  2, glsl_type::vec2_type),
+                _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, 2, glsl_type::vec2_type),
+                _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, 2, glsl_type::vec2_type),
+
+                _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler2DRectShadow_type, 2, glsl_type::vec3_type),
+
+                _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type,   1, glsl_type::vec3_type),
+                _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type,   2, glsl_type::vec3_type),
+                _texture(ir_txd, v130, glsl_type::float_type, glsl_type::samplerCubeShadow_type, 3, glsl_type::vec4_type),
+
+                _texture(ir_txd, v130, glsl_type::vec4_type,  glsl_type::sampler1DArray_type,  2, glsl_type::vec2_type),
+                _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler1DArray_type, 2, glsl_type::vec2_type),
+                _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler1DArray_type, 2, glsl_type::vec2_type),
+
+                _texture(ir_txd, v130, glsl_type::vec4_type,  glsl_type::sampler2DArray_type,  3, glsl_type::vec3_type),
+                _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, 3, glsl_type::vec3_type),
+                _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, 3, glsl_type::vec3_type),
+
+                _texture(ir_txd, texture_cube_map_array, glsl_type::vec4_type,  glsl_type::samplerCubeArray_type,  4, glsl_type::vec4_type),
+                _texture(ir_txd, texture_cube_map_array, glsl_type::ivec4_type, glsl_type::isamplerCubeArray_type, 4, glsl_type::vec4_type),
+                _texture(ir_txd, texture_cube_map_array, glsl_type::uvec4_type, glsl_type::usamplerCubeArray_type, 4, glsl_type::vec4_type),
+
+                _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler1DArrayShadow_type, 2, glsl_type::vec3_type),
+                _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler2DArrayShadow_type, 3, glsl_type::vec4_type),
+                NULL);
+
+   add_function("textureGradOffset",
+                _texture(ir_txd, v130, glsl_type::vec4_type,  glsl_type::sampler1D_type,  1, glsl_type::float_type, TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, 1, glsl_type::float_type, TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, 1, glsl_type::float_type, TEX_OFFSET),
+
+                _texture(ir_txd, v130, glsl_type::vec4_type,  glsl_type::sampler2D_type,  2, glsl_type::vec2_type, TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, 2, glsl_type::vec2_type, TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, 2, glsl_type::vec2_type, TEX_OFFSET),
+
+                _texture(ir_txd, v130, glsl_type::vec4_type,  glsl_type::sampler3D_type,  3, glsl_type::vec3_type, TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, 3, glsl_type::vec3_type, TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, 3, glsl_type::vec3_type, TEX_OFFSET),
+
+                _texture(ir_txd, v130, glsl_type::vec4_type,  glsl_type::sampler2DRect_type,  2, glsl_type::vec2_type, TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, 2, glsl_type::vec2_type, TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, 2, glsl_type::vec2_type, TEX_OFFSET),
+
+                _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler2DRectShadow_type, 2, glsl_type::vec3_type, TEX_OFFSET),
+
+                _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type, 1, glsl_type::vec3_type, TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type, 2, glsl_type::vec3_type, TEX_OFFSET),
+
+                _texture(ir_txd, v130, glsl_type::vec4_type,  glsl_type::sampler1DArray_type,  2, glsl_type::vec2_type, TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler1DArray_type, 2, glsl_type::vec2_type, TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler1DArray_type, 2, glsl_type::vec2_type, TEX_OFFSET),
+
+                _texture(ir_txd, v130, glsl_type::vec4_type,  glsl_type::sampler2DArray_type,  3, glsl_type::vec3_type, TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, 3, glsl_type::vec3_type, TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, 3, glsl_type::vec3_type, TEX_OFFSET),
+
+                _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler1DArrayShadow_type, 2, glsl_type::vec3_type, TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler2DArrayShadow_type, 3, glsl_type::vec4_type, TEX_OFFSET),
+                NULL);
+
+   add_function("textureProjGrad",
+                _texture(ir_txd, v130, glsl_type::vec4_type,  glsl_type::sampler1D_type,  1, glsl_type::vec2_type, TEX_PROJECT),
+                _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, 1, glsl_type::vec2_type, TEX_PROJECT),
+                _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, 1, glsl_type::vec2_type, TEX_PROJECT),
+                _texture(ir_txd, v130, glsl_type::vec4_type,  glsl_type::sampler1D_type,  1, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, 1, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, 1, glsl_type::vec4_type, TEX_PROJECT),
+
+                _texture(ir_txd, v130, glsl_type::vec4_type,  glsl_type::sampler2D_type,  2, glsl_type::vec3_type, TEX_PROJECT),
+                _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, 2, glsl_type::vec3_type, TEX_PROJECT),
+                _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, 2, glsl_type::vec3_type, TEX_PROJECT),
+                _texture(ir_txd, v130, glsl_type::vec4_type,  glsl_type::sampler2D_type,  2, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+
+                _texture(ir_txd, v130, glsl_type::vec4_type,  glsl_type::sampler3D_type,  3, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, 3, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, 3, glsl_type::vec4_type, TEX_PROJECT),
+
+                _texture(ir_txd, v130, glsl_type::vec4_type,  glsl_type::sampler2DRect_type,  2, glsl_type::vec3_type, TEX_PROJECT),
+                _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, 2, glsl_type::vec3_type, TEX_PROJECT),
+                _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, 2, glsl_type::vec3_type, TEX_PROJECT),
+                _texture(ir_txd, v130, glsl_type::vec4_type,  glsl_type::sampler2DRect_type,  2, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+
+                _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler2DRectShadow_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+
+                _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type, 1, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+                NULL);
+
+   add_function("textureProjGradOffset",
+                _texture(ir_txd, v130, glsl_type::vec4_type,  glsl_type::sampler1D_type,  1, glsl_type::vec2_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, 1, glsl_type::vec2_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, 1, glsl_type::vec2_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::vec4_type,  glsl_type::sampler1D_type,  1, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, 1, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, 1, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+
+                _texture(ir_txd, v130, glsl_type::vec4_type,  glsl_type::sampler2D_type,  2, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, 2, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, 2, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::vec4_type,  glsl_type::sampler2D_type,  2, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, 2, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, 2, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+
+                _texture(ir_txd, v130, glsl_type::vec4_type,  glsl_type::sampler3D_type,  3, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, 3, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, 3, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+
+                _texture(ir_txd, v130, glsl_type::vec4_type,  glsl_type::sampler2DRect_type,  2, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, 2, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, 2, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::vec4_type,  glsl_type::sampler2DRect_type,  2, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, 2, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, 2, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+
+                _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler2DRectShadow_type, 2, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+
+                _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type, 1, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type, 2, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET),
+                NULL);
+
+   add_function("EmitVertex",   _EmitVertex(),   NULL);
+   add_function("EndPrimitive", _EndPrimitive(), NULL);
+
+   add_function("textureQueryLOD",
+                _textureQueryLod(glsl_type::sampler1D_type,  glsl_type::float_type),
+                _textureQueryLod(glsl_type::isampler1D_type, glsl_type::float_type),
+                _textureQueryLod(glsl_type::usampler1D_type, glsl_type::float_type),
+
+                _textureQueryLod(glsl_type::sampler2D_type,  glsl_type::vec2_type),
+                _textureQueryLod(glsl_type::isampler2D_type, glsl_type::vec2_type),
+                _textureQueryLod(glsl_type::usampler2D_type, glsl_type::vec2_type),
+
+                _textureQueryLod(glsl_type::sampler3D_type,  glsl_type::vec3_type),
+                _textureQueryLod(glsl_type::isampler3D_type, glsl_type::vec3_type),
+                _textureQueryLod(glsl_type::usampler3D_type, glsl_type::vec3_type),
+
+                _textureQueryLod(glsl_type::samplerCube_type,  glsl_type::vec3_type),
+                _textureQueryLod(glsl_type::isamplerCube_type, glsl_type::vec3_type),
+                _textureQueryLod(glsl_type::usamplerCube_type, glsl_type::vec3_type),
+
+                _textureQueryLod(glsl_type::sampler1DArray_type,  glsl_type::float_type),
+                _textureQueryLod(glsl_type::isampler1DArray_type, glsl_type::float_type),
+                _textureQueryLod(glsl_type::usampler1DArray_type, glsl_type::float_type),
+
+                _textureQueryLod(glsl_type::sampler2DArray_type,  glsl_type::vec2_type),
+                _textureQueryLod(glsl_type::isampler2DArray_type, glsl_type::vec2_type),
+                _textureQueryLod(glsl_type::usampler2DArray_type, glsl_type::vec2_type),
+
+                _textureQueryLod(glsl_type::samplerCubeArray_type,  glsl_type::vec3_type),
+                _textureQueryLod(glsl_type::isamplerCubeArray_type, glsl_type::vec3_type),
+                _textureQueryLod(glsl_type::usamplerCubeArray_type, glsl_type::vec3_type),
+
+                _textureQueryLod(glsl_type::sampler1DShadow_type, glsl_type::float_type),
+                _textureQueryLod(glsl_type::sampler2DShadow_type, glsl_type::vec2_type),
+                _textureQueryLod(glsl_type::samplerCubeShadow_type, glsl_type::vec3_type),
+                _textureQueryLod(glsl_type::sampler1DArrayShadow_type, glsl_type::float_type),
+                _textureQueryLod(glsl_type::sampler2DArrayShadow_type, glsl_type::vec2_type),
+                _textureQueryLod(glsl_type::samplerCubeArrayShadow_type, glsl_type::vec3_type),
+                NULL);
+
+   add_function("texture1D",
+                _texture(ir_tex, v110,         glsl_type::vec4_type,  glsl_type::sampler1D_type, 1, glsl_type::float_type),
+                _texture(ir_txb, v110_fs_only, glsl_type::vec4_type,  glsl_type::sampler1D_type, 1, glsl_type::float_type),
+                NULL);
+
+   add_function("texture1DArray",
+                _texture(ir_tex, texture_array,    glsl_type::vec4_type, glsl_type::sampler1DArray_type, 2, glsl_type::vec2_type),
+                _texture(ir_txb, fs_texture_array, glsl_type::vec4_type, glsl_type::sampler1DArray_type, 2, glsl_type::vec2_type),
+                NULL);
+
+   add_function("texture1DProj",
+                _texture(ir_tex, v110,         glsl_type::vec4_type,  glsl_type::sampler1D_type, 1, glsl_type::vec2_type, TEX_PROJECT),
+                _texture(ir_tex, v110,         glsl_type::vec4_type,  glsl_type::sampler1D_type, 1, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txb, v110_fs_only, glsl_type::vec4_type,  glsl_type::sampler1D_type, 1, glsl_type::vec2_type, TEX_PROJECT),
+                _texture(ir_txb, v110_fs_only, glsl_type::vec4_type,  glsl_type::sampler1D_type, 1, glsl_type::vec4_type, TEX_PROJECT),
+                NULL);
+
+   add_function("texture1DLod",
+                _texture(ir_txl, tex1d_lod, glsl_type::vec4_type,  glsl_type::sampler1D_type, 1, glsl_type::float_type),
+                NULL);
+
+   add_function("texture1DArrayLod",
+                _texture(ir_txl, vs_texture_array, glsl_type::vec4_type, glsl_type::sampler1DArray_type, 2, glsl_type::vec2_type),
+                NULL);
+
+   add_function("texture1DProjLod",
+                _texture(ir_txl, tex1d_lod, glsl_type::vec4_type,  glsl_type::sampler1D_type, 1, glsl_type::vec2_type, TEX_PROJECT),
+                _texture(ir_txl, tex1d_lod, glsl_type::vec4_type,  glsl_type::sampler1D_type, 1, glsl_type::vec4_type, TEX_PROJECT),
+                NULL);
+
+   add_function("texture2D",
+                _texture(ir_tex, always_available, glsl_type::vec4_type,  glsl_type::sampler2D_type, 2, glsl_type::vec2_type),
+                _texture(ir_txb, fs_only,          glsl_type::vec4_type,  glsl_type::sampler2D_type, 2, glsl_type::vec2_type),
+                _texture(ir_tex, texture_external, glsl_type::vec4_type,  glsl_type::samplerExternalOES_type, 2, glsl_type::vec2_type),
+                NULL);
+
+   add_function("texture2DArray",
+                _texture(ir_tex, texture_array,    glsl_type::vec4_type, glsl_type::sampler2DArray_type, 3, glsl_type::vec3_type),
+                _texture(ir_txb, fs_texture_array, glsl_type::vec4_type, glsl_type::sampler2DArray_type, 3, glsl_type::vec3_type),
+                NULL);
+
+   add_function("texture2DProj",
+                _texture(ir_tex, always_available, glsl_type::vec4_type,  glsl_type::sampler2D_type, 2, glsl_type::vec3_type, TEX_PROJECT),
+                _texture(ir_tex, always_available, glsl_type::vec4_type,  glsl_type::sampler2D_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txb, fs_only,          glsl_type::vec4_type,  glsl_type::sampler2D_type, 2, glsl_type::vec3_type, TEX_PROJECT),
+                _texture(ir_txb, fs_only,          glsl_type::vec4_type,  glsl_type::sampler2D_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_tex, texture_external, glsl_type::vec4_type,  glsl_type::samplerExternalOES_type, 2, glsl_type::vec3_type, TEX_PROJECT),
+                _texture(ir_tex, texture_external, glsl_type::vec4_type,  glsl_type::samplerExternalOES_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+                NULL);
+
+   add_function("texture2DLod",
+                _texture(ir_txl, lod_exists_in_stage, glsl_type::vec4_type,  glsl_type::sampler2D_type, 2, glsl_type::vec2_type),
+                NULL);
+
+   add_function("texture2DArrayLod",
+                _texture(ir_txl, vs_texture_array, glsl_type::vec4_type, glsl_type::sampler2DArray_type, 3, glsl_type::vec3_type),
+                NULL);
+
+   add_function("texture2DProjLod",
+                _texture(ir_txl, v110_lod, glsl_type::vec4_type,  glsl_type::sampler2D_type, 2, glsl_type::vec3_type, TEX_PROJECT),
+                _texture(ir_txl, v110_lod, glsl_type::vec4_type,  glsl_type::sampler2D_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+                NULL);
+
+   add_function("texture3D",
+                _texture(ir_tex, tex3d,    glsl_type::vec4_type,  glsl_type::sampler3D_type, 3, glsl_type::vec3_type),
+                _texture(ir_txb, fs_tex3d, glsl_type::vec4_type,  glsl_type::sampler3D_type, 3, glsl_type::vec3_type),
+                NULL);
+
+   add_function("texture3DProj",
+                _texture(ir_tex, tex3d,    glsl_type::vec4_type,  glsl_type::sampler3D_type, 3, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txb, fs_tex3d, glsl_type::vec4_type,  glsl_type::sampler3D_type, 3, glsl_type::vec4_type, TEX_PROJECT),
+                NULL);
+
+   add_function("texture3DLod",
+                _texture(ir_txl, tex3d_lod, glsl_type::vec4_type,  glsl_type::sampler3D_type, 3, glsl_type::vec3_type),
+                NULL);
+
+   add_function("texture3DProjLod",
+                _texture(ir_txl, tex3d_lod, glsl_type::vec4_type,  glsl_type::sampler3D_type, 3, glsl_type::vec4_type, TEX_PROJECT),
+                NULL);
+
+   add_function("textureCube",
+                _texture(ir_tex, always_available, glsl_type::vec4_type,  glsl_type::samplerCube_type, 3, glsl_type::vec3_type),
+                _texture(ir_txb, fs_only,          glsl_type::vec4_type,  glsl_type::samplerCube_type, 3, glsl_type::vec3_type),
+                NULL);
+
+   add_function("textureCubeLod",
+                _texture(ir_txl, v110_lod, glsl_type::vec4_type,  glsl_type::samplerCube_type, 3, glsl_type::vec3_type),
+                NULL);
+
+   add_function("texture2DRect",
+                _texture(ir_tex, texture_rectangle, glsl_type::vec4_type,  glsl_type::sampler2DRect_type, 2, glsl_type::vec2_type),
+                NULL);
+
+   add_function("texture2DRectProj",
+                _texture(ir_tex, texture_rectangle, glsl_type::vec4_type,  glsl_type::sampler2DRect_type, 2, glsl_type::vec3_type, TEX_PROJECT),
+                _texture(ir_tex, texture_rectangle, glsl_type::vec4_type,  glsl_type::sampler2DRect_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+                NULL);
+
+   add_function("shadow1D",
+                _texture(ir_tex, v110,         glsl_type::vec4_type,  glsl_type::sampler1DShadow_type, 1, glsl_type::vec3_type),
+                _texture(ir_txb, v110_fs_only, glsl_type::vec4_type,  glsl_type::sampler1DShadow_type, 1, glsl_type::vec3_type),
+                NULL);
+
+   add_function("shadow1DArray",
+                _texture(ir_tex, texture_array,    glsl_type::vec4_type,  glsl_type::sampler1DArrayShadow_type, 2, glsl_type::vec3_type),
+                _texture(ir_txb, fs_texture_array, glsl_type::vec4_type,  glsl_type::sampler1DArrayShadow_type, 2, glsl_type::vec3_type),
+                NULL);
+
+   add_function("shadow2D",
+                _texture(ir_tex, v110,         glsl_type::vec4_type,  glsl_type::sampler2DShadow_type, 2, glsl_type::vec3_type),
+                _texture(ir_txb, v110_fs_only, glsl_type::vec4_type,  glsl_type::sampler2DShadow_type, 2, glsl_type::vec3_type),
+                NULL);
+
+   add_function("shadow2DArray",
+                _texture(ir_tex, texture_array,    glsl_type::vec4_type,  glsl_type::sampler2DArrayShadow_type, 3, glsl_type::vec4_type),
+                _texture(ir_txb, fs_texture_array, glsl_type::vec4_type,  glsl_type::sampler2DArrayShadow_type, 3, glsl_type::vec4_type),
+                NULL);
+
+   add_function("shadow1DProj",
+                _texture(ir_tex, v110,         glsl_type::vec4_type,  glsl_type::sampler1DShadow_type, 1, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txb, v110_fs_only, glsl_type::vec4_type,  glsl_type::sampler1DShadow_type, 1, glsl_type::vec4_type, TEX_PROJECT),
+                NULL);
+
+   add_function("shadow2DProj",
+                _texture(ir_tex, v110,         glsl_type::vec4_type,  glsl_type::sampler2DShadow_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+                _texture(ir_txb, v110_fs_only, glsl_type::vec4_type,  glsl_type::sampler2DShadow_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+                NULL);
+
+   add_function("shadow1DLod",
+                _texture(ir_txl, v110_lod, glsl_type::vec4_type,  glsl_type::sampler1DShadow_type, 1, glsl_type::vec3_type),
+                NULL);
+
+   add_function("shadow2DLod",
+                _texture(ir_txl, v110_lod, glsl_type::vec4_type,  glsl_type::sampler2DShadow_type, 2, glsl_type::vec3_type),
+                NULL);
+
+   add_function("shadow1DArrayLod",
+                _texture(ir_txl, vs_texture_array, glsl_type::vec4_type, glsl_type::sampler1DArrayShadow_type, 2, glsl_type::vec3_type),
+                NULL);
+
+   add_function("shadow1DProjLod",
+                _texture(ir_txl, v110_lod, glsl_type::vec4_type,  glsl_type::sampler1DShadow_type, 1, glsl_type::vec4_type, TEX_PROJECT),
+                NULL);
+
+   add_function("shadow2DProjLod",
+                _texture(ir_txl, v110_lod, glsl_type::vec4_type,  glsl_type::sampler2DShadow_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+                NULL);
+
+   add_function("shadow2DRect",
+                _texture(ir_tex, texture_rectangle, glsl_type::vec4_type,  glsl_type::sampler2DRectShadow_type, 2, glsl_type::vec3_type),
+                NULL);
+
+   add_function("shadow2DRectProj",
+                _texture(ir_tex, texture_rectangle, glsl_type::vec4_type,  glsl_type::sampler2DRectShadow_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+                NULL);
+
+   add_function("texture1DGradARB",
+                _texture(ir_txd, shader_texture_lod, glsl_type::vec4_type,  glsl_type::sampler1D_type, 1, glsl_type::float_type),
+                NULL);
+
+   add_function("texture1DProjGradARB",
+                _texture(ir_txd, shader_texture_lod, glsl_type::vec4_type,  glsl_type::sampler1D_type, 1, glsl_type::vec2_type, TEX_PROJECT),
+                _texture(ir_txd, shader_texture_lod, glsl_type::vec4_type,  glsl_type::sampler1D_type, 1, glsl_type::vec4_type, TEX_PROJECT),
+                NULL);
+
+   add_function("texture2DGradARB",
+                _texture(ir_txd, shader_texture_lod, glsl_type::vec4_type,  glsl_type::sampler2D_type, 2, glsl_type::vec2_type),
+                NULL);
+
+   add_function("texture2DProjGradARB",
+                _texture(ir_txd, shader_texture_lod, glsl_type::vec4_type,  glsl_type::sampler2D_type, 2, glsl_type::vec3_type, TEX_PROJECT),
+                _texture(ir_txd, shader_texture_lod, glsl_type::vec4_type,  glsl_type::sampler2D_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+                NULL);
+
+   add_function("texture3DGradARB",
+                _texture(ir_txd, shader_texture_lod, glsl_type::vec4_type,  glsl_type::sampler3D_type, 3, glsl_type::vec3_type),
+                NULL);
+
+   add_function("texture3DProjGradARB",
+                _texture(ir_txd, shader_texture_lod, glsl_type::vec4_type,  glsl_type::sampler3D_type, 3, glsl_type::vec4_type, TEX_PROJECT),
+                NULL);
+
+   add_function("textureCubeGradARB",
+                _texture(ir_txd, shader_texture_lod, glsl_type::vec4_type,  glsl_type::samplerCube_type, 3, glsl_type::vec3_type),
+                NULL);
+
+   add_function("shadow1DGradARB",
+                _texture(ir_txd, shader_texture_lod, glsl_type::vec4_type,  glsl_type::sampler1DShadow_type, 1, glsl_type::vec3_type),
+                NULL);
+
+   add_function("shadow1DProjGradARB",
+                _texture(ir_txd, shader_texture_lod, glsl_type::vec4_type,  glsl_type::sampler1DShadow_type, 1, glsl_type::vec4_type, TEX_PROJECT),
+                NULL);
+
+   add_function("shadow2DGradARB",
+                _texture(ir_txd, shader_texture_lod, glsl_type::vec4_type,  glsl_type::sampler2DShadow_type, 2, glsl_type::vec3_type),
+                NULL);
+
+   add_function("shadow2DProjGradARB",
+                _texture(ir_txd, shader_texture_lod, glsl_type::vec4_type,  glsl_type::sampler2DShadow_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+                NULL);
+
+   add_function("texture2DRectGradARB",
+                _texture(ir_txd, shader_texture_lod_and_rect, glsl_type::vec4_type,  glsl_type::sampler2DRect_type, 2, glsl_type::vec2_type),
+                NULL);
+
+   add_function("texture2DRectProjGradARB",
+                _texture(ir_txd, shader_texture_lod_and_rect, glsl_type::vec4_type,  glsl_type::sampler2DRect_type, 2, glsl_type::vec3_type, TEX_PROJECT),
+                _texture(ir_txd, shader_texture_lod_and_rect, glsl_type::vec4_type,  glsl_type::sampler2DRect_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+                NULL);
+
+   add_function("shadow2DRectGradARB",
+                _texture(ir_txd, shader_texture_lod_and_rect, glsl_type::vec4_type,  glsl_type::sampler2DRectShadow_type, 2, glsl_type::vec3_type),
+                NULL);
+
+   add_function("shadow2DRectProjGradARB",
+                _texture(ir_txd, shader_texture_lod_and_rect, glsl_type::vec4_type,  glsl_type::sampler2DRectShadow_type, 2, glsl_type::vec4_type, TEX_PROJECT),
+                NULL);
+
+   F(dFdx)
+   F(dFdy)
+   F(fwidth)
+   F(noise1)
+   F(noise2)
+   F(noise3)
+   F(noise4)
+
+   IU(bitfieldExtract)
+   IU(bitfieldInsert)
+   IU(bitfieldReverse)
+   IU(bitCount)
+   IU(findLSB)
+   IU(findMSB)
+   F(fma)
+#undef F
+#undef FI
+#undef FIU
+#undef FIUB
+#undef FIU2_MIXED
+}
+
+void
+builtin_builder::add_function(const char *name, ...)
+{
+   va_list ap;
+
+   ir_function *f = new(mem_ctx) ir_function(name);
+
+   va_start(ap, name);
+   while (true) {
+      ir_function_signature *sig = va_arg(ap, ir_function_signature *);
+      if (sig == NULL)
+         break;
+
+      sig->is_defined = true;
+
+      if (false) {
+         exec_list stuff;
+         stuff.push_tail(sig);
+         validate_ir_tree(&stuff);
+      }
+
+      f->add_signature(sig);
+   }
+
+   shader->symbols->add_function(f);
+}
+
+ir_variable *
+builtin_builder::in_var(const glsl_type *type, const char *name)
+{
+   return new(mem_ctx) ir_variable(type, name, ir_var_function_in);
+}
+
+ir_variable *
+builtin_builder::out_var(const glsl_type *type, const char *name)
+{
+   return new(mem_ctx) ir_variable(type, name, ir_var_function_out);
+}
+
+ir_constant *
+builtin_builder::imm(float f)
+{
+   return new(mem_ctx) ir_constant(f);
+}
+
+ir_constant *
+builtin_builder::imm(int i)
+{
+   return new(mem_ctx) ir_constant(i);
+}
+
+ir_constant *
+builtin_builder::imm(unsigned u)
+{
+   return new(mem_ctx) ir_constant(u);
+}
+
+ir_constant *
+builtin_builder::imm(const glsl_type *type, const ir_constant_data &data)
+{
+   return new(mem_ctx) ir_constant(type, &data);
+}
+
+ir_dereference_variable *
+builtin_builder::var_ref(ir_variable *var)
+{
+   return new(mem_ctx) ir_dereference_variable(var);
+}
+
+ir_dereference_array *
+builtin_builder::array_ref(ir_variable *var, int idx)
+{
+   return new(mem_ctx) ir_dereference_array(var, imm(idx));
+}
+
+/** Return an element of a matrix */
+ir_swizzle *
+builtin_builder::matrix_elt(ir_variable *var, int column, int row)
+{
+   return swizzle(array_ref(var, column), row, 1);
+}
+
+/**
+ * Implementations of built-in functions:
+ *  @{
+ */
+ir_function_signature *
+builtin_builder::new_sig(const glsl_type *return_type,
+                         builtin_available_predicate avail,
+                         int num_params,
+                         ...)
+{
+   va_list ap;
+
+   ir_function_signature *sig =
+      new(mem_ctx) ir_function_signature(return_type, avail);
+
+   exec_list plist;
+   va_start(ap, num_params);
+   for (int i = 0; i < num_params; i++) {
+      plist.push_tail(va_arg(ap, ir_variable *));
+   }
+   va_end(ap);
+
+   sig->replace_parameters(&plist);
+   return sig;
+}
+
+#define MAKE_SIG(return_type, avail, rest...) \
+   ir_function_signature *sig =               \
+      new_sig(return_type, avail, rest);      \
+   ir_factory body(&sig->body, mem_ctx);
+
+ir_function_signature *
+builtin_builder::unop(builtin_available_predicate avail,
+                      ir_expression_operation opcode,
+                      const glsl_type *return_type,
+                      const glsl_type *param_type)
+{
+   ir_variable *x = in_var(param_type, "x");
+   MAKE_SIG(return_type, avail, 1, x);
+   body.emit(ret(expr(opcode, x)));
+   return sig;
+}
+
+#define UNOP(NAME, OPCODE, AVAIL)               \
+ir_function_signature *                         \
+builtin_builder::_##NAME(const glsl_type *type) \
+{                                               \
+   return unop(&AVAIL, OPCODE, type, type);     \
+}
+
+ir_function_signature *
+builtin_builder::binop(ir_expression_operation opcode,
+                       builtin_available_predicate avail,
+                       const glsl_type *return_type,
+                       const glsl_type *param0_type,
+                       const glsl_type *param1_type)
+{
+   ir_variable *x = in_var(param0_type, "x");
+   ir_variable *y = in_var(param1_type, "y");
+   MAKE_SIG(return_type, avail, 2, x, y);
+   body.emit(ret(expr(opcode, x, y)));
+   return sig;
+}
+
+#define BINOP(NAME, OPCODE, AVAIL)                                      \
+ir_function_signature *                                                 \
+builtin_builder::_##NAME(const glsl_type *return_type,                  \
+                         const glsl_type *param0_type,                  \
+                         const glsl_type *param1_type)                  \
+{                                                                       \
+   return binop(&AVAIL, OPCODE, return_type, param0_type, param1_type); \
+}
+
+/**
+ * Angle and Trigonometry Functions @{
+ */
+
+ir_function_signature *
+builtin_builder::_radians(const glsl_type *type)
+{
+   ir_variable *degrees = in_var(type, "degrees");
+   MAKE_SIG(type, always_available, 1, degrees);
+   body.emit(ret(mul(degrees, imm(0.0174532925f))));
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_degrees(const glsl_type *type)
+{
+   ir_variable *radians = in_var(type, "radians");
+   MAKE_SIG(type, always_available, 1, radians);
+   body.emit(ret(mul(radians, imm(57.29578f))));
+   return sig;
+}
+
+UNOP(sin, ir_unop_sin, always_available)
+UNOP(cos, ir_unop_cos, always_available)
+
+ir_function_signature *
+builtin_builder::_tan(const glsl_type *type)
+{
+   ir_variable *theta = in_var(type, "theta");
+   MAKE_SIG(type, always_available, 1, theta);
+   body.emit(ret(div(sin(theta), cos(theta))));
+   return sig;
+}
+
+ir_expression *
+builtin_builder::asin_expr(ir_variable *x)
+{
+   return mul(sign(x),
+              sub(imm(1.5707964f),
+                  mul(sqrt(sub(imm(1.0f), abs(x))),
+                      add(imm(1.5707964f),
+                          mul(abs(x),
+                              add(imm(-0.21460183f),
+                                  mul(abs(x),
+                                      add(imm(0.086566724f),
+                                          mul(abs(x), imm(-0.03102955f))))))))));
+}
+
+
+ir_function_signature *
+builtin_builder::_asin(const glsl_type *type)
+{
+   ir_variable *x = in_var(type, "x");
+   MAKE_SIG(type, always_available, 1, x);
+
+   body.emit(ret(asin_expr(x)));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_acos(const glsl_type *type)
+{
+   ir_variable *x = in_var(type, "x");
+   MAKE_SIG(type, always_available, 1, x);
+
+   body.emit(ret(sub(imm(1.5707964f), asin_expr(x))));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_atan2(const glsl_type *type)
+{
+   ir_variable *vec_y = in_var(type, "vec_y");
+   ir_variable *vec_x = in_var(type, "vec_x");
+   MAKE_SIG(type, always_available, 2, vec_y, vec_x);
+
+   ir_variable *vec_result = body.make_temp(type, "vec_result");
+   ir_variable *r = body.make_temp(glsl_type::float_type, "r");
+   for (int i = 0; i < type->vector_elements; i++) {
+      ir_variable *y = body.make_temp(glsl_type::float_type, "y");
+      ir_variable *x = body.make_temp(glsl_type::float_type, "x");
+      body.emit(assign(y, swizzle(vec_y, i, 1)));
+      body.emit(assign(x, swizzle(vec_x, i, 1)));
+
+      /* If |x| >= 1.0e-8 * |y|: */
+      ir_if *outer_if =
+         new(mem_ctx) ir_if(greater(abs(x), mul(imm(1.0e-8f), abs(y))));
+
+      ir_factory outer_then(&outer_if->then_instructions, mem_ctx);
+
+      /* Then...call atan(y/x) */
+      ir_variable *y_over_x = outer_then.make_temp(glsl_type::float_type, "y_over_x");
+      outer_then.emit(assign(y_over_x, div(y, x)));
+      outer_then.emit(assign(r, mul(y_over_x, rsq(add(mul(y_over_x, y_over_x),
+                                                      imm(1.0f))))));
+      outer_then.emit(assign(r, asin_expr(r)));
+
+      /*     ...and fix it up: */
+      ir_if *inner_if = new(mem_ctx) ir_if(less(x, imm(0.0f)));
+      inner_if->then_instructions.push_tail(
+         if_tree(gequal(y, imm(0.0f)),
+                 assign(r, add(r, imm(3.141593f))),
+                 assign(r, sub(r, imm(3.141593f)))));
+      outer_then.emit(inner_if);
+
+      /* Else... */
+      outer_if->else_instructions.push_tail(
+         assign(r, mul(sign(y), imm(1.5707965f))));
+
+      body.emit(outer_if);
+
+      body.emit(assign(vec_result, r, 1 << i));
+   }
+   body.emit(ret(vec_result));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_atan(const glsl_type *type)
+{
+   ir_variable *y_over_x = in_var(type, "y_over_x");
+   MAKE_SIG(type, always_available, 1, y_over_x);
+
+   ir_variable *t = body.make_temp(type, "t");
+   body.emit(assign(t, mul(y_over_x, rsq(add(mul(y_over_x, y_over_x),
+                                             imm(1.0f))))));
+
+   body.emit(ret(asin_expr(t)));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_sinh(const glsl_type *type)
+{
+   ir_variable *x = in_var(type, "x");
+   MAKE_SIG(type, v130, 1, x);
+
+   /* 0.5 * (e^x - e^(-x)) */
+   body.emit(ret(mul(imm(0.5f), sub(exp(x), exp(neg(x))))));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_cosh(const glsl_type *type)
+{
+   ir_variable *x = in_var(type, "x");
+   MAKE_SIG(type, v130, 1, x);
+
+   /* 0.5 * (e^x + e^(-x)) */
+   body.emit(ret(mul(imm(0.5f), add(exp(x), exp(neg(x))))));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_tanh(const glsl_type *type)
+{
+   ir_variable *x = in_var(type, "x");
+   MAKE_SIG(type, v130, 1, x);
+
+   /* (e^x - e^(-x)) / (e^x + e^(-x)) */
+   body.emit(ret(div(sub(exp(x), exp(neg(x))),
+                     add(exp(x), exp(neg(x))))));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_asinh(const glsl_type *type)
+{
+   ir_variable *x = in_var(type, "x");
+   MAKE_SIG(type, v130, 1, x);
+
+   body.emit(ret(mul(sign(x), log(add(abs(x), sqrt(add(mul(x, x),
+                                                       imm(1.0f))))))));
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_acosh(const glsl_type *type)
+{
+   ir_variable *x = in_var(type, "x");
+   MAKE_SIG(type, v130, 1, x);
+
+   body.emit(ret(log(add(x, sqrt(sub(mul(x, x), imm(1.0f)))))));
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_atanh(const glsl_type *type)
+{
+   ir_variable *x = in_var(type, "x");
+   MAKE_SIG(type, v130, 1, x);
+
+   body.emit(ret(mul(imm(0.5f), log(div(add(imm(1.0f), x),
+                                        sub(imm(1.0f), x))))));
+   return sig;
+}
+/** @} */
+
+/**
+ * Exponential Functions @{
+ */
+
+ir_function_signature *
+builtin_builder::_pow(const glsl_type *type)
+{
+   return binop(ir_binop_pow, always_available, type, type, type);
+}
+
+UNOP(exp,         ir_unop_exp,  always_available)
+UNOP(log,         ir_unop_log,  always_available)
+UNOP(exp2,        ir_unop_exp2, always_available)
+UNOP(log2,        ir_unop_log2, always_available)
+UNOP(sqrt,        ir_unop_sqrt, always_available)
+UNOP(inversesqrt, ir_unop_rsq,  always_available)
+
+/** @} */
+
+UNOP(abs,       ir_unop_abs,        always_available)
+UNOP(sign,      ir_unop_sign,       always_available)
+UNOP(floor,     ir_unop_floor,      always_available)
+UNOP(trunc,     ir_unop_trunc,      v130)
+UNOP(round,     ir_unop_round_even, always_available)
+UNOP(roundEven, ir_unop_round_even, always_available)
+UNOP(ceil,      ir_unop_ceil,       always_available)
+UNOP(fract,     ir_unop_fract,      always_available)
+
+ir_function_signature *
+builtin_builder::_mod(const glsl_type *x_type, const glsl_type *y_type)
+{
+   return binop(ir_binop_mod, always_available, x_type, x_type, y_type);
+}
+
+ir_function_signature *
+builtin_builder::_modf(const glsl_type *type)
+{
+   ir_variable *x = in_var(type, "x");
+   ir_variable *i = out_var(type, "i");
+   MAKE_SIG(type, v130, 2, x, i);
+
+   ir_variable *t = body.make_temp(type, "t");
+   body.emit(assign(t, expr(ir_unop_trunc, x)));
+   body.emit(assign(i, t));
+   body.emit(ret(sub(x, t)));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_min(builtin_available_predicate avail,
+                      const glsl_type *x_type, const glsl_type *y_type)
+{
+   return binop(ir_binop_min, avail, x_type, x_type, y_type);
+}
+
+ir_function_signature *
+builtin_builder::_max(builtin_available_predicate avail,
+                      const glsl_type *x_type, const glsl_type *y_type)
+{
+   return binop(ir_binop_max, avail, x_type, x_type, y_type);
+}
+
+ir_function_signature *
+builtin_builder::_clamp(builtin_available_predicate avail,
+                        const glsl_type *val_type, const glsl_type *bound_type)
+{
+   ir_variable *x = in_var(val_type, "x");
+   ir_variable *minVal = in_var(bound_type, "minVal");
+   ir_variable *maxVal = in_var(bound_type, "maxVal");
+   MAKE_SIG(val_type, avail, 3, x, minVal, maxVal);
+
+   body.emit(ret(clamp(x, minVal, maxVal)));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_mix_lrp(const glsl_type *val_type, const glsl_type *blend_type)
+{
+   ir_variable *x = in_var(val_type, "x");
+   ir_variable *y = in_var(val_type, "y");
+   ir_variable *a = in_var(blend_type, "a");
+   MAKE_SIG(val_type, always_available, 3, x, y, a);
+
+   body.emit(ret(lrp(x, y, a)));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_mix_sel(const glsl_type *val_type, const glsl_type *blend_type)
+{
+   ir_variable *x = in_var(val_type, "x");
+   ir_variable *y = in_var(val_type, "y");
+   ir_variable *a = in_var(blend_type, "a");
+   MAKE_SIG(val_type, v130, 3, x, y, a);
+
+   if (blend_type->vector_elements == 1) {
+      body.emit(assign(x, y, a));
+   } else {
+      for (int i = 0; i < blend_type->vector_elements; i++) {
+         body.emit(assign(x, swizzle(y, i, 1), swizzle(a, i, 1), 1 << i));
+      }
+   }
+   body.emit(ret(x));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_step(const glsl_type *edge_type, const glsl_type *x_type)
+{
+   ir_variable *edge = in_var(edge_type, "edge");
+   ir_variable *x = in_var(x_type, "x");
+   MAKE_SIG(x_type, always_available, 2, edge, x);
+
+   ir_variable *t = body.make_temp(x_type, "t");
+   if (x_type->vector_elements == 1) {
+      /* Both are floats */
+      body.emit(assign(t, b2f(gequal(x, edge))));
+   } else if (edge_type->vector_elements == 1) {
+      /* x is a vector but edge is a float */
+      for (int i = 0; i < x_type->vector_elements; i++) {
+         body.emit(assign(t, b2f(gequal(swizzle(x, i, 1), edge)), 1 << i));
+      }
+   } else {
+      /* Both are vectors */
+      for (int i = 0; i < x_type->vector_elements; i++) {
+         body.emit(assign(t, b2f(gequal(swizzle(x, i, 1), swizzle(edge, i, 1))),
+                          1 << i));
+      }
+   }
+   body.emit(ret(t));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_smoothstep(const glsl_type *edge_type, const glsl_type *x_type)
+{
+   ir_variable *edge0 = in_var(edge_type, "edge0");
+   ir_variable *edge1 = in_var(edge_type, "edge1");
+   ir_variable *x = in_var(x_type, "x");
+   MAKE_SIG(x_type, always_available, 3, edge0, edge1, x);
+
+   /* From the GLSL 1.10 specification:
+    *
+    *    genType t;
+    *    t = clamp((x - edge0) / (edge1 - edge0), 0, 1);
+    *    return t * t * (3 - 2 * t);
+    */
+
+   ir_variable *t = body.make_temp(x_type, "t");
+   body.emit(assign(t, clamp(div(sub(x, edge0), sub(edge1, edge0)),
+                             imm(0.0f), imm(1.0f))));
+
+   body.emit(ret(mul(t, mul(t, sub(imm(3.0f), mul(imm(2.0f), t))))));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_isnan(const glsl_type *type)
+{
+   ir_variable *x = in_var(type, "x");
+   MAKE_SIG(glsl_type::bvec(type->vector_elements), v130, 1, x);
+
+   body.emit(ret(nequal(x, x)));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_isinf(const glsl_type *type)
+{
+   ir_variable *x = in_var(type, "x");
+   MAKE_SIG(glsl_type::bvec(type->vector_elements), v130, 1, x);
+
+   ir_constant_data infinities;
+   for (int i = 0; i < type->vector_elements; i++) {
+      infinities.f[i] = std::numeric_limits<float>::infinity();
+   }
+
+   body.emit(ret(equal(abs(x), imm(type, infinities))));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_floatBitsToInt(const glsl_type *type)
+{
+   ir_variable *x = in_var(type, "x");
+   MAKE_SIG(glsl_type::ivec(type->vector_elements), shader_bit_encoding, 1, x);
+   body.emit(ret(bitcast_f2i(x)));
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_floatBitsToUint(const glsl_type *type)
+{
+   ir_variable *x = in_var(type, "x");
+   MAKE_SIG(glsl_type::uvec(type->vector_elements), shader_bit_encoding, 1, x);
+   body.emit(ret(bitcast_f2u(x)));
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_intBitsToFloat(const glsl_type *type)
+{
+   ir_variable *x = in_var(type, "x");
+   MAKE_SIG(glsl_type::vec(type->vector_elements), shader_bit_encoding, 1, x);
+   body.emit(ret(bitcast_i2f(x)));
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_uintBitsToFloat(const glsl_type *type)
+{
+   ir_variable *x = in_var(type, "x");
+   MAKE_SIG(glsl_type::vec(type->vector_elements), shader_bit_encoding, 1, x);
+   body.emit(ret(bitcast_u2f(x)));
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_packUnorm2x16(builtin_available_predicate avail)
+{
+   ir_variable *v = in_var(glsl_type::vec2_type, "v");
+   MAKE_SIG(glsl_type::uint_type, avail, 1, v);
+   body.emit(ret(expr(ir_unop_pack_unorm_2x16, v)));
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_packSnorm2x16(builtin_available_predicate avail)
+{
+   ir_variable *v = in_var(glsl_type::vec2_type, "v");
+   MAKE_SIG(glsl_type::uint_type, avail, 1, v);
+   body.emit(ret(expr(ir_unop_pack_snorm_2x16, v)));
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_packUnorm4x8(builtin_available_predicate avail)
+{
+   ir_variable *v = in_var(glsl_type::vec4_type, "v");
+   MAKE_SIG(glsl_type::uint_type, avail, 1, v);
+   body.emit(ret(expr(ir_unop_pack_unorm_4x8, v)));
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_packSnorm4x8(builtin_available_predicate avail)
+{
+   ir_variable *v = in_var(glsl_type::vec4_type, "v");
+   MAKE_SIG(glsl_type::uint_type, avail, 1, v);
+   body.emit(ret(expr(ir_unop_pack_snorm_4x8, v)));
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_unpackUnorm2x16(builtin_available_predicate avail)
+{
+   ir_variable *p = in_var(glsl_type::uint_type, "p");
+   MAKE_SIG(glsl_type::vec2_type, avail, 1, p);
+   body.emit(ret(expr(ir_unop_unpack_unorm_2x16, p)));
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_unpackSnorm2x16(builtin_available_predicate avail)
+{
+   ir_variable *p = in_var(glsl_type::uint_type, "p");
+   MAKE_SIG(glsl_type::vec2_type, avail, 1, p);
+   body.emit(ret(expr(ir_unop_unpack_snorm_2x16, p)));
+   return sig;
+}
+
+
+ir_function_signature *
+builtin_builder::_unpackUnorm4x8(builtin_available_predicate avail)
+{
+   ir_variable *p = in_var(glsl_type::uint_type, "p");
+   MAKE_SIG(glsl_type::vec4_type, avail, 1, p);
+   body.emit(ret(expr(ir_unop_unpack_unorm_4x8, p)));
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_unpackSnorm4x8(builtin_available_predicate avail)
+{
+   ir_variable *p = in_var(glsl_type::uint_type, "p");
+   MAKE_SIG(glsl_type::vec4_type, avail, 1, p);
+   body.emit(ret(expr(ir_unop_unpack_snorm_4x8, p)));
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_packHalf2x16(builtin_available_predicate avail)
+{
+   ir_variable *v = in_var(glsl_type::vec2_type, "v");
+   MAKE_SIG(glsl_type::uint_type, avail, 1, v);
+   body.emit(ret(expr(ir_unop_pack_half_2x16, v)));
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_unpackHalf2x16(builtin_available_predicate avail)
+{
+   ir_variable *p = in_var(glsl_type::uint_type, "p");
+   MAKE_SIG(glsl_type::vec2_type, avail, 1, p);
+   body.emit(ret(expr(ir_unop_unpack_half_2x16, p)));
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_length(const glsl_type *type)
+{
+   ir_variable *x = in_var(type, "x");
+   MAKE_SIG(glsl_type::float_type, always_available, 1, x);
+
+   body.emit(ret(sqrt(dotlike(x, x))));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_distance(const glsl_type *type)
+{
+   ir_variable *p0 = in_var(type, "p0");
+   ir_variable *p1 = in_var(type, "p1");
+   MAKE_SIG(glsl_type::float_type, always_available, 2, p0, p1);
+
+   if (type->vector_elements == 1) {
+      body.emit(ret(abs(sub(p0, p1))));
+   } else {
+      ir_variable *p = body.make_temp(type, "p");
+      body.emit(assign(p, sub(p0, p1)));
+      body.emit(ret(sqrt(dot(p, p))));
+   }
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_dot(const glsl_type *type)
+{
+   if (type->vector_elements == 1)
+      return binop(ir_binop_mul, always_available, type, type, type);
+
+   return binop(ir_binop_dot, always_available,
+                glsl_type::float_type, type, type);
+}
+
+ir_function_signature *
+builtin_builder::_cross(const glsl_type *type)
+{
+   ir_variable *a = in_var(type, "a");
+   ir_variable *b = in_var(type, "b");
+   MAKE_SIG(type, always_available, 2, a, b);
+
+   int yzx = MAKE_SWIZZLE4(SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_X, 0);
+   int zxy = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_X, SWIZZLE_Y, 0);
+
+   body.emit(ret(sub(mul(swizzle(a, yzx, 3), swizzle(b, zxy, 3)),
+                     mul(swizzle(a, zxy, 3), swizzle(b, yzx, 3)))));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_normalize(const glsl_type *type)
+{
+   ir_variable *x = in_var(type, "x");
+   MAKE_SIG(type, always_available, 1, x);
+
+   if (type->vector_elements == 1) {
+      body.emit(ret(sign(x)));
+   } else {
+      body.emit(ret(mul(x, rsq(dot(x, x)))));
+   }
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_ftransform()
+{
+   MAKE_SIG(glsl_type::vec4_type, compatibility_vs_only, 0);
+
+   body.emit(ret(new(mem_ctx) ir_expression(ir_binop_mul,
+      glsl_type::vec4_type,
+      var_ref(gl_ModelViewProjectionMatrix),
+      var_ref(gl_Vertex))));
+
+   /* FINISHME: Once the ir_expression() constructor handles type inference
+    *           for matrix operations, we can simplify this to:
+    *
+    *    body.emit(ret(mul(gl_ModelViewProjectionMatrix, gl_Vertex)));
+    */
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_faceforward(const glsl_type *type)
+{
+   ir_variable *N = in_var(type, "N");
+   ir_variable *I = in_var(type, "I");
+   ir_variable *Nref = in_var(type, "Nref");
+   MAKE_SIG(type, always_available, 3, N, I, Nref);
+
+   body.emit(if_tree(less(dotlike(Nref, I), imm(0.0f)),
+                     ret(N), ret(neg(N))));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_reflect(const glsl_type *type)
+{
+   ir_variable *I = in_var(type, "I");
+   ir_variable *N = in_var(type, "N");
+   MAKE_SIG(type, always_available, 2, I, N);
+
+   /* I - 2 * dot(N, I) * N */
+   body.emit(ret(sub(I, mul(imm(2.0f), mul(dotlike(N, I), N)))));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_refract(const glsl_type *type)
+{
+   ir_variable *I = in_var(type, "I");
+   ir_variable *N = in_var(type, "N");
+   ir_variable *eta = in_var(glsl_type::float_type, "eta");
+   MAKE_SIG(type, always_available, 3, I, N, eta);
+
+   ir_variable *n_dot_i = body.make_temp(glsl_type::float_type, "n_dot_i");
+   body.emit(assign(n_dot_i, dotlike(N, I)));
+
+   /* From the GLSL 1.10 specification:
+    * k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))
+    * if (k < 0.0)
+    *    return genType(0.0)
+    * else
+    *    return eta * I - (eta * dot(N, I) + sqrt(k)) * N
+    */
+   ir_variable *k = body.make_temp(glsl_type::float_type, "k");
+   body.emit(assign(k, sub(imm(1.0f),
+                           mul(eta, mul(eta, sub(imm(1.0f),
+                                                 mul(n_dot_i, n_dot_i)))))));
+   body.emit(if_tree(less(k, imm(0.0f)),
+                     ret(ir_constant::zero(mem_ctx, type)),
+                     ret(sub(mul(eta, I),
+                             mul(add(mul(eta, n_dot_i), sqrt(k)), N)))));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_matrixCompMult(const glsl_type *type)
+{
+   ir_variable *x = in_var(type, "x");
+   ir_variable *y = in_var(type, "y");
+   MAKE_SIG(type, always_available, 2, x, y);
+
+   ir_variable *z = body.make_temp(type, "z");
+   for (int i = 0; i < type->matrix_columns; i++) {
+      body.emit(assign(array_ref(z, i), mul(array_ref(x, i), array_ref(y, i))));
+   }
+   body.emit(ret(z));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_outerProduct(const glsl_type *type)
+{
+   ir_variable *c = in_var(glsl_type::vec(type->vector_elements), "c");
+   ir_variable *r = in_var(glsl_type::vec(type->matrix_columns), "r");
+   MAKE_SIG(type, v120, 2, c, r);
+
+   ir_variable *m = body.make_temp(type, "m");
+   for (int i = 0; i < type->matrix_columns; i++) {
+      body.emit(assign(array_ref(m, i), mul(c, swizzle(r, i, 1))));
+   }
+   body.emit(ret(m));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_transpose(const glsl_type *orig_type)
+{
+   const glsl_type *transpose_type =
+      glsl_type::get_instance(GLSL_TYPE_FLOAT,
+                              orig_type->matrix_columns,
+                              orig_type->vector_elements);
+
+   ir_variable *m = in_var(orig_type, "m");
+   MAKE_SIG(transpose_type, v120, 1, m);
+
+   ir_variable *t = body.make_temp(transpose_type, "t");
+   for (int i = 0; i < orig_type->matrix_columns; i++) {
+      for (int j = 0; j < orig_type->vector_elements; j++) {
+         body.emit(assign(array_ref(t, j),
+                          matrix_elt(m, i, j),
+                          1 << i));
+      }
+   }
+   body.emit(ret(t));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_determinant_mat2()
+{
+   ir_variable *m = in_var(glsl_type::mat2_type, "m");
+   MAKE_SIG(glsl_type::float_type, v120, 1, m);
+
+   body.emit(ret(sub(mul(matrix_elt(m, 0, 0), matrix_elt(m, 1, 1)),
+                     mul(matrix_elt(m, 1, 0), matrix_elt(m, 0, 1)))));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_determinant_mat3()
+{
+   ir_variable *m = in_var(glsl_type::mat3_type, "m");
+   MAKE_SIG(glsl_type::float_type, v120, 1, m);
+
+   ir_expression *f1 =
+      sub(mul(matrix_elt(m, 1, 1), matrix_elt(m, 2, 2)),
+          mul(matrix_elt(m, 1, 2), matrix_elt(m, 2, 1)));
+
+   ir_expression *f2 =
+      sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 2, 2)),
+          mul(matrix_elt(m, 1, 2), matrix_elt(m, 2, 0)));
+
+   ir_expression *f3 =
+      sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 2, 1)),
+          mul(matrix_elt(m, 1, 1), matrix_elt(m, 2, 0)));
+
+   body.emit(ret(add(sub(mul(matrix_elt(m, 0, 0), f1),
+                         mul(matrix_elt(m, 0, 1), f2)),
+                     mul(matrix_elt(m, 0, 2), f3))));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_determinant_mat4()
+{
+   ir_variable *m = in_var(glsl_type::mat4_type, "m");
+   MAKE_SIG(glsl_type::float_type, v120, 1, m);
+
+   ir_variable *SubFactor00 = body.make_temp(glsl_type::float_type, "SubFactor00");
+   ir_variable *SubFactor01 = body.make_temp(glsl_type::float_type, "SubFactor01");
+   ir_variable *SubFactor02 = body.make_temp(glsl_type::float_type, "SubFactor02");
+   ir_variable *SubFactor03 = body.make_temp(glsl_type::float_type, "SubFactor03");
+   ir_variable *SubFactor04 = body.make_temp(glsl_type::float_type, "SubFactor04");
+   ir_variable *SubFactor05 = body.make_temp(glsl_type::float_type, "SubFactor05");
+   ir_variable *SubFactor06 = body.make_temp(glsl_type::float_type, "SubFactor06");
+   ir_variable *SubFactor07 = body.make_temp(glsl_type::float_type, "SubFactor07");
+   ir_variable *SubFactor08 = body.make_temp(glsl_type::float_type, "SubFactor08");
+   ir_variable *SubFactor09 = body.make_temp(glsl_type::float_type, "SubFactor09");
+   ir_variable *SubFactor10 = body.make_temp(glsl_type::float_type, "SubFactor10");
+   ir_variable *SubFactor11 = body.make_temp(glsl_type::float_type, "SubFactor11");
+   ir_variable *SubFactor12 = body.make_temp(glsl_type::float_type, "SubFactor12");
+   ir_variable *SubFactor13 = body.make_temp(glsl_type::float_type, "SubFactor13");
+   ir_variable *SubFactor14 = body.make_temp(glsl_type::float_type, "SubFactor14");
+   ir_variable *SubFactor15 = body.make_temp(glsl_type::float_type, "SubFactor15");
+   ir_variable *SubFactor16 = body.make_temp(glsl_type::float_type, "SubFactor16");
+   ir_variable *SubFactor17 = body.make_temp(glsl_type::float_type, "SubFactor17");
+   ir_variable *SubFactor18 = body.make_temp(glsl_type::float_type, "SubFactor18");
+
+   body.emit(assign(SubFactor00, sub(mul(matrix_elt(m, 2, 2), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 2), matrix_elt(m, 2, 3)))));
+   body.emit(assign(SubFactor01, sub(mul(matrix_elt(m, 2, 1), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 1), matrix_elt(m, 2, 3)))));
+   body.emit(assign(SubFactor02, sub(mul(matrix_elt(m, 2, 1), matrix_elt(m, 3, 2)), mul(matrix_elt(m, 3, 1), matrix_elt(m, 2, 2)))));
+   body.emit(assign(SubFactor03, sub(mul(matrix_elt(m, 2, 0), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 0), matrix_elt(m, 2, 3)))));
+   body.emit(assign(SubFactor04, sub(mul(matrix_elt(m, 2, 0), matrix_elt(m, 3, 2)), mul(matrix_elt(m, 3, 0), matrix_elt(m, 2, 2)))));
+   body.emit(assign(SubFactor05, sub(mul(matrix_elt(m, 2, 0), matrix_elt(m, 3, 1)), mul(matrix_elt(m, 3, 0), matrix_elt(m, 2, 1)))));
+   body.emit(assign(SubFactor06, sub(mul(matrix_elt(m, 1, 2), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 2), matrix_elt(m, 1, 3)))));
+   body.emit(assign(SubFactor07, sub(mul(matrix_elt(m, 1, 1), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 1), matrix_elt(m, 1, 3)))));
+   body.emit(assign(SubFactor08, sub(mul(matrix_elt(m, 1, 1), matrix_elt(m, 3, 2)), mul(matrix_elt(m, 3, 1), matrix_elt(m, 1, 2)))));
+   body.emit(assign(SubFactor09, sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 0), matrix_elt(m, 1, 3)))));
+   body.emit(assign(SubFactor10, sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 3, 2)), mul(matrix_elt(m, 3, 0), matrix_elt(m, 1, 2)))));
+   body.emit(assign(SubFactor11, sub(mul(matrix_elt(m, 1, 1), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 1), matrix_elt(m, 1, 3)))));
+   body.emit(assign(SubFactor12, sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 3, 1)), mul(matrix_elt(m, 3, 0), matrix_elt(m, 1, 1)))));
+   body.emit(assign(SubFactor13, sub(mul(matrix_elt(m, 1, 2), matrix_elt(m, 2, 3)), mul(matrix_elt(m, 2, 2), matrix_elt(m, 1, 3)))));
+   body.emit(assign(SubFactor14, sub(mul(matrix_elt(m, 1, 1), matrix_elt(m, 2, 3)), mul(matrix_elt(m, 2, 1), matrix_elt(m, 1, 3)))));
+   body.emit(assign(SubFactor15, sub(mul(matrix_elt(m, 1, 1), matrix_elt(m, 2, 2)), mul(matrix_elt(m, 2, 1), matrix_elt(m, 1, 2)))));
+   body.emit(assign(SubFactor16, sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 2, 3)), mul(matrix_elt(m, 2, 0), matrix_elt(m, 1, 3)))));
+   body.emit(assign(SubFactor17, sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 2, 2)), mul(matrix_elt(m, 2, 0), matrix_elt(m, 1, 2)))));
+   body.emit(assign(SubFactor18, sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 2, 1)), mul(matrix_elt(m, 2, 0), matrix_elt(m, 1, 1)))));
+
+   ir_variable *adj_0 = body.make_temp(glsl_type::vec4_type, "adj_0");
+
+   body.emit(assign(adj_0,
+                    add(sub(mul(matrix_elt(m, 1, 1), SubFactor00),
+                            mul(matrix_elt(m, 1, 2), SubFactor01)),
+                        mul(matrix_elt(m, 1, 3), SubFactor02)),
+                    WRITEMASK_X));
+   body.emit(assign(adj_0, neg(
+                    add(sub(mul(matrix_elt(m, 1, 0), SubFactor00),
+                            mul(matrix_elt(m, 1, 2), SubFactor03)),
+                        mul(matrix_elt(m, 1, 3), SubFactor04))),
+                    WRITEMASK_Y));
+   body.emit(assign(adj_0,
+                    add(sub(mul(matrix_elt(m, 1, 0), SubFactor01),
+                            mul(matrix_elt(m, 1, 1), SubFactor03)),
+                        mul(matrix_elt(m, 1, 3), SubFactor05)),
+                    WRITEMASK_Z));
+   body.emit(assign(adj_0, neg(
+                    add(sub(mul(matrix_elt(m, 1, 0), SubFactor02),
+                            mul(matrix_elt(m, 1, 1), SubFactor04)),
+                        mul(matrix_elt(m, 1, 2), SubFactor05))),
+                    WRITEMASK_W));
+
+   body.emit(ret(dot(array_ref(m, 0), adj_0)));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_inverse_mat2()
+{
+   ir_variable *m = in_var(glsl_type::mat2_type, "m");
+   MAKE_SIG(glsl_type::mat2_type, v120, 1, m);
+
+   ir_variable *adj = body.make_temp(glsl_type::mat2_type, "adj");
+   body.emit(assign(array_ref(adj, 0), matrix_elt(m, 1, 1), 1 << 0));
+   body.emit(assign(array_ref(adj, 0), neg(matrix_elt(m, 0, 1)), 1 << 1));
+   body.emit(assign(array_ref(adj, 1), neg(matrix_elt(m, 1, 0)), 1 << 0));
+   body.emit(assign(array_ref(adj, 1), matrix_elt(m, 0, 0), 1 << 1));
+
+   ir_expression *det =
+      sub(mul(matrix_elt(m, 0, 0), matrix_elt(m, 1, 1)),
+          mul(matrix_elt(m, 1, 0), matrix_elt(m, 0, 1)));
+
+   body.emit(ret(div(adj, det)));
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_inverse_mat3()
+{
+   ir_variable *m = in_var(glsl_type::mat3_type, "m");
+   MAKE_SIG(glsl_type::mat3_type, v120, 1, m);
+
+   ir_variable *f11_22_21_12 = body.make_temp(glsl_type::float_type, "f11_22_21_12");
+   ir_variable *f10_22_20_12 = body.make_temp(glsl_type::float_type, "f10_22_20_12");
+   ir_variable *f10_21_20_11 = body.make_temp(glsl_type::float_type, "f10_21_20_11");
+
+   body.emit(assign(f11_22_21_12,
+                    sub(mul(matrix_elt(m, 1, 1), matrix_elt(m, 2, 2)),
+                        mul(matrix_elt(m, 2, 1), matrix_elt(m, 1, 2)))));
+   body.emit(assign(f10_22_20_12,
+                    sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 2, 2)),
+                        mul(matrix_elt(m, 2, 0), matrix_elt(m, 1, 2)))));
+   body.emit(assign(f10_21_20_11,
+                    sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 2, 1)),
+                        mul(matrix_elt(m, 2, 0), matrix_elt(m, 1, 1)))));
+
+   ir_variable *adj = body.make_temp(glsl_type::mat3_type, "adj");
+   body.emit(assign(array_ref(adj, 0), f11_22_21_12, WRITEMASK_X));
+   body.emit(assign(array_ref(adj, 1), neg(f10_22_20_12), WRITEMASK_X));
+   body.emit(assign(array_ref(adj, 2), f10_21_20_11, WRITEMASK_X));
+
+   body.emit(assign(array_ref(adj, 0), neg(
+                    sub(mul(matrix_elt(m, 0, 1), matrix_elt(m, 2, 2)),
+                        mul(matrix_elt(m, 2, 1), matrix_elt(m, 0, 2)))),
+                    WRITEMASK_Y));
+   body.emit(assign(array_ref(adj, 1),
+                    sub(mul(matrix_elt(m, 0, 0), matrix_elt(m, 2, 2)),
+                        mul(matrix_elt(m, 2, 0), matrix_elt(m, 0, 2))),
+                    WRITEMASK_Y));
+   body.emit(assign(array_ref(adj, 2), neg(
+                    sub(mul(matrix_elt(m, 0, 0), matrix_elt(m, 2, 1)),
+                        mul(matrix_elt(m, 2, 0), matrix_elt(m, 0, 1)))),
+                    WRITEMASK_Y));
+
+   body.emit(assign(array_ref(adj, 0),
+                    sub(mul(matrix_elt(m, 0, 1), matrix_elt(m, 1, 2)),
+                        mul(matrix_elt(m, 1, 1), matrix_elt(m, 0, 2))),
+                    WRITEMASK_Z));
+   body.emit(assign(array_ref(adj, 1), neg(
+                    sub(mul(matrix_elt(m, 0, 0), matrix_elt(m, 1, 2)),
+                        mul(matrix_elt(m, 1, 0), matrix_elt(m, 0, 2)))),
+                    WRITEMASK_Z));
+   body.emit(assign(array_ref(adj, 2),
+                    sub(mul(matrix_elt(m, 0, 0), matrix_elt(m, 1, 1)),
+                        mul(matrix_elt(m, 1, 0), matrix_elt(m, 0, 1))),
+                    WRITEMASK_Z));
+
+   ir_expression *det =
+      add(sub(mul(matrix_elt(m, 0, 0), f11_22_21_12),
+              mul(matrix_elt(m, 0, 1), f10_22_20_12)),
+          mul(matrix_elt(m, 0, 2), f10_21_20_11));
+
+   body.emit(ret(div(adj, det)));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_inverse_mat4()
+{
+   ir_variable *m = in_var(glsl_type::mat4_type, "m");
+   MAKE_SIG(glsl_type::mat4_type, v120, 1, m);
+
+   ir_variable *SubFactor00 = body.make_temp(glsl_type::float_type, "SubFactor00");
+   ir_variable *SubFactor01 = body.make_temp(glsl_type::float_type, "SubFactor01");
+   ir_variable *SubFactor02 = body.make_temp(glsl_type::float_type, "SubFactor02");
+   ir_variable *SubFactor03 = body.make_temp(glsl_type::float_type, "SubFactor03");
+   ir_variable *SubFactor04 = body.make_temp(glsl_type::float_type, "SubFactor04");
+   ir_variable *SubFactor05 = body.make_temp(glsl_type::float_type, "SubFactor05");
+   ir_variable *SubFactor06 = body.make_temp(glsl_type::float_type, "SubFactor06");
+   ir_variable *SubFactor07 = body.make_temp(glsl_type::float_type, "SubFactor07");
+   ir_variable *SubFactor08 = body.make_temp(glsl_type::float_type, "SubFactor08");
+   ir_variable *SubFactor09 = body.make_temp(glsl_type::float_type, "SubFactor09");
+   ir_variable *SubFactor10 = body.make_temp(glsl_type::float_type, "SubFactor10");
+   ir_variable *SubFactor11 = body.make_temp(glsl_type::float_type, "SubFactor11");
+   ir_variable *SubFactor12 = body.make_temp(glsl_type::float_type, "SubFactor12");
+   ir_variable *SubFactor13 = body.make_temp(glsl_type::float_type, "SubFactor13");
+   ir_variable *SubFactor14 = body.make_temp(glsl_type::float_type, "SubFactor14");
+   ir_variable *SubFactor15 = body.make_temp(glsl_type::float_type, "SubFactor15");
+   ir_variable *SubFactor16 = body.make_temp(glsl_type::float_type, "SubFactor16");
+   ir_variable *SubFactor17 = body.make_temp(glsl_type::float_type, "SubFactor17");
+   ir_variable *SubFactor18 = body.make_temp(glsl_type::float_type, "SubFactor18");
+
+   body.emit(assign(SubFactor00, sub(mul(matrix_elt(m, 2, 2), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 2), matrix_elt(m, 2, 3)))));
+   body.emit(assign(SubFactor01, sub(mul(matrix_elt(m, 2, 1), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 1), matrix_elt(m, 2, 3)))));
+   body.emit(assign(SubFactor02, sub(mul(matrix_elt(m, 2, 1), matrix_elt(m, 3, 2)), mul(matrix_elt(m, 3, 1), matrix_elt(m, 2, 2)))));
+   body.emit(assign(SubFactor03, sub(mul(matrix_elt(m, 2, 0), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 0), matrix_elt(m, 2, 3)))));
+   body.emit(assign(SubFactor04, sub(mul(matrix_elt(m, 2, 0), matrix_elt(m, 3, 2)), mul(matrix_elt(m, 3, 0), matrix_elt(m, 2, 2)))));
+   body.emit(assign(SubFactor05, sub(mul(matrix_elt(m, 2, 0), matrix_elt(m, 3, 1)), mul(matrix_elt(m, 3, 0), matrix_elt(m, 2, 1)))));
+   body.emit(assign(SubFactor06, sub(mul(matrix_elt(m, 1, 2), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 2), matrix_elt(m, 1, 3)))));
+   body.emit(assign(SubFactor07, sub(mul(matrix_elt(m, 1, 1), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 1), matrix_elt(m, 1, 3)))));
+   body.emit(assign(SubFactor08, sub(mul(matrix_elt(m, 1, 1), matrix_elt(m, 3, 2)), mul(matrix_elt(m, 3, 1), matrix_elt(m, 1, 2)))));
+   body.emit(assign(SubFactor09, sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 0), matrix_elt(m, 1, 3)))));
+   body.emit(assign(SubFactor10, sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 3, 2)), mul(matrix_elt(m, 3, 0), matrix_elt(m, 1, 2)))));
+   body.emit(assign(SubFactor11, sub(mul(matrix_elt(m, 1, 1), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 1), matrix_elt(m, 1, 3)))));
+   body.emit(assign(SubFactor12, sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 3, 1)), mul(matrix_elt(m, 3, 0), matrix_elt(m, 1, 1)))));
+   body.emit(assign(SubFactor13, sub(mul(matrix_elt(m, 1, 2), matrix_elt(m, 2, 3)), mul(matrix_elt(m, 2, 2), matrix_elt(m, 1, 3)))));
+   body.emit(assign(SubFactor14, sub(mul(matrix_elt(m, 1, 1), matrix_elt(m, 2, 3)), mul(matrix_elt(m, 2, 1), matrix_elt(m, 1, 3)))));
+   body.emit(assign(SubFactor15, sub(mul(matrix_elt(m, 1, 1), matrix_elt(m, 2, 2)), mul(matrix_elt(m, 2, 1), matrix_elt(m, 1, 2)))));
+   body.emit(assign(SubFactor16, sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 2, 3)), mul(matrix_elt(m, 2, 0), matrix_elt(m, 1, 3)))));
+   body.emit(assign(SubFactor17, sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 2, 2)), mul(matrix_elt(m, 2, 0), matrix_elt(m, 1, 2)))));
+   body.emit(assign(SubFactor18, sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 2, 1)), mul(matrix_elt(m, 2, 0), matrix_elt(m, 1, 1)))));
+
+   ir_variable *adj = body.make_temp(glsl_type::mat4_type, "adj");
+   body.emit(assign(array_ref(adj, 0),
+                    add(sub(mul(matrix_elt(m, 1, 1), SubFactor00),
+                            mul(matrix_elt(m, 1, 2), SubFactor01)),
+                        mul(matrix_elt(m, 1, 3), SubFactor02)),
+                    WRITEMASK_X));
+   body.emit(assign(array_ref(adj, 1), neg(
+                    add(sub(mul(matrix_elt(m, 1, 0), SubFactor00),
+                            mul(matrix_elt(m, 1, 2), SubFactor03)),
+                        mul(matrix_elt(m, 1, 3), SubFactor04))),
+                    WRITEMASK_X));
+   body.emit(assign(array_ref(adj, 2),
+                    add(sub(mul(matrix_elt(m, 1, 0), SubFactor01),
+                            mul(matrix_elt(m, 1, 1), SubFactor03)),
+                        mul(matrix_elt(m, 1, 3), SubFactor05)),
+                    WRITEMASK_X));
+   body.emit(assign(array_ref(adj, 3), neg(
+                    add(sub(mul(matrix_elt(m, 1, 0), SubFactor02),
+                            mul(matrix_elt(m, 1, 1), SubFactor04)),
+                        mul(matrix_elt(m, 1, 2), SubFactor05))),
+                    WRITEMASK_X));
+
+   body.emit(assign(array_ref(adj, 0), neg(
+                    add(sub(mul(matrix_elt(m, 0, 1), SubFactor00),
+                            mul(matrix_elt(m, 0, 2), SubFactor01)),
+                        mul(matrix_elt(m, 0, 3), SubFactor02))),
+                    WRITEMASK_Y));
+   body.emit(assign(array_ref(adj, 1),
+                    add(sub(mul(matrix_elt(m, 0, 0), SubFactor00),
+                            mul(matrix_elt(m, 0, 2), SubFactor03)),
+                        mul(matrix_elt(m, 0, 3), SubFactor04)),
+                    WRITEMASK_Y));
+   body.emit(assign(array_ref(adj, 2), neg(
+                    add(sub(mul(matrix_elt(m, 0, 0), SubFactor01),
+                            mul(matrix_elt(m, 0, 1), SubFactor03)),
+                        mul(matrix_elt(m, 0, 3), SubFactor05))),
+                    WRITEMASK_Y));
+   body.emit(assign(array_ref(adj, 3),
+                    add(sub(mul(matrix_elt(m, 0, 0), SubFactor02),
+                            mul(matrix_elt(m, 0, 1), SubFactor04)),
+                        mul(matrix_elt(m, 0, 2), SubFactor05)),
+                    WRITEMASK_Y));
+
+   body.emit(assign(array_ref(adj, 0),
+                    add(sub(mul(matrix_elt(m, 0, 1), SubFactor06),
+                            mul(matrix_elt(m, 0, 2), SubFactor07)),
+                        mul(matrix_elt(m, 0, 3), SubFactor08)),
+                    WRITEMASK_Z));
+   body.emit(assign(array_ref(adj, 1), neg(
+                    add(sub(mul(matrix_elt(m, 0, 0), SubFactor06),
+                            mul(matrix_elt(m, 0, 2), SubFactor09)),
+                        mul(matrix_elt(m, 0, 3), SubFactor10))),
+                    WRITEMASK_Z));
+   body.emit(assign(array_ref(adj, 2),
+                    add(sub(mul(matrix_elt(m, 0, 0), SubFactor11),
+                            mul(matrix_elt(m, 0, 1), SubFactor09)),
+                        mul(matrix_elt(m, 0, 3), SubFactor12)),
+                    WRITEMASK_Z));
+   body.emit(assign(array_ref(adj, 3), neg(
+                    add(sub(mul(matrix_elt(m, 0, 0), SubFactor08),
+                            mul(matrix_elt(m, 0, 1), SubFactor10)),
+                        mul(matrix_elt(m, 0, 2), SubFactor12))),
+                    WRITEMASK_Z));
+
+   body.emit(assign(array_ref(adj, 0), neg(
+                    add(sub(mul(matrix_elt(m, 0, 1), SubFactor13),
+                            mul(matrix_elt(m, 0, 2), SubFactor14)),
+                        mul(matrix_elt(m, 0, 3), SubFactor15))),
+                    WRITEMASK_W));
+   body.emit(assign(array_ref(adj, 1),
+                    add(sub(mul(matrix_elt(m, 0, 0), SubFactor13),
+                            mul(matrix_elt(m, 0, 2), SubFactor16)),
+                        mul(matrix_elt(m, 0, 3), SubFactor17)),
+                    WRITEMASK_W));
+   body.emit(assign(array_ref(adj, 2), neg(
+                    add(sub(mul(matrix_elt(m, 0, 0), SubFactor14),
+                            mul(matrix_elt(m, 0, 1), SubFactor16)),
+                        mul(matrix_elt(m, 0, 3), SubFactor18))),
+                    WRITEMASK_W));
+   body.emit(assign(array_ref(adj, 3),
+                    add(sub(mul(matrix_elt(m, 0, 0), SubFactor15),
+                            mul(matrix_elt(m, 0, 1), SubFactor17)),
+                        mul(matrix_elt(m, 0, 2), SubFactor18)),
+                    WRITEMASK_W));
+
+   ir_expression *det =
+      add(mul(matrix_elt(m, 0, 0), matrix_elt(adj, 0, 0)),
+          add(mul(matrix_elt(m, 0, 1), matrix_elt(adj, 1, 0)),
+              add(mul(matrix_elt(m, 0, 2), matrix_elt(adj, 2, 0)),
+                  mul(matrix_elt(m, 0, 3), matrix_elt(adj, 3, 0)))));
+
+   body.emit(ret(div(adj, det)));
+
+   return sig;
+}
+
+
+ir_function_signature *
+builtin_builder::_lessThan(builtin_available_predicate avail,
+                           const glsl_type *type)
+{
+   return binop(ir_binop_less, avail,
+                glsl_type::bvec(type->vector_elements), type, type);
+}
+
+ir_function_signature *
+builtin_builder::_lessThanEqual(builtin_available_predicate avail,
+                                const glsl_type *type)
+{
+   return binop(ir_binop_lequal, avail,
+                glsl_type::bvec(type->vector_elements), type, type);
+}
+
+ir_function_signature *
+builtin_builder::_greaterThan(builtin_available_predicate avail,
+                              const glsl_type *type)
+{
+   return binop(ir_binop_greater, avail,
+                glsl_type::bvec(type->vector_elements), type, type);
+}
+
+ir_function_signature *
+builtin_builder::_greaterThanEqual(builtin_available_predicate avail,
+                                   const glsl_type *type)
+{
+   return binop(ir_binop_gequal, avail,
+                glsl_type::bvec(type->vector_elements), type, type);
+}
+
+ir_function_signature *
+builtin_builder::_equal(builtin_available_predicate avail,
+                        const glsl_type *type)
+{
+   return binop(ir_binop_equal, avail,
+                glsl_type::bvec(type->vector_elements), type, type);
+}
+
+ir_function_signature *
+builtin_builder::_notEqual(builtin_available_predicate avail,
+                           const glsl_type *type)
+{
+   return binop(ir_binop_nequal, avail,
+                glsl_type::bvec(type->vector_elements), type, type);
+}
+
+ir_function_signature *
+builtin_builder::_any(const glsl_type *type)
+{
+   return unop(always_available, ir_unop_any, glsl_type::bool_type, type);
+}
+
+ir_function_signature *
+builtin_builder::_all(const glsl_type *type)
+{
+   ir_variable *v = in_var(type, "v");
+   MAKE_SIG(glsl_type::bool_type, always_available, 1, v);
+
+   switch (type->vector_elements) {
+   case 2:
+      body.emit(ret(logic_and(swizzle_x(v), swizzle_y(v))));
+      break;
+   case 3:
+      body.emit(ret(logic_and(logic_and(swizzle_x(v), swizzle_y(v)),
+                              swizzle_z(v))));
+      break;
+   case 4:
+      body.emit(ret(logic_and(logic_and(logic_and(swizzle_x(v), swizzle_y(v)),
+                                        swizzle_z(v)),
+                              swizzle_w(v))));
+      break;
+   }
+
+   return sig;
+}
+
+UNOP(not, ir_unop_logic_not, always_available)
+
+static bool
+has_lod(const glsl_type *sampler_type)
+{
+   assert(sampler_type->is_sampler());
+
+   switch (sampler_type->sampler_dimensionality) {
+   case GLSL_SAMPLER_DIM_RECT:
+   case GLSL_SAMPLER_DIM_BUF:
+   case GLSL_SAMPLER_DIM_MS:
+      return false;
+   default:
+      return true;
+   }
+}
+
+ir_function_signature *
+builtin_builder::_textureSize(builtin_available_predicate avail,
+                              const glsl_type *return_type,
+                              const glsl_type *sampler_type)
+{
+   ir_variable *s = in_var(sampler_type, "sampler");
+   /* The sampler always exists; add optional lod later. */
+   MAKE_SIG(return_type, avail, 1, s);
+
+   ir_texture *tex = new(mem_ctx) ir_texture(ir_txs);
+   tex->set_sampler(new(mem_ctx) ir_dereference_variable(s), return_type);
+
+   if (has_lod(sampler_type)) {
+      ir_variable *lod = in_var(glsl_type::int_type, "lod");
+      sig->parameters.push_tail(lod);
+      tex->lod_info.lod = var_ref(lod);
+   } else {
+      tex->lod_info.lod = imm(0u);
+   }
+
+   body.emit(ret(tex));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_texture(ir_texture_opcode opcode,
+                          builtin_available_predicate avail,
+                          const glsl_type *return_type,
+                          const glsl_type *sampler_type,
+                          int coord_size,
+                          const glsl_type *coord_type,
+                          int flags)
+{
+   ir_variable *s = in_var(sampler_type, "sampler");
+   ir_variable *P = in_var(coord_type, "P");
+   /* The sampler and coordinate always exist; add optional parameters later. */
+   MAKE_SIG(return_type, avail, 2, s, P);
+
+   ir_texture *tex = new(mem_ctx) ir_texture(opcode);
+   tex->set_sampler(var_ref(s), return_type);
+
+   if (coord_size == coord_type->vector_elements) {
+      tex->coordinate = var_ref(P);
+   } else {
+      /* The incoming coordinate also has the projector or shadow comparitor,
+       * so we need to swizzle those away.
+       */
+      tex->coordinate = swizzle_for_size(P, coord_size);
+   }
+
+   /* The projector is always in the last component. */
+   if (flags & TEX_PROJECT)
+      tex->projector = swizzle(P, coord_type->vector_elements - 1, 1);
+
+   /* The shadow comparitor is normally in the Z component, but a few types
+    * have sufficiently large coordinates that it's in W.
+    */
+   if (sampler_type->sampler_shadow)
+      tex->shadow_comparitor = swizzle(P, MAX2(coord_size, SWIZZLE_Z), 1);
+
+   if (opcode == ir_txl) {
+      ir_variable *lod = in_var(glsl_type::float_type, "lod");
+      sig->parameters.push_tail(lod);
+      tex->lod_info.lod = var_ref(lod);
+   } else if (opcode == ir_txd) {
+      int grad_size = coord_size - (sampler_type->sampler_array ? 1 : 0);
+      ir_variable *dPdx = in_var(glsl_type::vec(grad_size), "dPdx");
+      ir_variable *dPdy = in_var(glsl_type::vec(grad_size), "dPdy");
+      sig->parameters.push_tail(dPdx);
+      sig->parameters.push_tail(dPdy);
+      tex->lod_info.grad.dPdx = var_ref(dPdx);
+      tex->lod_info.grad.dPdy = var_ref(dPdy);
+   }
+
+   if (flags & TEX_OFFSET) {
+      int offset_size = coord_size - (sampler_type->sampler_array ? 1 : 0);
+      ir_variable *offset =
+         new(mem_ctx) ir_variable(glsl_type::ivec(offset_size), "offset", ir_var_const_in);
+      sig->parameters.push_tail(offset);
+      tex->offset = var_ref(offset);
+   }
+
+   /* The "bias" parameter comes /after/ the "offset" parameter, which is
+    * inconsistent with both textureLodOffset and textureGradOffset.
+    */
+   if (opcode == ir_txb) {
+      ir_variable *bias = in_var(glsl_type::float_type, "bias");
+      sig->parameters.push_tail(bias);
+      tex->lod_info.bias = var_ref(bias);
+   }
+
+   body.emit(ret(tex));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_textureCubeArrayShadow()
+{
+   ir_variable *s = in_var(glsl_type::samplerCubeArrayShadow_type, "sampler");
+   ir_variable *P = in_var(glsl_type::vec4_type, "P");
+   ir_variable *compare = in_var(glsl_type::float_type, "compare");
+   MAKE_SIG(glsl_type::float_type, texture_cube_map_array, 3, s, P, compare);
+
+   ir_texture *tex = new(mem_ctx) ir_texture(ir_tex);
+   tex->set_sampler(var_ref(s), glsl_type::float_type);
+
+   tex->coordinate = var_ref(P);
+   tex->shadow_comparitor = var_ref(compare);
+
+   body.emit(ret(tex));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_texelFetch(builtin_available_predicate avail,
+                             const glsl_type *return_type,
+                             const glsl_type *sampler_type,
+                             const glsl_type *coord_type,
+                             const glsl_type *offset_type)
+{
+   ir_variable *s = in_var(sampler_type, "sampler");
+   ir_variable *P = in_var(coord_type, "P");
+   /* The sampler and coordinate always exist; add optional parameters later. */
+   MAKE_SIG(return_type, avail, 2, s, P);
+
+   ir_texture *tex = new(mem_ctx) ir_texture(ir_txf);
+   tex->coordinate = var_ref(P);
+   tex->set_sampler(var_ref(s), return_type);
+
+   if (sampler_type->sampler_dimensionality == GLSL_SAMPLER_DIM_MS) {
+      ir_variable *sample = in_var(glsl_type::int_type, "sample");
+      sig->parameters.push_tail(sample);
+      tex->lod_info.sample_index = var_ref(sample);
+      tex->op = ir_txf_ms;
+   } else if (has_lod(sampler_type)) {
+      ir_variable *lod = in_var(glsl_type::int_type, "lod");
+      sig->parameters.push_tail(lod);
+      tex->lod_info.lod = var_ref(lod);
+   } else {
+      tex->lod_info.lod = imm(0u);
+   }
+
+   if (offset_type != NULL) {
+      ir_variable *offset =
+         new(mem_ctx) ir_variable(offset_type, "offset", ir_var_const_in);
+      sig->parameters.push_tail(offset);
+      tex->offset = var_ref(offset);
+   }
+
+   body.emit(ret(tex));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_EmitVertex()
+{
+   MAKE_SIG(glsl_type::void_type, gs_only, 0);
+
+   body.emit(new(mem_ctx) ir_emit_vertex());
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_EndPrimitive()
+{
+   MAKE_SIG(glsl_type::void_type, gs_only, 0);
+
+   body.emit(new(mem_ctx) ir_end_primitive());
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_textureQueryLod(const glsl_type *sampler_type,
+                                  const glsl_type *coord_type)
+{
+   ir_variable *s = in_var(sampler_type, "sampler");
+   ir_variable *coord = in_var(coord_type, "coord");
+   /* The sampler and coordinate always exist; add optional parameters later. */
+   MAKE_SIG(glsl_type::vec2_type, texture_query_lod, 2, s, coord);
+
+   ir_texture *tex = new(mem_ctx) ir_texture(ir_lod);
+   tex->coordinate = var_ref(coord);
+   tex->set_sampler(var_ref(s), glsl_type::vec2_type);
+
+   body.emit(ret(tex));
+
+   return sig;
+}
+
+UNOP(dFdx, ir_unop_dFdx, fs_oes_derivatives)
+UNOP(dFdy, ir_unop_dFdy, fs_oes_derivatives)
+
+ir_function_signature *
+builtin_builder::_fwidth(const glsl_type *type)
+{
+   ir_variable *p = in_var(type, "p");
+   MAKE_SIG(type, fs_oes_derivatives, 1, p);
+
+   body.emit(ret(add(abs(expr(ir_unop_dFdx, p)), abs(expr(ir_unop_dFdy, p)))));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_noise1(const glsl_type *type)
+{
+   return unop(v110, ir_unop_noise, glsl_type::float_type, type);
+}
+
+ir_function_signature *
+builtin_builder::_noise2(const glsl_type *type)
+{
+   ir_variable *p = in_var(type, "p");
+   MAKE_SIG(glsl_type::vec2_type, v110, 1, p);
+
+   ir_constant_data b_offset;
+   b_offset.f[0] = 601.0f;
+   b_offset.f[1] = 313.0f;
+   b_offset.f[2] = 29.0f;
+   b_offset.f[3] = 277.0f;
+
+   ir_variable *a = body.make_temp(glsl_type::float_type, "a");
+   ir_variable *b = body.make_temp(glsl_type::float_type, "b");
+   ir_variable *t = body.make_temp(glsl_type::vec2_type,  "t");
+   body.emit(assign(a, expr(ir_unop_noise, p)));
+   body.emit(assign(b, expr(ir_unop_noise, add(p, imm(type, b_offset)))));
+   body.emit(assign(t, a, WRITEMASK_X));
+   body.emit(assign(t, b, WRITEMASK_Y));
+   body.emit(ret(t));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_noise3(const glsl_type *type)
+{
+   ir_variable *p = in_var(type, "p");
+   MAKE_SIG(glsl_type::vec3_type, v110, 1, p);
+
+   ir_constant_data b_offset;
+   b_offset.f[0] = 601.0f;
+   b_offset.f[1] = 313.0f;
+   b_offset.f[2] = 29.0f;
+   b_offset.f[3] = 277.0f;
+
+   ir_constant_data c_offset;
+   c_offset.f[0] = 1559.0f;
+   c_offset.f[1] = 113.0f;
+   c_offset.f[2] = 1861.0f;
+   c_offset.f[3] = 797.0f;
+
+   ir_variable *a = body.make_temp(glsl_type::float_type, "a");
+   ir_variable *b = body.make_temp(glsl_type::float_type, "b");
+   ir_variable *c = body.make_temp(glsl_type::float_type, "c");
+   ir_variable *t = body.make_temp(glsl_type::vec3_type,  "t");
+   body.emit(assign(a, expr(ir_unop_noise, p)));
+   body.emit(assign(b, expr(ir_unop_noise, add(p, imm(type, b_offset)))));
+   body.emit(assign(c, expr(ir_unop_noise, add(p, imm(type, c_offset)))));
+   body.emit(assign(t, a, WRITEMASK_X));
+   body.emit(assign(t, b, WRITEMASK_Y));
+   body.emit(assign(t, c, WRITEMASK_Z));
+   body.emit(ret(t));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_noise4(const glsl_type *type)
+{
+   ir_variable *p = in_var(type, "p");
+   MAKE_SIG(glsl_type::vec4_type, v110, 1, p);
+
+   ir_variable *_p = body.make_temp(type, "_p");
+
+   ir_constant_data p_offset;
+   p_offset.f[0] = 1559.0f;
+   p_offset.f[1] = 113.0f;
+   p_offset.f[2] = 1861.0f;
+   p_offset.f[3] = 797.0f;
+
+   body.emit(assign(_p, add(p, imm(type, p_offset))));
+
+   ir_constant_data offset;
+   offset.f[0] = 601.0f;
+   offset.f[1] = 313.0f;
+   offset.f[2] = 29.0f;
+   offset.f[3] = 277.0f;
+
+   ir_variable *a = body.make_temp(glsl_type::float_type, "a");
+   ir_variable *b = body.make_temp(glsl_type::float_type, "b");
+   ir_variable *c = body.make_temp(glsl_type::float_type, "c");
+   ir_variable *d = body.make_temp(glsl_type::float_type, "d");
+   ir_variable *t = body.make_temp(glsl_type::vec4_type,  "t");
+   body.emit(assign(a, expr(ir_unop_noise, p)));
+   body.emit(assign(b, expr(ir_unop_noise, add(p, imm(type, offset)))));
+   body.emit(assign(c, expr(ir_unop_noise, _p)));
+   body.emit(assign(d, expr(ir_unop_noise, add(_p, imm(type, offset)))));
+   body.emit(assign(t, a, WRITEMASK_X));
+   body.emit(assign(t, b, WRITEMASK_Y));
+   body.emit(assign(t, c, WRITEMASK_Z));
+   body.emit(assign(t, d, WRITEMASK_W));
+   body.emit(ret(t));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_bitfieldExtract(const glsl_type *type)
+{
+   ir_variable *value  = in_var(type, "value");
+   ir_variable *offset = in_var(glsl_type::int_type, "offset");
+   ir_variable *bits   = in_var(glsl_type::int_type, "bits");
+   MAKE_SIG(type, gpu_shader5, 3, value, offset, bits);
+
+   body.emit(ret(expr(ir_triop_bitfield_extract, value, offset, bits)));
+
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_bitfieldInsert(const glsl_type *type)
+{
+   ir_variable *base   = in_var(type, "base");
+   ir_variable *insert = in_var(type, "insert");
+   ir_variable *offset = in_var(glsl_type::int_type, "offset");
+   ir_variable *bits   = in_var(glsl_type::int_type, "bits");
+   MAKE_SIG(type, gpu_shader5, 4, base, insert, offset, bits);
+
+   body.emit(ret(bitfield_insert(base, insert, offset, bits)));
+
+   return sig;
+}
+
+UNOP(bitfieldReverse, ir_unop_bitfield_reverse, gpu_shader5)
+
+ir_function_signature *
+builtin_builder::_bitCount(const glsl_type *type)
+{
+   return unop(gpu_shader5, ir_unop_bit_count,
+               glsl_type::ivec(type->vector_elements), type);
+}
+
+ir_function_signature *
+builtin_builder::_findLSB(const glsl_type *type)
+{
+   return unop(gpu_shader5, ir_unop_find_lsb,
+               glsl_type::ivec(type->vector_elements), type);
+}
+
+ir_function_signature *
+builtin_builder::_findMSB(const glsl_type *type)
+{
+   return unop(gpu_shader5, ir_unop_find_msb,
+               glsl_type::ivec(type->vector_elements), type);
+}
+
+ir_function_signature *
+builtin_builder::_fma(const glsl_type *type)
+{
+   ir_variable *a = in_var(type, "a");
+   ir_variable *b = in_var(type, "b");
+   ir_variable *c = in_var(type, "c");
+   MAKE_SIG(type, gpu_shader5, 3, a, b, c);
+
+   body.emit(ret(fma(a, b, c)));
+
+   return sig;
+}
+/** @} */
+
+/******************************************************************************/
+
+/* The singleton instance of builtin_builder. */
+static builtin_builder builtins;
+
+/**
+ * External API (exposing the built-in module to the rest of the compiler):
+ *  @{
+ */
+void
+_mesa_glsl_initialize_builtin_functions()
+{
+   builtins.initialize();
+}
+
+void
+_mesa_glsl_release_builtin_functions()
+{
+   builtins.release();
+}
+
+ir_function_signature *
+_mesa_glsl_find_builtin_function(_mesa_glsl_parse_state *state,
+                                 const char *name, exec_list *actual_parameters)
+{
+   return builtins.find(state, name, actual_parameters);
+}
+/** @} */
index 0646e6d754c905ff23ae372dccb363b37cd0f2eb..bfbb94c5b157a9be1f0406f89c9acf4d4cda785d 100644 (file)
@@ -2126,9 +2126,19 @@ _mesa_glsl_initialize_variables(exec_list *instructions,
 extern void
 _mesa_glsl_initialize_functions(_mesa_glsl_parse_state *state);
 
+extern void
+_mesa_glsl_initialize_builtin_functions();
+
+extern ir_function_signature *
+_mesa_glsl_find_builtin_function(_mesa_glsl_parse_state *state,
+                                 const char *name, exec_list *actual_parameters);
+
 extern void
 _mesa_glsl_release_functions(void);
 
+extern void
+_mesa_glsl_release_builtin_functions(void);
+
 extern void
 reparent_ir(exec_list *list, void *mem_ctx);