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 <ian.d.romanick@intel.com> v2: Define local helper function to generate ir_call nodes in the builtin generator.
This commit is contained in:
@@ -365,6 +365,7 @@ private:
|
|||||||
ir_variable *gl_Vertex;
|
ir_variable *gl_Vertex;
|
||||||
|
|
||||||
void create_shader();
|
void create_shader();
|
||||||
|
void create_intrinsics();
|
||||||
void create_builtins();
|
void create_builtins();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -386,6 +387,14 @@ private:
|
|||||||
|
|
||||||
ir_expression *asin_expr(ir_variable *x);
|
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. */
|
/** Create a new function and add the given signatures. */
|
||||||
void add_function(const char *name, ...);
|
void add_function(const char *name, ...);
|
||||||
|
|
||||||
@@ -609,6 +618,7 @@ builtin_builder::initialize()
|
|||||||
|
|
||||||
mem_ctx = ralloc_context(NULL);
|
mem_ctx = ralloc_context(NULL);
|
||||||
create_shader();
|
create_shader();
|
||||||
|
create_intrinsics();
|
||||||
create_builtins();
|
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.
|
* 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)
|
if (sig == NULL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
sig->is_defined = true;
|
|
||||||
|
|
||||||
if (false) {
|
if (false) {
|
||||||
exec_list stuff;
|
exec_list stuff;
|
||||||
stuff.push_tail(sig);
|
stuff.push_tail(sig);
|
||||||
@@ -2170,7 +2187,13 @@ builtin_builder::new_sig(const glsl_type *return_type,
|
|||||||
#define MAKE_SIG(return_type, avail, ...) \
|
#define MAKE_SIG(return_type, avail, ...) \
|
||||||
ir_function_signature *sig = \
|
ir_function_signature *sig = \
|
||||||
new_sig(return_type, avail, __VA_ARGS__); \
|
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 *
|
ir_function_signature *
|
||||||
builtin_builder::unop(builtin_available_predicate avail,
|
builtin_builder::unop(builtin_available_predicate avail,
|
||||||
@@ -2262,6 +2285,26 @@ builtin_builder::asin_expr(ir_variable *x)
|
|||||||
mul(abs(x), imm(-0.03102955f))))))))));
|
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 *
|
ir_function_signature *
|
||||||
builtin_builder::_asin(const glsl_type *type)
|
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,
|
ir_function_signature::ir_function_signature(const glsl_type *return_type,
|
||||||
builtin_available_predicate b)
|
builtin_available_predicate b)
|
||||||
: return_type(return_type), is_defined(false), builtin_avail(b),
|
: return_type(return_type), is_defined(false), is_intrinsic(false),
|
||||||
_function(NULL)
|
builtin_avail(b), _function(NULL)
|
||||||
{
|
{
|
||||||
this->ir_type = ir_type_function_signature;
|
this->ir_type = ir_type_function_signature;
|
||||||
this->origin = NULL;
|
this->origin = NULL;
|
||||||
|
@@ -787,6 +787,12 @@ public:
|
|||||||
/** Whether or not this function signature is a built-in. */
|
/** Whether or not this function signature is a built-in. */
|
||||||
bool is_builtin() const;
|
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. */
|
/** Whether or not a built-in is available for this shader. */
|
||||||
bool is_builtin_available(const _mesa_glsl_parse_state *state) const;
|
bool is_builtin_available(const _mesa_glsl_parse_state *state) const;
|
||||||
|
|
||||||
|
@@ -155,6 +155,7 @@ public:
|
|||||||
|
|
||||||
linked_sig->replace_parameters(&formal_parameters);
|
linked_sig->replace_parameters(&formal_parameters);
|
||||||
|
|
||||||
|
if (sig->is_defined) {
|
||||||
foreach_list_const(node, &sig->body) {
|
foreach_list_const(node, &sig->body) {
|
||||||
const ir_instruction *const original = (ir_instruction *) node;
|
const ir_instruction *const original = (ir_instruction *) node;
|
||||||
|
|
||||||
@@ -163,6 +164,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
linked_sig->is_defined = true;
|
linked_sig->is_defined = true;
|
||||||
|
}
|
||||||
|
|
||||||
hash_table_dtor(ht);
|
hash_table_dtor(ht);
|
||||||
|
|
||||||
/* Patch references inside the function to things outside the function
|
/* 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 =
|
ir_function_signature *sig =
|
||||||
f->matching_signature(NULL, actual_parameters);
|
f->matching_signature(NULL, actual_parameters);
|
||||||
|
|
||||||
if ((sig == NULL) || !sig->is_defined)
|
if ((sig == NULL) ||
|
||||||
|
(!sig->is_defined && !sig->is_intrinsic))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* If this function expects to bind to a built-in function and the
|
/* If this function expects to bind to a built-in function and the
|
||||||
|
Reference in New Issue
Block a user