[Mesa-dev] [PATCH 16/16] st/nine: Rework texture data allocation

Ilia Mirkin imirkin at alum.mit.edu
Fri Apr 24 15:02:53 PDT 2015


On Fri, Apr 24, 2015 at 4:09 PM, Axel Davy <axel.davy at ens.fr> wrote:
> Some applications assume the memory for multilevel
> textures is allocated per continuous blocks.
>
> This patch implements that behaviour.
>
> Signed-off-by: Axel Davy <axel.davy at ens.fr>
> ---
>  src/gallium/state_trackers/nine/cubetexture9.c | 42 ++++++++++++++++------
>  src/gallium/state_trackers/nine/cubetexture9.h |  1 +
>  src/gallium/state_trackers/nine/nine_pipe.h    | 34 ++++++++++++++++++
>  src/gallium/state_trackers/nine/surface9.c     | 50 +++++++++++++-------------
>  src/gallium/state_trackers/nine/surface9.h     |  1 -
>  src/gallium/state_trackers/nine/texture9.c     | 18 ++++++++--
>  src/gallium/state_trackers/nine/texture9.h     |  1 +
>  7 files changed, 110 insertions(+), 37 deletions(-)
>
> diff --git a/src/gallium/state_trackers/nine/cubetexture9.c b/src/gallium/state_trackers/nine/cubetexture9.c
> index d81cc70..34ef4ec 100644
> --- a/src/gallium/state_trackers/nine/cubetexture9.c
> +++ b/src/gallium/state_trackers/nine/cubetexture9.c
> @@ -40,8 +40,9 @@ NineCubeTexture9_ctor( struct NineCubeTexture9 *This,
>      struct pipe_resource *info = &This->base.base.info;
>      struct pipe_screen *screen = pParams->device->screen;
>      enum pipe_format pf;
> -    unsigned i;
> +    unsigned i, l, f, offset, face_size = 0;
>      D3DSURFACE_DESC sfdesc;
> +    void *p;
>      HRESULT hr;
>
>      DBG("This=%p pParams=%p EdgeLength=%u Levels=%u Usage=%d "
> @@ -97,6 +98,14 @@ NineCubeTexture9_ctor( struct NineCubeTexture9 *This,
>          DBG("Application asked for Software Vertex Processing, "
>              "but this is unimplemented\n");
>
> +    if (Pool != D3DPOOL_DEFAULT) {
> +        face_size = nine_format_get_alloc_size(pf, EdgeLength, EdgeLength,
> +                                               info->last_level);
> +        This->managed_buffer = MALLOC(6 * face_size);
> +        if (!This->managed_buffer)
> +            return E_OUTOFMEMORY;
> +    }
> +
>      This->surfaces = CALLOC(6 * (info->last_level + 1), sizeof(*This->surfaces));
>      if (!This->surfaces)
>          return E_OUTOFMEMORY;
> @@ -117,16 +126,26 @@ NineCubeTexture9_ctor( struct NineCubeTexture9 *This,
>      sfdesc.Pool = Pool;
>      sfdesc.MultiSampleType = D3DMULTISAMPLE_NONE;
>      sfdesc.MultiSampleQuality = 0;
> -    for (i = 0; i < (info->last_level + 1) * 6; ++i) {
> -        sfdesc.Width = sfdesc.Height = u_minify(EdgeLength, i / 6);
> -
> -        hr = NineSurface9_new(This->base.base.base.device, NineUnknown(This),
> -                              This->base.base.resource, NULL, D3DRTYPE_CUBETEXTURE,
> -                              i / 6, i % 6,
> -                              &sfdesc, &This->surfaces[i]);
> -        if (FAILED(hr))
> -            return hr;
> +    /* We allocate the memory for the surfaces as continous blocks.
> +     * This is the expected behaviour, however we haven't tested for
> +     * cube textures in which order the faces/levels should be in memory
> +     */
> +    for (f = 0; f < 6; f++) {
> +        offset = f * face_size;
> +        for (l = 0; l < info->last_level + 1; l++) {

Elsewhere else you do <= info->last_level. Try to stay consistent...

> +            sfdesc.Width = sfdesc.Height = u_minify(EdgeLength, l);
> +            p = This->managed_buffer ? This->managed_buffer + offset +
> +                nine_format_get_p_offset(pf, EdgeLength, EdgeLength, l) :
> +                NULL;
> +
> +            hr = NineSurface9_new(This->base.base.base.device, NineUnknown(This),
> +                                  This->base.base.resource, p, D3DRTYPE_CUBETEXTURE,
> +                                  l, f, &sfdesc, &This->surfaces[f + 6 * l]);
> +            if (FAILED(hr))
> +                return hr;
> +        }
>      }
> +
>      for (i = 0; i < 6; ++i) /* width = 0 means empty, depth stays 1 */
>          This->dirty_rect[i].depth = 1;
>
> @@ -146,6 +165,9 @@ NineCubeTexture9_dtor( struct NineCubeTexture9 *This )
>          FREE(This->surfaces);
>      }
>
> +    if (This->managed_buffer)
> +        FREE(This->managed_buffer);
> +
>      NineBaseTexture9_dtor(&This->base);
>  }
>
> diff --git a/src/gallium/state_trackers/nine/cubetexture9.h b/src/gallium/state_trackers/nine/cubetexture9.h
> index e8594d3..ee7e275 100644
> --- a/src/gallium/state_trackers/nine/cubetexture9.h
> +++ b/src/gallium/state_trackers/nine/cubetexture9.h
> @@ -31,6 +31,7 @@ struct NineCubeTexture9
>      struct NineBaseTexture9 base;
>      struct NineSurface9 **surfaces;
>      struct pipe_box dirty_rect[6]; /* covers all mip levels */
> +    uint8_t *managed_buffer;
>  };
>  static INLINE struct NineCubeTexture9 *
>  NineCubeTexture9( void *data )
> diff --git a/src/gallium/state_trackers/nine/nine_pipe.h b/src/gallium/state_trackers/nine/nine_pipe.h
> index b8e728e..20916b7 100644
> --- a/src/gallium/state_trackers/nine/nine_pipe.h
> +++ b/src/gallium/state_trackers/nine/nine_pipe.h
> @@ -673,4 +673,38 @@ d3dtexturefiltertype_to_pipe_tex_mipfilter(D3DTEXTUREFILTERTYPE filter)
>      }
>  }
>
> +static INLINE unsigned nine_format_get_stride(enum pipe_format format,
> +                                              unsigned width)
> +{
> +    unsigned stride = util_format_get_stride(format, width);
> +
> +    return align(stride, 4);
> +}
> +
> +static INLINE unsigned nine_format_get_alloc_size(enum pipe_format format,
> +                                                  unsigned width,
> +                                                  unsigned height,
> +                                                  unsigned last_level)
> +{
> +    unsigned l, w, h, size = 0;
> +
> +    for (l = 0; l <= last_level; ++l) {
> +        w = u_minify(width, l);
> +        h = u_minify(height, l);
> +        size += nine_format_get_stride(format, w) *
> +            util_format_get_nblocksy(format, h);
> +    }
> +
> +    return size;
> +}
> +
> +static INLINE unsigned nine_format_get_p_offset(enum pipe_format format,
> +                                                unsigned width,
> +                                                unsigned height,
> +                                                unsigned level)
> +{
> +    if (!level)
> +        return 0;
> +    return nine_format_get_alloc_size(format, width, height, level-1);

This is going to be slow. Normally you just store the per-level
offsets in an array in the texture and look them up directly.

I'm having trouble understanding what you're changing here... perhaps
a better commit description could go a ways to clearing things up?
Were you allocating it a level at a time before? How did that work, I
don't see a per-level structure... I'm guessing there's a bit more
going on here.


More information about the mesa-dev mailing list