From 95629223761e076323faab93f72c955e61a38a75 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Wed, 25 Sep 2013 11:55:06 -0700 Subject: [PATCH] glsl: Basic support for built-in intrinsics. Fix the linker to deal with intrinsic functions which are undefined all the way down to the driver back-end, and introduce intrinsic definition helpers in the built-in generator. We still need to figure out what kind of interface we want for drivers to communicate to the GLSL front-end which of the supported intrinsics should use a default GLSL implementation and which should use a hardware-specific override. As there's no default GLSL implementation for atomic ops, this seems like something we can worry about later on. Reviewed-by: Ian Romanick v2: Define local helper function to generate ir_call nodes in the builtin generator. --- src/glsl/builtin_functions.cpp | 49 +++++++++++++++++++++++++++++++--- src/glsl/ir.cpp | 4 +-- src/glsl/ir.h | 6 +++++ src/glsl/link_functions.cpp | 16 ++++++----- 4 files changed, 64 insertions(+), 11 deletions(-) diff --git a/src/glsl/builtin_functions.cpp b/src/glsl/builtin_functions.cpp index 45fff4c096f..f122259e67d 100644 --- a/src/glsl/builtin_functions.cpp +++ b/src/glsl/builtin_functions.cpp @@ -365,6 +365,7 @@ private: ir_variable *gl_Vertex; void create_shader(); + void create_intrinsics(); void create_builtins(); /** @@ -386,6 +387,14 @@ private: ir_expression *asin_expr(ir_variable *x); + /** + * Call function \param f with parameters specified as the linked + * list \param params of \c ir_variable objects. \param ret should + * point to the ir_variable that will hold the function return + * value, or be \c NULL if the function has void return type. + */ + ir_call *call(ir_function *f, ir_variable *ret, exec_list params); + /** Create a new function and add the given signatures. */ void add_function(const char *name, ...); @@ -609,6 +618,7 @@ builtin_builder::initialize() mem_ctx = ralloc_context(NULL); create_shader(); + create_intrinsics(); create_builtins(); } @@ -645,6 +655,15 @@ builtin_builder::create_shader() /** @} */ +/** + * Create ir_function and ir_function_signature objects for each + * intrinsic. + */ +void +builtin_builder::create_intrinsics() +{ +} + /** * Create ir_function and ir_function_signature objects for each built-in. * @@ -2071,8 +2090,6 @@ builtin_builder::add_function(const char *name, ...) if (sig == NULL) break; - sig->is_defined = true; - if (false) { exec_list stuff; stuff.push_tail(sig); @@ -2170,7 +2187,13 @@ builtin_builder::new_sig(const glsl_type *return_type, #define MAKE_SIG(return_type, avail, ...) \ ir_function_signature *sig = \ new_sig(return_type, avail, __VA_ARGS__); \ - ir_factory body(&sig->body, mem_ctx); + ir_factory body(&sig->body, mem_ctx); \ + sig->is_defined = true; + +#define MAKE_INTRINSIC(return_type, avail, ...) \ + ir_function_signature *sig = \ + new_sig(return_type, avail, __VA_ARGS__); \ + sig->is_intrinsic = true; ir_function_signature * builtin_builder::unop(builtin_available_predicate avail, @@ -2262,6 +2285,26 @@ builtin_builder::asin_expr(ir_variable *x) mul(abs(x), imm(-0.03102955f)))))))))); } +ir_call * +builtin_builder::call(ir_function *f, ir_variable *ret, exec_list params) +{ + exec_list actual_params; + + foreach_iter(exec_list_iterator, it, params) { + ir_variable *var = ((ir_instruction *)it.get())->as_variable(); + actual_params.push_tail(var_ref(var)); + } + + ir_function_signature *sig = + f->exact_matching_signature(NULL, &actual_params); + if (!sig) + return NULL; + + ir_dereference_variable *deref = + (sig->return_type->is_void() ? NULL : var_ref(ret)); + + return new(mem_ctx) ir_call(sig, deref, &actual_params); +} ir_function_signature * builtin_builder::_asin(const glsl_type *type) diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 09dbf401fe4..768c4dcc707 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -1647,8 +1647,8 @@ ir_variable::determine_interpolation_mode(bool flat_shade) ir_function_signature::ir_function_signature(const glsl_type *return_type, builtin_available_predicate b) - : return_type(return_type), is_defined(false), builtin_avail(b), - _function(NULL) + : return_type(return_type), is_defined(false), is_intrinsic(false), + builtin_avail(b), _function(NULL) { this->ir_type = ir_type_function_signature; this->origin = NULL; diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 85b4d057f5e..49de9e358bd 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -787,6 +787,12 @@ public: /** Whether or not this function signature is a built-in. */ bool is_builtin() const; + /** + * Whether or not this function is an intrinsic to be implemented + * by the driver. + */ + bool is_intrinsic; + /** Whether or not a built-in is available for this shader. */ bool is_builtin_available(const _mesa_glsl_parse_state *state) const; diff --git a/src/glsl/link_functions.cpp b/src/glsl/link_functions.cpp index fd800999802..68aa6203289 100644 --- a/src/glsl/link_functions.cpp +++ b/src/glsl/link_functions.cpp @@ -155,14 +155,17 @@ public: linked_sig->replace_parameters(&formal_parameters); - foreach_list_const(node, &sig->body) { - const ir_instruction *const original = (ir_instruction *) node; + if (sig->is_defined) { + foreach_list_const(node, &sig->body) { + const ir_instruction *const original = (ir_instruction *) node; - ir_instruction *copy = original->clone(linked, ht); - linked_sig->body.push_tail(copy); + ir_instruction *copy = original->clone(linked, ht); + linked_sig->body.push_tail(copy); + } + + linked_sig->is_defined = true; } - linked_sig->is_defined = true; hash_table_dtor(ht); /* Patch references inside the function to things outside the function @@ -307,7 +310,8 @@ find_matching_signature(const char *name, const exec_list *actual_parameters, ir_function_signature *sig = f->matching_signature(NULL, actual_parameters); - if ((sig == NULL) || !sig->is_defined) + if ((sig == NULL) || + (!sig->is_defined && !sig->is_intrinsic)) continue; /* If this function expects to bind to a built-in function and the -- 2.30.2