[virglrenderer-devel] [PATCH 3/5] vrend: store offsets into backing ivo for mipmaps and use it when reading data back (v3)

Gert Wollny gert.wollny at collabora.com
Tue Jun 19 08:42:47 UTC 2018


In the copy fallback, when a texture can not be rendered, the data that resides
in the backing iovec needs to be used. For the non-zero levels of mip-map textures
the data is located at an offset. This patch adds storing this offset and using it
when data is read from the backing iovec and updating the dst iov. We limit the
mip-map levels for which this is done to 1-17, which is enough to cover
32kx32k textures. The patch also fixes the stride when accessing mip-map levels.

Fixes:
  dEQP-GLES3.functional.texture.specification.teximage3d_depth.depth_component24_2d_array
  dEQP-GLES3.functional.texture.specification.texsubimage3d_depth.depth_component32f_2d_array
  dEQP-GLES3.functional.texture.specification.texsubimage3d_depth.depth_component24_2d_array
  dEQP-GLES3.functional.texture.specification.texsubimage3d_depth.depth_component16_2d_array
  dEQP-GLES3.functional.texture.specification.texsubimage3d_depth.depth32f_stencil8_2d_array
  dEQP-GLES3.functional.texture.specification.texsubimage3d_depth.depth24_stencil8_2d_array

v2: * rebase and remove unused variables
    * also correct offset when writing to the destination backing iovec

v3: * follow mesa/virgl notation and range for storing the mip-map offsets
      Suggested-by: Gurchetan Singh <gurchetansingh at chromium.org>

Signed-off-by: Jakob Bornecrantz <jakob at collabora.com> (v1)
Signed-off-by: Gert Wollny <gert.wollny at collabora.com>
---
 src/vrend_renderer.c | 30 +++++++++++++++++++++++++-----
 src/vrend_renderer.h |  6 ++++++
 2 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c
index 1f709ad..ec5427b 100644
--- a/src/vrend_renderer.c
+++ b/src/vrend_renderer.c
@@ -5405,6 +5405,19 @@ static int vrend_renderer_transfer_write_iov(struct vrend_context *ctx,
          x = info->box->x;
          y = invert ? (int)res->base.height0 - info->box->y - info->box->height : info->box->y;
 
+
+         /* mipmaps are usually passed in one iov, and we need to keep the offset
+          * into the data in case we want to read back the data of a surface
+          * that can not be rendered. Since we can not assume that the whole texture
+          * is filled, we evaluate the offset for origin (0,0,0). Since it is also
+          * possible that a resource is reused and resized update the offset every time.
+          */
+         if (info->level < VR_MAX_TEXTURE_2D_LEVELS) {
+            int64_t level_height = u_minify(res->base.height0, info->level);
+            res->mipmap_offsets[info->level] = info->offset -
+                                               ((info->box->z * level_height + y) * stride + x * elsize);
+         }
+
          if (res->base.format == (enum pipe_format)VIRGL_FORMAT_Z24X8_UNORM) {
             /* we get values from the guest as 24-bit scaled integers
                but we give them to the host GL and it interprets them
@@ -6088,8 +6101,6 @@ static void vrend_resource_copy_fallback(struct vrend_resource *src_res,
 
    box = *src_box;
    box.depth = vrend_get_texture_depth(src_res, src_level);
-
-   src_stride = util_format_get_stride(src_res->base.format, src_res->base.width0);
    dst_stride = util_format_get_stride(dst_res->base.format, dst_res->base.width0);
 
    /* this is ugly need to do a full GetTexImage */
@@ -6111,12 +6122,21 @@ static void vrend_resource_copy_fallback(struct vrend_resource *src_res,
     * iovec to have the data we need, otherwise we can use glGetTexture
     */
    if (vrend_state.use_gles) {
-      read_transfer_data(&src_res->base, src_res->iov, src_res->num_iovs,
-                         tptr, src_stride, &box, src_level, 0, false);
+      uint64_t src_offset = 0;
+      uint64_t dst_offset = 0;
+      if (src_level < VR_MAX_TEXTURE_2D_LEVELS) {
+         src_offset = src_res->mipmap_offsets[src_level];
+         dst_offset = dst_res->mipmap_offsets[src_level];
+      }
+
+      src_stride = util_format_get_nblocksx(src_res->base.format,
+                                            u_minify(src_res->base.width0, src_level)) * elsize;
+      read_transfer_data(&src_res->base, src_res->iov, src_res->num_iovs, tptr,
+                         src_stride, &box, src_level, src_offset, false);
       /* In on GLES Sync the iov that backs the dst resource because
        * we might need it in a chain copy A->B, B->C */
       write_transfer_data(&dst_res->base, dst_res->iov, dst_res->num_iovs, tptr,
-                          dst_stride, &box, src_level, 0, false);
+                          dst_stride, &box, src_level, dst_offset, false);
       /* we get values from the guest as 24-bit scaled integers
          but we give them to the host GL and it interprets them
          as 32-bit scaled integers, so we need to scale them here */
diff --git a/src/vrend_renderer.h b/src/vrend_renderer.h
index 5a48990..e702d8e 100644
--- a/src/vrend_renderer.h
+++ b/src/vrend_renderer.h
@@ -44,6 +44,11 @@ struct virgl_gl_ctx_param {
 extern int vrend_dump_shaders;
 struct vrend_context;
 
+/* Number of mipmap levels for which to keep the backing iov offsets.
+ * Value mirrored from mesa/virgl
+ */
+#define VR_MAX_TEXTURE_2D_LEVELS 15
+
 struct vrend_resource {
    struct pipe_resource base;
    GLuint id;
@@ -62,6 +67,7 @@ struct vrend_resource {
    char *ptr;
    struct iovec *iov;
    uint32_t num_iovs;
+   uint64_t mipmap_offsets[VR_MAX_TEXTURE_2D_LEVELS];
 };
 
 /* assume every format is sampler friendly */
-- 
2.17.1



More information about the virglrenderer-devel mailing list