Skip to content

Commit

Permalink
rasterizer_cache: Improve validation skip heuristic (PabloMK7#69)
Browse files Browse the repository at this point in the history
  • Loading branch information
raphaelthegreat authored Apr 10, 2024
1 parent f5cf180 commit 9dfe3eb
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 24 deletions.
31 changes: 10 additions & 21 deletions src/video_core/rasterizer_cache/rasterizer_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -1180,27 +1180,16 @@ bool RasterizerCache<T>::ValidateByReinterpretation(Surface& surface, SurfacePar
}

// No surfaces were found in the cache that had a matching bit-width.
// If there's a surface with invalid format it means the region was cleared
// so we don't want to skip validation in that case.
const bool has_invalid = IntervalHasInvalidPixelFormat(params, interval);
const bool is_gpu_modified = boost::icl::contains(dirty_regions, interval);
return !has_invalid && is_gpu_modified;
}

template <class T>
bool RasterizerCache<T>::IntervalHasInvalidPixelFormat(const SurfaceParams& params,
SurfaceInterval interval) {
bool invalid_format_found = false;
const PAddr addr = boost::icl::lower(interval);
const u32 size = boost::icl::length(interval);
ForEachSurfaceInRegion(addr, size, [&](SurfaceId surface_id, Surface& surface) {
if (surface.pixel_format == PixelFormat::Invalid) {
invalid_format_found = true;
return true;
}
return false;
});
return invalid_format_found;
// Before entering the slow path, check if part of the interval is owned
// by a gpu modified surface with a different stride than ours. This is indicative
// of texture aliasing by the guest, which for the vast majority of cases we don't
// need to validate.
// TODO: While this works for the vast majority of cases, in Fire Emblem: Shadows of Valentia
// the warping effect when running in dugeons relies on this stride reinterpretation.
// In the future this transformation should be properly implemented with a GPU shader.
const auto it = dirty_regions.find(interval);
return it != dirty_regions.end() && it->second &&
slot_surfaces[it->second].stride != surface.stride;
}

template <class T>
Expand Down
3 changes: 0 additions & 3 deletions src/video_core/rasterizer_cache/rasterizer_cache_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,6 @@ class RasterizerCache {
bool ValidateByReinterpretation(Surface& surface, SurfaceParams params,
const SurfaceInterval& interval);

/// Return true if a surface with an invalid pixel format exists at the interval
bool IntervalHasInvalidPixelFormat(const SurfaceParams& params, SurfaceInterval interval);

/// Create a new surface
SurfaceId CreateSurface(const SurfaceParams& params);

Expand Down

0 comments on commit 9dfe3eb

Please sign in to comment.