Skip to content

Commit

Permalink
drm/vmwgfx: Fix cpu updates of coherent multisample surfaces
Browse files Browse the repository at this point in the history
[ Upstream commit 88509f6 ]

In cases where the dirty linear memory range spans multiple sample sheets
in a surface, the dirty surface region is incorrectly computed.
To do this correctly and in an optimized fashion  we would have to compute
the dirty region of each sample sheet and compute the union of those
regions.

But assuming that cpu writing to a multisample surface is rather a corner
case than a common case, just set the dirty region to the full surface.

This fixes OpenGL piglit errors with SVGA_FORCE_COHERENT=1
and the piglit test:

fbo-depthstencil blit default_fb -samples=2 -auto

Fixes: 9ca7d19 ("drm/vmwgfx: Add surface dirty-tracking callbacks")
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: Charmaine Lee <charmainel@vmware.com>
Reviewed-by: Roland Scheidegger <sroland@vmware.com>
Signed-off-by: Zack Rusin <zackr@vmware.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210505035740.286923-4-zackr@vmware.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
thomashvmw authored and gregkh committed Jul 14, 2021
1 parent a8e85ed commit 40b7017
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 2 deletions.
8 changes: 6 additions & 2 deletions drivers/gpu/drm/vmwgfx/device_include/svga3d_surfacedefs.h
Expand Up @@ -1467,13 +1467,15 @@ struct svga3dsurface_cache {

/**
* struct svga3dsurface_loc - Surface location
* @sheet: The multisample sheet.
* @sub_resource: Surface subresource. Defined as layer * num_mip_levels +
* mip_level.
* @x: X coordinate.
* @y: Y coordinate.
* @z: Z coordinate.
*/
struct svga3dsurface_loc {
u32 sheet;
u32 sub_resource;
u32 x, y, z;
};
Expand Down Expand Up @@ -1566,8 +1568,8 @@ svga3dsurface_get_loc(const struct svga3dsurface_cache *cache,
u32 layer;
int i;

if (offset >= cache->sheet_bytes)
offset %= cache->sheet_bytes;
loc->sheet = offset / cache->sheet_bytes;
offset -= loc->sheet * cache->sheet_bytes;

layer = offset / cache->mip_chain_bytes;
offset -= layer * cache->mip_chain_bytes;
Expand Down Expand Up @@ -1631,6 +1633,7 @@ svga3dsurface_min_loc(const struct svga3dsurface_cache *cache,
u32 sub_resource,
struct svga3dsurface_loc *loc)
{
loc->sheet = 0;
loc->sub_resource = sub_resource;
loc->x = loc->y = loc->z = 0;
}
Expand All @@ -1652,6 +1655,7 @@ svga3dsurface_max_loc(const struct svga3dsurface_cache *cache,
const struct drm_vmw_size *size;
u32 mip;

loc->sheet = 0;
loc->sub_resource = sub_resource + 1;
mip = sub_resource % cache->num_mip_levels;
size = &cache->mip[mip].size;
Expand Down
13 changes: 13 additions & 0 deletions drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
Expand Up @@ -1802,6 +1802,19 @@ static void vmw_surface_tex_dirty_range_add(struct vmw_resource *res,
svga3dsurface_get_loc(cache, &loc2, end - 1);
svga3dsurface_inc_loc(cache, &loc2);

if (loc1.sheet != loc2.sheet) {
u32 sub_res;

/*
* Multiple multisample sheets. To do this in an optimized
* fashion, compute the dirty region for each sheet and the
* resulting union. Since this is not a common case, just dirty
* the whole surface.
*/
for (sub_res = 0; sub_res < dirty->num_subres; ++sub_res)
vmw_subres_dirty_full(dirty, sub_res);
return;
}
if (loc1.sub_resource + 1 == loc2.sub_resource) {
/* Dirty range covers a single sub-resource */
vmw_subres_dirty_add(dirty, &loc1, &loc2);
Expand Down

0 comments on commit 40b7017

Please sign in to comment.