+
+union packed_type {
+ uint32_t u32;
+ struct {
+ unsigned base_type:5;
+ unsigned interface_row_major:1;
+ unsigned vector_elements:3;
+ unsigned matrix_columns:3;
+ unsigned explicit_stride:16;
+ unsigned explicit_alignment:4;
+ } basic;
+ struct {
+ unsigned base_type:5;
+ unsigned dimensionality:4;
+ unsigned shadow:1;
+ unsigned array:1;
+ unsigned sampled_type:5;
+ unsigned _pad:16;
+ } sampler;
+ struct {
+ unsigned base_type:5;
+ unsigned length:13;
+ unsigned explicit_stride:14;
+ } array;
+ struct {
+ unsigned base_type:5;
+ unsigned interface_packing_or_packed:2;
+ unsigned interface_row_major:1;
+ unsigned length:20;
+ unsigned explicit_alignment:4;
+ } strct;
+};
+
+static void
+encode_glsl_struct_field(blob *blob, const glsl_struct_field *struct_field)
+{
+ encode_type_to_blob(blob, struct_field->type);
+ blob_write_string(blob, struct_field->name);
+ blob_write_uint32(blob, struct_field->location);
+ blob_write_uint32(blob, struct_field->offset);
+ blob_write_uint32(blob, struct_field->xfb_buffer);
+ blob_write_uint32(blob, struct_field->xfb_stride);
+ blob_write_uint32(blob, struct_field->image_format);
+ blob_write_uint32(blob, struct_field->flags);
+}
+
+static void
+decode_glsl_struct_field_from_blob(blob_reader *blob, glsl_struct_field *struct_field)
+{
+ struct_field->type = decode_type_from_blob(blob);
+ struct_field->name = blob_read_string(blob);
+ struct_field->location = blob_read_uint32(blob);
+ struct_field->offset = blob_read_uint32(blob);
+ struct_field->xfb_buffer = blob_read_uint32(blob);
+ struct_field->xfb_stride = blob_read_uint32(blob);
+ struct_field->image_format = (pipe_format)blob_read_uint32(blob);
+ struct_field->flags = blob_read_uint32(blob);
+}
+
+void
+encode_type_to_blob(struct blob *blob, const glsl_type *type)
+{
+ if (!type) {
+ blob_write_uint32(blob, 0);
+ return;
+ }
+
+ STATIC_ASSERT(sizeof(union packed_type) == 4);
+ union packed_type encoded;
+ encoded.u32 = 0;
+ encoded.basic.base_type = type->base_type;
+
+ switch (type->base_type) {
+ case GLSL_TYPE_UINT:
+ case GLSL_TYPE_INT:
+ case GLSL_TYPE_FLOAT:
+ case GLSL_TYPE_FLOAT16:
+ case GLSL_TYPE_DOUBLE:
+ case GLSL_TYPE_UINT8:
+ case GLSL_TYPE_INT8:
+ case GLSL_TYPE_UINT16:
+ case GLSL_TYPE_INT16:
+ case GLSL_TYPE_UINT64:
+ case GLSL_TYPE_INT64:
+ case GLSL_TYPE_BOOL:
+ encoded.basic.interface_row_major = type->interface_row_major;
+ assert(type->matrix_columns < 8);
+ if (type->vector_elements <= 4)
+ encoded.basic.vector_elements = type->vector_elements;
+ else if (type->vector_elements == 8)
+ encoded.basic.vector_elements = 5;
+ else if (type->vector_elements == 16)
+ encoded.basic.vector_elements = 6;
+ encoded.basic.matrix_columns = type->matrix_columns;
+ encoded.basic.explicit_stride = MIN2(type->explicit_stride, 0xffff);
+ encoded.basic.explicit_alignment =
+ MIN2(ffs(type->explicit_alignment), 0xf);
+ blob_write_uint32(blob, encoded.u32);
+ /* If we don't have enough bits for explicit_stride, store it
+ * separately.
+ */
+ if (encoded.basic.explicit_stride == 0xffff)
+ blob_write_uint32(blob, type->explicit_stride);
+ if (encoded.basic.explicit_alignment == 0xf)
+ blob_write_uint32(blob, type->explicit_alignment);
+ return;
+ case GLSL_TYPE_SAMPLER:
+ encoded.sampler.dimensionality = type->sampler_dimensionality;
+ encoded.sampler.shadow = type->sampler_shadow;
+ encoded.sampler.array = type->sampler_array;
+ encoded.sampler.sampled_type = type->sampled_type;
+ break;
+ case GLSL_TYPE_SUBROUTINE:
+ blob_write_uint32(blob, encoded.u32);
+ blob_write_string(blob, type->name);
+ return;
+ case GLSL_TYPE_IMAGE:
+ encoded.sampler.dimensionality = type->sampler_dimensionality;
+ encoded.sampler.array = type->sampler_array;
+ encoded.sampler.sampled_type = type->sampled_type;
+ break;
+ case GLSL_TYPE_ATOMIC_UINT:
+ break;
+ case GLSL_TYPE_ARRAY:
+ encoded.array.length = MIN2(type->length, 0x1fff);
+ encoded.array.explicit_stride = MIN2(type->explicit_stride, 0x3fff);
+ blob_write_uint32(blob, encoded.u32);
+ /* If we don't have enough bits for length or explicit_stride, store it
+ * separately.
+ */
+ if (encoded.array.length == 0x1fff)
+ blob_write_uint32(blob, type->length);
+ if (encoded.array.explicit_stride == 0x3fff)
+ blob_write_uint32(blob, type->explicit_stride);
+ encode_type_to_blob(blob, type->fields.array);
+ return;
+ case GLSL_TYPE_STRUCT:
+ case GLSL_TYPE_INTERFACE:
+ encoded.strct.length = MIN2(type->length, 0xfffff);
+ encoded.strct.explicit_alignment =
+ MIN2(ffs(type->explicit_alignment), 0xf);
+ if (type->is_interface()) {
+ encoded.strct.interface_packing_or_packed = type->interface_packing;
+ encoded.strct.interface_row_major = type->interface_row_major;
+ } else {
+ encoded.strct.interface_packing_or_packed = type->packed;
+ }
+ blob_write_uint32(blob, encoded.u32);
+ blob_write_string(blob, type->name);
+
+ /* If we don't have enough bits for length, store it separately. */
+ if (encoded.strct.length == 0xfffff)
+ blob_write_uint32(blob, type->length);
+ if (encoded.strct.explicit_alignment == 0xf)
+ blob_write_uint32(blob, type->explicit_alignment);
+
+ for (unsigned i = 0; i < type->length; i++)
+ encode_glsl_struct_field(blob, &type->fields.structure[i]);
+ return;
+ case GLSL_TYPE_VOID:
+ break;
+ case GLSL_TYPE_ERROR:
+ default:
+ assert(!"Cannot encode type!");
+ encoded.u32 = 0;
+ break;
+ }
+
+ blob_write_uint32(blob, encoded.u32);
+}
+
+const glsl_type *
+decode_type_from_blob(struct blob_reader *blob)
+{
+ union packed_type encoded;
+ encoded.u32 = blob_read_uint32(blob);
+
+ if (encoded.u32 == 0) {
+ return NULL;
+ }
+
+ glsl_base_type base_type = (glsl_base_type)encoded.basic.base_type;
+
+ switch (base_type) {
+ case GLSL_TYPE_UINT:
+ case GLSL_TYPE_INT:
+ case GLSL_TYPE_FLOAT:
+ case GLSL_TYPE_FLOAT16:
+ case GLSL_TYPE_DOUBLE:
+ case GLSL_TYPE_UINT8:
+ case GLSL_TYPE_INT8:
+ case GLSL_TYPE_UINT16:
+ case GLSL_TYPE_INT16:
+ case GLSL_TYPE_UINT64:
+ case GLSL_TYPE_INT64:
+ case GLSL_TYPE_BOOL: {
+ unsigned explicit_stride = encoded.basic.explicit_stride;
+ if (explicit_stride == 0xffff)
+ explicit_stride = blob_read_uint32(blob);
+ unsigned explicit_alignment = encoded.basic.explicit_alignment;
+ if (explicit_alignment == 0xf)
+ explicit_alignment = blob_read_uint32(blob);
+ else if (explicit_alignment > 0)
+ explicit_alignment = 1 << (explicit_alignment - 1);
+ uint32_t vector_elements = encoded.basic.vector_elements;
+ if (vector_elements == 5)
+ vector_elements = 8;
+ else if (vector_elements == 6)
+ vector_elements = 16;
+ return glsl_type::get_instance(base_type, encoded.basic.vector_elements,
+ encoded.basic.matrix_columns,
+ explicit_stride,
+ encoded.basic.interface_row_major,
+ explicit_alignment);
+ }
+ case GLSL_TYPE_SAMPLER:
+ return glsl_type::get_sampler_instance((enum glsl_sampler_dim)encoded.sampler.dimensionality,
+ encoded.sampler.shadow,
+ encoded.sampler.array,
+ (glsl_base_type) encoded.sampler.sampled_type);
+ case GLSL_TYPE_SUBROUTINE:
+ return glsl_type::get_subroutine_instance(blob_read_string(blob));
+ case GLSL_TYPE_IMAGE:
+ return glsl_type::get_image_instance((enum glsl_sampler_dim)encoded.sampler.dimensionality,
+ encoded.sampler.array,
+ (glsl_base_type) encoded.sampler.sampled_type);
+ case GLSL_TYPE_ATOMIC_UINT:
+ return glsl_type::atomic_uint_type;
+ case GLSL_TYPE_ARRAY: {
+ unsigned length = encoded.array.length;
+ if (length == 0x1fff)
+ length = blob_read_uint32(blob);
+ unsigned explicit_stride = encoded.array.explicit_stride;
+ if (explicit_stride == 0x3fff)
+ explicit_stride = blob_read_uint32(blob);
+ return glsl_type::get_array_instance(decode_type_from_blob(blob),
+ length, explicit_stride);
+ }
+ case GLSL_TYPE_STRUCT:
+ case GLSL_TYPE_INTERFACE: {
+ char *name = blob_read_string(blob);
+ unsigned num_fields = encoded.strct.length;
+ if (num_fields == 0xfffff)
+ num_fields = blob_read_uint32(blob);
+ unsigned explicit_alignment = encoded.strct.explicit_alignment;
+ if (explicit_alignment == 0xf)
+ explicit_alignment = blob_read_uint32(blob);
+ else if (explicit_alignment > 0)
+ explicit_alignment = 1 << (explicit_alignment - 1);
+
+ glsl_struct_field *fields =
+ (glsl_struct_field *) malloc(sizeof(glsl_struct_field) * num_fields);
+ for (unsigned i = 0; i < num_fields; i++)
+ decode_glsl_struct_field_from_blob(blob, &fields[i]);
+
+ const glsl_type *t;
+ if (base_type == GLSL_TYPE_INTERFACE) {
+ assert(explicit_alignment == 0);
+ enum glsl_interface_packing packing =
+ (glsl_interface_packing) encoded.strct.interface_packing_or_packed;
+ bool row_major = encoded.strct.interface_row_major;
+ t = glsl_type::get_interface_instance(fields, num_fields, packing,
+ row_major, name);
+ } else {
+ unsigned packed = encoded.strct.interface_packing_or_packed;
+ t = glsl_type::get_struct_instance(fields, num_fields, name, packed,
+ explicit_alignment);
+ }
+
+ free(fields);
+ return t;
+ }
+ case GLSL_TYPE_VOID:
+ return glsl_type::void_type;
+ case GLSL_TYPE_ERROR:
+ default:
+ assert(!"Cannot decode type!");
+ return NULL;
+ }
+}
+
+unsigned
+glsl_type::cl_alignment() const
+{
+ /* vectors unlike arrays are aligned to their size */
+ if (this->is_scalar() || this->is_vector())
+ return this->cl_size();
+ else if (this->is_array())
+ return this->without_array()->cl_alignment();
+ else if (this->is_struct()) {
+ /* Packed Structs are 0x1 aligned despite their size. */
+ if (this->packed)
+ return 1;
+
+ unsigned res = 1;
+ for (unsigned i = 0; i < this->length; ++i) {
+ struct glsl_struct_field &field = this->fields.structure[i];
+ res = MAX2(res, field.type->cl_alignment());
+ }
+ return res;
+ }
+ return 1;
+}
+
+unsigned
+glsl_type::cl_size() const
+{
+ if (this->is_scalar() || this->is_vector()) {
+ return util_next_power_of_two(this->vector_elements) *
+ explicit_type_scalar_byte_size(this);
+ } else if (this->is_array()) {
+ unsigned size = this->without_array()->cl_size();
+ return size * this->length;
+ } else if (this->is_struct()) {
+ unsigned size = 0;
+ for (unsigned i = 0; i < this->length; ++i) {
+ struct glsl_struct_field &field = this->fields.structure[i];
+ /* if a struct is packed, members don't get aligned */
+ if (!this->packed)
+ size = align(size, field.type->cl_alignment());
+ size += field.type->cl_size();
+ }
+ return size;
+ }
+ return 1;
+}
+
+extern "C" {
+
+int
+glsl_get_sampler_dim_coordinate_components(enum glsl_sampler_dim dim)
+{
+ switch (dim) {
+ case GLSL_SAMPLER_DIM_1D:
+ case GLSL_SAMPLER_DIM_BUF:
+ return 1;
+ case GLSL_SAMPLER_DIM_2D:
+ case GLSL_SAMPLER_DIM_RECT:
+ case GLSL_SAMPLER_DIM_MS:
+ case GLSL_SAMPLER_DIM_EXTERNAL:
+ case GLSL_SAMPLER_DIM_SUBPASS:
+ case GLSL_SAMPLER_DIM_SUBPASS_MS:
+ return 2;
+ case GLSL_SAMPLER_DIM_3D:
+ case GLSL_SAMPLER_DIM_CUBE:
+ return 3;
+ default:
+ unreachable("Unknown sampler dim");
+ }
+}
+
+void
+glsl_print_type(FILE *f, const glsl_type *t)
+{
+ if (t->is_array()) {
+ fprintf(f, "(array ");
+ glsl_print_type(f, t->fields.array);
+ fprintf(f, " %u)", t->length);
+ } else if (t->is_struct() && !is_gl_identifier(t->name)) {
+ fprintf(f, "%s@%p", t->name, (void *) t);
+ } else {
+ fprintf(f, "%s", t->name);
+ }
+}
+
+}