On Tue, Nov 21, 2017 at 4:13 PM, Eric Anholt <e...@anholt.net> wrote: > v2: Remove the callback, leave avoiding the recursion up to the caller > (probably by rewriting the vtbl either in pctx or u_resource_vtbl)
hmm, that is still a bit ugly.. and looking at the equiv thing that Ilia implemented in freedreno, I think there is also so special handling needed for ->transfer_flush_region().. If you don't want to add it in u_resource/_vtbl (and I agree, a per rsc vtbl is kinda unneeded), maybe we could introduce in a similar way, u_transfer_vtbl/u_transfer_resource/u_transfer, ie. struct u_transfer_resource { struct pipe_resource b; struct pipe_resource *stencil; /* holds separate stencil buffer for z32x24s8 */ } struct u_transfer { struct pipe_transfer b; void *staging; } struct u_transfer_vtbl { struct pipe_resource (*resource_create)(...); void (*resource_destroy)(...); void *(*transfer_map)(...); void (*transfer_flush_region)(...); void (*transfer_unmap)(...); bool lower_z32s8; bool lower_rgtc; } Note that I had schemes to move the rgtc handling that freedreno does over to this new scheme too. Probably the MSAA resolve stuff could be folded into this same scheme, I haven't thought about that yet. The vtbl ptr doesn't have to be global. I think we can just stash a pointer in pipe_context like what is done for draw module and a few other things. If you want, I can take a stab at this approach, since I'm also messing w/ a staging buffer approach for uploads to flushed but busy buffers/textures to avoid a stall, and that gets easier once the staging stuff is separated ;-) BR, -R > --- > src/gallium/auxiliary/util/u_transfer.c | 114 > ++++++++++++++++++++++++++++++++ > src/gallium/auxiliary/util/u_transfer.h | 11 +++ > 2 files changed, 125 insertions(+) > > diff --git a/src/gallium/auxiliary/util/u_transfer.c > b/src/gallium/auxiliary/util/u_transfer.c > index 104d0505aaa8..2d219721dcf8 100644 > --- a/src/gallium/auxiliary/util/u_transfer.c > +++ b/src/gallium/auxiliary/util/u_transfer.c > @@ -1,4 +1,5 @@ > #include "pipe/p_context.h" > +#include "util/u_format_zs.h" > #include "util/u_surface.h" > #include "util/u_inlines.h" > #include "util/u_transfer.h" > @@ -272,3 +273,116 @@ void u_transfer_unmap_msaa_helper(struct pipe_context > *pctx, > pipe_resource_reference(&trans->ss, NULL); > free(trans); > } > + > +struct u_transfer_z32f_s8_helper { > + struct pipe_transfer base; > + struct pipe_transfer *z_ptrans; > + struct pipe_transfer *s_ptrans; > + void *z, *s; > + void *merged; > +}; > + > +/** > + * Helper to implement the PIPE_FORMAT_Z32_FLOAT_S8X24_UINT mappings when the > + * driver stores the Z and S in separate resources. > + * > + * We malloc temporary storage, map each resource, and use the CPU to pack > the > + * values into the temporary. > + * > + * Note that the driver's unmap will be called with our ptrans: They need to > + * detect it and call u_transfer_unmap_z32f_s8_helper() and return > + * immediately. > + * > + * In both the map and unmap paths, the driver will need to be careful to > + * unwrap its transfer_map()/unmap() method that would call us, so that it > + * doesn't recurse when we call back into it. > + */ > +void * > +u_transfer_map_z32f_s8_helper(struct pipe_context *pctx, > + struct pipe_resource *z, > + struct pipe_resource *s, > + unsigned level, unsigned usage, > + const struct pipe_box *box, > + struct pipe_transfer **pptrans) > +{ > + struct u_transfer_z32f_s8_helper *trans = calloc(1, sizeof(*trans)); > + if (!trans) > + return NULL; > + struct pipe_transfer *ptrans = &trans->base; > + > + pipe_resource_reference(&ptrans->resource, z); > + ptrans->level = level; > + ptrans->usage = usage; > + ptrans->box = *box; > + > + trans->z = pctx->transfer_map(pctx, z, level, usage, box, > + &trans->z_ptrans); > + if (!trans->z) > + goto fail_unref; > + trans->s = pctx->transfer_map(pctx, s, level, usage, box, > + &trans->s_ptrans); > + if (!trans->s) > + goto fail_unmap_z; > + > + ptrans->stride = 8 * box->width; > + trans->merged = malloc(ptrans->stride * box->height); > + if (!trans->merged) > + goto fail_unmap_s; > + > + if (usage & PIPE_TRANSFER_READ) { > + util_format_z32_float_s8x24_uint_pack_z_float(trans->merged, > + ptrans->stride, > + trans->z, > + trans->z_ptrans->stride, > + box->width, > + box->height); > + util_format_z32_float_s8x24_uint_pack_s_8uint(trans->merged, > + ptrans->stride, > + trans->s, > + trans->s_ptrans->stride, > + box->width, > + box->height); > + } > + > + *pptrans = ptrans; > + return trans->merged; > + > + fail_unmap_s: > + pctx->transfer_unmap(pctx, trans->s_ptrans); > + fail_unmap_z: > + pctx->transfer_unmap(pctx, trans->z_ptrans); > + fail_unref: > + pipe_resource_reference(&ptrans->resource, NULL); > + free(trans); > + return NULL; > +} > + > +void u_transfer_unmap_z32f_s8_helper(struct pipe_context *pctx, > + struct pipe_transfer *ptrans) > +{ > + struct u_transfer_z32f_s8_helper *trans = > + (struct u_transfer_z32f_s8_helper *)ptrans; > + > + if (ptrans->usage & PIPE_TRANSFER_WRITE) { > + uint32_t width = ptrans->box.width; > + uint32_t height = ptrans->box.height; > + > + util_format_z32_float_s8x24_uint_unpack_z_float(trans->z, > + > trans->z_ptrans->stride, > + trans->merged, > + ptrans->stride, > + width, height); > + util_format_z32_float_s8x24_uint_unpack_s_8uint(trans->s, > + > trans->s_ptrans->stride, > + trans->merged, > + ptrans->stride, > + width, height); > + } > + > + pctx->transfer_unmap(pctx, trans->s_ptrans); > + pctx->transfer_unmap(pctx, trans->z_ptrans); > + > + pipe_resource_reference(&ptrans->resource, NULL); > + free(trans->merged); > + free(trans); > +} > diff --git a/src/gallium/auxiliary/util/u_transfer.h > b/src/gallium/auxiliary/util/u_transfer.h > index 237930c06007..0a8a649df1f5 100644 > --- a/src/gallium/auxiliary/util/u_transfer.h > +++ b/src/gallium/auxiliary/util/u_transfer.h > @@ -24,6 +24,17 @@ u_transfer_map_msaa_helper(struct pipe_context *pctx, > void u_transfer_unmap_msaa_helper(struct pipe_context *pctx, > struct pipe_transfer *ptrans); > > +void * > +u_transfer_map_z32f_s8_helper(struct pipe_context *pctx, > + struct pipe_resource *z, > + struct pipe_resource *s, > + unsigned level, unsigned usage, > + const struct pipe_box *box, > + struct pipe_transfer **pptrans); > + > +void u_transfer_unmap_z32f_s8_helper(struct pipe_context *pctx, > + struct pipe_transfer *ptrans); > + > boolean u_default_resource_get_handle(struct pipe_screen *screen, > struct pipe_resource *resource, > struct winsys_handle *handle); > -- > 2.15.0 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev