[virglrenderer-devel] [PATCH v2 1/2] vrend: If available use glCopyImageSubData to execute memcopy like blits

Gert Wollny gert.wollny at collabora.com
Tue Jul 3 11:21:47 UTC 2018


When the host is  gles >= 3.2, gl >= 4.3, or when the extension
GL_(ARB|EXT|OES)_copy_image is available, memcopy like blitting and region
copying can be done for many color format combinations by using
glCopyImageSubData.

This fixes a number of tests from the subset
  dEQP-GLES31.functional.copy_image.non_compressed.viewclass_*

v2: - Clean list of canonical formats (Gurchetan Singh)
    - Use size of canonical formats to decide whether they can be copied via
      gCopyImageSubData
    - Also honour the render state when deciding whether glCopyImageSubData
      will do, or whether we need to do a blit.

Signed-off-by: Gert Wollny <gert.wollny at collabora.com>
---
 src/vrend_formats.c  | 40 +++++++++++++++++++++++++++++++
 src/vrend_renderer.c | 57 ++++++++++++++++++++++++++++++++++++++++++--
 src/vrend_renderer.h |  2 ++
 3 files changed, 97 insertions(+), 2 deletions(-)

diff --git a/src/vrend_formats.c b/src/vrend_formats.c
index eb9f217..07f9985 100644
--- a/src/vrend_formats.c
+++ b/src/vrend_formats.c
@@ -443,3 +443,43 @@ void vrend_build_format_list_gles(void)
    */
   add_formats(gles_z32_format);
 }
+
+static uint vrend_is_canonical_format(enum pipe_format format)
+{
+   /* These are the canonical formats that are set by gallium */
+
+   switch (format) {
+   /* 128 bit */
+   case PIPE_FORMAT_R32G32B32A32_UINT:
+      return 128;
+
+    /* 64 bit */
+   case PIPE_FORMAT_R32G32_UINT:
+   case PIPE_FORMAT_R16G16B16A16_UINT:
+      return 64;
+
+   /* 32 bit */
+   case PIPE_FORMAT_R8G8B8A8_UNORM:
+   case PIPE_FORMAT_R16G16_UNORM:
+   case PIPE_FORMAT_R32_UINT:
+      return 32;
+
+   /* 16 bit */
+   case PIPE_FORMAT_R8G8_UNORM:
+   case PIPE_FORMAT_R16_UINT:
+      return 16;
+
+   case PIPE_FORMAT_R8_UINT:
+      return 8;
+   default:
+      return 0;
+   }
+}
+
+bool vrend_canonical_formats_of_same_size(enum pipe_format lhs, enum pipe_format rhs)
+{
+   uint lhss = vrend_is_canonical_format(lhs);
+   uint rhss = vrend_is_canonical_format(rhs);
+
+   return (lhss > 0 ) && (lhss == rhss);
+}
\ No newline at end of file
diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c
index 23494a8..1bf33f1 100644
--- a/src/vrend_renderer.c
+++ b/src/vrend_renderer.c
@@ -119,6 +119,7 @@ struct global_renderer_state {
    bool have_texture_storage;
    bool have_tessellation;
    bool have_texture_view;
+   bool have_copy_image;
 
    /* these appeared broken on at least one driver */
    bool use_explicit_locations;
@@ -4527,6 +4528,12 @@ int vrend_renderer_init(struct vrend_if_cbs *cbs, uint32_t flags)
    if (gl_ver >= 46 || epoxy_has_gl_extension("GL_ARB_polygon_offset_clamp"))
       vrend_state.have_polygon_offset_clamp = true;
 
+   if (gl_ver >= 43 || (gles && gl_ver >= 32) ||
+       epoxy_has_gl_extension("GL_ARB_copy_image") ||
+       epoxy_has_gl_extension("GL_EXT_copy_image") ||
+       epoxy_has_gl_extension("GL_OES_copy_image"))
+       vrend_state.have_copy_image = true;
+
    /* callbacks for when we are cleaning up the object table */
    vrend_resource_set_destroy_callback(vrend_destroy_resource_object);
    vrend_object_set_destroy_callback(VIRGL_OBJECT_QUERY, vrend_destroy_query_object);
@@ -5746,9 +5753,11 @@ static int vrend_transfer_send_readpixels(struct vrend_context *ctx,
 
    switch (elsize) {
    case 1:
+   case 3:
       glPixelStorei(GL_PACK_ALIGNMENT, 1);
       break;
    case 2:
+   case 6:
       glPixelStorei(GL_PACK_ALIGNMENT, 2);
       break;
    case 4:
@@ -6330,6 +6339,22 @@ static void vrend_resource_copy_fallback(struct vrend_resource *src_res,
    free(tptr);
 }
 
+
+static inline void
+vrend_copy_sub_image(struct vrend_resource* src_res, struct vrend_resource * dst_res,
+                     uint32_t src_level, const struct pipe_box *src_box,
+                     uint32_t dst_level, uint32_t dstx, uint32_t dsty, uint32_t dstz)
+{
+   glCopyImageSubData(src_res->id,
+                      tgsitargettogltarget(src_res->base.target, src_res->base.nr_samples),
+                      src_level, src_box->x, src_box->y, src_box->z,
+                      dst_res->id,
+                      tgsitargettogltarget(dst_res->base.target, dst_res->base.nr_samples),
+                      dst_level, dstx, dsty, dstz,
+                      src_box->width, src_box->height,src_box->depth);
+}
+
+
 void vrend_renderer_resource_copy_region(struct vrend_context *ctx,
                                          uint32_t dst_handle, uint32_t dst_level,
                                          uint32_t dstx, uint32_t dsty, uint32_t dstz,
@@ -6362,11 +6387,21 @@ void vrend_renderer_resource_copy_region(struct vrend_context *ctx,
       return;
    }
 
+   if (vrend_state.have_copy_image) {
+      const struct util_format_description *src_desc = util_format_description(src_res->base.format);
+      const struct util_format_description *dst_desc = util_format_description(dst_res->base.format);
+      if (util_is_format_compatible(src_desc,dst_desc) &&
+          src_res->base.nr_samples == dst_res->base.nr_samples) {
+         vrend_copy_sub_image(src_res, dst_res, src_level, src_box,
+                              dst_level, dstx, dsty, dstz);
+         return;
+      }
+   }
+
    if (!vrend_format_can_render(src_res->base.format) ||
        !vrend_format_can_render(dst_res->base.format)) {
       vrend_resource_copy_fallback(src_res, dst_res, dst_level, dstx,
                                    dsty, dstz, src_level, src_box);
-
       return;
    }
 
@@ -6638,7 +6673,25 @@ void vrend_renderer_blit(struct vrend_context *ctx,
    if (info->render_condition_enable == false)
       vrend_pause_render_condition(ctx, true);
 
-   vrend_renderer_blit_int(ctx, src_res, dst_res, info);
+   /* The gallium blit function can be called for a general blit that may
+    * scale, convert the data, and apply some rander states or if is called via
+    * glCopyImageSubData. For the latter case forward the call to the
+    * glCopyImageSubData function, otherwise use a framebuffer blit.
+    */
+   if (vrend_state.have_copy_image && !info->render_condition_enable &&
+       vrend_canonical_formats_of_same_size(info->src.format, info->dst.format) &&
+       !info->scissor_enable && (info->filter == PIPE_TEX_FILTER_NEAREST) &&
+       !info->alpha_blend && (info->mask == PIPE_MASK_RGBA) &&
+       (src_res->base.nr_samples == dst_res->base.nr_samples) &&
+       info->src.box.width == info->dst.box.width &&
+       info->src.box.height == info->dst.box.height &&
+       info->src.box.depth == info->dst.box.depth) {
+      vrend_copy_sub_image(src_res, dst_res, info->src.level, &info->src.box,
+                           info->dst.level, info->dst.box.x, info->dst.box.y,
+                           info->dst.box.z);
+   } else {
+      vrend_renderer_blit_int(ctx, src_res, dst_res, info);
+   }
 
    if (info->render_condition_enable == false)
       vrend_pause_render_condition(ctx, false);
diff --git a/src/vrend_renderer.h b/src/vrend_renderer.h
index d07d11c..f81f60a 100644
--- a/src/vrend_renderer.h
+++ b/src/vrend_renderer.h
@@ -325,6 +325,8 @@ GLint64 vrend_renderer_get_timestamp(void);
 void vrend_build_format_list_common(void);
 void vrend_build_format_list_gl(void);
 void vrend_build_format_list_gles(void);
+bool vrend_canonical_formats_of_same_size(enum pipe_format lhs, enum pipe_format rhs);
+
 
 int vrend_renderer_resource_attach_iov(int res_handle, struct iovec *iov,
                                        int num_iovs);
-- 
2.17.1



More information about the virglrenderer-devel mailing list