[Mesa-dev] [PATCH 1/2] gallium/util: add u_transfer_helper
Rob Clark
robdclark at gmail.com
Wed Dec 6 22:50:17 UTC 2017
On Wed, Dec 6, 2017 at 4:48 PM, Eric Anholt <eric at anholt.net> wrote:
> Rob Clark <robdclark at gmail.com> writes:
>
>> Add a new helper that drivers can use to emulate various things that
>> need special handling in particular in transfer_map:
>>
>> 1) z32_s8x24.. gl/gallium treats this as a single buffer with depth
>> and stencil interleaved but hardware frequently treats this as
>> separate z32 and s8 buffers. Special pack/unpack handling is
>> needed in transfer_map/unmap to pack/unpack the exposed buffer
>>
>> 2) fake RGTC.. GPUs designed with GLES in mind, but which can other-
>> wise do GL3, if native RGTC is not supported it can be emulated
>> by converting to uncompressed internally, but needs pack/unpack
>> in transfer_map/unmap
>>
>> 3) MSAA resolves in the transfer_map() case
>>
>> v2: add MSAA resolve based on Eric's "gallium: Add helpers for MSAA
>> resolves in pipe_transfer_map()/unmap()." patch; avoid wrapping
>> pipe_resource, to make it possible for drivers to use both this
>> and threaded_context.
>
> The driver side is clean enough with this layer that I'm pretty happy
> now. Just one significant review comment, then I think we'll be
> ready...
>
>> +static void
>> +flush_region(struct pipe_context *pctx, struct pipe_transfer *ptrans,
>> + const struct pipe_box *box)
>> +{
>> + struct u_transfer *trans = u_transfer(ptrans);
>> + enum pipe_format format = ptrans->resource->format;
>> + unsigned width = ptrans->box.width;
>> + unsigned height = ptrans->box.height;
>
> It seems silly to be implementing flush_region and ignoring the box
> argument to flush the entire mapped region on every call. We should
> either drop this implementation in favor of the no-op and flush at
> unmap, or actually use the box in the flushes.
oh, whoops.. and I guess in theory I should use those dimensions for
the MSAA blit too..
> That said, I don't think you can reach flush_region with explicit flush
> for non-buffer resources?
hmm, not 100% sure about the APIs on the GL side of things, but I
think if that were the case mesa/st would dtrt. (I guess it could be
different w/ gallium9, not that I have a big collection of windows arm
games to play :-P)
>> +
>> + if (!(ptrans->usage & PIPE_TRANSFER_WRITE))
>> + return;
>> +
>> + if (trans->ss) {
>> + struct pipe_blit_info blit;
>> + memset(&blit, 0, sizeof(blit));
>> +
>> + blit.src.resource = trans->ss;
>> + blit.src.format = trans->ss->format;
>> + blit.src.box.width = ptrans->box.width;
>> + blit.src.box.height = ptrans->box.height;
>> + blit.src.box.depth = 1;
>> +
>> + blit.dst.resource = ptrans->resource;
>> + blit.dst.format = ptrans->resource->format;
>> + blit.dst.level = ptrans->level;
>> + blit.dst.box = ptrans->box;
>> +
>> + blit.mask = util_format_get_mask(ptrans->resource->format);
>> + blit.filter = PIPE_TEX_FILTER_NEAREST;
>> +
>> + pctx->blit(pctx, &blit);
>> +
>> + return;
>> + }
>> +
>> + switch (format) {
>> + case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
>> + util_format_z32_float_s8x24_uint_unpack_z_float(trans->ptr,
>> + trans->trans->stride,
>> + trans->staging,
>> + ptrans->stride,
>> + width, height);
>> + /* fallthru */
>> + case PIPE_FORMAT_X32_S8X24_UINT:
>> + util_format_z32_float_s8x24_uint_unpack_s_8uint(trans->ptr2,
>> + trans->trans2->stride,
>> + trans->staging,
>> + ptrans->stride,
>> + width, height);
>> + break;
>> + case PIPE_FORMAT_RGTC1_UNORM:
>> + case PIPE_FORMAT_RGTC1_SNORM:
>> + case PIPE_FORMAT_LATC1_UNORM:
>> + case PIPE_FORMAT_LATC1_SNORM:
>> + util_format_rgtc1_unorm_unpack_rgba_8unorm(trans->ptr,
>> + trans->trans->stride,
>> + trans->staging,
>> + ptrans->stride,
>> + width, height);
>> + break;
>> + case PIPE_FORMAT_RGTC2_UNORM:
>> + case PIPE_FORMAT_RGTC2_SNORM:
>> + case PIPE_FORMAT_LATC2_UNORM:
>> + case PIPE_FORMAT_LATC2_SNORM:
>> + util_format_rgtc2_unorm_unpack_rgba_8unorm(trans->ptr,
>> + trans->trans->stride,
>> + trans->staging,
>> + ptrans->stride,
>> + width, height);
>> + break;
>> + default:
>> + assert(!"Unexpected staging transfer type");
>> + break;
>> + }
>> +}
>
>> diff --git a/src/gallium/auxiliary/util/u_transfer_helper.h b/src/gallium/auxiliary/util/u_transfer_helper.h
>> new file mode 100644
>> index 00000000000..392b34f0697
>> --- /dev/null
>> +++ b/src/gallium/auxiliary/util/u_transfer_helper.h
>> @@ -0,0 +1,132 @@
>> +/*
>> + * Copyright © 2017 Red Hat
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining a
>> + * copy of this software and associated documentation files (the "Software"),
>> + * to deal in the Software without restriction, including without limitation
>> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
>> + * and/or sell copies of the Software, and to permit persons to whom the
>> + * Software is furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice (including the next
>> + * paragraph) shall be included in all copies or substantial portions of the
>> + * Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
>> + * SOFTWARE.
>> + */
>> +
>> +#ifndef _U_TRANSFER_HELPER_H
>> +#define _U_TRANSFER_HELPER_H
>> +
>> +#include "pipe/p_state.h"
>> +#include "pipe/p_context.h"
>> +
>> +#ifdef __cplusplus
>> +extern "C" {
>> +#endif
>> +
>> +/* A helper to implement various "lowering" for transfers:
>> + *
>> + * - exposing separate z32 and s8 as z32x24s8
>> + * - fake RGTC support for GLES class hardware which needs it to expose GL3+
>> + * - MSAA resolves
>> + *
>> + * To use this, drivers should:
>> + *
>> + * 1) populate u_transfer_vtbl and plug that into pipe_screen::transfer_helper
>> + * 2) plug the the transfer helpers into pipe_screen/pipe_context
>
> s/the the/the/
opps
>> + *
>> + * To avoid subclassing pipe_resource (and conflicting with threaded_context)
>> + * the vtbl contains setter/getter methods used for fake_rgct & separate_stencil
>> + * to access the internal_format and separate stencil buffer.
>> + */
>> +
>> +struct u_transfer_vtbl {
>> + /* NOTE I am not expecting resource_create_from_handle() or
>> + * resource_create_with_modifiers() paths to be creating any
>> + * resources that need special handling. Otherwise they would
>> + * need to be wrapped too.
>> + */
>> + struct pipe_resource * (*resource_create)(struct pipe_screen *pscreen,
>> + const struct pipe_resource *templ);
>> +
>> + void (*resource_destroy)(struct pipe_screen *pscreen,
>> + struct pipe_resource *prsc);
>> +
>> + void *(*transfer_map)(struct pipe_context *pctx,
>> + struct pipe_resource *prsc,
>> + unsigned level,
>> + unsigned usage,
>> + const struct pipe_box *box,
>> + struct pipe_transfer **pptrans);
>> +
>> +
>> + void (*transfer_flush_region)(struct pipe_context *pctx,
>> + struct pipe_transfer *ptrans,
>> + const struct pipe_box *box);
>> +
>> + void (*transfer_unmap)(struct pipe_context *pctx,
>> + struct pipe_transfer *ptrans);
>> +
>> + /*
>> + * auxiliary methods to access internal format, stencil:
>> + */
>> +
>> + /**
>> + * Must be implemented if separate_z32s8 or fake_rgtc is used. The
>> + * internal_format is the format the resource was created with. In
>> + * the case of separate_z32s8 or fake_rgtc, prsc->format is set back
>> + * to the state tracker visible format (Z32_FLOAT_S8X24_UINT or
>> + * PIPE_FORMAT_{RTGC,LATC}* after the resource is created.
>> + */
>> + enum pipe_format (*get_internal_format)(struct pipe_resource *prsc);
>> +
>> + /**
>> + * Must be implemented if separate_z32s8 is used. Used to set/get
>> + * the separate s8 stencil buffer.
>> + */
>> + void (*set_stencil)(struct pipe_resource *prsc, struct pipe_resource *stencil);
>> + struct pipe_resource *(*get_stencil)(struct pipe_resource *prsc);
>
> Maybe we should note that these two ops are intended to be pointer
> assignments, not refcounted?
Yeah, probably.. and I guess document who destroys the stencil
resource. I'm pretty sure I was leaking those before in freedreno..
BR,
-R
More information about the mesa-dev
mailing list