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 <ian.d.romanick@intel.com> v2: Define local helper function to generate ir_call nodes in the builtin generator.tags/mesa-10.1-devel
@@ -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) |
@@ -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; |
@@ -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; | |||
@@ -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 |