#include "util/hash_table.h"
-mtx_t glsl_type::mutex = _MTX_INITIALIZER_NP;
+mtx_t glsl_type::mem_mutex = _MTX_INITIALIZER_NP;
+mtx_t glsl_type::hash_mutex = _MTX_INITIALIZER_NP;
hash_table *glsl_type::array_types = NULL;
hash_table *glsl_type::record_types = NULL;
hash_table *glsl_type::interface_types = NULL;
+hash_table *glsl_type::function_types = NULL;
hash_table *glsl_type::subroutine_types = NULL;
void *glsl_type::mem_ctx = NULL;
glsl_type::init_ralloc_type_ctx(void)
{
if (glsl_type::mem_ctx == NULL) {
- glsl_type::mem_ctx = ralloc_autofree_context();
+ glsl_type::mem_ctx = ralloc_context(NULL);
assert(glsl_type::mem_ctx != NULL);
}
}
gl_type(gl_type),
base_type(base_type),
sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
- sampler_type(0), interface_packing(0),
+ sampled_type(0), interface_packing(0), interface_row_major(0),
vector_elements(vector_elements), matrix_columns(matrix_columns),
length(0)
{
- mtx_lock(&glsl_type::mutex);
+ /* Values of these types must fit in the two bits of
+ * glsl_type::sampled_type.
+ */
+ STATIC_ASSERT((unsigned(GLSL_TYPE_UINT) & 3) == unsigned(GLSL_TYPE_UINT));
+ STATIC_ASSERT((unsigned(GLSL_TYPE_INT) & 3) == unsigned(GLSL_TYPE_INT));
+ STATIC_ASSERT((unsigned(GLSL_TYPE_FLOAT) & 3) == unsigned(GLSL_TYPE_FLOAT));
+
+ mtx_lock(&glsl_type::mem_mutex);
init_ralloc_type_ctx();
assert(name != NULL);
this->name = ralloc_strdup(this->mem_ctx, name);
- mtx_unlock(&glsl_type::mutex);
+ mtx_unlock(&glsl_type::mem_mutex);
/* Neither dimension is zero or both dimensions are zero.
*/
gl_type(gl_type),
base_type(base_type),
sampler_dimensionality(dim), sampler_shadow(shadow),
- sampler_array(array), sampler_type(type), interface_packing(0),
- length(0)
+ sampler_array(array), sampled_type(type), interface_packing(0),
+ interface_row_major(0), length(0)
{
- mtx_lock(&glsl_type::mutex);
+ mtx_lock(&glsl_type::mem_mutex);
init_ralloc_type_ctx();
assert(name != NULL);
this->name = ralloc_strdup(this->mem_ctx, name);
- mtx_unlock(&glsl_type::mutex);
+ mtx_unlock(&glsl_type::mem_mutex);
memset(& fields, 0, sizeof(fields));
- if (base_type == GLSL_TYPE_SAMPLER) {
- /* Samplers take no storage whatsoever. */
- matrix_columns = vector_elements = 0;
- } else {
- matrix_columns = vector_elements = 1;
- }
+ matrix_columns = vector_elements = 1;
}
glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
gl_type(0),
base_type(GLSL_TYPE_STRUCT),
sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
- sampler_type(0), interface_packing(0),
+ sampled_type(0), interface_packing(0), interface_row_major(0),
vector_elements(0), matrix_columns(0),
length(num_fields)
{
unsigned int i;
- mtx_lock(&glsl_type::mutex);
+ mtx_lock(&glsl_type::mem_mutex);
init_ralloc_type_ctx();
assert(name != NULL);
glsl_struct_field, length);
for (i = 0; i < length; i++) {
- this->fields.structure[i].type = fields[i].type;
+ this->fields.structure[i] = fields[i];
this->fields.structure[i].name = ralloc_strdup(this->fields.structure,
fields[i].name);
- this->fields.structure[i].location = fields[i].location;
- this->fields.structure[i].interpolation = fields[i].interpolation;
- this->fields.structure[i].centroid = fields[i].centroid;
- this->fields.structure[i].sample = fields[i].sample;
- this->fields.structure[i].matrix_layout = fields[i].matrix_layout;
- this->fields.structure[i].patch = fields[i].patch;
- this->fields.structure[i].image_read_only = fields[i].image_read_only;
- this->fields.structure[i].image_write_only = fields[i].image_write_only;
- this->fields.structure[i].image_coherent = fields[i].image_coherent;
- this->fields.structure[i].image_volatile = fields[i].image_volatile;
- this->fields.structure[i].image_restrict = fields[i].image_restrict;
- this->fields.structure[i].precision = fields[i].precision;
}
- mtx_unlock(&glsl_type::mutex);
+ mtx_unlock(&glsl_type::mem_mutex);
}
glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
- enum glsl_interface_packing packing, const char *name) :
+ enum glsl_interface_packing packing,
+ bool row_major, const char *name) :
gl_type(0),
base_type(GLSL_TYPE_INTERFACE),
sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
- sampler_type(0), interface_packing((unsigned) packing),
+ sampled_type(0), interface_packing((unsigned) packing),
+ interface_row_major((unsigned) row_major),
vector_elements(0), matrix_columns(0),
length(num_fields)
{
unsigned int i;
- mtx_lock(&glsl_type::mutex);
+ mtx_lock(&glsl_type::mem_mutex);
init_ralloc_type_ctx();
assert(name != NULL);
this->name = ralloc_strdup(this->mem_ctx, name);
- this->fields.structure = ralloc_array(this->mem_ctx,
- glsl_struct_field, length);
+ this->fields.structure = rzalloc_array(this->mem_ctx,
+ glsl_struct_field, length);
for (i = 0; i < length; i++) {
- this->fields.structure[i].type = fields[i].type;
+ this->fields.structure[i] = fields[i];
this->fields.structure[i].name = ralloc_strdup(this->fields.structure,
fields[i].name);
- this->fields.structure[i].location = fields[i].location;
- this->fields.structure[i].interpolation = fields[i].interpolation;
- this->fields.structure[i].centroid = fields[i].centroid;
- this->fields.structure[i].sample = fields[i].sample;
- this->fields.structure[i].matrix_layout = fields[i].matrix_layout;
- this->fields.structure[i].patch = fields[i].patch;
- this->fields.structure[i].precision = fields[i].precision;
}
- mtx_unlock(&glsl_type::mutex);
+ mtx_unlock(&glsl_type::mem_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), interface_row_major(0),
+ vector_elements(0), matrix_columns(0),
+ length(num_params)
+{
+ unsigned int i;
+
+ mtx_lock(&glsl_type::mem_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::mem_mutex);
}
glsl_type::glsl_type(const char *subroutine_name) :
gl_type(0),
base_type(GLSL_TYPE_SUBROUTINE),
sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
- sampler_type(0), interface_packing(0),
+ sampled_type(0), interface_packing(0), interface_row_major(0),
vector_elements(1), matrix_columns(1),
length(0)
{
- mtx_lock(&glsl_type::mutex);
+ mtx_lock(&glsl_type::mem_mutex);
init_ralloc_type_ctx();
assert(subroutine_name != NULL);
this->name = ralloc_strdup(this->mem_ctx, subroutine_name);
- mtx_unlock(&glsl_type::mutex);
+ mtx_unlock(&glsl_type::mem_mutex);
}
bool
{
if (this->is_array()) {
return this->fields.array->contains_sampler();
- } else if (this->is_record()) {
+ } else if (this->is_record() || this->is_interface()) {
for (unsigned int i = 0; i < this->length; i++) {
if (this->fields.structure[i].type->contains_sampler())
return true;
}
}
+bool
+glsl_type::contains_array() const
+{
+ if (this->is_record() || this->is_interface()) {
+ for (unsigned int i = 0; i < this->length; i++) {
+ if (this->fields.structure[i].type->contains_array())
+ return true;
+ }
+ return false;
+ } else {
+ return this->is_array();
+ }
+}
bool
glsl_type::contains_integer() const
{
if (this->is_array()) {
return this->fields.array->contains_integer();
- } else if (this->is_record()) {
+ } else if (this->is_record() || this->is_interface()) {
for (unsigned int i = 0; i < this->length; i++) {
if (this->fields.structure[i].type->contains_integer())
return true;
{
if (this->is_array()) {
return this->fields.array->contains_double();
- } else if (this->is_record()) {
+ } else if (this->is_record() || this->is_interface()) {
for (unsigned int i = 0; i < this->length; i++) {
if (this->fields.structure[i].type->contains_double())
return true;
case GLSL_TYPE_ARRAY:
return fields.array->contains_opaque();
case GLSL_TYPE_STRUCT:
+ case GLSL_TYPE_INTERFACE:
for (unsigned int i = 0; i < length; i++) {
if (fields.structure[i].type->contains_opaque())
return true;
{
if (this->is_array()) {
return this->fields.array->contains_subroutine();
- } else if (this->is_record()) {
+ } else if (this->is_record() || this->is_interface()) {
for (unsigned int i = 0; i < this->length; i++) {
if (this->fields.structure[i].type->contains_subroutine())
return true;
{
const glsl_type *const t = (this->is_array()) ? this->fields.array : this;
- assert(t->is_sampler());
+ assert(t->is_sampler() || t->is_image());
switch (t->sampler_dimensionality) {
case GLSL_SAMPLER_DIM_1D:
{
if (this->is_array()) {
return this->fields.array->contains_image();
- } else if (this->is_record()) {
+ } else if (this->is_record() || this->is_interface()) {
for (unsigned int i = 0; i < this->length; i++) {
if (this->fields.structure[i].type->contains_image())
return true;
return double_type;
case GLSL_TYPE_BOOL:
return bool_type;
+ case GLSL_TYPE_UINT64:
+ return uint64_t_type;
+ case GLSL_TYPE_INT64:
+ return int64_t_type;
default:
return error_type;
}
return double_type;
case GLSL_TYPE_BOOL:
return bool_type;
+ case GLSL_TYPE_UINT64:
+ return uint64_t_type;
+ case GLSL_TYPE_INT64:
+ return int64_t_type;
default:
/* Handle everything else */
return type;
_mesa_hash_table_destroy(glsl_type::interface_types, NULL);
glsl_type::interface_types = NULL;
}
+
+ if (glsl_type::function_types != NULL) {
+ _mesa_hash_table_destroy(glsl_type::function_types, NULL);
+ glsl_type::function_types = NULL;
+ }
+
+ if (glsl_type::subroutine_types != NULL) {
+ _mesa_hash_table_destroy(glsl_type::subroutine_types, NULL);
+ glsl_type::subroutine_types = NULL;
+ }
+
+ ralloc_free(glsl_type::mem_ctx);
+ glsl_type::mem_ctx = NULL;
}
glsl_type::glsl_type(const glsl_type *array, unsigned length) :
base_type(GLSL_TYPE_ARRAY),
sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
- sampler_type(0), interface_packing(0),
+ sampled_type(0), interface_packing(0), interface_row_major(0),
vector_elements(0), matrix_columns(0),
length(length), name(NULL)
{
*/
const unsigned name_length = strlen(array->name) + 10 + 3;
- mtx_lock(&glsl_type::mutex);
+ mtx_lock(&glsl_type::mem_mutex);
char *const n = (char *) ralloc_size(this->mem_ctx, name_length);
- mtx_unlock(&glsl_type::mutex);
+ mtx_unlock(&glsl_type::mem_mutex);
if (length == 0)
snprintf(n, name_length, "%s[]", array->name);
}
+const glsl_type *
+glsl_type::i64vec(unsigned components)
+{
+ if (components == 0 || components > 4)
+ return error_type;
+
+ static const glsl_type *const ts[] = {
+ int64_t_type, i64vec2_type, i64vec3_type, i64vec4_type
+ };
+ return ts[components - 1];
+}
+
+
+const glsl_type *
+glsl_type::u64vec(unsigned components)
+{
+ if (components == 0 || components > 4)
+ return error_type;
+
+ static const glsl_type *const ts[] = {
+ uint64_t_type, u64vec2_type, u64vec3_type, u64vec4_type
+ };
+ return ts[components - 1];
+}
+
const glsl_type *
glsl_type::get_instance(unsigned base_type, unsigned rows, unsigned columns)
{
return dvec(rows);
case GLSL_TYPE_BOOL:
return bvec(rows);
+ case GLSL_TYPE_UINT64:
+ return u64vec(rows);
+ case GLSL_TYPE_INT64:
+ return i64vec(rows);
default:
return error_type;
}
return error_type;
else
return samplerExternalOES_type;
+ case GLSL_SAMPLER_DIM_SUBPASS:
+ case GLSL_SAMPLER_DIM_SUBPASS_MS:
+ return error_type;
}
case GLSL_TYPE_INT:
if (shadow)
return (array ? isampler2DMSArray_type : isampler2DMS_type);
case GLSL_SAMPLER_DIM_EXTERNAL:
return error_type;
+ case GLSL_SAMPLER_DIM_SUBPASS:
+ case GLSL_SAMPLER_DIM_SUBPASS_MS:
+ return error_type;
}
case GLSL_TYPE_UINT:
if (shadow)
return (array ? usampler2DMSArray_type : usampler2DMS_type);
case GLSL_SAMPLER_DIM_EXTERNAL:
return error_type;
+ case GLSL_SAMPLER_DIM_SUBPASS:
+ case GLSL_SAMPLER_DIM_SUBPASS_MS:
+ return error_type;
+ }
+ default:
+ return error_type;
+ }
+
+ unreachable("switch statement above should be complete");
+}
+
+const glsl_type *
+glsl_type::get_image_instance(enum glsl_sampler_dim dim,
+ bool array, glsl_base_type type)
+{
+ switch (type) {
+ case GLSL_TYPE_FLOAT:
+ switch (dim) {
+ case GLSL_SAMPLER_DIM_1D:
+ return (array ? image1DArray_type : image1D_type);
+ case GLSL_SAMPLER_DIM_2D:
+ return (array ? image2DArray_type : image2D_type);
+ case GLSL_SAMPLER_DIM_3D:
+ return image3D_type;
+ case GLSL_SAMPLER_DIM_CUBE:
+ return (array ? imageCubeArray_type : imageCube_type);
+ case GLSL_SAMPLER_DIM_RECT:
+ if (array)
+ return error_type;
+ else
+ return image2DRect_type;
+ case GLSL_SAMPLER_DIM_BUF:
+ if (array)
+ return error_type;
+ else
+ return imageBuffer_type;
+ case GLSL_SAMPLER_DIM_MS:
+ return (array ? image2DMSArray_type : image2DMS_type);
+ case GLSL_SAMPLER_DIM_SUBPASS:
+ return subpassInput_type;
+ case GLSL_SAMPLER_DIM_SUBPASS_MS:
+ return subpassInputMS_type;
+ case GLSL_SAMPLER_DIM_EXTERNAL:
+ return error_type;
+ }
+ case GLSL_TYPE_INT:
+ switch (dim) {
+ case GLSL_SAMPLER_DIM_1D:
+ return (array ? iimage1DArray_type : iimage1D_type);
+ case GLSL_SAMPLER_DIM_2D:
+ return (array ? iimage2DArray_type : iimage2D_type);
+ case GLSL_SAMPLER_DIM_3D:
+ if (array)
+ return error_type;
+ return iimage3D_type;
+ case GLSL_SAMPLER_DIM_CUBE:
+ return (array ? iimageCubeArray_type : iimageCube_type);
+ case GLSL_SAMPLER_DIM_RECT:
+ if (array)
+ return error_type;
+ return iimage2DRect_type;
+ case GLSL_SAMPLER_DIM_BUF:
+ if (array)
+ return error_type;
+ return iimageBuffer_type;
+ case GLSL_SAMPLER_DIM_MS:
+ return (array ? iimage2DMSArray_type : iimage2DMS_type);
+ case GLSL_SAMPLER_DIM_SUBPASS:
+ return isubpassInput_type;
+ case GLSL_SAMPLER_DIM_SUBPASS_MS:
+ return isubpassInputMS_type;
+ case GLSL_SAMPLER_DIM_EXTERNAL:
+ return error_type;
+ }
+ case GLSL_TYPE_UINT:
+ switch (dim) {
+ case GLSL_SAMPLER_DIM_1D:
+ return (array ? uimage1DArray_type : uimage1D_type);
+ case GLSL_SAMPLER_DIM_2D:
+ return (array ? uimage2DArray_type : uimage2D_type);
+ case GLSL_SAMPLER_DIM_3D:
+ if (array)
+ return error_type;
+ return uimage3D_type;
+ case GLSL_SAMPLER_DIM_CUBE:
+ return (array ? uimageCubeArray_type : uimageCube_type);
+ case GLSL_SAMPLER_DIM_RECT:
+ if (array)
+ return error_type;
+ return uimage2DRect_type;
+ case GLSL_SAMPLER_DIM_BUF:
+ if (array)
+ return error_type;
+ return uimageBuffer_type;
+ case GLSL_SAMPLER_DIM_MS:
+ return (array ? uimage2DMSArray_type : uimage2DMS_type);
+ case GLSL_SAMPLER_DIM_SUBPASS:
+ return usubpassInput_type;
+ case GLSL_SAMPLER_DIM_SUBPASS_MS:
+ return usubpassInputMS_type;
+ case GLSL_SAMPLER_DIM_EXTERNAL:
+ return error_type;
}
default:
return error_type;
char key[128];
snprintf(key, sizeof(key), "%p[%u]", (void *) base, array_size);
- mtx_lock(&glsl_type::mutex);
+ mtx_lock(&glsl_type::hash_mutex);
if (array_types == NULL) {
array_types = _mesa_hash_table_create(NULL, _mesa_key_hash_string,
const struct hash_entry *entry = _mesa_hash_table_search(array_types, key);
if (entry == NULL) {
- mtx_unlock(&glsl_type::mutex);
const glsl_type *t = new glsl_type(base, array_size);
- mtx_lock(&glsl_type::mutex);
entry = _mesa_hash_table_insert(array_types,
ralloc_strdup(mem_ctx, key),
assert(((glsl_type *) entry->data)->length == array_size);
assert(((glsl_type *) entry->data)->fields.array == base);
- mtx_unlock(&glsl_type::mutex);
+ mtx_unlock(&glsl_type::hash_mutex);
return (glsl_type *) entry->data;
}
bool
-glsl_type::record_compare(const glsl_type *b) const
+glsl_type::record_compare(const glsl_type *b, bool match_locations) const
{
if (this->length != b->length)
return false;
if (this->interface_packing != b->interface_packing)
return false;
+ if (this->interface_row_major != b->interface_row_major)
+ return false;
+
/* From the GLSL 4.20 specification (Sec 4.2):
*
* "Structures must have the same name, sequence of type names, and
* type definitions, and field names to be considered the same type."
*
* GLSL ES behaves the same (Ver 1.00 Sec 4.2.4, Ver 3.00 Sec 4.2.5).
- *
- * Note that we cannot force type name check when comparing unnamed
- * structure types, these have a unique name assigned during parsing.
*/
- if (!this->is_anonymous() && !b->is_anonymous())
- if (strcmp(this->name, b->name) != 0)
- return false;
+ if (strcmp(this->name, b->name) != 0)
+ return false;
for (unsigned i = 0; i < this->length; i++) {
if (this->fields.structure[i].type != b->fields.structure[i].type)
if (this->fields.structure[i].matrix_layout
!= b->fields.structure[i].matrix_layout)
return false;
- if (this->fields.structure[i].location
+ if (match_locations && this->fields.structure[i].location
!= b->fields.structure[i].location)
return false;
+ if (this->fields.structure[i].offset
+ != b->fields.structure[i].offset)
+ return false;
if (this->fields.structure[i].interpolation
!= b->fields.structure[i].interpolation)
return false;
if (this->fields.structure[i].patch
!= b->fields.structure[i].patch)
return false;
- if (this->fields.structure[i].image_read_only
- != b->fields.structure[i].image_read_only)
+ if (this->fields.structure[i].memory_read_only
+ != b->fields.structure[i].memory_read_only)
+ return false;
+ if (this->fields.structure[i].memory_write_only
+ != b->fields.structure[i].memory_write_only)
return false;
- if (this->fields.structure[i].image_write_only
- != b->fields.structure[i].image_write_only)
+ if (this->fields.structure[i].memory_coherent
+ != b->fields.structure[i].memory_coherent)
return false;
- if (this->fields.structure[i].image_coherent
- != b->fields.structure[i].image_coherent)
+ if (this->fields.structure[i].memory_volatile
+ != b->fields.structure[i].memory_volatile)
return false;
- if (this->fields.structure[i].image_volatile
- != b->fields.structure[i].image_volatile)
+ if (this->fields.structure[i].memory_restrict
+ != b->fields.structure[i].memory_restrict)
return false;
- if (this->fields.structure[i].image_restrict
- != b->fields.structure[i].image_restrict)
+ if (this->fields.structure[i].image_format
+ != b->fields.structure[i].image_format)
return false;
if (this->fields.structure[i].precision
!= b->fields.structure[i].precision)
return false;
+ if (this->fields.structure[i].explicit_xfb_buffer
+ != b->fields.structure[i].explicit_xfb_buffer)
+ return false;
+ if (this->fields.structure[i].xfb_buffer
+ != b->fields.structure[i].xfb_buffer)
+ return false;
+ if (this->fields.structure[i].xfb_stride
+ != b->fields.structure[i].xfb_stride)
+ return false;
}
return true;
{
const glsl_type key(fields, num_fields, name);
- mtx_lock(&glsl_type::mutex);
+ mtx_lock(&glsl_type::hash_mutex);
if (record_types == NULL) {
record_types = _mesa_hash_table_create(NULL, record_key_hash,
const struct hash_entry *entry = _mesa_hash_table_search(record_types,
&key);
if (entry == NULL) {
- mtx_unlock(&glsl_type::mutex);
const glsl_type *t = new glsl_type(fields, num_fields, name);
- mtx_lock(&glsl_type::mutex);
entry = _mesa_hash_table_insert(record_types, t, (void *) t);
}
assert(((glsl_type *) entry->data)->length == num_fields);
assert(strcmp(((glsl_type *) entry->data)->name, name) == 0);
- mtx_unlock(&glsl_type::mutex);
+ mtx_unlock(&glsl_type::hash_mutex);
return (glsl_type *) entry->data;
}
glsl_type::get_interface_instance(const glsl_struct_field *fields,
unsigned num_fields,
enum glsl_interface_packing packing,
+ bool row_major,
const char *block_name)
{
- const glsl_type key(fields, num_fields, packing, block_name);
+ const glsl_type key(fields, num_fields, packing, row_major, block_name);
- mtx_lock(&glsl_type::mutex);
+ mtx_lock(&glsl_type::hash_mutex);
if (interface_types == NULL) {
interface_types = _mesa_hash_table_create(NULL, record_key_hash,
const struct hash_entry *entry = _mesa_hash_table_search(interface_types,
&key);
if (entry == NULL) {
- mtx_unlock(&glsl_type::mutex);
const glsl_type *t = new glsl_type(fields, num_fields,
- packing, block_name);
- mtx_lock(&glsl_type::mutex);
+ packing, row_major, block_name);
entry = _mesa_hash_table_insert(interface_types, t, (void *) t);
}
assert(((glsl_type *) entry->data)->length == num_fields);
assert(strcmp(((glsl_type *) entry->data)->name, block_name) == 0);
- mtx_unlock(&glsl_type::mutex);
+ mtx_unlock(&glsl_type::hash_mutex);
return (glsl_type *) entry->data;
}
{
const glsl_type key(subroutine_name);
- mtx_lock(&glsl_type::mutex);
+ mtx_lock(&glsl_type::hash_mutex);
if (subroutine_types == NULL) {
subroutine_types = _mesa_hash_table_create(NULL, record_key_hash,
const struct hash_entry *entry = _mesa_hash_table_search(subroutine_types,
&key);
if (entry == NULL) {
- mtx_unlock(&glsl_type::mutex);
const glsl_type *t = new glsl_type(subroutine_name);
- mtx_lock(&glsl_type::mutex);
entry = _mesa_hash_table_insert(subroutine_types, t, (void *) t);
}
assert(((glsl_type *) entry->data)->base_type == GLSL_TYPE_SUBROUTINE);
assert(strcmp(((glsl_type *) entry->data)->name, subroutine_name) == 0);
- mtx_unlock(&glsl_type::mutex);
+ mtx_unlock(&glsl_type::hash_mutex);
return (glsl_type *) entry->data;
}
+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 false;
+
+ 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;
+ return _mesa_hash_data(key->fields.parameters,
+ (key->length + 1) * sizeof(*key->fields.parameters));
+}
+
+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::hash_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) {
+ const glsl_type *t = new glsl_type(return_type, params, num_params);
+
+ 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::hash_mutex);
+
+ return t;
+}
+
+
const glsl_type *
glsl_type::get_mul_type(const glsl_type *type_a, const glsl_type *type_b)
{
return this->components();
case GLSL_TYPE_DOUBLE:
+ case GLSL_TYPE_UINT64:
+ case GLSL_TYPE_INT64:
return 2 * this->components();
case GLSL_TYPE_STRUCT:
case GLSL_TYPE_ARRAY:
return this->length * this->fields.array->component_slots();
+ case GLSL_TYPE_SAMPLER:
case GLSL_TYPE_IMAGE:
- return 1;
+ return 2;
+
case GLSL_TYPE_SUBROUTINE:
- return 1;
- case GLSL_TYPE_SAMPLER:
+ return 1;
+
+ case GLSL_TYPE_FUNCTION:
case GLSL_TYPE_ATOMIC_UINT:
case GLSL_TYPE_VOID:
case GLSL_TYPE_ERROR:
case GLSL_TYPE_INT:
case GLSL_TYPE_FLOAT:
case GLSL_TYPE_DOUBLE:
+ case GLSL_TYPE_UINT64:
+ case GLSL_TYPE_INT64:
case GLSL_TYPE_BOOL:
case GLSL_TYPE_SAMPLER:
case GLSL_TYPE_IMAGE:
}
}
+unsigned
+glsl_type::varying_count() const
+{
+ unsigned size = 0;
+
+ switch (this->base_type) {
+ case GLSL_TYPE_UINT:
+ case GLSL_TYPE_INT:
+ case GLSL_TYPE_FLOAT:
+ case GLSL_TYPE_DOUBLE:
+ case GLSL_TYPE_BOOL:
+ case GLSL_TYPE_UINT64:
+ case GLSL_TYPE_INT64:
+ return 1;
+
+ case GLSL_TYPE_STRUCT:
+ case GLSL_TYPE_INTERFACE:
+ for (unsigned i = 0; i < this->length; i++)
+ size += this->fields.structure[i].type->varying_count();
+ return size;
+ case GLSL_TYPE_ARRAY:
+ /* Don't count innermost array elements */
+ if (this->without_array()->is_record() ||
+ this->without_array()->is_interface() ||
+ this->fields.array->is_array())
+ return this->length * this->fields.array->varying_count();
+ else
+ return this->fields.array->varying_count();
+ default:
+ assert(!"unsupported varying type");
+ return 0;
+ }
+}
+
bool
glsl_type::can_implicitly_convert_to(const glsl_type *desired,
_mesa_glsl_parse_state *state) const
if (this == desired)
return true;
- /* ESSL does not allow implicit conversions. If there is no state, we're
- * doing intra-stage function linking where these checks have already been
- * done.
+ /* GLSL 1.10 and ESSL do not allow implicit conversions. If there is no
+ * state, we're doing intra-stage function linking where these checks have
+ * already been done.
*/
- if (state && state->es_shader)
+ if (state && (state->es_shader || !state->is_version(120, 0)))
return false;
/* There is no conversion among matrix types. */
if (desired->is_float() && this->is_integer())
return true;
- /* With GLSL 4.0 / ARB_gpu_shader5, int can be converted to uint.
- * Note that state may be NULL here, when resolving function calls in the
- * linker. By this time, all the state-dependent checks have already
- * happened though, so allow anything that's allowed in any shader version. */
- if ((!state || state->is_version(400, 0) || state->ARB_gpu_shader5_enable) &&
+ /* With GLSL 4.0, ARB_gpu_shader5, or MESA_shader_integer_functions, int
+ * can be converted to uint. Note that state may be NULL here, when
+ * resolving function calls in the linker. By this time, all the
+ * state-dependent checks have already happened though, so allow anything
+ * that's allowed in any shader version.
+ */
+ if ((!state || state->is_version(400, 0) || state->ARB_gpu_shader5_enable ||
+ state->MESA_shader_integer_functions_enable) &&
desired->base_type == GLSL_TYPE_UINT && this->base_type == GLSL_TYPE_INT)
return true;
unsigned
glsl_type::std140_base_alignment(bool row_major) const
{
- unsigned N = is_double() ? 8 : 4;
+ unsigned N = is_64bit() ? 8 : 4;
/* (1) If the member is a scalar consuming <N> basic machine units, the
* base alignment is <N>.
unsigned
glsl_type::std140_size(bool row_major) const
{
- unsigned N = is_double() ? 8 : 4;
+ unsigned N = is_64bit() ? 8 : 4;
/* (1) If the member is a scalar consuming <N> basic machine units, the
* base alignment is <N>.
glsl_type::std430_base_alignment(bool row_major) const
{
- unsigned N = is_double() ? 8 : 4;
+ unsigned N = is_64bit() ? 8 : 4;
/* (1) If the member is a scalar consuming <N> basic machine units, the
* base alignment is <N>.
unsigned
glsl_type::std430_array_stride(bool row_major) const
{
- unsigned N = is_double() ? 8 : 4;
+ unsigned N = is_64bit() ? 8 : 4;
/* Notice that the array stride of a vec3 is not 3 * N but 4 * N.
* See OpenGL 4.30 spec, section 7.6.2.2 "Standard Uniform Block Layout"
unsigned
glsl_type::std430_size(bool row_major) const
{
- unsigned N = is_double() ? 8 : 4;
+ unsigned N = is_64bit() ? 8 : 4;
/* OpenGL 4.30 spec, section 7.6.2.2 "Standard Uniform Block Layout":
*
}
unsigned
-glsl_type::count_attribute_slots(bool vertex_input_slots) const
+glsl_type::count_attribute_slots(bool is_vertex_input) const
{
/* From page 31 (page 37 of the PDF) of the GLSL 1.50 spec:
*
case GLSL_TYPE_INT:
case GLSL_TYPE_FLOAT:
case GLSL_TYPE_BOOL:
+ case GLSL_TYPE_SAMPLER:
+ case GLSL_TYPE_IMAGE:
return this->matrix_columns;
case GLSL_TYPE_DOUBLE:
- if (this->vector_elements > 2 && !vertex_input_slots)
+ case GLSL_TYPE_UINT64:
+ case GLSL_TYPE_INT64:
+ if (this->vector_elements > 2 && !is_vertex_input)
return this->matrix_columns * 2;
else
return this->matrix_columns;
unsigned size = 0;
for (unsigned i = 0; i < this->length; i++)
- size += this->fields.structure[i].type->count_attribute_slots(vertex_input_slots);
+ size += this->fields.structure[i].type->count_attribute_slots(is_vertex_input);
return size;
}
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(is_vertex_input);
- case GLSL_TYPE_SAMPLER:
- case GLSL_TYPE_IMAGE:
+ case GLSL_TYPE_SUBROUTINE:
+ return 1;
+
+ case GLSL_TYPE_FUNCTION:
case GLSL_TYPE_ATOMIC_UINT:
case GLSL_TYPE_VOID:
- case GLSL_TYPE_SUBROUTINE:
case GLSL_TYPE_ERROR:
break;
}
case GLSL_SAMPLER_DIM_RECT:
case GLSL_SAMPLER_DIM_MS:
case GLSL_SAMPLER_DIM_EXTERNAL:
+ case GLSL_SAMPLER_DIM_SUBPASS:
size = 2;
break;
case GLSL_SAMPLER_DIM_3D:
* cubemap faces.
*/
if (sampler_array &&
- !(base_type == GLSL_TYPE_IMAGE &&
- sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE))
+ !(is_image() && sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE))
size += 1;
return size;