svga: use upload buffer if texture has pending changes

When establishing a texture transfer map, if there is any pending changes on the
texture, instead of trying direct map with DONTBLOCK first, just
use the upload buffer path.

Fixes piglit tests gen-teximages, arb_copy_images-formats

Cc: mesa-stable

Reviewed-by: Neha Bhende <bhenden@vmware.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21393>
(cherry picked from commit 1b9b060f0e)
This commit is contained in:
Charmaine Lee 2023-02-14 03:47:39 +02:00 committed by Dylan Baker
parent da8139e5e4
commit 9fdfa9d9bb
3 changed files with 23 additions and 9 deletions

View file

@ -256,7 +256,7 @@
"description": "svga: use upload buffer if texture has pending changes",
"nominated": true,
"nomination_type": 0,
"resolution": 0,
"resolution": 1,
"main_sha": null,
"because_sha": null
},

View file

@ -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
@ -357,7 +357,7 @@ svga_texture_transfer_map_direct(struct svga_context *svga,
else {
assert(usage & PIPE_MAP_WRITE);
if ((usage & PIPE_MAP_UNSYNCHRONIZED) == 0) {
if (svga_is_texture_dirty(tex, st->slice, level)) {
if (svga_is_texture_level_dirty(tex, st->slice, level)) {
/*
* do a surface flush if the subresource has been modified
* in this command buffer.
@ -567,14 +567,15 @@ svga_texture_transfer_map(struct pipe_context *pipe,
!(st->base.usage & PIPE_MAP_READ);
boolean was_rendered_to =
svga_was_texture_rendered_to(svga_texture(texture));
boolean is_dirty = svga_is_texture_dirty(svga_texture(texture));
/* If the texture was already rendered to and upload buffer
* is supported, then we will use upload buffer to
/* If the texture was already rendered to or has pending changes and
* upload buffer is supported, then we will use upload buffer to
* avoid the need to read back the texture content; otherwise,
* we'll first try to map directly to the GB surface, if it is blocked,
* then we'll try the upload buffer.
*/
if (was_rendered_to && can_use_upload) {
if ((was_rendered_to || is_dirty) && can_use_upload) {
map = svga_texture_transfer_map_upload(svga, st);
}
else {

View file

@ -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
@ -85,6 +85,11 @@ struct svga_texture
*/
boolean can_use_upload;
/**
* Whether texture is modified. Set if any of the dirty bits is set.
*/
boolean modified;
unsigned size; /**< Approximate size in bytes */
/** array indexed by cube face or 3D/array slice, one bit per mipmap level */
@ -242,6 +247,7 @@ svga_set_texture_dirty(struct svga_texture *tex,
{
check_face_level(tex, face, level);
tex->dirty[face] |= 1 << level;
tex->modified = TRUE;
}
static inline void
@ -251,16 +257,23 @@ svga_clear_texture_dirty(struct svga_texture *tex)
for (i = 0; i < tex->b.depth0 * tex->b.array_size; i++) {
tex->dirty[i] = 0;
}
tex->modified = FALSE;
}
static inline boolean
svga_is_texture_dirty(const struct svga_texture *tex,
unsigned face, unsigned level)
svga_is_texture_level_dirty(const struct svga_texture *tex,
unsigned face, unsigned level)
{
check_face_level(tex, face, level);
return !!(tex->dirty[face] & (1 << level));
}
static inline boolean
svga_is_texture_dirty(const struct svga_texture *tex)
{
return tex->modified;
}
struct pipe_resource *
svga_texture_create(struct pipe_screen *screen,
const struct pipe_resource *template);