From 25c771a77853141fcc220ae74b30492f8199709c Mon Sep 17 00:00:00 2001 From: Charmaine Lee Date: Wed, 7 Jun 2023 23:49:28 +0300 Subject: [PATCH] svga: sync resource content from backing resource before image upload When a backing resource is created for a render target view when the same resource is currently bound to a shader resource view, the content update back to the original resource happens when the associated render target view is unbound. But state update only happens at clear or draw time. So if TexSubImage happens after BindFrameBuffer and before Draw, the original texture resource that is mapped to for subimage update would not have been updated. As a matter of fact at the subsequent state update at the next draw, the render target views will be updated, the content from the previous backing resource will be propogated to the original resource, hence overwriting the changes from the last TexSubImage. To fix the problem, this patch validates the texture resource, updates any pending changes from the backing resource before transfer map upload occurs. Fixes the rendering issue demonstrated from the fbo_texsubimage_update trace Reviewed-by: Martin Krastev Part-of: --- src/gallium/drivers/svga/svga_pipe_draw.c | 16 ++---- .../drivers/svga/svga_resource_texture.c | 56 ++++++++++++++++++- src/gallium/drivers/svga/svga_surface.h | 6 +- 3 files changed, 66 insertions(+), 12 deletions(-) diff --git a/src/gallium/drivers/svga/svga_pipe_draw.c b/src/gallium/drivers/svga/svga_pipe_draw.c index bd88f5bb173..72087561b06 100644 --- a/src/gallium/drivers/svga/svga_pipe_draw.c +++ b/src/gallium/drivers/svga/svga_pipe_draw.c @@ -1,5 +1,5 @@ /********************************************************** - * Copyright 2008-2009 VMware, Inc. All rights reserved. + * Copyright 2008-2023 VMware, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -245,15 +245,6 @@ svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, svga->curr.rast->templ.cull_face == PIPE_FACE_FRONT_AND_BACK) goto done; - /* - * Mark currently bound target surfaces as dirty - * doesn't really matter if it is done before drawing. - * - * TODO If we ever normaly return something other then - * true we should not mark it as dirty then. - */ - svga_mark_surfaces_dirty(svga_context(pipe)); - if (svga->curr.reduced_prim != reduced_prim) { svga->curr.reduced_prim = reduced_prim; svga->dirty |= SVGA_NEW_REDUCED_PRIMITIVE; @@ -373,6 +364,11 @@ svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, } } + /* + * Mark currently bound target surfaces as dirty after draw is completed. + */ + svga_mark_surfaces_dirty(svga_context(pipe)); + /* XXX: Silence warnings, do something sensible here? */ (void)ret; diff --git a/src/gallium/drivers/svga/svga_resource_texture.c b/src/gallium/drivers/svga/svga_resource_texture.c index 8ce5b945520..17d91d16fcd 100644 --- a/src/gallium/drivers/svga/svga_resource_texture.c +++ b/src/gallium/drivers/svga/svga_resource_texture.c @@ -43,6 +43,7 @@ #include "svga_resource_texture.h" #include "svga_resource_buffer.h" #include "svga_sampler_view.h" +#include "svga_surface.h" #include "svga_winsys.h" #include "svga_debug.h" @@ -1346,6 +1347,51 @@ svga_texture_transfer_map_can_upload(const struct svga_screen *svgascreen, } +/** + * Return TRUE if the same texture is bound to the specified + * surface view and a backing resource is created for the surface view. + */ +static bool +need_update_texture_resource(struct pipe_surface *surf, + struct svga_texture *tex) +{ + struct svga_texture *stex = svga_texture(surf->texture); + struct svga_surface *s = svga_surface(surf); + + return (stex == tex && s->handle != tex->handle); +} + + +/** + * Make sure the texture resource is up-to-date. If the texture is + * currently bound to a render target view and a backing resource is + * created, we will need to update the original resource with the + * changes in the backing resource. + */ +static void +svga_validate_texture_resource(struct svga_context *svga, + struct svga_texture *tex) +{ + if (svga_was_texture_rendered_to(tex) == false) + return; + + if ((svga->state.hw_draw.has_backed_views == false) || + (tex->backed_handle == NULL)) + return; + + struct pipe_surface *s; + for (unsigned i = 0; i < svga->state.hw_clear.num_rendertargets; i++) { + s = svga->state.hw_clear.rtv[i]; + if (s && need_update_texture_resource(s, tex)) + svga_propagate_surface(svga, s, true); + } + + s = svga->state.hw_clear.dsv; + if (s && need_update_texture_resource(s, tex)) + svga_propagate_surface(svga, s, true); +} + + /** * Use upload buffer for the transfer map request. */ @@ -1355,6 +1401,7 @@ svga_texture_transfer_map_upload(struct svga_context *svga, { struct pipe_resource *texture = st->base.resource; struct pipe_resource *tex_buffer = NULL; + struct svga_texture *tex = svga_texture(texture); void *tex_map; unsigned nblocksx, nblocksy; unsigned offset; @@ -1362,6 +1409,14 @@ svga_texture_transfer_map_upload(struct svga_context *svga, assert(svga->tex_upload); + /* Validate the texture resource in case there is any changes + * in the backing resource that needs to be updated to the original + * texture resource first before the transfer upload occurs, otherwise, + * the later update from backing resource to original will overwrite the + * changes in this transfer map update. + */ + svga_validate_texture_resource(svga, tex); + st->upload.box.x = st->base.box.x; st->upload.box.y = st->base.box.y; st->upload.box.z = st->base.box.z; @@ -1407,7 +1462,6 @@ svga_texture_transfer_map_upload(struct svga_context *svga, #ifdef DEBUG if (util_format_is_compressed(texture->format)) { - struct svga_texture *tex = svga_texture(texture); unsigned blockw, blockh, bytesPerBlock; svga_format_size(tex->key.format, &blockw, &blockh, &bytesPerBlock); diff --git a/src/gallium/drivers/svga/svga_surface.h b/src/gallium/drivers/svga/svga_surface.h index b2745f44dfe..48ad4b406fd 100644 --- a/src/gallium/drivers/svga/svga_surface.h +++ b/src/gallium/drivers/svga/svga_surface.h @@ -1,5 +1,5 @@ /********************************************************** - * Copyright 2008-2009 VMware, Inc. All rights reserved. + * Copyright 2008-2023 VMware, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -142,6 +142,10 @@ svga_surface_const(const struct pipe_surface *surface) struct pipe_surface * svga_validate_surface_view(struct svga_context *svga, struct svga_surface *s); +void +svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf, + bool reset); + static inline SVGA3dResourceType svga_resource_type(enum pipe_texture_target target) {