st/nine: Allocate surface resources in surface ctor
[mesa.git] / src / compiler / glsl_types.cpp
index ef6c3c6e3b7dbc053c481f9721a55da1d593a2d4..73e3abd329d74b528860ff57ebad4896d5193f8b 100644 (file)
@@ -32,6 +32,7 @@ mtx_t glsl_type::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;
 
@@ -50,10 +51,17 @@ glsl_type::glsl_type(GLenum gl_type,
    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),
    vector_elements(vector_elements), matrix_columns(matrix_columns),
    length(0)
 {
+   /* 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::mutex);
 
    init_ralloc_type_ctx();
@@ -74,7 +82,7 @@ glsl_type::glsl_type(GLenum gl_type, glsl_base_type base_type,
    gl_type(gl_type),
    base_type(base_type),
    sampler_dimensionality(dim), sampler_shadow(shadow),
-   sampler_array(array), sampler_type(type), interface_packing(0),
+   sampler_array(array), sampled_type(type), interface_packing(0),
    length(0)
 {
    mtx_lock(&glsl_type::mutex);
@@ -100,7 +108,7 @@ 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),
    vector_elements(0), matrix_columns(0),
    length(num_fields)
 {
@@ -119,6 +127,7 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
       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].offset = fields[i].offset;
       this->fields.structure[i].interpolation = fields[i].interpolation;
       this->fields.structure[i].centroid = fields[i].centroid;
       this->fields.structure[i].sample = fields[i].sample;
@@ -130,6 +139,10 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
       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;
+      this->fields.structure[i].explicit_xfb_buffer =
+         fields[i].explicit_xfb_buffer;
+      this->fields.structure[i].xfb_buffer = fields[i].xfb_buffer;
+      this->fields.structure[i].xfb_stride = fields[i].xfb_stride;
    }
 
    mtx_unlock(&glsl_type::mutex);
@@ -140,7 +153,7 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
    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),
    vector_elements(0), matrix_columns(0),
    length(num_fields)
 {
@@ -158,12 +171,55 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
       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].offset = fields[i].offset;
       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;
+      this->fields.structure[i].explicit_xfb_buffer =
+         fields[i].explicit_xfb_buffer;
+      this->fields.structure[i].xfb_buffer = fields[i].xfb_buffer;
+      this->fields.structure[i].xfb_stride = fields[i].xfb_stride;
+   }
+
+   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);
@@ -173,7 +229,7 @@ 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),
    vector_elements(1), matrix_columns(1),
    length(0)
 {
@@ -389,7 +445,7 @@ _mesa_glsl_release_types(void)
 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),
    vector_elements(0), matrix_columns(0),
    length(length), name(NULL)
 {
@@ -618,6 +674,8 @@ glsl_type::get_sampler_instance(enum glsl_sampler_dim dim,
             return error_type;
          else
             return samplerExternalOES_type;
+      case GLSL_SAMPLER_DIM_SUBPASS:
+         return error_type;
       }
    case GLSL_TYPE_INT:
       if (shadow)
@@ -645,6 +703,8 @@ glsl_type::get_sampler_instance(enum glsl_sampler_dim dim,
          return (array ? isampler2DMSArray_type : isampler2DMS_type);
       case GLSL_SAMPLER_DIM_EXTERNAL:
          return error_type;
+      case GLSL_SAMPLER_DIM_SUBPASS:
+         return error_type;
       }
    case GLSL_TYPE_UINT:
       if (shadow)
@@ -672,6 +732,100 @@ glsl_type::get_sampler_instance(enum glsl_sampler_dim dim,
          return (array ? usampler2DMSArray_type : usampler2DMS_type);
       case GLSL_SAMPLER_DIM_EXTERNAL:
          return error_type;
+      case GLSL_SAMPLER_DIM_SUBPASS:
+         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)
+{
+   if (dim == GLSL_SAMPLER_DIM_SUBPASS)
+      return subpassInput_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_EXTERNAL:
+      case GLSL_SAMPLER_DIM_SUBPASS:
+         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_EXTERNAL:
+      case GLSL_SAMPLER_DIM_SUBPASS:
+         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_EXTERNAL:
+      case GLSL_SAMPLER_DIM_SUBPASS:
+         return error_type;
       }
    default:
       return error_type;
@@ -720,7 +874,7 @@ glsl_type::get_array_instance(const glsl_type *base, unsigned array_size)
 
 
 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;
@@ -751,9 +905,12 @@ glsl_type::record_compare(const glsl_type *b) const
       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;
@@ -784,6 +941,15 @@ glsl_type::record_compare(const glsl_type *b) const
       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;
@@ -924,6 +1090,62 @@ 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 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::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 *
 glsl_type::get_mul_type(const glsl_type *type_a, const glsl_type *type_b)
 {
@@ -1053,6 +1275,8 @@ glsl_type::component_slots() const
       return 1;
    case GLSL_TYPE_SUBROUTINE:
      return 1;
+
+   case GLSL_TYPE_FUNCTION:
    case GLSL_TYPE_SAMPLER:
    case GLSL_TYPE_ATOMIC_UINT:
    case GLSL_TYPE_VOID:
@@ -1132,6 +1356,38 @@ glsl_type::uniform_locations() const
    }
 }
 
+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:
+      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
@@ -1139,11 +1395,11 @@ glsl_type::can_implicitly_convert_to(const glsl_type *desired,
    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. */
@@ -1158,11 +1414,14 @@ glsl_type::can_implicitly_convert_to(const glsl_type *desired,
    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;
 
@@ -1184,7 +1443,7 @@ glsl_type::can_implicitly_convert_to(const glsl_type *desired,
 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>.
@@ -1302,7 +1561,7 @@ glsl_type::std140_base_alignment(bool row_major) const
 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>.
@@ -1439,7 +1698,7 @@ unsigned
 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>.
@@ -1548,7 +1807,7 @@ glsl_type::std430_base_alignment(bool row_major) const
 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"
@@ -1566,7 +1825,7 @@ glsl_type::std430_array_stride(bool row_major) const
 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":
     *
@@ -1647,7 +1906,7 @@ glsl_type::std430_size(bool row_major) const
 }
 
 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:
     *
@@ -1681,7 +1940,7 @@ glsl_type::count_attribute_slots(bool vertex_input_slots) const
    case GLSL_TYPE_BOOL:
       return this->matrix_columns;
    case GLSL_TYPE_DOUBLE:
-      if (this->vector_elements > 2 && !vertex_input_slots)
+      if (this->vector_elements > 2 && !is_vertex_input)
          return this->matrix_columns * 2;
       else
          return this->matrix_columns;
@@ -1690,14 +1949,15 @@ glsl_type::count_attribute_slots(bool vertex_input_slots) const
       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_FUNCTION:
    case GLSL_TYPE_SAMPLER:
    case GLSL_TYPE_IMAGE:
    case GLSL_TYPE_ATOMIC_UINT:
@@ -1726,6 +1986,7 @@ glsl_type::coordinate_components() const
    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: