citra-emu
/
citra-canary
Archived
1
0
Fork 0

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
This commit is contained in:
GPUCode 2023-08-02 21:38:45 +03:00 committed by GitHub
parent 88ea66053e
commit 6f7612f73d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 26 additions and 17 deletions

View File

@ -1051,15 +1051,15 @@ bool RasterizerCache<T>::UploadCustomSurface(SurfaceId surface_id, SurfaceInterv
surface.flags |= SurfaceFlagBits::Custom; surface.flags |= SurfaceFlagBits::Custom;
const auto upload = [this, level, surface_id, material]() -> bool { const auto upload = [this, level, surface_id, material]() -> bool {
Surface& surface = slot_surfaces[surface_id]; ASSERT_MSG(True(slot_surfaces[surface_id].flags & SurfaceFlagBits::Custom),
ASSERT_MSG(True(surface.flags & SurfaceFlagBits::Custom),
"Surface is not suitable for custom upload, aborting!"); "Surface is not suitable for custom upload, aborting!");
if (!surface.IsCustom()) { if (!slot_surfaces[surface_id].IsCustom()) {
const SurfaceBase old_surface{surface}; const SurfaceBase old_surface{slot_surfaces[surface_id]};
const SurfaceId old_id = const SurfaceId old_id =
slot_surfaces.swap_and_insert(surface_id, runtime, old_surface, material); slot_surfaces.swap_and_insert(surface_id, runtime, old_surface, material);
sentenced.emplace_back(old_id, frame_tick); sentenced.emplace_back(old_id, frame_tick);
} }
Surface& surface = slot_surfaces[surface_id];
surface.UploadCustom(material, level); surface.UploadCustom(material, level);
if (custom_tex_manager.SkipMipmaps()) { if (custom_tex_manager.SkipMipmaps()) {
runtime.GenerateMipmaps(surface); runtime.GenerateMipmaps(surface);
@ -1316,14 +1316,17 @@ SurfaceId RasterizerCache<T>::CreateSurface(const SurfaceParams& params) {
const auto it = std::find_if(sentenced.begin(), sentenced.end(), [&](const auto& pair) { const auto it = std::find_if(sentenced.begin(), sentenced.end(), [&](const auto& pair) {
return slot_surfaces[pair.first] == params; return slot_surfaces[pair.first] == params;
}); });
if (it != sentenced.end()) { if (it == sentenced.end()) {
const SurfaceId surface_id = it->first; return slot_surfaces.insert(runtime, params);
sentenced.erase(it);
return surface_id;
} }
return slot_surfaces.insert(runtime, params); const SurfaceId surface_id = it->first;
sentenced.erase(it);
return surface_id;
}(); }();
Surface& surface = slot_surfaces[surface_id]; Surface& surface = slot_surfaces[surface_id];
if (params.res_scale > surface.res_scale) {
surface.ScaleUp(params.res_scale);
}
surface.MarkInvalid(surface.GetInterval()); surface.MarkInvalid(surface.GetInterval());
return surface_id; return surface_id;
} }
@ -1368,8 +1371,8 @@ void RasterizerCache<T>::UnregisterSurface(SurfaceId surface_id) {
return; return;
} }
std::erase_if(texture_cube_cache, [&](auto& pair) { for (auto it = texture_cube_cache.begin(); it != texture_cube_cache.end();) {
TextureCube& cube = pair.second; TextureCube& cube = it->second;
for (SurfaceId& face_id : cube.face_ids) { for (SurfaceId& face_id : cube.face_ids) {
if (face_id == surface_id) { if (face_id == surface_id) {
face_id = SurfaceId{}; face_id = SurfaceId{};
@ -1378,10 +1381,11 @@ void RasterizerCache<T>::UnregisterSurface(SurfaceId surface_id) {
if (std::none_of(cube.face_ids.begin(), cube.face_ids.end(), if (std::none_of(cube.face_ids.begin(), cube.face_ids.end(),
[](SurfaceId id) { return id; })) { [](SurfaceId id) { return id; })) {
sentenced.emplace_back(cube.surface_id, frame_tick); sentenced.emplace_back(cube.surface_id, frame_tick);
return true; it = texture_cube_cache.erase(it);
} else {
it++;
} }
return false; }
});
} }
template <class T> template <class T>

View File

@ -227,4 +227,11 @@ std::string SurfaceParams::DebugName(bool scaled, bool custom) const noexcept {
custom ? "custom," : "", scaled ? "scaled" : "unscaled"); 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 } // namespace VideoCore

View File

@ -53,9 +53,7 @@ public:
/// Returns a string identifier of the params object /// Returns a string identifier of the params object
std::string DebugName(bool scaled, bool custom = false) const noexcept; std::string DebugName(bool scaled, bool custom = false) const noexcept;
bool operator==(const SurfaceParams& other) const noexcept { bool operator==(const SurfaceParams& other) const noexcept;
return std::memcmp(this, &other, sizeof(SurfaceParams)) == 0;
}
[[nodiscard]] SurfaceInterval GetInterval() const noexcept { [[nodiscard]] SurfaceInterval GetInterval() const noexcept {
return SurfaceInterval{addr, end}; return SurfaceInterval{addr, end};