citra-emu
/
citra
Archived
1
0
Fork 0

rasterizer_cache: Allow custom recycle (#6851)

* surface_params: Allow custom surface recycling

* rasterizer_cache: Cleanup
This commit is contained in:
GPUCode 2023-08-06 22:59:54 +03:00 committed by GitHub
parent 20f4677f80
commit 5b52849f90
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 34 additions and 68 deletions

View File

@ -127,6 +127,29 @@ void RasterizerCache<T>::RemoveFramebuffers(SurfaceId surface_id) {
} }
} }
template <class T>
void RasterizerCache<T>::RemoveTextureCubeFace(SurfaceId surface_id) {
if (False(slot_surfaces[surface_id].flags & SurfaceFlagBits::Tracked)) {
return;
}
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{};
}
}
if (std::none_of(cube.face_ids.begin(), cube.face_ids.end(),
[](SurfaceId id) { return id; })) {
sentenced.emplace_back(cube.surface_id, frame_tick);
it = texture_cube_cache.erase(it);
} else {
it++;
}
}
}
template <class T> template <class T>
bool RasterizerCache<T>::AccelerateTextureCopy(const GPU::Regs::DisplayTransferConfig& config) { bool RasterizerCache<T>::AccelerateTextureCopy(const GPU::Regs::DisplayTransferConfig& config) {
const DebugScope scope{runtime, Common::Vec4f{0.f, 0.f, 1.f, 1.f}, const DebugScope scope{runtime, Common::Vec4f{0.f, 0.f, 1.f, 1.f},
@ -866,39 +889,6 @@ SurfaceId RasterizerCache<T>::FindMatch(const SurfaceParams& params, ScaleMatch
return match_id; return match_id;
} }
template <class T>
void RasterizerCache<T>::DuplicateSurface(SurfaceId src_id, SurfaceId dst_id) {
Surface& src_surface = slot_surfaces[src_id];
Surface& dst_surface = slot_surfaces[dst_id];
ASSERT(dst_surface.addr <= src_surface.addr && dst_surface.end >= src_surface.end);
const auto src_rect = src_surface.GetScaledRect();
const auto dst_rect = dst_surface.GetScaledSubRect(src_surface);
ASSERT(src_rect.GetWidth() == dst_rect.GetWidth());
const TextureCopy copy = {
.src_level = 0,
.dst_level = 0,
.src_offset = {src_rect.left, src_rect.bottom},
.dst_offset = {dst_rect.left, dst_rect.bottom},
.extent = {src_rect.GetWidth(), src_rect.GetHeight()},
};
runtime.CopyTextures(src_surface, dst_surface, copy);
dst_surface.invalid_regions -= src_surface.GetInterval();
dst_surface.invalid_regions += src_surface.invalid_regions;
SurfaceRegions regions;
for (const auto& pair : RangeFromInterval(dirty_regions, src_surface.GetInterval())) {
if (pair.second == src_id) {
regions += pair.first;
}
}
for (const auto& interval : regions) {
dirty_regions.set({interval, dst_id});
}
}
template <class T> template <class T>
void RasterizerCache<T>::ValidateSurface(SurfaceId surface_id, PAddr addr, u32 size) { void RasterizerCache<T>::ValidateSurface(SurfaceId surface_id, PAddr addr, u32 size) {
if (size == 0) [[unlikely]] { if (size == 0) [[unlikely]] {
@ -1057,6 +1047,7 @@ bool RasterizerCache<T>::UploadCustomSurface(SurfaceId surface_id, SurfaceInterv
const SurfaceBase old_surface{slot_surfaces[surface_id]}; 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);
slot_surfaces[old_id].flags &= ~SurfaceFlagBits::Registered;
sentenced.emplace_back(old_id, frame_tick); sentenced.emplace_back(old_id, frame_tick);
} }
Surface& surface = slot_surfaces[surface_id]; Surface& surface = slot_surfaces[surface_id];
@ -1203,7 +1194,6 @@ void RasterizerCache<T>::ClearAll(bool flush) {
cached_pages -= flush_interval; cached_pages -= flush_interval;
dirty_regions.clear(); dirty_regions.clear();
page_table.clear(); page_table.clear();
remove_surfaces.clear();
} }
template <class T> template <class T>
@ -1232,7 +1222,7 @@ void RasterizerCache<T>::FlushRegion(PAddr addr, u32 size, SurfaceId flush_surfa
interval.lower(), interval.upper()}; interval.lower(), interval.upper()};
SCOPE_EXIT({ flushed_intervals += interval; }); SCOPE_EXIT({ flushed_intervals += interval; });
if (surface.IsFill()) { if (surface.type == SurfaceType::Fill) {
DownloadFillSurface(surface, interval); DownloadFillSurface(surface, interval);
continue; continue;
} }
@ -1274,6 +1264,7 @@ void RasterizerCache<T>::InvalidateRegion(PAddr addr, u32 size, SurfaceId region
region_owner.MarkValid(invalid_interval); region_owner.MarkValid(invalid_interval);
} }
boost::container::small_vector<SurfaceId, 4> remove_surfaces;
ForEachSurfaceInRegion(addr, size, [&](SurfaceId surface_id, Surface& surface) { ForEachSurfaceInRegion(addr, size, [&](SurfaceId surface_id, Surface& surface) {
if (surface_id == region_owner_id) { if (surface_id == region_owner_id) {
return; return;
@ -1301,13 +1292,12 @@ void RasterizerCache<T>::InvalidateRegion(PAddr addr, u32 size, SurfaceId region
for (const SurfaceId surface_id : remove_surfaces) { for (const SurfaceId surface_id : remove_surfaces) {
UnregisterSurface(surface_id); UnregisterSurface(surface_id);
if (!slot_surfaces[surface_id].IsFill()) { if (slot_surfaces[surface_id].type != SurfaceType::Fill) {
sentenced.emplace_back(surface_id, frame_tick); sentenced.emplace_back(surface_id, frame_tick);
} else { } else {
slot_surfaces.erase(surface_id); slot_surfaces.erase(surface_id);
} }
} }
remove_surfaces.clear();
} }
template <class T> template <class T>
@ -1367,25 +1357,7 @@ void RasterizerCache<T>::UnregisterSurface(SurfaceId surface_id) {
surfaces.erase(vector_it); surfaces.erase(vector_it);
}); });
if (False(surface.flags & SurfaceFlagBits::Tracked)) { RemoveTextureCubeFace(surface_id);
return;
}
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{};
}
}
if (std::none_of(cube.face_ids.begin(), cube.face_ids.end(),
[](SurfaceId id) { return id; })) {
sentenced.emplace_back(cube.surface_id, frame_tick);
it = texture_cube_cache.erase(it);
} else {
it++;
}
}
} }
template <class T> template <class T>
@ -1397,7 +1369,6 @@ void RasterizerCache<T>::UnregisterAll() {
} }
} }
texture_cube_cache.clear(); texture_cube_cache.clear();
remove_surfaces.clear();
} }
template <class T> template <class T>

View File

@ -165,8 +165,8 @@ private:
/// Removes any framebuffers that reference the provided surface_id. /// Removes any framebuffers that reference the provided surface_id.
void RemoveFramebuffers(SurfaceId surface_id); void RemoveFramebuffers(SurfaceId surface_id);
/// Transfers ownership of a memory region from src_surface to dest_surface /// Removes any references of the provided surface id from cached texture cubes.
void DuplicateSurface(SurfaceId src_id, SurfaceId dst_id); void RemoveTextureCubeFace(SurfaceId surface_id);
/// Computes the hash of the provided texture data. /// Computes the hash of the provided texture data.
u64 ComputeHash(const SurfaceParams& load_info, std::span<u8> upload_data); u64 ComputeHash(const SurfaceParams& load_info, std::span<u8> upload_data);
@ -224,7 +224,6 @@ private:
Common::SlotVector<Framebuffer> slot_framebuffers; Common::SlotVector<Framebuffer> slot_framebuffers;
SurfaceMap dirty_regions; SurfaceMap dirty_regions;
PageMap cached_pages; PageMap cached_pages;
std::vector<SurfaceId> remove_surfaces;
u32 resolution_scale_factor; u32 resolution_scale_factor;
u64 frame_tick{}; u64 frame_tick{};
FramebufferParams fb_params; FramebufferParams fb_params;

View File

@ -46,10 +46,6 @@ public:
/// Returns true if the surface contains a custom material with a normal map. /// Returns true if the surface contains a custom material with a normal map.
bool HasNormalMap() const noexcept; bool HasNormalMap() const noexcept;
bool IsFill() const noexcept {
return type == SurfaceType::Fill;
}
bool Overlaps(PAddr overlap_addr, size_t overlap_size) const noexcept { bool Overlaps(PAddr overlap_addr, size_t overlap_size) const noexcept {
const PAddr overlap_end = overlap_addr + static_cast<PAddr>(overlap_size); const PAddr overlap_end = overlap_addr + static_cast<PAddr>(overlap_size);
return addr < overlap_end && overlap_addr < end; return addr < overlap_end && overlap_addr < end;

View File

@ -228,10 +228,10 @@ std::string SurfaceParams::DebugName(bool scaled, bool custom) const noexcept {
} }
bool SurfaceParams::operator==(const SurfaceParams& other) const noexcept { bool SurfaceParams::operator==(const SurfaceParams& other) const noexcept {
return std::tie(addr, end, width, height, stride, levels, is_tiled, texture_type, pixel_format, return std::tie(addr, end, width, height, stride, levels, is_tiled, texture_type,
custom_format) == pixel_format) == std::tie(other.addr, other.end, other.width, other.height,
std::tie(other.addr, other.end, other.width, other.height, other.stride, other.levels, other.stride, other.levels, other.is_tiled,
other.is_tiled, other.texture_type, other.pixel_format, other.custom_format); other.texture_type, other.pixel_format);
} }
} // namespace VideoCore } // namespace VideoCore