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

Ilia Mirkin imirkin at alum.mit.edu
Mon Apr 27 10:47:10 PDT 2015


On Mon, Apr 27, 2015 at 1:39 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.
>
> v2: cache offsets

Thanks, this is much nicer IMO.

Reviewed-by: Ilia Mirkin <imirkin at alum.mit.edu>

>
> Signed-off-by: Axel Davy <axel.davy at ens.fr>
> ---
>  src/gallium/state_trackers/nine/cubetexture9.c | 46 ++++++++++++++++++-----
>  src/gallium/state_trackers/nine/cubetexture9.h |  1 +
>  src/gallium/state_trackers/nine/nine_pipe.h    | 41 +++++++++++++++++++++
>  src/gallium/state_trackers/nine/surface9.c     | 51 ++++++++++++++------------
>  src/gallium/state_trackers/nine/surface9.h     |  1 -
>  src/gallium/state_trackers/nine/texture9.c     | 27 +++++++++++++-
>  src/gallium/state_trackers/nine/texture9.h     |  1 +
>  7 files changed, 131 insertions(+), 37 deletions(-)
>
> diff --git a/src/gallium/state_trackers/nine/cubetexture9.c b/src/gallium/state_trackers/nine/cubetexture9.c
> index d81cc70..f64764c 100644
> --- a/src/gallium/state_trackers/nine/cubetexture9.c
> +++ b/src/gallium/state_trackers/nine/cubetexture9.c
> @@ -20,6 +20,8 @@
>   * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
>   * USE OR OTHER DEALINGS IN THE SOFTWARE. */
>
> +#include "c99_alloca.h"
> +
>  #include "device9.h"
>  #include "cubetexture9.h"
>  #include "nine_helpers.h"
> @@ -40,8 +42,10 @@ 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;
> +    unsigned *level_offsets;
>      D3DSURFACE_DESC sfdesc;
> +    void *p;
>      HRESULT hr;
>
>      DBG("This=%p pParams=%p EdgeLength=%u Levels=%u Usage=%d "
> @@ -97,6 +101,16 @@ NineCubeTexture9_ctor( struct NineCubeTexture9 *This,
>          DBG("Application asked for Software Vertex Processing, "
>              "but this is unimplemented\n");
>
> +    if (Pool != D3DPOOL_DEFAULT) {
> +        level_offsets = alloca(sizeof(unsigned) * (info->last_level + 1));
> +        face_size = nine_format_get_size_and_offsets(pf, level_offsets,
> +                                                     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 +131,25 @@ 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; l++) {
> +            sfdesc.Width = sfdesc.Height = u_minify(EdgeLength, l);
> +            p = This->managed_buffer ? This->managed_buffer + offset +
> +                    level_offsets[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 +169,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..1b88612 100644
> --- a/src/gallium/state_trackers/nine/nine_pipe.h
> +++ b/src/gallium/state_trackers/nine/nine_pipe.h
> @@ -673,4 +673,45 @@ 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_level_alloc_size(enum pipe_format format,
> +                                                        unsigned width,
> +                                                        unsigned height,
> +                                                        unsigned level)
> +{
> +    unsigned w, h, size;
> +
> +    w = u_minify(width, level);
> +    h = u_minify(height, level);
> +    size = nine_format_get_stride(format, w) *
> +        util_format_get_nblocksy(format, h);
> +    return size;
> +}
> +
> +static INLINE unsigned nine_format_get_size_and_offsets(enum pipe_format format,
> +                                                        unsigned *offsets,
> +                                                        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);
> +        offsets[l] = size;
> +        size += nine_format_get_stride(format, w) *
> +            util_format_get_nblocksy(format, h);
> +    }
> +
> +    return size;
> +}
> +
>  #endif /* _NINE_PIPE_H_ */
> diff --git a/src/gallium/state_trackers/nine/surface9.c b/src/gallium/state_trackers/nine/surface9.c
> index f1b4aa9..e202f87 100644
> --- a/src/gallium/state_trackers/nine/surface9.c
> +++ b/src/gallium/state_trackers/nine/surface9.c
> @@ -62,10 +62,17 @@ NineSurface9_ctor( struct NineSurface9 *This,
>      user_assert(!(pDesc->Usage & D3DUSAGE_DYNAMIC) ||
>                  (pDesc->Pool != D3DPOOL_MANAGED), D3DERR_INVALIDCALL);
>
> -    assert(pResource ||
> -           pDesc->Pool != D3DPOOL_DEFAULT || pDesc->Format == D3DFMT_NULL);
> +    assert(pResource || (user_buffer && pDesc->Pool != D3DPOOL_DEFAULT) ||
> +           (!pContainer && pDesc->Pool != D3DPOOL_DEFAULT) ||
> +           pDesc->Format == D3DFMT_NULL);
>
>      assert(!pResource || !user_buffer);
> +    assert(!user_buffer || pDesc->Pool != D3DPOOL_DEFAULT);
> +    /* The only way we can have !pContainer is being created
> +     * from create_zs_or_rt_surface with params 0 0 0 */
> +    assert(pContainer || (Level == 0 && Layer == 0 && TextureType == 0));
> +
> +    This->data = (uint8_t *)user_buffer;
>
>      This->base.info.screen = pParams->device->screen;
>      This->base.info.target = PIPE_TEXTURE_2D;
> @@ -90,9 +97,20 @@ NineSurface9_ctor( struct NineSurface9 *This,
>      if (pDesc->Usage & D3DUSAGE_DEPTHSTENCIL)
>          This->base.info.bind |= PIPE_BIND_DEPTH_STENCIL;
>
> +    /* Ram buffer with no parent. Has to allocate the resource itself */
> +    if (!pResource && !pContainer) {
> +        assert(!user_buffer);
> +        This->data = MALLOC(
> +            nine_format_get_level_alloc_size(This->base.info.format,
> +                                             pDesc->Width,
> +                                             pDesc->Height,
> +                                             0));
> +        if (!This->data)
> +            return E_OUTOFMEMORY;
> +    }
> +
>      if (pDesc->Pool == D3DPOOL_SYSTEMMEM) {
>          This->base.info.usage = PIPE_USAGE_STAGING;
> -        This->data = (uint8_t *)user_buffer; /* this is *pSharedHandle */
>          assert(!pResource);
>      } else {
>          if (pResource && (pDesc->Usage & D3DUSAGE_DYNAMIC))
> @@ -113,24 +131,10 @@ NineSurface9_ctor( struct NineSurface9 *This,
>      This->layer = Layer;
>      This->desc = *pDesc;
>
> -    This->stride = util_format_get_stride(This->base.info.format, pDesc->Width);
> -    This->stride = align(This->stride, 4);
> -
> -    if (!pResource && !This->data) {
> -        const unsigned size = This->stride *
> -            util_format_get_nblocksy(This->base.info.format, This->desc.Height);
> +    This->stride = nine_format_get_stride(This->base.info.format, pDesc->Width);
>
> -        DBG("(%p(This=%p),level=%u) Allocating 0x%x bytes of system memory.\n",
> -            This->base.base.container, This, This->level, size);
> -
> -        This->data = (uint8_t *)MALLOC(size);
> -        if (!This->data)
> -            return E_OUTOFMEMORY;
> -        This->manage_data = TRUE;
> -    } else {
> -        if (pResource && NineSurface9_IsOffscreenPlain(This))
> -            pResource->flags |= NINE_RESOURCE_FLAG_LOCKABLE; /* why setting this flag there ? too late ? should be before NineResource9_ctor call perhaps ? */
> -    }
> +    if (pResource && NineSurface9_IsOffscreenPlain(This))
> +        pResource->flags |= NINE_RESOURCE_FLAG_LOCKABLE;
>
>      NineSurface9_Dump(This);
>
> @@ -147,8 +151,8 @@ NineSurface9_dtor( struct NineSurface9 *This )
>      pipe_surface_reference(&This->surface[0], NULL);
>      pipe_surface_reference(&This->surface[1], NULL);
>
> -    /* release allocated system memory for non-D3DPOOL_DEFAULT resources */
> -    if (This->manage_data && This->data)
> +    /* Release system memory when we have to manage it (no parent) */
> +    if (!This->base.base.container && This->data)
>          FREE(This->data);
>      NineResource9_dtor(&This->base);
>  }
> @@ -678,9 +682,8 @@ NineSurface9_SetResourceResize( struct NineSurface9 *This,
>      This->desc.Height = This->base.info.height0 = resource->height0;
>      This->desc.MultiSampleType = This->base.info.nr_samples = resource->nr_samples;
>
> -    This->stride = util_format_get_stride(This->base.info.format,
> +    This->stride = nine_format_get_stride(This->base.info.format,
>                                            This->desc.Width);
> -    This->stride = align(This->stride, 4);
>
>      pipe_surface_reference(&This->surface[0], NULL);
>      pipe_surface_reference(&This->surface[1], NULL);
> diff --git a/src/gallium/state_trackers/nine/surface9.h b/src/gallium/state_trackers/nine/surface9.h
> index 32e1722..7d6932a 100644
> --- a/src/gallium/state_trackers/nine/surface9.h
> +++ b/src/gallium/state_trackers/nine/surface9.h
> @@ -48,7 +48,6 @@ struct NineSurface9
>      D3DSURFACE_DESC desc;
>
>      uint8_t *data; /* system memory backing */
> -    boolean manage_data;
>      unsigned stride; /* for system memory backing */
>
>      /* wine doesn't even use these, 2 will be enough */
> diff --git a/src/gallium/state_trackers/nine/texture9.c b/src/gallium/state_trackers/nine/texture9.c
> index 78a632f..536d631 100644
> --- a/src/gallium/state_trackers/nine/texture9.c
> +++ b/src/gallium/state_trackers/nine/texture9.c
> @@ -20,6 +20,8 @@
>   * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
>   * USE OR OTHER DEALINGS IN THE SOFTWARE. */
>
> +#include "c99_alloca.h"
> +
>  #include "device9.h"
>  #include "surface9.h"
>  #include "texture9.h"
> @@ -48,10 +50,11 @@ NineTexture9_ctor( struct NineTexture9 *This,
>      struct pipe_resource *info = &This->base.base.info;
>      struct pipe_resource *resource;
>      enum pipe_format pf;
> +    unsigned *level_offsets;
>      unsigned l;
>      D3DSURFACE_DESC sfdesc;
>      HRESULT hr;
> -    void *user_buffer = NULL;
> +    void *user_buffer = NULL, *user_buffer_for_level;
>
>      DBG("(%p) Width=%u Height=%u Levels=%u Usage=%s Format=%s Pool=%s "
>          "pSharedHandle=%p\n", This, Width, Height, Levels,
> @@ -138,6 +141,19 @@ NineTexture9_ctor( struct NineTexture9 *This,
>
>      if (pSharedHandle && *pSharedHandle) { /* Pool == D3DPOOL_SYSTEMMEM */
>          user_buffer = (void *)*pSharedHandle;
> +        level_offsets = alloca(sizeof(unsigned) * (info->last_level + 1));
> +        (void) nine_format_get_size_and_offsets(pf, level_offsets,
> +                                                Width, Height,
> +                                                info->last_level);
> +    } else if (Pool != D3DPOOL_DEFAULT) {
> +        level_offsets = alloca(sizeof(unsigned) * (info->last_level + 1));
> +        user_buffer = MALLOC(
> +            nine_format_get_size_and_offsets(pf, level_offsets,
> +                                             Width, Height,
> +                                             info->last_level));
> +        This->managed_buffer = user_buffer;
> +        if (!This->managed_buffer)
> +            return E_OUTOFMEMORY;
>      }
>
>      This->surfaces = CALLOC(info->last_level + 1, sizeof(*This->surfaces));
> @@ -168,9 +184,13 @@ NineTexture9_ctor( struct NineTexture9 *This,
>      for (l = 0; l <= info->last_level; ++l) {
>          sfdesc.Width = u_minify(Width, l);
>          sfdesc.Height = u_minify(Height, l);
> +        /* Some apps expect the memory to be allocated in
> +         * continous blocks */
> +        user_buffer_for_level = user_buffer ? user_buffer +
> +            level_offsets[l] : NULL;
>
>          hr = NineSurface9_new(This->base.base.base.device, NineUnknown(This),
> -                              resource, user_buffer,
> +                              resource, user_buffer_for_level,
>                                D3DRTYPE_TEXTURE, l, 0,
>                                &sfdesc, &This->surfaces[l]);
>          if (FAILED(hr))
> @@ -198,6 +218,9 @@ NineTexture9_dtor( struct NineTexture9 *This )
>          FREE(This->surfaces);
>      }
>
> +    if (This->managed_buffer)
> +        FREE(This->managed_buffer);
> +
>      NineBaseTexture9_dtor(&This->base);
>  }
>
> diff --git a/src/gallium/state_trackers/nine/texture9.h b/src/gallium/state_trackers/nine/texture9.h
> index 5e37a12..65db874 100644
> --- a/src/gallium/state_trackers/nine/texture9.h
> +++ b/src/gallium/state_trackers/nine/texture9.h
> @@ -31,6 +31,7 @@ struct NineTexture9
>      struct NineBaseTexture9 base;
>      struct NineSurface9 **surfaces;
>      struct pipe_box dirty_rect; /* covers all mip levels */
> +    uint8_t *managed_buffer;
>  };
>  static INLINE struct NineTexture9 *
>  NineTexture9( void *data )
> --
> 2.1.0
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list