On Mon, Apr 27, 2015 at 1:39 PM, Axel Davy <axel.d...@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 <imir...@alum.mit.edu> > > Signed-off-by: Axel Davy <axel.d...@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@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev