[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