glsl: Add atomic functions from ARB_shader_storage_buffer_object
authorIago Toral Quiroga <itoral@igalia.com>
Thu, 23 Apr 2015 09:21:54 +0000 (11:21 +0200)
committerSamuel Iglesias Gonsalvez <siglesias@igalia.com>
Fri, 25 Sep 2015 06:39:22 +0000 (08:39 +0200)
Reviewed-by: Kristian Høgsberg <krh@bitplanet.net>
src/glsl/builtin_functions.cpp

index ede9dd867df9d8eb7055f7f82d224309413cc5e2..f0f6be21b7d49acce8bd15e8c8289734019c58d6 100644 (file)
@@ -400,6 +400,12 @@ shader_atomic_counters(const _mesa_glsl_parse_state *state)
    return state->has_atomic_counters();
 }
 
+static bool
+shader_storage_buffer_object(const _mesa_glsl_parse_state *state)
+{
+   return state->ARB_shader_storage_buffer_object_enable;
+}
+
 static bool
 shader_trinary_minmax(const _mesa_glsl_parse_state *state)
 {
@@ -741,6 +747,17 @@ private:
    ir_function_signature *_atomic_counter_op(const char *intrinsic,
                                              builtin_available_predicate avail);
 
+   ir_function_signature *_atomic_ssbo_intrinsic2(builtin_available_predicate avail,
+                                                  const glsl_type *type);
+   ir_function_signature *_atomic_ssbo_op2(const char *intrinsic,
+                                           builtin_available_predicate avail,
+                                           const glsl_type *type);
+   ir_function_signature *_atomic_ssbo_intrinsic3(builtin_available_predicate avail,
+                                                  const glsl_type *type);
+   ir_function_signature *_atomic_ssbo_op3(const char *intrinsic,
+                                           builtin_available_predicate avail,
+                                           const glsl_type *type);
+
    B1(min3)
    B1(max3)
    B1(mid3)
@@ -881,6 +898,55 @@ builtin_builder::create_intrinsics()
                 _atomic_counter_intrinsic(shader_atomic_counters),
                 NULL);
 
+   add_function("__intrinsic_ssbo_atomic_add",
+                _atomic_ssbo_intrinsic2(shader_storage_buffer_object,
+                                        glsl_type::uint_type),
+                _atomic_ssbo_intrinsic2(shader_storage_buffer_object,
+                                        glsl_type::int_type),
+                NULL);
+   add_function("__intrinsic_ssbo_atomic_min",
+                _atomic_ssbo_intrinsic2(shader_storage_buffer_object,
+                                        glsl_type::uint_type),
+                _atomic_ssbo_intrinsic2(shader_storage_buffer_object,
+                                        glsl_type::int_type),
+                NULL);
+   add_function("__intrinsic_ssbo_atomic_max",
+                _atomic_ssbo_intrinsic2(shader_storage_buffer_object,
+                                        glsl_type::uint_type),
+                _atomic_ssbo_intrinsic2(shader_storage_buffer_object,
+                                        glsl_type::int_type),
+                NULL);
+   add_function("__intrinsic_ssbo_atomic_and",
+                _atomic_ssbo_intrinsic2(shader_storage_buffer_object,
+                                        glsl_type::uint_type),
+                _atomic_ssbo_intrinsic2(shader_storage_buffer_object,
+                                        glsl_type::int_type),
+                NULL);
+   add_function("__intrinsic_ssbo_atomic_or",
+                _atomic_ssbo_intrinsic2(shader_storage_buffer_object,
+                                        glsl_type::uint_type),
+                _atomic_ssbo_intrinsic2(shader_storage_buffer_object,
+                                        glsl_type::int_type),
+                NULL);
+   add_function("__intrinsic_ssbo_atomic_xor",
+                _atomic_ssbo_intrinsic2(shader_storage_buffer_object,
+                                        glsl_type::uint_type),
+                _atomic_ssbo_intrinsic2(shader_storage_buffer_object,
+                                        glsl_type::int_type),
+                NULL);
+   add_function("__intrinsic_ssbo_atomic_exchange",
+                _atomic_ssbo_intrinsic2(shader_storage_buffer_object,
+                                        glsl_type::uint_type),
+                _atomic_ssbo_intrinsic2(shader_storage_buffer_object,
+                                        glsl_type::int_type),
+                NULL);
+   add_function("__intrinsic_ssbo_atomic_comp_swap",
+                _atomic_ssbo_intrinsic3(shader_storage_buffer_object,
+                                        glsl_type::uint_type),
+                _atomic_ssbo_intrinsic3(shader_storage_buffer_object,
+                                        glsl_type::int_type),
+                NULL);
+
    add_image_functions(false);
 
    add_function("__intrinsic_memory_barrier",
@@ -2553,6 +2619,71 @@ builtin_builder::create_builtins()
                                    shader_atomic_counters),
                 NULL);
 
+   add_function("atomicAdd",
+                _atomic_ssbo_op2("__intrinsic_ssbo_atomic_add",
+                                 shader_storage_buffer_object,
+                                 glsl_type::uint_type),
+                _atomic_ssbo_op2("__intrinsic_ssbo_atomic_add",
+                                 shader_storage_buffer_object,
+                                 glsl_type::int_type),
+                NULL);
+   add_function("atomicMin",
+                _atomic_ssbo_op2("__intrinsic_ssbo_atomic_min",
+                                 shader_storage_buffer_object,
+                                 glsl_type::uint_type),
+                _atomic_ssbo_op2("__intrinsic_ssbo_atomic_min",
+                                 shader_storage_buffer_object,
+                                 glsl_type::int_type),
+                NULL);
+   add_function("atomicMax",
+                _atomic_ssbo_op2("__intrinsic_ssbo_atomic_max",
+                                 shader_storage_buffer_object,
+                                 glsl_type::uint_type),
+                _atomic_ssbo_op2("__intrinsic_ssbo_atomic_max",
+                                 shader_storage_buffer_object,
+                                 glsl_type::int_type),
+                NULL);
+   add_function("atomicAnd",
+                _atomic_ssbo_op2("__intrinsic_ssbo_atomic_and",
+                                 shader_storage_buffer_object,
+                                 glsl_type::uint_type),
+                _atomic_ssbo_op2("__intrinsic_ssbo_atomic_and",
+                                 shader_storage_buffer_object,
+                                 glsl_type::int_type),
+                NULL);
+   add_function("atomicOr",
+                _atomic_ssbo_op2("__intrinsic_ssbo_atomic_or",
+                                 shader_storage_buffer_object,
+                                 glsl_type::uint_type),
+                _atomic_ssbo_op2("__intrinsic_ssbo_atomic_or",
+                                 shader_storage_buffer_object,
+                                 glsl_type::int_type),
+                NULL);
+   add_function("atomicXor",
+                _atomic_ssbo_op2("__intrinsic_ssbo_atomic_xor",
+                                 shader_storage_buffer_object,
+                                 glsl_type::uint_type),
+                _atomic_ssbo_op2("__intrinsic_ssbo_atomic_xor",
+                                 shader_storage_buffer_object,
+                                 glsl_type::int_type),
+                NULL);
+   add_function("atomicExchange",
+                _atomic_ssbo_op2("__intrinsic_ssbo_atomic_exchange",
+                                 shader_storage_buffer_object,
+                                 glsl_type::uint_type),
+                _atomic_ssbo_op2("__intrinsic_ssbo_atomic_exchange",
+                                 shader_storage_buffer_object,
+                                 glsl_type::int_type),
+                NULL);
+   add_function("atomicCompSwap",
+                _atomic_ssbo_op3("__intrinsic_ssbo_atomic_comp_swap",
+                                 shader_storage_buffer_object,
+                                 glsl_type::uint_type),
+                _atomic_ssbo_op3("__intrinsic_ssbo_atomic_comp_swap",
+                                 shader_storage_buffer_object,
+                                 glsl_type::int_type),
+                NULL);
+
    add_function("min3",
                 _min3(glsl_type::float_type),
                 _min3(glsl_type::vec2_type),
@@ -4848,6 +4979,27 @@ builtin_builder::_atomic_counter_intrinsic(builtin_available_predicate avail)
    return sig;
 }
 
+ir_function_signature *
+builtin_builder::_atomic_ssbo_intrinsic2(builtin_available_predicate avail,
+                                         const glsl_type *type)
+{
+   ir_variable *atomic = in_var(type, "atomic");
+   ir_variable *data = in_var(type, "data");
+   MAKE_INTRINSIC(type, avail, 2, atomic, data);
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_atomic_ssbo_intrinsic3(builtin_available_predicate avail,
+                                         const glsl_type *type)
+{
+   ir_variable *atomic = in_var(type, "atomic");
+   ir_variable *data1 = in_var(type, "data1");
+   ir_variable *data2 = in_var(type, "data2");
+   MAKE_INTRINSIC(type, avail, 3, atomic, data1, data2);
+   return sig;
+}
+
 ir_function_signature *
 builtin_builder::_atomic_counter_op(const char *intrinsic,
                                     builtin_available_predicate avail)
@@ -4862,6 +5014,39 @@ builtin_builder::_atomic_counter_op(const char *intrinsic,
    return sig;
 }
 
+ir_function_signature *
+builtin_builder::_atomic_ssbo_op2(const char *intrinsic,
+                                  builtin_available_predicate avail,
+                                  const glsl_type *type)
+{
+   ir_variable *atomic = in_var(type, "atomic_var");
+   ir_variable *data = in_var(type, "atomic_data");
+   MAKE_SIG(type, avail, 2, atomic, data);
+
+   ir_variable *retval = body.make_temp(type, "atomic_retval");
+   body.emit(call(shader->symbols->get_function(intrinsic), retval,
+                  sig->parameters));
+   body.emit(ret(retval));
+   return sig;
+}
+
+ir_function_signature *
+builtin_builder::_atomic_ssbo_op3(const char *intrinsic,
+                                  builtin_available_predicate avail,
+                                  const glsl_type *type)
+{
+   ir_variable *atomic = in_var(type, "atomic_var");
+   ir_variable *data1 = in_var(type, "atomic_data1");
+   ir_variable *data2 = in_var(type, "atomic_data2");
+   MAKE_SIG(type, avail, 3, atomic, data1, data2);
+
+   ir_variable *retval = body.make_temp(type, "atomic_retval");
+   body.emit(call(shader->symbols->get_function(intrinsic), retval,
+                  sig->parameters));
+   body.emit(ret(retval));
+   return sig;
+}
+
 ir_function_signature *
 builtin_builder::_min3(const glsl_type *type)
 {