mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	rasterizer_cache: Allow custom recycle (#6851)
* surface_params: Allow custom surface recycling * rasterizer_cache: Cleanup
This commit is contained in:
		
							parent
							
								
									20f4677f80
								
							
						
					
					
						commit
						5b52849f90
					
				
					 4 changed files with 34 additions and 68 deletions
				
			
		|  | @ -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> | ||||
| bool RasterizerCache<T>::AccelerateTextureCopy(const GPU::Regs::DisplayTransferConfig& config) { | ||||
|     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; | ||||
| } | ||||
| 
 | ||||
| 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> | ||||
| void RasterizerCache<T>::ValidateSurface(SurfaceId surface_id, PAddr addr, u32 size) { | ||||
|     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 SurfaceId old_id = | ||||
|                 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); | ||||
|         } | ||||
|         Surface& surface = slot_surfaces[surface_id]; | ||||
|  | @ -1203,7 +1194,6 @@ void RasterizerCache<T>::ClearAll(bool flush) { | |||
|     cached_pages -= flush_interval; | ||||
|     dirty_regions.clear(); | ||||
|     page_table.clear(); | ||||
|     remove_surfaces.clear(); | ||||
| } | ||||
| 
 | ||||
| template <class T> | ||||
|  | @ -1232,7 +1222,7 @@ void RasterizerCache<T>::FlushRegion(PAddr addr, u32 size, SurfaceId flush_surfa | |||
|                                interval.lower(), interval.upper()}; | ||||
| 
 | ||||
|         SCOPE_EXIT({ flushed_intervals += interval; }); | ||||
|         if (surface.IsFill()) { | ||||
|         if (surface.type == SurfaceType::Fill) { | ||||
|             DownloadFillSurface(surface, interval); | ||||
|             continue; | ||||
|         } | ||||
|  | @ -1274,6 +1264,7 @@ void RasterizerCache<T>::InvalidateRegion(PAddr addr, u32 size, SurfaceId region | |||
|         region_owner.MarkValid(invalid_interval); | ||||
|     } | ||||
| 
 | ||||
|     boost::container::small_vector<SurfaceId, 4> remove_surfaces; | ||||
|     ForEachSurfaceInRegion(addr, size, [&](SurfaceId surface_id, Surface& surface) { | ||||
|         if (surface_id == region_owner_id) { | ||||
|             return; | ||||
|  | @ -1301,13 +1292,12 @@ void RasterizerCache<T>::InvalidateRegion(PAddr addr, u32 size, SurfaceId region | |||
| 
 | ||||
|     for (const SurfaceId surface_id : remove_surfaces) { | ||||
|         UnregisterSurface(surface_id); | ||||
|         if (!slot_surfaces[surface_id].IsFill()) { | ||||
|         if (slot_surfaces[surface_id].type != SurfaceType::Fill) { | ||||
|             sentenced.emplace_back(surface_id, frame_tick); | ||||
|         } else { | ||||
|             slot_surfaces.erase(surface_id); | ||||
|         } | ||||
|     } | ||||
|     remove_surfaces.clear(); | ||||
| } | ||||
| 
 | ||||
| template <class T> | ||||
|  | @ -1367,25 +1357,7 @@ void RasterizerCache<T>::UnregisterSurface(SurfaceId surface_id) { | |||
|         surfaces.erase(vector_it); | ||||
|     }); | ||||
| 
 | ||||
|     if (False(surface.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++; | ||||
|         } | ||||
|     } | ||||
|     RemoveTextureCubeFace(surface_id); | ||||
| } | ||||
| 
 | ||||
| template <class T> | ||||
|  | @ -1397,7 +1369,6 @@ void RasterizerCache<T>::UnregisterAll() { | |||
|         } | ||||
|     } | ||||
|     texture_cube_cache.clear(); | ||||
|     remove_surfaces.clear(); | ||||
| } | ||||
| 
 | ||||
| template <class T> | ||||
|  |  | |||
|  | @ -165,8 +165,8 @@ private: | |||
|     /// Removes any framebuffers that reference the provided surface_id.
 | ||||
|     void RemoveFramebuffers(SurfaceId surface_id); | ||||
| 
 | ||||
|     /// Transfers ownership of a memory region from src_surface to dest_surface
 | ||||
|     void DuplicateSurface(SurfaceId src_id, SurfaceId dst_id); | ||||
|     /// Removes any references of the provided surface id from cached texture cubes.
 | ||||
|     void RemoveTextureCubeFace(SurfaceId surface_id); | ||||
| 
 | ||||
|     /// Computes the hash of the provided texture data.
 | ||||
|     u64 ComputeHash(const SurfaceParams& load_info, std::span<u8> upload_data); | ||||
|  | @ -224,7 +224,6 @@ private: | |||
|     Common::SlotVector<Framebuffer> slot_framebuffers; | ||||
|     SurfaceMap dirty_regions; | ||||
|     PageMap cached_pages; | ||||
|     std::vector<SurfaceId> remove_surfaces; | ||||
|     u32 resolution_scale_factor; | ||||
|     u64 frame_tick{}; | ||||
|     FramebufferParams fb_params; | ||||
|  |  | |||
|  | @ -46,10 +46,6 @@ public: | |||
|     /// Returns true if the surface contains a custom material with a normal map.
 | ||||
|     bool HasNormalMap() const noexcept; | ||||
| 
 | ||||
|     bool IsFill() const noexcept { | ||||
|         return type == SurfaceType::Fill; | ||||
|     } | ||||
| 
 | ||||
|     bool Overlaps(PAddr overlap_addr, size_t overlap_size) const noexcept { | ||||
|         const PAddr overlap_end = overlap_addr + static_cast<PAddr>(overlap_size); | ||||
|         return addr < overlap_end && overlap_addr < end; | ||||
|  |  | |||
|  | @ -228,10 +228,10 @@ std::string SurfaceParams::DebugName(bool scaled, bool custom) 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, | ||||
|                     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); | ||||
|     return std::tie(addr, end, width, height, stride, levels, is_tiled, texture_type, | ||||
|                     pixel_format) == std::tie(other.addr, other.end, other.width, other.height, | ||||
|                                               other.stride, other.levels, other.is_tiled, | ||||
|                                               other.texture_type, other.pixel_format); | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCore
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue