glsl/types: Add support for function types

SPIR-V has a concept of a function type that's used fairly heavily.  We
could special-case function types in SPIR-V -> NIR but it's easier if we
just add support to glsl_types.

Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
This commit is contained in:
Jason Ekstrand
2016-02-09 18:17:06 -08:00
parent 5ec6a65388
commit 95ea9f7708
11 changed files with 140 additions and 1 deletions

View File

@@ -1135,6 +1135,7 @@ do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1)
case GLSL_TYPE_INTERFACE: case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_ATOMIC_UINT: case GLSL_TYPE_ATOMIC_UINT:
case GLSL_TYPE_SUBROUTINE: case GLSL_TYPE_SUBROUTINE:
case GLSL_TYPE_FUNCTION:
/* I assume a comparison of a struct containing a sampler just /* I assume a comparison of a struct containing a sampler just
* ignores the sampler present in the type. * ignores the sampler present in the type.
*/ */

View File

@@ -373,6 +373,7 @@ ir_constant::clone(void *mem_ctx, struct hash_table *ht) const
case GLSL_TYPE_ERROR: case GLSL_TYPE_ERROR:
case GLSL_TYPE_SUBROUTINE: case GLSL_TYPE_SUBROUTINE:
case GLSL_TYPE_INTERFACE: case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_FUNCTION:
assert(!"Should not get here."); assert(!"Should not get here.");
break; break;
} }

View File

@@ -90,6 +90,7 @@ copy_constant_to_storage(union gl_constant_value *storage,
case GLSL_TYPE_INTERFACE: case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_VOID: case GLSL_TYPE_VOID:
case GLSL_TYPE_SUBROUTINE: case GLSL_TYPE_SUBROUTINE:
case GLSL_TYPE_FUNCTION:
case GLSL_TYPE_ERROR: case GLSL_TYPE_ERROR:
/* All other types should have already been filtered by other /* All other types should have already been filtered by other
* paths in the caller. * paths in the caller.

View File

@@ -103,6 +103,7 @@ generate_data_element(void *mem_ctx, const glsl_type *type,
case GLSL_TYPE_ERROR: case GLSL_TYPE_ERROR:
case GLSL_TYPE_INTERFACE: case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_SUBROUTINE: case GLSL_TYPE_SUBROUTINE:
case GLSL_TYPE_FUNCTION:
ASSERT_TRUE(false); ASSERT_TRUE(false);
break; break;
} }
@@ -136,6 +137,7 @@ generate_data_element(void *mem_ctx, const glsl_type *type,
case GLSL_TYPE_ERROR: case GLSL_TYPE_ERROR:
case GLSL_TYPE_INTERFACE: case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_SUBROUTINE: case GLSL_TYPE_SUBROUTINE:
case GLSL_TYPE_FUNCTION:
ASSERT_TRUE(false); ASSERT_TRUE(false);
break; break;
} }
@@ -241,6 +243,7 @@ verify_data(gl_constant_value *storage, unsigned storage_array_size,
case GLSL_TYPE_ERROR: case GLSL_TYPE_ERROR:
case GLSL_TYPE_INTERFACE: case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_SUBROUTINE: case GLSL_TYPE_SUBROUTINE:
case GLSL_TYPE_FUNCTION:
ASSERT_TRUE(false); ASSERT_TRUE(false);
break; break;
} }

View File

@@ -32,6 +32,7 @@ mtx_t glsl_type::mutex = _MTX_INITIALIZER_NP;
hash_table *glsl_type::array_types = NULL; hash_table *glsl_type::array_types = NULL;
hash_table *glsl_type::record_types = NULL; hash_table *glsl_type::record_types = NULL;
hash_table *glsl_type::interface_types = NULL; hash_table *glsl_type::interface_types = NULL;
hash_table *glsl_type::function_types = NULL;
hash_table *glsl_type::subroutine_types = NULL; hash_table *glsl_type::subroutine_types = NULL;
void *glsl_type::mem_ctx = NULL; void *glsl_type::mem_ctx = NULL;
@@ -174,6 +175,39 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
mtx_unlock(&glsl_type::mutex); mtx_unlock(&glsl_type::mutex);
} }
glsl_type::glsl_type(const glsl_type *return_type,
const glsl_function_param *params, unsigned num_params) :
gl_type(0),
base_type(GLSL_TYPE_FUNCTION),
sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
sampled_type(0), interface_packing(0),
vector_elements(0), matrix_columns(0),
length(num_params)
{
unsigned int i;
mtx_lock(&glsl_type::mutex);
init_ralloc_type_ctx();
this->fields.parameters = rzalloc_array(this->mem_ctx,
glsl_function_param, num_params + 1);
/* We store the return type as the first parameter */
this->fields.parameters[0].type = return_type;
this->fields.parameters[0].in = false;
this->fields.parameters[0].out = true;
/* We store the i'th parameter in slot i+1 */
for (i = 0; i < length; i++) {
this->fields.parameters[i + 1].type = params[i].type;
this->fields.parameters[i + 1].in = params[i].in;
this->fields.parameters[i + 1].out = params[i].out;
}
mtx_unlock(&glsl_type::mutex);
}
glsl_type::glsl_type(const char *subroutine_name) : glsl_type::glsl_type(const char *subroutine_name) :
gl_type(0), gl_type(0),
base_type(GLSL_TYPE_SUBROUTINE), base_type(GLSL_TYPE_SUBROUTINE),
@@ -929,6 +963,74 @@ glsl_type::get_subroutine_instance(const char *subroutine_name)
} }
static bool
function_key_compare(const void *a, const void *b)
{
const glsl_type *const key1 = (glsl_type *) a;
const glsl_type *const key2 = (glsl_type *) b;
if (key1->length != key2->length)
return 1;
return memcmp(key1->fields.parameters, key2->fields.parameters,
(key1->length + 1) * sizeof(*key1->fields.parameters)) == 0;
}
static uint32_t
function_key_hash(const void *a)
{
const glsl_type *const key = (glsl_type *) a;
char hash_key[128];
unsigned size = 0;
size = snprintf(hash_key, sizeof(hash_key), "%08x", key->length);
for (unsigned i = 0; i < key->length; i++) {
if (size >= sizeof(hash_key))
break;
size += snprintf(& hash_key[size], sizeof(hash_key) - size,
"%p", (void *) key->fields.structure[i].type);
}
return _mesa_hash_string(hash_key);
}
const glsl_type *
glsl_type::get_function_instance(const glsl_type *return_type,
const glsl_function_param *params,
unsigned num_params)
{
const glsl_type key(return_type, params, num_params);
mtx_lock(&glsl_type::mutex);
if (function_types == NULL) {
function_types = _mesa_hash_table_create(NULL, function_key_hash,
function_key_compare);
}
struct hash_entry *entry = _mesa_hash_table_search(function_types, &key);
if (entry == NULL) {
mtx_unlock(&glsl_type::mutex);
const glsl_type *t = new glsl_type(return_type, params, num_params);
mtx_lock(&glsl_type::mutex);
entry = _mesa_hash_table_insert(function_types, t, (void *) t);
}
const glsl_type *t = (const glsl_type *)entry->data;
assert(t->base_type == GLSL_TYPE_FUNCTION);
assert(t->length == num_params);
mtx_unlock(&glsl_type::mutex);
return t;
}
const glsl_type * const glsl_type *
glsl_type::get_mul_type(const glsl_type *type_a, const glsl_type *type_b) glsl_type::get_mul_type(const glsl_type *type_a, const glsl_type *type_b)
{ {
@@ -1058,6 +1160,8 @@ glsl_type::component_slots() const
return 1; return 1;
case GLSL_TYPE_SUBROUTINE: case GLSL_TYPE_SUBROUTINE:
return 1; return 1;
case GLSL_TYPE_FUNCTION:
case GLSL_TYPE_SAMPLER: case GLSL_TYPE_SAMPLER:
case GLSL_TYPE_ATOMIC_UINT: case GLSL_TYPE_ATOMIC_UINT:
case GLSL_TYPE_VOID: case GLSL_TYPE_VOID:
@@ -1703,6 +1807,7 @@ glsl_type::count_attribute_slots(bool vertex_input_slots) const
case GLSL_TYPE_ARRAY: case GLSL_TYPE_ARRAY:
return this->length * this->fields.array->count_attribute_slots(vertex_input_slots); return this->length * this->fields.array->count_attribute_slots(vertex_input_slots);
case GLSL_TYPE_FUNCTION:
case GLSL_TYPE_SAMPLER: case GLSL_TYPE_SAMPLER:
case GLSL_TYPE_IMAGE: case GLSL_TYPE_IMAGE:
case GLSL_TYPE_ATOMIC_UINT: case GLSL_TYPE_ATOMIC_UINT:

View File

@@ -60,6 +60,7 @@ enum glsl_base_type {
GLSL_TYPE_ARRAY, GLSL_TYPE_ARRAY,
GLSL_TYPE_VOID, GLSL_TYPE_VOID,
GLSL_TYPE_SUBROUTINE, GLSL_TYPE_SUBROUTINE,
GLSL_TYPE_FUNCTION,
GLSL_TYPE_ERROR GLSL_TYPE_ERROR
}; };
@@ -187,7 +188,7 @@ struct glsl_type {
*/ */
union { union {
const struct glsl_type *array; /**< Type of array elements. */ const struct glsl_type *array; /**< Type of array elements. */
const struct glsl_type *parameters; /**< Parameters to function. */ struct glsl_function_param *parameters; /**< Parameters to function. */
struct glsl_struct_field *structure; /**< List of struct fields. */ struct glsl_struct_field *structure; /**< List of struct fields. */
} fields; } fields;
@@ -277,6 +278,13 @@ struct glsl_type {
*/ */
static const glsl_type *get_subroutine_instance(const char *subroutine_name); static const glsl_type *get_subroutine_instance(const char *subroutine_name);
/**
* Get the instance of a function type
*/
static const glsl_type *get_function_instance(const struct glsl_type *return_type,
const glsl_function_param *parameters,
unsigned num_params);
/** /**
* Get the type resulting from a multiplication of \p type_a * \p type_b * Get the type resulting from a multiplication of \p type_a * \p type_b
*/ */
@@ -758,6 +766,10 @@ private:
glsl_type(const glsl_struct_field *fields, unsigned num_fields, glsl_type(const glsl_struct_field *fields, unsigned num_fields,
enum glsl_interface_packing packing, const char *name); enum glsl_interface_packing packing, const char *name);
/** Constructor for interface types */
glsl_type(const glsl_type *return_type,
const glsl_function_param *params, unsigned num_params);
/** Constructor for array types */ /** Constructor for array types */
glsl_type(const glsl_type *array, unsigned length); glsl_type(const glsl_type *array, unsigned length);
@@ -776,6 +788,9 @@ private:
/** Hash table containing the known subroutine types. */ /** Hash table containing the known subroutine types. */
static struct hash_table *subroutine_types; static struct hash_table *subroutine_types;
/** Hash table containing the known function types. */
static struct hash_table *function_types;
static bool record_key_compare(const void *a, const void *b); static bool record_key_compare(const void *a, const void *b);
static unsigned record_key_hash(const void *key); static unsigned record_key_hash(const void *key);
@@ -875,6 +890,13 @@ struct glsl_struct_field {
} }
}; };
struct glsl_function_param {
const struct glsl_type *type;
bool in;
bool out;
};
static inline unsigned int static inline unsigned int
glsl_align(unsigned int a, unsigned int align) glsl_align(unsigned int a, unsigned int align)
{ {

View File

@@ -510,6 +510,7 @@ type_size_scalar(const struct glsl_type *type)
case GLSL_TYPE_ERROR: case GLSL_TYPE_ERROR:
case GLSL_TYPE_INTERFACE: case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_DOUBLE: case GLSL_TYPE_DOUBLE:
case GLSL_TYPE_FUNCTION:
unreachable("not reached"); unreachable("not reached");
} }

View File

@@ -84,6 +84,7 @@ brw_type_for_base_type(const struct glsl_type *type)
case GLSL_TYPE_ERROR: case GLSL_TYPE_ERROR:
case GLSL_TYPE_INTERFACE: case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_DOUBLE: case GLSL_TYPE_DOUBLE:
case GLSL_TYPE_FUNCTION:
unreachable("not reached"); unreachable("not reached");
} }

View File

@@ -622,6 +622,7 @@ type_size_vec4(const struct glsl_type *type)
case GLSL_TYPE_DOUBLE: case GLSL_TYPE_DOUBLE:
case GLSL_TYPE_ERROR: case GLSL_TYPE_ERROR:
case GLSL_TYPE_INTERFACE: case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_FUNCTION:
unreachable("not reached"); unreachable("not reached");
} }

View File

@@ -541,6 +541,7 @@ type_size(const struct glsl_type *type)
case GLSL_TYPE_VOID: case GLSL_TYPE_VOID:
case GLSL_TYPE_ERROR: case GLSL_TYPE_ERROR:
case GLSL_TYPE_INTERFACE: case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_FUNCTION:
assert(!"Invalid type in type_size"); assert(!"Invalid type in type_size");
break; break;
} }
@@ -2521,6 +2522,7 @@ _mesa_associate_uniform_storage(struct gl_context *ctx,
case GLSL_TYPE_STRUCT: case GLSL_TYPE_STRUCT:
case GLSL_TYPE_ERROR: case GLSL_TYPE_ERROR:
case GLSL_TYPE_INTERFACE: case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_FUNCTION:
assert(!"Should not get here."); assert(!"Should not get here.");
break; break;
} }

View File

@@ -1216,6 +1216,7 @@ attrib_type_size(const struct glsl_type *type, bool is_vs_input)
case GLSL_TYPE_INTERFACE: case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_VOID: case GLSL_TYPE_VOID:
case GLSL_TYPE_ERROR: case GLSL_TYPE_ERROR:
case GLSL_TYPE_FUNCTION:
assert(!"Invalid type in type_size"); assert(!"Invalid type in type_size");
break; break;
} }