Re: [Mesa-dev] [PATCH 19/23] glsl: Add image built-in function generator.

2013-12-13 Thread Francisco Jerez
Kenneth Graunke kenn...@whitecape.org writes:

 On 11/26/2013 12:02 AM, Francisco Jerez wrote:
 [snip]
 +   add_image_function(imageLoad,
 +  image_builtin_builder(*this)
 +  .emit_stub(__intrinsic_image_load)
 +  .has_return()
 +  .has_vector_data_type()
 +  .has_float_data_type()
 +  .read_only());

 I agree with Paul...I'm not a huge fan of using this pattern here.

 Using true/false, i.e.
 add_image_function(imageLoad, true, true, true, true, false, ...);
 is clearly awful.

 But what about using a flags bitfield?  Something like:

 enum image_function_flags {
RETURNS_DATA= (1  0),
HAS_VECTOR_DATA_TYPE= (1  1),
SUPPORTS_FLOATING_POINT_IMAGES  = (1  2),
READ_ONLY   = (1  3),
EMIT_STUB   = (1  4),
 };

 and then:

 void
 add_image_function(const char *name,
unsigned num_arguments,
uint32_t flags);

 i.e.
 add_image_function(imageLoad, 0,
RETURNS_DATA |
HAS_VECTOR_DATA_TYPE |
SUPPORTS_FLOATING_POINT_IMAGES |
READ_ONLY);

 That remains readable, like your code, but follows an extremely common
 pattern we already use all over the place.

That would be a reasonable solution too, I'll have a look into it.

Thanks.

 --Ken


pgpGtZjz9aAOb.pgp
Description: PGP signature
___
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev


Re: [Mesa-dev] [PATCH 19/23] glsl: Add image built-in function generator.

2013-12-12 Thread Francisco Jerez
Paul Berry stereotype...@gmail.com writes:

[...]
 I see a few downsides to this approach:

 - There is unnecessary code duplication between
 builtin_builder::create_intrinsics() and
 builtin_builder::create_builtins().  Both of them create the same set of
 functions using the same parameters, with the only difference being the
 function names and whether emit_stub() is called.  Furthermore, if the
 names passed to emit_stub() in create_builtins() have to match the function
 names used in create_intrinsics().


I've fixed this one issue (and the other minor problems you pointed out)
here [1].

 - builtin_builder::create_intrinsics() and
 builtin_builder::create_builtins() create the same set of
 image_builtin_builder objects every time they are called.  I think the code
 would be easier to follow if the set of image_builtin_builter objects were
 declared as a static const table.

 - Currently we don't have any precedent for the use of the fluent interface
 style in Mesa.  While I'm not opposed to it on principle, I don't think
 this particular use of it is very compelling, and I'd prefer to delay
 introducing it until we have a case where the benefit is clearer.


 Here's what I would recommend doing instead:

 - Change image_builtin_builder to a plain struct, and remove the fluent
 setter functions for setting its fields.

 - Remove the emit_stub boolean and instead make it an argument to
 add_image_function().

 - Remove the name parameter to add_image_function(), and instead store both
 the intrinsic name and the builtin name as separate fields in the struct.
 add_image_function() will choose which name to use based on its emit_stub
 argument.

 - At toplevel in buildin_functions.cpp, declare a static const array of
 image_builtin_builder objects, one for each image function.

 - In builtin_builder::create_intrinsics(), loop through the static array of
 image_builtin_builders, calling add_image_function() on each and passing
 false for emit_stub.

 - In builtin_builder::create_builtins(), loop through the static array of
 image_builtin_builders, calling add_image_function() on each and passing
 true for emit_stub.

Sorry but I don't see the point, the code looks considerably easier to
follow passing parameters this way rather than using anonymous
parameters because of the many arguments which are used or not in
different combinations depending on the intrinsic.  Using fluent
parameter passing was an after-the-fact change motivated by the
difficulty of verifying the correctness of the built-in definitions,
which are obviously correct structured this way.

I've actually had what you describe in front of me already and this is
cleaner [though that might well be a matter of personal taste].  I'm not
planning on going back to anonymous arguments and static arrays.

Thanks.

[1] 
http://cgit.freedesktop.org/~currojerez/mesa/commit/?h=image-load-storeid=02d4e6ee0f7665f87564ee372317fc530e0e0ef6


pgpmYLYsl2sTP.pgp
Description: PGP signature
___
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev


Re: [Mesa-dev] [PATCH 19/23] glsl: Add image built-in function generator.

2013-12-12 Thread Kenneth Graunke
On 11/26/2013 12:02 AM, Francisco Jerez wrote:
[snip]
 +   add_image_function(imageLoad,
 +  image_builtin_builder(*this)
 +  .emit_stub(__intrinsic_image_load)
 +  .has_return()
 +  .has_vector_data_type()
 +  .has_float_data_type()
 +  .read_only());

I agree with Paul...I'm not a huge fan of using this pattern here.

Using true/false, i.e.
add_image_function(imageLoad, true, true, true, true, false, ...);
is clearly awful.

But what about using a flags bitfield?  Something like:

enum image_function_flags {
   RETURNS_DATA= (1  0),
   HAS_VECTOR_DATA_TYPE= (1  1),
   SUPPORTS_FLOATING_POINT_IMAGES  = (1  2),
   READ_ONLY   = (1  3),
   EMIT_STUB   = (1  4),
};

and then:

void
add_image_function(const char *name,
   unsigned num_arguments,
   uint32_t flags);

i.e.
add_image_function(imageLoad, 0,
   RETURNS_DATA |
   HAS_VECTOR_DATA_TYPE |
   SUPPORTS_FLOATING_POINT_IMAGES |
   READ_ONLY);

That remains readable, like your code, but follows an extremely common
pattern we already use all over the place.

--Ken
___
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev


Re: [Mesa-dev] [PATCH 19/23] glsl: Add image built-in function generator.

2013-12-11 Thread Paul Berry
On 26 November 2013 00:02, Francisco Jerez curroje...@riseup.net wrote:

 Because of the combinatorial explosion of different image built-ins
 with different image dimensionalities and base data types, enumerating
 all the 242 possibilities would be annoying and a waste of .text
 space.  Instead use a special path in the built-in builder that loops
 over all the known image types.
 ---
  src/glsl/builtin_functions.cpp | 378
 +
  1 file changed, 378 insertions(+)

 diff --git a/src/glsl/builtin_functions.cpp
 b/src/glsl/builtin_functions.cpp
 index a1a338d..760e264 100644
 --- a/src/glsl/builtin_functions.cpp
 +++ b/src/glsl/builtin_functions.cpp
 @@ -334,12 +334,20 @@ shader_atomic_counters(const _mesa_glsl_parse_state
 *state)
 return state-ARB_shader_atomic_counters_enable;
  }

 +static bool
 +shader_image_load_store(const _mesa_glsl_parse_state *state)
 +{
 +   return state-ARB_shader_image_load_store_enable;


As in the previous patch, let's make this state-is_version(420, 0) ||
state-ARB_shader_image_load_store_enable so that the right thing will
happen when we get to GLSL version 4.20.


 +}
 +
  /** @} */


  
 /**/

  namespace {

 +class image_builtin_builder;
 +
  /**
   * builtin_builder: A singleton object representing the core of the
 built-in
   * function module.
 @@ -406,6 +414,13 @@ private:
 /** Create a new function and add the given signatures. */
 void add_function(const char *name, ...);

 +   /**
 +* Create a new function calling \param func for each known image
 +* type to generate its signatures.
 +*/
 +   void add_image_function(const char *name,
 +   const image_builtin_builder func);
 +
 ir_function_signature *new_sig(const glsl_type *return_type,
builtin_available_predicate avail,
int num_params, ...);
 @@ -569,6 +584,11 @@ private:
 ir_function_signature *_atomic_op(const char *intrinsic,
   builtin_available_predicate avail);

 +   ir_function_signature *_memory_barrier_intrinsic(
 +  builtin_available_predicate avail);
 +   ir_function_signature *_memory_barrier(
 +  builtin_available_predicate avail);
 +
  #undef B0
  #undef B1
  #undef B2
 @@ -576,6 +596,171 @@ private:
  #undef BA1
  #undef BA2
 /** @} */
 +
 +   friend class image_builtin_builder;
 +};
 +
 +/**
 + * Functor that generates image load, store or atomic built-in
 + * signatures given some settings.
 + */
 +class image_builtin_builder
 +{
 +public:
 +   image_builtin_builder(builtin_builder bld)
 +  : bld(bld),
 +_emit_stub(false),
 +_intrinsic_name(NULL),
 +_has_return(false),
 +_has_arguments(0),
 +_has_vector_data_type(false),
 +_has_float_data_type(false),
 +_read_only(false),
 +_write_only(false)
 +   {
 +   }
 +
 +   /**
 +* Build a stub function that calls \c intrinsic_name forwarding
 +* arguments and return type.
 +*/
 +   image_builtin_builder 
 +   emit_stub(const char *intrinsic_name)
 +   {
 +  _emit_stub = true;
 +  _intrinsic_name = intrinsic_name;
 +  return *this;
 +   }
 +
 +   image_builtin_builder 
 +   has_return()
 +   {
 +  _has_return = true;
 +  return *this;
 +   }
 +
 +   image_builtin_builder 
 +   has_arguments(unsigned n)
 +   {
 +  _has_arguments = n;
 +  return *this;
 +   }
 +
 +   image_builtin_builder 
 +   has_vector_data_type()
 +   {
 +  _has_vector_data_type = true;
 +  return *this;
 +   }
 +
 +   image_builtin_builder 
 +   has_float_data_type()
 +   {
 +  _has_float_data_type = true;
 +  return *this;
 +   }


has_float_data_type is a confusing name.  What this boolean really
represents is the fact that the function in question *supports* floating
point images.  Functions having this property may or may not have float
point data types involved in their signatures depending on the image type.
I'd suggest changing the name to supports_floating_point_images.


 +
 +   image_builtin_builder 
 +   read_only()
 +   {
 +  _read_only = true;
 +  return *this;
 +   }
 +
 +   image_builtin_builder 
 +   write_only()
 +   {
 +  _write_only = true;
 +  return *this;
 +   }
 +
 +   /**
 +* Generate the image built-in.
 +*/
 +   ir_function_signature *
 +   operator()(const glsl_type *image_type) const
 +   {
 +  if (image_type-fields.image.type == GLSL_TYPE_FLOAT 
 +  !_has_float_data_type)
 + return NULL;
 +
 +  ir_function_signature *sig = create_signature(image_type);
 +
 +  if (_emit_stub) {
 + ir_factory body(sig-body, bld.mem_ctx);
 + ir_function *f =
 bld.shader-symbols-get_function(_intrinsic_name);
 +
 + if (_has_return) {
 +ir_variable *ret_val =
 +