[virglrenderer-devel] [PATCH 1/2] vrend: store offsets into backing ivo for mipmaps and use it when reading data back

Gert Wollny gert.wollny at collabora.com
Thu Jun 7 19:58:15 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. 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

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

diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c
index d3553c5..5534ce4 100644
--- a/src/vrend_renderer.c
+++ b/src/vrend_renderer.c
@@ -5205,6 +5205,20 @@ static int vrend_renderer_transfer_write_iov(struct vrend_context *ctx,
          x = info->box->x;
          y = invert ? 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.
+          * We assume that level 0 has offset 0.
+          */
+         if (info->level> 0 && info->level <= MAX_READBACK_MIPMAP_LEVELS) {
+            int64_t level_height = u_minify(res->base.height0, info->level);
+            res->mipmap_offsets[info->level-1] = 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
@@ -5868,7 +5882,7 @@ static void vrend_resource_copy_fallback(struct vrend_context *ctx,
    int compressed = util_format_is_compressed(dst_res->base.format);
    int cube_slice = 1;
    uint32_t slice_size, slice_offset;
-   int i;
+   int i, stride;
    struct pipe_box box;
 
    if (src_res->target == GL_TEXTURE_CUBE_MAP)
@@ -5900,13 +5914,19 @@ static void vrend_resource_copy_fallback(struct vrend_context *ctx,
    if (compressed)
       glformat = tex_conv_table[src_res->base.format].internalformat;
 
-   if (!vrend_format_can_render(src_res->base.format)) {
+   if (vrend_state.use_gles && !vrend_format_can_render(src_res->base.format)) {
       /*
        * If the src resource isn't renderable, we can rely on its backing
        * iovec having the data we need.
        */
-      read_transfer_data(&src_res->base, src_res->iov, src_res->num_iovs,
-                         tptr, src_stride, &box, src_level, 0, false);
+      uint64_t offset = 0;
+      if (src_level > 0 && src_level <= MAX_READBACK_MIPMAP_LEVELS)
+         offset = src_res->mipmap_offsets[src_level-1];
+
+      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, stride,
+                         &box, src_level, offset, false);
 
       if (dst_res->base.format == (enum pipe_format)VIRGL_FORMAT_Z24X8_UNORM) {
          /* we get values from the guest as 24-bit scaled integers
@@ -5915,7 +5935,6 @@ static void vrend_resource_copy_fallback(struct vrend_context *ctx,
          float depth_scale = 256.0;
          vrend_scale_depth(tptr, transfer_size, depth_scale);
       }
-
    } else {
       switch (elsize) {
       case 1:
@@ -5978,6 +5997,7 @@ static void vrend_resource_copy_fallback(struct vrend_context *ctx,
    cube_slice = (src_res->target == GL_TEXTURE_CUBE_MAP) ? src_box->z + src_box->depth : cube_slice;
    i = (src_res->target == GL_TEXTURE_CUBE_MAP) ? src_box->z : 0;
    for (; i < cube_slice; i++) {
+
       GLenum ctarget = dst_res->target == GL_TEXTURE_CUBE_MAP ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + i : dst_res->target;
       if (compressed) {
          if (ctarget == GL_TEXTURE_1D) {
diff --git a/src/vrend_renderer.h b/src/vrend_renderer.h
index 5554edb..dc1a618 100644
--- a/src/vrend_renderer.h
+++ b/src/vrend_renderer.h
@@ -43,6 +43,9 @@ 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 */
+#define MAX_READBACK_MIPMAP_LEVELS 16
+
 struct vrend_resource {
    struct pipe_resource base;
    GLuint id;
@@ -61,6 +64,7 @@ struct vrend_resource {
    char *ptr;
    struct iovec *iov;
    uint32_t num_iovs;
+   uint64_t mipmap_offsets[MAX_READBACK_MIPMAP_LEVELS];
 };
 
 /* assume every format is sampler friendly */
-- 
2.17.1



More information about the virglrenderer-devel mailing list