[Mesa-dev] [PATCH 4/8] i965: Update the shadow miptree from the main to fake the ETC2 compression
Nanley Chery
nanleychery at gmail.com
Sat Jan 19 01:09:03 UTC 2019
On Mon, Nov 19, 2018 at 10:54:08AM +0200, Eleni Maria Stea wrote:
> On GPUs gen < 8 that don't support ETC2 sampling/rendering we now fake
> the support using 2 mipmap trees: one (the main) that stores the
> compressed data for the Get* functions to work and one (the shadow) that
> stores the same data decompressed for the render/sampling to work.
>
> Added the intel_update_decompressed_shadow function to update the shadow
> tree with the decompressed data whenever the main miptree with the
> compressed is changing.
> ---
> .../drivers/dri/i965/brw_wm_surface_state.c | 1 +
> src/mesa/drivers/dri/i965/intel_mipmap_tree.c | 70 ++++++++++++++++++-
> src/mesa/drivers/dri/i965/intel_mipmap_tree.h | 3 +
> 3 files changed, 71 insertions(+), 3 deletions(-)
>
> diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
> index 4d1eafac91..2e6d85e1fe 100644
> --- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
> +++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
> @@ -579,6 +579,7 @@ static void brw_update_texture_surface(struct gl_context *ctx,
>
> if (obj->StencilSampling && firstImage->_BaseFormat == GL_DEPTH_STENCIL) {
> if (devinfo->gen <= 7) {
> + assert(!intel_obj->mt->needs_fake_etc);
> assert(mt->shadow_mt && !mt->stencil_mt->shadow_needs_update);
> mt = mt->shadow_mt;
> } else {
> diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
> index b24332ff67..ef3e2c33d3 100644
> --- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
> +++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
> @@ -3740,12 +3740,15 @@ intel_miptree_map(struct brw_context *brw,
> assert(mt->surf.samples == 1);
>
> if (mt->needs_fake_etc) {
> - if (!(mode & BRW_MAP_ETC_BIT)) {
> + if (!(mode & BRW_MAP_ETC_BIT) && !(mode & GL_MAP_READ_BIT)) {
> assert(mt->shadow_mt);
>
> - mt->is_shadow_mapped = true;
> + if (mt->shadow_needs_update) {
> + intel_update_decompressed_shadow(brw, mt);
> + mt->shadow_needs_update = false;
> + }
>
> - mt->shadow_needs_update = false;
> + mt->is_shadow_mapped = true;
> mt = miptree->shadow_mt;
> } else {
> mt->is_shadow_mapped = false;
> @@ -3762,6 +3765,8 @@ intel_miptree_map(struct brw_context *brw,
>
> map = intel_miptree_attach_map(mt, level, slice, x, y, w, h, mode);
> if (!map){
> + miptree->is_shadow_mapped = false;
> +
> *out_ptr = NULL;
> *out_stride = 0;
> return;
> @@ -3942,3 +3947,62 @@ intel_miptree_get_clear_color(const struct gen_device_info *devinfo,
> return mt->fast_clear_color;
> }
> }
> +
> +void
> +intel_update_decompressed_shadow(struct brw_context *brw,
> + struct intel_mipmap_tree *mt)
> +{
> + struct intel_mipmap_tree *smt = mt->shadow_mt;
> +
> + assert(smt);
> + assert(mt->needs_fake_etc);
> + assert(mt->surf.size_B > 0);
> +
> + int img_w = smt->surf.logical_level0_px.width;
> + int img_h = smt->surf.logical_level0_px.height;
> + int img_d = smt->surf.logical_level0_px.depth;
I don't think 3D ETC textures are possible. From the GL4.6 spec:
An INVALID_OPERATION error is generated by CompressedTexImage3D
if internalformat is one of the EAC, ETC2, or RGTC formats and
either border is non-zero, or target is not TEXTURE_2D_ARRAY.
> +
> + ptrdiff_t shadow_stride = _mesa_format_row_stride(smt->format, img_w);
> +
This variable gets overwritten when calling intel_miptree_map().
> + for (int level = smt->first_level; level <= smt->last_level; level++) {
Since we're already iterating levels here we should fold in patch 6 to
get the right level dimensions.
> + struct compressed_pixelstore store;
> + _mesa_compute_compressed_pixelstore(mt->surf.dim,
> + mt->format,
> + img_w, img_h, img_d,
> + &brw->ctx.Unpack,
> + &store);
store.TotalBytesPerRow will give you the pitch for a buffer allocated
without padding. mt->surf->row_pitch_B gives you the actual pitch.
> + for (unsigned int slice = 0; slice < img_d; slice++) {
> + GLbitfield mmode = GL_MAP_READ_BIT | BRW_MAP_DIRECT_BIT |
> + BRW_MAP_ETC_BIT;
> + GLbitfield smode = GL_MAP_WRITE_BIT |
> + GL_MAP_INVALIDATE_RANGE_BIT |
> + BRW_MAP_DIRECT_BIT;
> +
> + uint32_t img_x, img_y;
> + intel_miptree_get_image_offset(smt, level, slice, &img_x, &img_y);
> +
> + void *mptr = intel_miptree_map_raw(brw, mt, mmode) + mt->offset
> + + img_y * store.TotalBytesPerRow
> + + img_x * store.TotalBytesPerRow / img_w;
Due to the padding mentioned earlier, the pitch divided by the width
won't always give you the bytes per pixel. If we reorder the patches a
bit, we should be able to use intel_miptree_map() to get mptr and it's
pitch.
> +
> + void *sptr;
> + intel_miptree_map(brw, smt, level, slice, img_x, img_y, img_w, img_h,
> + smode, &sptr, &shadow_stride);
img_x and img_y are offsets relative to the start of the image
(level 0/slice 0). intel_miptree_map() is looking for the x and y offset
relative to each level / slice.
-Nanley
> +
> + if (mt->format == MESA_FORMAT_ETC1_RGB8) {
> + _mesa_etc1_unpack_rgba8888(sptr, shadow_stride,
> + mptr, store.TotalBytesPerRow,
> + img_w, img_h);
> + } else {
> + _mesa_unpack_etc2_format(sptr, shadow_stride,
> + mptr, store.TotalBytesPerRow,
> + img_w, img_h, mt->format, true);
> + }
> +
> + intel_miptree_unmap_raw(mt);
> + intel_miptree_unmap(brw, smt, level, slice);
> + }
> + }
> +
> + mt->shadow_needs_update = false;
> +}
> diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
> index aca45cfaa4..02c98c80ca 100644
> --- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
> +++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
> @@ -733,6 +733,9 @@ intel_miptree_get_clear_color(const struct gen_device_info *devinfo,
> struct brw_bo **clear_color_bo,
> uint32_t *clear_color_offset);
>
> +void
> +intel_update_decompressed_shadow(struct brw_context *brw,
> + struct intel_mipmap_tree *mt);
>
> static inline int
> intel_miptree_blt_pitch(struct intel_mipmap_tree *mt)
> --
> 2.19.0
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
More information about the mesa-dev
mailing list