glsl: Implement the required built-in functions when OES_shader_image_atomic is enabled.
authorFrancisco Jerez <currojerez@riseup.net>
Fri, 21 Aug 2015 11:12:22 +0000 (14:12 +0300)
committerFrancisco Jerez <currojerez@riseup.net>
Tue, 23 Feb 2016 03:56:54 +0000 (19:56 -0800)
This is basically just the same atomic functions exposed by
ARB_shader_image_load_store, with one exception:

    "highp float imageAtomicExchange(
         coherent IMAGE_PARAMS,
         float data);"

There's no float atomic exchange overload in the original
ARB_shader_image_load_store or GL 4.2, so this seems like new
functionality that requires specific back-end support and a separate
availability condition in the built-in function generator.

v2: Move image availability predicate logic into a separate static
    function for clarity.  Had to pull out the image_function_flags
    enum from the builtin_builder class for that to be possible.

Reviewed-by: Ilia Mirkin <imirkin@alum.mit.edu>
src/compiler/glsl/builtin_functions.cpp

index f488434e4c9298e1b70cb8d4580c3b5025f1aece..bbb237a102c47f137da0bd372c1751e4b557e605 100644 (file)
@@ -448,8 +448,16 @@ shader_image_load_store(const _mesa_glsl_parse_state *state)
 static bool
 shader_image_atomic(const _mesa_glsl_parse_state *state)
 {
-   return (state->is_version(420, 0) ||
-           state->ARB_shader_image_load_store_enable);
+   return (state->is_version(420, 320) ||
+           state->ARB_shader_image_load_store_enable ||
+           state->OES_shader_image_atomic_enable);
+}
+
+static bool
+shader_image_atomic_exchange_float(const _mesa_glsl_parse_state *state)
+{
+   return (state->is_version(450, 320) ||
+           state->OES_shader_image_atomic_enable);
 }
 
 static bool
@@ -577,17 +585,6 @@ private:
                                                                           unsigned num_arguments,
                                                                           unsigned flags);
 
-   enum image_function_flags {
-      IMAGE_FUNCTION_EMIT_STUB = (1 << 0),
-      IMAGE_FUNCTION_RETURNS_VOID = (1 << 1),
-      IMAGE_FUNCTION_HAS_VECTOR_DATA_TYPE = (1 << 2),
-      IMAGE_FUNCTION_SUPPORTS_FLOAT_DATA_TYPE = (1 << 3),
-      IMAGE_FUNCTION_READ_ONLY = (1 << 4),
-      IMAGE_FUNCTION_WRITE_ONLY = (1 << 5),
-      IMAGE_FUNCTION_AVAIL_ATOMIC = (1 << 6),
-      IMAGE_FUNCTION_MS_ONLY = (1 << 7),
-   };
-
    /**
     * Create a new image built-in function for all known image types.
     * \p flags is a bitfield of \c image_function_flags flags.
@@ -836,6 +833,18 @@ private:
    /** @} */
 };
 
+enum image_function_flags {
+   IMAGE_FUNCTION_EMIT_STUB = (1 << 0),
+   IMAGE_FUNCTION_RETURNS_VOID = (1 << 1),
+   IMAGE_FUNCTION_HAS_VECTOR_DATA_TYPE = (1 << 2),
+   IMAGE_FUNCTION_SUPPORTS_FLOAT_DATA_TYPE = (1 << 3),
+   IMAGE_FUNCTION_READ_ONLY = (1 << 4),
+   IMAGE_FUNCTION_WRITE_ONLY = (1 << 5),
+   IMAGE_FUNCTION_AVAIL_ATOMIC = (1 << 6),
+   IMAGE_FUNCTION_MS_ONLY = (1 << 7),
+   IMAGE_FUNCTION_AVAIL_ATOMIC_EXCHANGE = (1 << 8)
+};
+
 } /* anonymous namespace */
 
 /**
@@ -2981,7 +2990,9 @@ builtin_builder::add_image_functions(bool glsl)
    add_image_function((glsl ? "imageAtomicExchange" :
                        "__intrinsic_image_atomic_exchange"),
                       "__intrinsic_image_atomic_exchange",
-                      &builtin_builder::_image_prototype, 1, atom_flags);
+                      &builtin_builder::_image_prototype, 1,
+                      (flags | IMAGE_FUNCTION_AVAIL_ATOMIC_EXCHANGE |
+                       IMAGE_FUNCTION_SUPPORTS_FLOAT_DATA_TYPE));
 
    add_image_function((glsl ? "imageAtomicCompSwap" :
                        "__intrinsic_image_atomic_comp_swap"),
@@ -5232,6 +5243,21 @@ builtin_builder::_mid3(const glsl_type *type)
    return sig;
 }
 
+static builtin_available_predicate
+get_image_available_predicate(const glsl_type *type, unsigned flags)
+{
+   if ((flags & IMAGE_FUNCTION_AVAIL_ATOMIC_EXCHANGE) &&
+       type->sampled_type == GLSL_TYPE_FLOAT)
+      return shader_image_atomic_exchange_float;
+
+   else if (flags & (IMAGE_FUNCTION_AVAIL_ATOMIC_EXCHANGE |
+                     IMAGE_FUNCTION_AVAIL_ATOMIC))
+      return shader_image_atomic;
+
+   else
+      return shader_image_load_store;
+}
+
 ir_function_signature *
 builtin_builder::_image_prototype(const glsl_type *image_type,
                                   unsigned num_arguments,
@@ -5249,10 +5275,9 @@ builtin_builder::_image_prototype(const glsl_type *image_type,
    ir_variable *coord = in_var(
       glsl_type::ivec(image_type->coordinate_components()), "coord");
 
-   const builtin_available_predicate avail =
-      (flags & IMAGE_FUNCTION_AVAIL_ATOMIC ? shader_image_atomic :
-       shader_image_load_store);
-   ir_function_signature *sig = new_sig(ret_type, avail, 2, image, coord);
+   ir_function_signature *sig = new_sig(
+      ret_type, get_image_available_predicate(image_type, flags),
+      2, image, coord);
 
    /* Sample index for multisample images. */
    if (image_type->sampler_dimensionality == GLSL_SAMPLER_DIM_MS)