[Mesa-dev] [PATCH 18/21] glsl: Write a new built-in function module.

Pohjolainen, Topi topi.pohjolainen at intel.com
Thu Sep 5 04:47:52 PDT 2013


On Thu, Sep 05, 2013 at 02:27:04PM +0300, Pohjolainen, Topi wrote:
> On Wed, Sep 04, 2013 at 03:22:41PM -0700, Kenneth Graunke wrote:
> > 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.
> > 
> > Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
> > ---
> >  src/glsl/Makefile.sources      |    1 +
> >  src/glsl/builtin_functions.cpp | 3466 ++++++++++++++++++++++++++++++++++++++++
> >  src/glsl/ir.h                  |   10 +
> >  3 files changed, 3477 insertions(+)
> >  create mode 100644 src/glsl/builtin_functions.cpp
> > 
> > diff --git a/src/glsl/Makefile.sources b/src/glsl/Makefile.sources
> > index 979c416..3e706ef 100644
> > --- a/src/glsl/Makefile.sources
> > +++ b/src/glsl/Makefile.sources
> > @@ -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
> > index 0000000..440ec41
> > --- /dev/null
> > +++ b/src/glsl/builtin_functions.cpp
> > @@ -0,0 +1,3466 @@
> > +/*
> > + * 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 "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
> > +legacy_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;
> > +}
> > +
> > +static bool
> > +vs_or_shader_texture_lod(const _mesa_glsl_parse_state *state)
> > +{
> > +   return state->target == vertex_shader ||
> > +          state->ARB_shader_texture_lod_enable ||
> > +          state->is_version(130, 0);
> > +}
> > +
> > +static bool
> > +v110_vs_or_shader_texture_lod(const _mesa_glsl_parse_state *state)
> > +{
> > +   return !state->es_shader && vs_or_shader_texture_lod(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->is_version(400, 0) || 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
> > +oes_tex3d(const _mesa_glsl_parse_state *state)
> > +{
> > +   return !state->es_shader || state->OES_texture_3D_enable;
> > +}
> > +
> > +static bool
> > +vs_oes_tex3d(const _mesa_glsl_parse_state *state)
> > +{
> > +   return state->target == vertex_shader &&
> > +          (!state->es_shader || state->OES_texture_3D_enable);
> > +}
> > +
> > +static bool
> > +fs_oes_tex3d(const _mesa_glsl_parse_state *state)
> > +{
> > +   return state->target == fragment_shader &&
> > +          (!state->es_shader || state->OES_texture_3D_enable);
> > +}
> > +
> > +static bool
> > +vs_oes_tex3d_or_shader_texture_lod(const _mesa_glsl_parse_state *state)
> > +{
> > +   return state->ARB_shader_texture_lod_enable || vs_oes_tex3d(state);
> > +}
> > +/** @} */
> > +
> > +/******************************************************************************/
> > +
> > +/**
> > + * builtin_builder: A singleton object representing the core of the built-in
> > + * function module.
> 
> I also started wondering about the meaning for "singleton" here, below there is
> public constructor allowing one to create more than one instance.
> 

I should have read until the end before commenting - even though the class does
not limit the number of instances, there is only one static instance created out
of the class. Sorry for the noise.

> > + *
> > + * It has code to generate
> > + * 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;
> > +   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_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 *);
> > +   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)
> > +   B2(min)
> > +   B2(max)
> > +   B2(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);
> > +   B1(lessThan);
> > +   B1(lessThanEqual);
> > +   B1(greaterThan);
> > +   B1(greaterThanEqual);
> > +   B1(equal);
> > +   B1(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 B
> > +   /** @} */
> > +};
> 
> <snip>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list