[Mesa-dev] [PATCH v2 3/4] mesa/st: add ARB_texture_view support

Roland Scheidegger sroland at vmware.com
Thu Aug 21 10:46:28 PDT 2014


Am 21.08.2014 04:42, schrieb Ilia Mirkin:
> Signed-off-by: Ilia Mirkin <imirkin at alum.mit.edu>
> ---
> 
> v1 -> v2:
>  - make use of new PIPE_CAP to determine whether ARB_texture_view is available
>  - set the gl_texture_object's Target in the sampler view object
> 
>  src/mesa/state_tracker/st_atom_texture.c | 30 ++++++++++++----
>  src/mesa/state_tracker/st_cb_fbo.c       | 10 ++++++
>  src/mesa/state_tracker/st_cb_texture.c   | 62 +++++++++++++++++++++++++++-----
>  src/mesa/state_tracker/st_extensions.c   |  1 +
>  src/mesa/state_tracker/st_format.c       |  5 +--
>  src/mesa/state_tracker/st_texture.c      | 15 ++++++--
>  6 files changed, 105 insertions(+), 18 deletions(-)
> 
> diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c
> index 03d0593..ed9a444 100644
> --- a/src/mesa/state_tracker/st_atom_texture.c
> +++ b/src/mesa/state_tracker/st_atom_texture.c
> @@ -192,9 +192,9 @@ get_texture_format_swizzle(const struct st_texture_object *stObj)
>     return swizzle_swizzle(stObj->base._Swizzle, tex_swizzle);
>  }
>  
> -                            
> +
>  /**
> - * Return TRUE if the texture's sampler view swizzle is equal to
> + * Return TRUE if the texture's sampler view swizzle is not equal to
>   * the texture's swizzle.
>   *
>   * \param stObj  the st texture object,
> @@ -214,9 +214,20 @@ check_sampler_swizzle(const struct st_texture_object *stObj,
>  
>  static unsigned last_level(struct st_texture_object *stObj)
>  {
> -   return MIN2(stObj->base._MaxLevel, stObj->pt->last_level);
> +   unsigned ret = MIN2(stObj->base.MinLevel + stObj->base._MaxLevel,
> +                       stObj->pt->last_level);
> +   if (stObj->base.Immutable)
> +      ret = MIN2(ret, stObj->base.MinLevel + stObj->base.NumLevels - 1);
> +   return ret;
>  }
>  
> +static unsigned last_layer(struct st_texture_object *stObj)
> +{
> +   if (stObj->base.Immutable)
> +      return MIN2(stObj->base.MinLayer + stObj->base.NumLayers - 1,
> +                  stObj->pt->array_size - 1);
> +   return stObj->pt->array_size - 1;
> +}
>  
>  static struct pipe_sampler_view *
>  st_create_texture_sampler_view_from_stobj(struct pipe_context *pipe,
> @@ -249,9 +260,13 @@ st_create_texture_sampler_view_from_stobj(struct pipe_context *pipe,
>        templ.u.buf.first_element = f;
>        templ.u.buf.last_element  = f + (n - 1);
>     } else {
> -      templ.u.tex.first_level = stObj->base.BaseLevel;
> +      templ.u.tex.first_level = stObj->base.MinLevel + stObj->base.BaseLevel;
>        templ.u.tex.last_level = last_level(stObj);
>        assert(templ.u.tex.first_level <= templ.u.tex.last_level);
> +      templ.u.tex.first_layer = stObj->base.MinLayer;
> +      templ.u.tex.last_layer = last_layer(stObj);
> +      assert(templ.u.tex.first_layer <= templ.u.tex.last_layer);
> +      templ.target = gl_target_to_pipe(stObj->base.Target);
>     }
>  
>     if (swizzle != SWIZZLE_NOOP) {
> @@ -287,8 +302,11 @@ st_get_texture_sampler_view_from_stobj(struct st_context *st,
>     if (*sv) {
>        if (check_sampler_swizzle(stObj, *sv) ||
>  	  (format != (*sv)->format) ||
> -          stObj->base.BaseLevel != (*sv)->u.tex.first_level ||
> -          last_level(stObj) != (*sv)->u.tex.last_level) {
> +          gl_target_to_pipe(stObj->base.Target) != (*sv)->target ||
> +          stObj->base.MinLevel + stObj->base.BaseLevel != (*sv)->u.tex.first_level ||
> +          last_level(stObj) != (*sv)->u.tex.last_level ||
> +          stObj->base.MinLayer != (*sv)->u.tex.first_layer ||
> +          last_layer(stObj) != (*sv)->u.tex.last_layer) {
>  	 pipe_sampler_view_reference(sv, NULL);
>        }
>     }
> diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c
> index 7cfd3da..470ab27 100644
> --- a/src/mesa/state_tracker/st_cb_fbo.c
> +++ b/src/mesa/state_tracker/st_cb_fbo.c
> @@ -450,6 +450,16 @@ st_update_renderbuffer_surface(struct st_context *st,
>        last_layer = strb->rtt_face + strb->rtt_slice;
>     }
>  
> +   /* Adjust for texture views */
> +   if (strb->is_rtt) {
> +      struct gl_texture_object *tex = strb->Base.TexImage->TexObject;
> +      first_layer += tex->MinLayer;
> +      if (!strb->rtt_layered)
> +         last_layer += tex->MinLayer;
> +      else
> +         last_layer = MIN2(first_layer + tex->NumLayers - 1, last_layer);
> +   }
> +
>     if (!strb->surface ||
>         strb->surface->texture->nr_samples != strb->Base.NumSamples ||
>         strb->surface->format != format ||
> diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c
> index ad14bd9..dfa188a 100644
> --- a/src/mesa/state_tracker/st_cb_texture.c
> +++ b/src/mesa/state_tracker/st_cb_texture.c
> @@ -829,12 +829,12 @@ st_TexSubImage(struct gl_context *ctx, GLuint dims,
>     blit.src.level = 0;
>     blit.src.format = src_format;
>     blit.dst.resource = dst;
> -   blit.dst.level = stObj->pt != stImage->pt ? 0 : texImage->Level;
> +   blit.dst.level = stObj->pt != stImage->pt ? 0 : texImage->TexObject->MinLevel + texImage->Level;
>     blit.dst.format = dst_format;
>     blit.src.box.x = blit.src.box.y = blit.src.box.z = 0;
>     blit.dst.box.x = xoffset;
>     blit.dst.box.y = yoffset;
> -   blit.dst.box.z = zoffset + texImage->Face;
> +   blit.dst.box.z = zoffset + texImage->Face + texImage->TexObject->MinLayer;
>     blit.src.box.width = blit.dst.box.width = width;
>     blit.src.box.height = blit.dst.box.height = height;
>     blit.src.box.depth = blit.dst.box.depth = depth;
> @@ -916,7 +916,8 @@ st_GetTexImage(struct gl_context * ctx,
>     GLuint height = texImage->Height;
>     GLuint depth = texImage->Depth;
>     struct st_texture_image *stImage = st_texture_image(texImage);
> -   struct pipe_resource *src = st_texture_object(texImage->TexObject)->pt;
> +   struct st_texture_object *stObj = st_texture_object(texImage->TexObject);
> +   struct pipe_resource *src = stObj->pt;
>     struct pipe_resource *dst = NULL;
>     struct pipe_resource dst_templ;
>     enum pipe_format dst_format, src_format;
> @@ -970,7 +971,10 @@ st_GetTexImage(struct gl_context * ctx,
>      * - Luminance alpha must be returned as (L,0,0,A).
>      * - Intensity must be returned as (I,0,0,1)
>      */
> -   src_format = util_format_linear(src->format);
> +   if (stObj->surface_based)
> +      src_format = util_format_linear(stObj->surface_format);
> +   else
> +      src_format = util_format_linear(src->format);
>     src_format = util_format_luminance_to_red(src_format);
>     src_format = util_format_intensity_to_red(src_format);
>  
> @@ -1069,14 +1073,14 @@ st_GetTexImage(struct gl_context * ctx,
>  
>     memset(&blit, 0, sizeof(blit));
>     blit.src.resource = src;
> -   blit.src.level = texImage->Level;
> +   blit.src.level = texImage->Level + texImage->TexObject->MinLevel;
>     blit.src.format = src_format;
>     blit.dst.resource = dst;
>     blit.dst.level = 0;
>     blit.dst.format = dst->format;
>     blit.src.box.x = blit.dst.box.x = 0;
>     blit.src.box.y = blit.dst.box.y = 0;
> -   blit.src.box.z = texImage->Face;
> +   blit.src.box.z = texImage->Face + texImage->TexObject->MinLayer;
>     blit.dst.box.z = 0;
>     blit.src.box.width = blit.dst.box.width = width;
>     blit.src.box.height = blit.dst.box.height = height;
> @@ -1441,10 +1445,10 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
>     blit.src.box.depth = 1;
>     blit.dst.resource = stImage->pt;
>     blit.dst.format = dst_format;
> -   blit.dst.level = stObj->pt != stImage->pt ? 0 : texImage->Level;
> +   blit.dst.level = stObj->pt != stImage->pt ? 0 : texImage->Level + texImage->TexObject->MinLevel;
>     blit.dst.box.x = destX;
>     blit.dst.box.y = destY;
> -   blit.dst.box.z = stImage->base.Face + slice;
> +   blit.dst.box.z = stImage->base.Face + slice + texImage->TexObject->MinLayer;
>     blit.dst.box.width = width;
>     blit.dst.box.height = height;
>     blit.dst.box.depth = 1;
> @@ -1545,6 +1549,9 @@ st_finalize_texture(struct gl_context *ctx,
>     enum pipe_format firstImageFormat;
>     GLuint ptWidth, ptHeight, ptDepth, ptLayers, ptNumSamples;
>  
> +   if (tObj->Immutable)
> +      return GL_TRUE;
> +
>     if (_mesa_is_texture_complete(tObj, &tObj->Sampler)) {
>        /* The texture is complete and we know exactly how many mipmap levels
>         * are present/needed.  This is conditional because we may be called
> @@ -1824,6 +1831,44 @@ st_TestProxyTexImage(struct gl_context *ctx, GLenum target,
>     }
>  }
>  
> +static GLboolean
> +st_TextureView(struct gl_context *ctx,
> +               struct gl_texture_object *texObj,
> +               struct gl_texture_object *origTexObj)
> +{
> +   struct st_texture_object *orig = st_texture_object(origTexObj);
> +   struct st_texture_object *tex = st_texture_object(texObj);
> +   struct gl_texture_image *image = texObj->Image[0][0];
> +
> +   const int numFaces = _mesa_num_tex_faces(texObj->Target);
> +   const int numLevels = texObj->NumLevels;
> +
> +   int face;
> +   int level;
> +
> +   pipe_resource_reference(&tex->pt, orig->pt);
> +
> +   /* Set image resource pointers */
> +   for (level = 0; level < numLevels; level++) {
> +      for (face = 0; face < numFaces; face++) {
> +         struct st_texture_image *stImage =
> +            st_texture_image(texObj->Image[face][level]);
> +         pipe_resource_reference(&stImage->pt, tex->pt);
> +      }
> +   }
> +
> +   tex->surface_based = GL_TRUE;
> +   tex->surface_format =
> +      st_mesa_format_to_pipe_format(st_context(ctx), image->TexFormat);
> +
> +   tex->width0 = image->Width;
> +   tex->height0 = image->Height;
> +   tex->depth0 = image->Depth;
> +   tex->lastLevel = numLevels - 1;
> +
> +   return GL_TRUE;
> +}
> +
>  
>  void
>  st_init_texture_functions(struct dd_function_table *functions)
> @@ -1855,4 +1900,5 @@ st_init_texture_functions(struct dd_function_table *functions)
>     functions->TestProxyTexImage = st_TestProxyTexImage;
>  
>     functions->AllocTextureStorage = st_AllocTextureStorage;
> +   functions->TextureView = st_TextureView;
>  }
> diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c
> index 4110eb5..78cdee7 100644
> --- a/src/mesa/state_tracker/st_extensions.c
> +++ b/src/mesa/state_tracker/st_extensions.c
> @@ -461,6 +461,7 @@ void st_init_extensions(struct pipe_screen *screen,
>        { o(ARB_draw_indirect),                PIPE_CAP_DRAW_INDIRECT                    },
>        { o(ARB_derivative_control),           PIPE_CAP_TGSI_FS_FINE_DERIVATIVE          },
>        { o(ARB_conditional_render_inverted),  PIPE_CAP_CONDITIONAL_RENDER_INVERTED      },
> +      { o(ARB_texture_view),                 PIPE_CAP_SAMPLER_VIEW_TARGET              },
>     };
>  
>     /* Required: render target and sampler support */
> diff --git a/src/mesa/state_tracker/st_format.c b/src/mesa/state_tracker/st_format.c
> index b5e03b0..531bc65 100644
> --- a/src/mesa/state_tracker/st_format.c
> +++ b/src/mesa/state_tracker/st_format.c
> @@ -879,6 +879,7 @@ struct format_mapping
>  
>  #define DEFAULT_SRGBA_FORMATS \
>        PIPE_FORMAT_B8G8R8A8_SRGB, \
> +      PIPE_FORMAT_R8G8B8A8_SRGB, \
>        PIPE_FORMAT_A8R8G8B8_SRGB, \
>        PIPE_FORMAT_A8B8G8R8_SRGB, \
>        0
> @@ -919,11 +920,11 @@ static const struct format_mapping format_map[] = {
>     },
>     {
>        { 4, GL_RGBA, GL_RGBA8, 0 },
> -      { PIPE_FORMAT_R8G8B8A8_UNORM, DEFAULT_RGBA_FORMATS }
> +      { DEFAULT_RGBA_FORMATS }
>     },
>     {
>        { GL_BGRA, 0 },
> -      { PIPE_FORMAT_B8G8R8A8_UNORM, DEFAULT_RGBA_FORMATS }
> +      { DEFAULT_RGBA_FORMATS }
>     },
>     {
>        { 3, GL_RGB, GL_RGB8, 0 },
> diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c
> index af9b767..c84aa45 100644
> --- a/src/mesa/state_tracker/st_texture.c
> +++ b/src/mesa/state_tracker/st_texture.c
> @@ -260,6 +260,12 @@ st_texture_image_map(struct st_context *st, struct st_texture_image *stImage,
>     else
>        level = stImage->base.Level;
>  
> +   if (stObj->base.Immutable) {
> +      level += stObj->base.MinLevel;
> +      z += stObj->base.MinLayer;
> +      d = MIN2(d, stObj->base.NumLayers);
> +   }
> +
>     z += stImage->base.Face;
>  
>     map = pipe_transfer_map_3d(st->pipe, stImage->pt, level, usage,
> @@ -289,8 +295,13 @@ st_texture_image_unmap(struct st_context *st,
>                         struct st_texture_image *stImage, unsigned slice)
>  {
>     struct pipe_context *pipe = st->pipe;
> -   struct pipe_transfer **transfer =
> -      &stImage->transfer[slice + stImage->base.Face].transfer;
> +   struct st_texture_object *stObj =
> +      st_texture_object(stImage->base.TexObject);
> +   struct pipe_transfer **transfer;
> +
> +   if (stObj->base.Immutable)
> +      slice += stObj->base.MinLayer;
> +   transfer = &stImage->transfer[slice + stImage->base.Face].transfer;
>  
>     DBG("%s\n", __FUNCTION__);
>  
> 

I wouldn't be able to spot errors here and it seems a bit more
complicated than I'd like, though it looks all the complexity really
comes from the GL side so nothing we can do about it. So, looks good to me.
One minor issue (which is sort of related to this) is that format
compatibility in gallium doesn't really follow ARB_texture_view view
classes. In particular, gl view classes only require that total bits per
pixel be identical, whereas gallium (and notably d3d10 with the typeless
groups) require that each component has the same size (and ordering)
too. This means that decisions if resource_copy_region can be used for
instance will say no there, despite that if ARB_texture_view is
supported (which forces things like R32F and R16G16F to have identical
layout in memory) the formats should probably be considered to be
compatible. But this shouldn't be a show-stopper.

Roland



More information about the mesa-dev mailing list