From 6f7612f73dd93212534c5957a32ef534ee1979ab Mon Sep 17 00:00:00 2001 From: GPUCode <47210458+GPUCode@users.noreply.github.com> Date: Wed, 2 Aug 2023 21:38:45 +0300 Subject: [PATCH] Res cache fixes (#6838) * rasterizer_cache: Dont consider res_scale during recycle * rasterizer_cache: Switch to plain erase loop * rasterizer_cache: Fix crash due to memory corruption --- .../rasterizer_cache/rasterizer_cache.h | 32 +++++++++++-------- .../rasterizer_cache/surface_params.cpp | 7 ++++ .../rasterizer_cache/surface_params.h | 4 +-- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/video_core/rasterizer_cache/rasterizer_cache.h b/src/video_core/rasterizer_cache/rasterizer_cache.h index 81e44504e..e4c4fb86e 100644 --- a/src/video_core/rasterizer_cache/rasterizer_cache.h +++ b/src/video_core/rasterizer_cache/rasterizer_cache.h @@ -1051,15 +1051,15 @@ bool RasterizerCache::UploadCustomSurface(SurfaceId surface_id, SurfaceInterv surface.flags |= SurfaceFlagBits::Custom; const auto upload = [this, level, surface_id, material]() -> bool { - Surface& surface = slot_surfaces[surface_id]; - ASSERT_MSG(True(surface.flags & SurfaceFlagBits::Custom), + ASSERT_MSG(True(slot_surfaces[surface_id].flags & SurfaceFlagBits::Custom), "Surface is not suitable for custom upload, aborting!"); - if (!surface.IsCustom()) { - const SurfaceBase old_surface{surface}; + if (!slot_surfaces[surface_id].IsCustom()) { + const SurfaceBase old_surface{slot_surfaces[surface_id]}; const SurfaceId old_id = slot_surfaces.swap_and_insert(surface_id, runtime, old_surface, material); sentenced.emplace_back(old_id, frame_tick); } + Surface& surface = slot_surfaces[surface_id]; surface.UploadCustom(material, level); if (custom_tex_manager.SkipMipmaps()) { runtime.GenerateMipmaps(surface); @@ -1316,14 +1316,17 @@ SurfaceId RasterizerCache::CreateSurface(const SurfaceParams& params) { const auto it = std::find_if(sentenced.begin(), sentenced.end(), [&](const auto& pair) { return slot_surfaces[pair.first] == params; }); - if (it != sentenced.end()) { - const SurfaceId surface_id = it->first; - sentenced.erase(it); - return surface_id; + if (it == sentenced.end()) { + return slot_surfaces.insert(runtime, params); } - return slot_surfaces.insert(runtime, params); + const SurfaceId surface_id = it->first; + sentenced.erase(it); + return surface_id; }(); Surface& surface = slot_surfaces[surface_id]; + if (params.res_scale > surface.res_scale) { + surface.ScaleUp(params.res_scale); + } surface.MarkInvalid(surface.GetInterval()); return surface_id; } @@ -1368,8 +1371,8 @@ void RasterizerCache::UnregisterSurface(SurfaceId surface_id) { return; } - std::erase_if(texture_cube_cache, [&](auto& pair) { - TextureCube& cube = pair.second; + for (auto it = texture_cube_cache.begin(); it != texture_cube_cache.end();) { + TextureCube& cube = it->second; for (SurfaceId& face_id : cube.face_ids) { if (face_id == surface_id) { face_id = SurfaceId{}; @@ -1378,10 +1381,11 @@ void RasterizerCache::UnregisterSurface(SurfaceId surface_id) { if (std::none_of(cube.face_ids.begin(), cube.face_ids.end(), [](SurfaceId id) { return id; })) { sentenced.emplace_back(cube.surface_id, frame_tick); - return true; + it = texture_cube_cache.erase(it); + } else { + it++; } - return false; - }); + } } template diff --git a/src/video_core/rasterizer_cache/surface_params.cpp b/src/video_core/rasterizer_cache/surface_params.cpp index 2f1496193..74ae8205c 100644 --- a/src/video_core/rasterizer_cache/surface_params.cpp +++ b/src/video_core/rasterizer_cache/surface_params.cpp @@ -227,4 +227,11 @@ std::string SurfaceParams::DebugName(bool scaled, bool custom) const noexcept { custom ? "custom," : "", scaled ? "scaled" : "unscaled"); } +bool SurfaceParams::operator==(const SurfaceParams& other) const noexcept { + return std::tie(addr, end, width, height, stride, levels, is_tiled, texture_type, pixel_format, + custom_format) == + std::tie(other.addr, other.end, other.width, other.height, other.stride, other.levels, + other.is_tiled, other.texture_type, other.pixel_format, other.custom_format); +} + } // namespace VideoCore diff --git a/src/video_core/rasterizer_cache/surface_params.h b/src/video_core/rasterizer_cache/surface_params.h index 89aff6043..23e4db7e2 100644 --- a/src/video_core/rasterizer_cache/surface_params.h +++ b/src/video_core/rasterizer_cache/surface_params.h @@ -53,9 +53,7 @@ public: /// Returns a string identifier of the params object std::string DebugName(bool scaled, bool custom = false) const noexcept; - bool operator==(const SurfaceParams& other) const noexcept { - return std::memcmp(this, &other, sizeof(SurfaceParams)) == 0; - } + bool operator==(const SurfaceParams& other) const noexcept; [[nodiscard]] SurfaceInterval GetInterval() const noexcept { return SurfaceInterval{addr, end};