Re: [Mesa-dev] [PATCH v2 3/4] etnaviv: hook-up etc2 patching

2019-02-27 Thread Christian Gmeiner
Hi Lucas

Am Mi., 27. Feb. 2019 um 10:19 Uhr schrieb Lucas Stach :
>
> Am Dienstag, den 26.02.2019, 19:15 +0100 schrieb Christian Gmeiner:
> > Changes v1 -> v2:
> >  - Avoid the GPU sampling from the resource that gets mutated by the the
> >transfer map by setting DRM_ETNA_PREP_WRITE.
> >
> > > Signed-off-by: Christian Gmeiner 
> > ---
> >  .../drivers/etnaviv/etnaviv_resource.c|  3 +
> >  .../drivers/etnaviv/etnaviv_resource.h|  5 ++
> >  .../drivers/etnaviv/etnaviv_transfer.c| 55 +++
> >  3 files changed, 63 insertions(+)
> >
> > diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.c 
> > b/src/gallium/drivers/etnaviv/etnaviv_resource.c
> > index db5ead4d0ba..45d5f69169e 100644
> > --- a/src/gallium/drivers/etnaviv/etnaviv_resource.c
> > +++ b/src/gallium/drivers/etnaviv/etnaviv_resource.c
> > @@ -478,6 +478,9 @@ etna_resource_destroy(struct pipe_screen *pscreen, 
> > struct pipe_resource *prsc)
> > pipe_resource_reference(>texture, NULL);
> > pipe_resource_reference(>external, NULL);
> >
> > +   for (unsigned i = 0; i < ETNA_NUM_LOD; i++)
> > +  FREE(rsc->levels[i].patch_offsets);
> > +
> > FREE(rsc);
> >  }
> >
> > diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.h 
> > b/src/gallium/drivers/etnaviv/etnaviv_resource.h
> > index 75aa80b3d7a..c45ff7586d1 100644
> > --- a/src/gallium/drivers/etnaviv/etnaviv_resource.h
> > +++ b/src/gallium/drivers/etnaviv/etnaviv_resource.h
> > @@ -33,6 +33,7 @@
> >  #include "util/list.h"
> >
> >  struct pipe_screen;
> > +struct util_dynarray;
> >
> >  struct etna_resource_level {
> > unsigned width, padded_width; /* in pixels */
> > @@ -47,6 +48,10 @@ struct etna_resource_level {
> > uint32_t ts_size;
> > uint32_t clear_value; /* clear value of resource level (mainly for TS) 
> > */
> > bool ts_valid;
> > +
> > +   /* keep track if we have done some per block patching */
> > +   bool patched;
> > +   struct util_dynarray *patch_offsets;
> >  };
> >
> >  enum etna_resource_addressing_mode {
> > diff --git a/src/gallium/drivers/etnaviv/etnaviv_transfer.c 
> > b/src/gallium/drivers/etnaviv/etnaviv_transfer.c
> > index 01da393d211..9a83c481dce 100644
> > --- a/src/gallium/drivers/etnaviv/etnaviv_transfer.c
> > +++ b/src/gallium/drivers/etnaviv/etnaviv_transfer.c
> > @@ -28,6 +28,7 @@
> >  #include "etnaviv_clear_blit.h"
> >  #include "etnaviv_context.h"
> >  #include "etnaviv_debug.h"
> > +#include "etnaviv_etc2.h"
> >  #include "etnaviv_screen.h"
> >
> >  #include "pipe/p_defines.h"
> > @@ -57,6 +58,46 @@ etna_compute_offset(enum pipe_format format, const 
> > struct pipe_box *box,
> >   util_format_get_blocksize(format);
> >  }
> >
> > +static void etna_patch_data(void *buffer, const struct pipe_transfer 
> > *ptrans)
> > +{
> > +   struct pipe_resource *prsc = ptrans->resource;
> > +   struct etna_resource *rsc = etna_resource(prsc);
> > +   struct etna_resource_level *level = >levels[ptrans->level];
> > +
> > +   if (!etna_etc2_needs_patching(prsc))
>
> Maybe likely() here?
>

okay.

> > +  return;
> > +
> > +   if (level->patched)
> > +  return;
> > +
> > +   /* do have the offsets of blocks to patch? */
> > +   if (!level->patch_offsets) {
> > +  level->patch_offsets = CALLOC_STRUCT(util_dynarray);
> > +
> > +  etna_etc2_calculate_blocks(buffer, ptrans->stride,
> > + ptrans->box.width, 
> > ptrans->box.height,
> > + prsc->format, 
> > level->patch_offsets);
> > +   }
> > +
> > +   etna_etc2_patch(buffer, level->patch_offsets);
> > +
> > +   level->patched = true;
> > +}
> > +
> > +static void etna_unpatch_data(void *buffer, const struct pipe_transfer 
> > *ptrans)
> > +{
> > +   struct pipe_resource *prsc = ptrans->resource;
> > +   struct etna_resource *rsc = etna_resource(prsc);
> > +   struct etna_resource_level *level = >levels[ptrans->level];
> > +
> > +   if (!level->patched)
> > +  return;
> > +
> > +   etna_etc2_patch(buffer, level->patch_offsets);
> > +
> > +   level->patched = false;
> > +}
> > +
> >  static void
> >  etna_transfer_unmap(struct pipe_context *pctx, struct pipe_transfer 
> > *ptrans)
> >  {
> > @@ -119,6 +160,10 @@ etna_transfer_unmap(struct pipe_context *pctx, struct 
> > pipe_transfer *ptrans)
> >}
> > }
> >
> > +   /* We need to have the patched data ready for the GPU. */
> > +   if (rsc->layout == ETNA_LAYOUT_LINEAR)
>
> I don't like the LAYOUT_LINEAR checks here, as GC3000 actually has a
> feature bit TEX_COMPRESSION_SUPERTILED, so I don't think the assertion
> that all compressed formats are linear will hold in the future and it
> seems like a minor optimization.
>

Makes sense - will remove it in v3.

> > +  etna_patch_data(trans->mapped, ptrans);
> > +
> > /*
> >  * Transfers without a temporary are only pulled into the CPU domain if 
> > they
> >  * are not mapped unsynchronized. If they are, must push them 

Re: [Mesa-dev] [PATCH v2 3/4] etnaviv: hook-up etc2 patching

2019-02-27 Thread Lucas Stach
Am Dienstag, den 26.02.2019, 19:15 +0100 schrieb Christian Gmeiner:
> Changes v1 -> v2:
>  - Avoid the GPU sampling from the resource that gets mutated by the the
>    transfer map by setting DRM_ETNA_PREP_WRITE.
> 
> > Signed-off-by: Christian Gmeiner 
> ---
>  .../drivers/etnaviv/etnaviv_resource.c|  3 +
>  .../drivers/etnaviv/etnaviv_resource.h|  5 ++
>  .../drivers/etnaviv/etnaviv_transfer.c| 55 +++
>  3 files changed, 63 insertions(+)
> 
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.c 
> b/src/gallium/drivers/etnaviv/etnaviv_resource.c
> index db5ead4d0ba..45d5f69169e 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_resource.c
> +++ b/src/gallium/drivers/etnaviv/etnaviv_resource.c
> @@ -478,6 +478,9 @@ etna_resource_destroy(struct pipe_screen *pscreen, struct 
> pipe_resource *prsc)
> pipe_resource_reference(>texture, NULL);
> pipe_resource_reference(>external, NULL);
>  
> +   for (unsigned i = 0; i < ETNA_NUM_LOD; i++)
> +  FREE(rsc->levels[i].patch_offsets);
> +
> FREE(rsc);
>  }
>  
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.h 
> b/src/gallium/drivers/etnaviv/etnaviv_resource.h
> index 75aa80b3d7a..c45ff7586d1 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_resource.h
> +++ b/src/gallium/drivers/etnaviv/etnaviv_resource.h
> @@ -33,6 +33,7 @@
>  #include "util/list.h"
>  
>  struct pipe_screen;
> +struct util_dynarray;
>  
>  struct etna_resource_level {
> unsigned width, padded_width; /* in pixels */
> @@ -47,6 +48,10 @@ struct etna_resource_level {
> uint32_t ts_size;
> uint32_t clear_value; /* clear value of resource level (mainly for TS) */
> bool ts_valid;
> +
> +   /* keep track if we have done some per block patching */
> +   bool patched;
> +   struct util_dynarray *patch_offsets;
>  };
>  
>  enum etna_resource_addressing_mode {
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_transfer.c 
> b/src/gallium/drivers/etnaviv/etnaviv_transfer.c
> index 01da393d211..9a83c481dce 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_transfer.c
> +++ b/src/gallium/drivers/etnaviv/etnaviv_transfer.c
> @@ -28,6 +28,7 @@
>  #include "etnaviv_clear_blit.h"
>  #include "etnaviv_context.h"
>  #include "etnaviv_debug.h"
> +#include "etnaviv_etc2.h"
>  #include "etnaviv_screen.h"
>  
>  #include "pipe/p_defines.h"
> @@ -57,6 +58,46 @@ etna_compute_offset(enum pipe_format format, const struct 
> pipe_box *box,
>   util_format_get_blocksize(format);
>  }
>  
> +static void etna_patch_data(void *buffer, const struct pipe_transfer *ptrans)
> +{
> +   struct pipe_resource *prsc = ptrans->resource;
> +   struct etna_resource *rsc = etna_resource(prsc);
> +   struct etna_resource_level *level = >levels[ptrans->level];
> +
> +   if (!etna_etc2_needs_patching(prsc))

Maybe likely() here?

> +  return;
> +
> +   if (level->patched)
> +  return;
> +
> +   /* do have the offsets of blocks to patch? */
> +   if (!level->patch_offsets) {
> +  level->patch_offsets = CALLOC_STRUCT(util_dynarray);
> +
> +  etna_etc2_calculate_blocks(buffer, ptrans->stride,
> + ptrans->box.width, 
> ptrans->box.height,
> + prsc->format, level->patch_offsets);
> +   }
> +
> +   etna_etc2_patch(buffer, level->patch_offsets);
> +
> +   level->patched = true;
> +}
> +
> +static void etna_unpatch_data(void *buffer, const struct pipe_transfer 
> *ptrans)
> +{
> +   struct pipe_resource *prsc = ptrans->resource;
> +   struct etna_resource *rsc = etna_resource(prsc);
> +   struct etna_resource_level *level = >levels[ptrans->level];
> +
> +   if (!level->patched)
> +  return;
> +
> +   etna_etc2_patch(buffer, level->patch_offsets);
> +
> +   level->patched = false;
> +}
> +
>  static void
>  etna_transfer_unmap(struct pipe_context *pctx, struct pipe_transfer *ptrans)
>  {
> @@ -119,6 +160,10 @@ etna_transfer_unmap(struct pipe_context *pctx, struct 
> pipe_transfer *ptrans)
>    }
> }
>  
> +   /* We need to have the patched data ready for the GPU. */
> +   if (rsc->layout == ETNA_LAYOUT_LINEAR)

I don't like the LAYOUT_LINEAR checks here, as GC3000 actually has a
feature bit TEX_COMPRESSION_SUPERTILED, so I don't think the assertion
that all compressed formats are linear will hold in the future and it
seems like a minor optimization.

> +  etna_patch_data(trans->mapped, ptrans);
> +
> /*
>  * Transfers without a temporary are only pulled into the CPU domain if 
> they
>  * are not mapped unsynchronized. If they are, must push them back into 
> GPU
> @@ -321,6 +366,12 @@ etna_transfer_map(struct pipe_context *pctx, struct 
> pipe_resource *prsc,
>    if (usage & PIPE_TRANSFER_WRITE)
>   prep_flags |= DRM_ETNA_PREP_WRITE;
>  
> +  /* avoid the GPU sampling from the resource that gets mutated */

This doesn't really explain to the reader of this function what happens
here. Maybe something along the 

[Mesa-dev] [PATCH v2 3/4] etnaviv: hook-up etc2 patching

2019-02-26 Thread Christian Gmeiner
Changes v1 -> v2:
 - Avoid the GPU sampling from the resource that gets mutated by the the
   transfer map by setting DRM_ETNA_PREP_WRITE.

Signed-off-by: Christian Gmeiner 
---
 .../drivers/etnaviv/etnaviv_resource.c|  3 +
 .../drivers/etnaviv/etnaviv_resource.h|  5 ++
 .../drivers/etnaviv/etnaviv_transfer.c| 55 +++
 3 files changed, 63 insertions(+)

diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.c 
b/src/gallium/drivers/etnaviv/etnaviv_resource.c
index db5ead4d0ba..45d5f69169e 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_resource.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_resource.c
@@ -478,6 +478,9 @@ etna_resource_destroy(struct pipe_screen *pscreen, struct 
pipe_resource *prsc)
pipe_resource_reference(>texture, NULL);
pipe_resource_reference(>external, NULL);
 
+   for (unsigned i = 0; i < ETNA_NUM_LOD; i++)
+  FREE(rsc->levels[i].patch_offsets);
+
FREE(rsc);
 }
 
diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.h 
b/src/gallium/drivers/etnaviv/etnaviv_resource.h
index 75aa80b3d7a..c45ff7586d1 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_resource.h
+++ b/src/gallium/drivers/etnaviv/etnaviv_resource.h
@@ -33,6 +33,7 @@
 #include "util/list.h"
 
 struct pipe_screen;
+struct util_dynarray;
 
 struct etna_resource_level {
unsigned width, padded_width; /* in pixels */
@@ -47,6 +48,10 @@ struct etna_resource_level {
uint32_t ts_size;
uint32_t clear_value; /* clear value of resource level (mainly for TS) */
bool ts_valid;
+
+   /* keep track if we have done some per block patching */
+   bool patched;
+   struct util_dynarray *patch_offsets;
 };
 
 enum etna_resource_addressing_mode {
diff --git a/src/gallium/drivers/etnaviv/etnaviv_transfer.c 
b/src/gallium/drivers/etnaviv/etnaviv_transfer.c
index 01da393d211..9a83c481dce 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_transfer.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_transfer.c
@@ -28,6 +28,7 @@
 #include "etnaviv_clear_blit.h"
 #include "etnaviv_context.h"
 #include "etnaviv_debug.h"
+#include "etnaviv_etc2.h"
 #include "etnaviv_screen.h"
 
 #include "pipe/p_defines.h"
@@ -57,6 +58,46 @@ etna_compute_offset(enum pipe_format format, const struct 
pipe_box *box,
  util_format_get_blocksize(format);
 }
 
+static void etna_patch_data(void *buffer, const struct pipe_transfer *ptrans)
+{
+   struct pipe_resource *prsc = ptrans->resource;
+   struct etna_resource *rsc = etna_resource(prsc);
+   struct etna_resource_level *level = >levels[ptrans->level];
+
+   if (!etna_etc2_needs_patching(prsc))
+  return;
+
+   if (level->patched)
+  return;
+
+   /* do have the offsets of blocks to patch? */
+   if (!level->patch_offsets) {
+  level->patch_offsets = CALLOC_STRUCT(util_dynarray);
+
+  etna_etc2_calculate_blocks(buffer, ptrans->stride,
+ ptrans->box.width, ptrans->box.height,
+ prsc->format, level->patch_offsets);
+   }
+
+   etna_etc2_patch(buffer, level->patch_offsets);
+
+   level->patched = true;
+}
+
+static void etna_unpatch_data(void *buffer, const struct pipe_transfer *ptrans)
+{
+   struct pipe_resource *prsc = ptrans->resource;
+   struct etna_resource *rsc = etna_resource(prsc);
+   struct etna_resource_level *level = >levels[ptrans->level];
+
+   if (!level->patched)
+  return;
+
+   etna_etc2_patch(buffer, level->patch_offsets);
+
+   level->patched = false;
+}
+
 static void
 etna_transfer_unmap(struct pipe_context *pctx, struct pipe_transfer *ptrans)
 {
@@ -119,6 +160,10 @@ etna_transfer_unmap(struct pipe_context *pctx, struct 
pipe_transfer *ptrans)
   }
}
 
+   /* We need to have the patched data ready for the GPU. */
+   if (rsc->layout == ETNA_LAYOUT_LINEAR)
+  etna_patch_data(trans->mapped, ptrans);
+
/*
 * Transfers without a temporary are only pulled into the CPU domain if they
 * are not mapped unsynchronized. If they are, must push them back into GPU
@@ -321,6 +366,12 @@ etna_transfer_map(struct pipe_context *pctx, struct 
pipe_resource *prsc,
   if (usage & PIPE_TRANSFER_WRITE)
  prep_flags |= DRM_ETNA_PREP_WRITE;
 
+  /* avoid the GPU sampling from the resource that gets mutated */
+  if (rsc->layout == ETNA_LAYOUT_LINEAR &&
+  (usage & PIPE_TRANSFER_READ) &&
+  etna_etc2_needs_patching(prsc))
+ prep_flags |= DRM_ETNA_PREP_WRITE;
+
   if (etna_bo_cpu_prep(rsc->bo, prep_flags))
  goto fail_prep;
}
@@ -340,6 +391,10 @@ etna_transfer_map(struct pipe_context *pctx, struct 
pipe_resource *prsc,
  etna_compute_offset(prsc->format, box, res_level->stride,
  res_level->layer_stride);
 
+  /* We need to have the unpatched data ready for the gfx stack. */
+  if (usage & PIPE_TRANSFER_READ)
+ etna_unpatch_data(trans->mapped, ptrans);
+
   return trans->mapped;
} else {