[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