Improve handling for unmapped GPU resources (#2083)
* Improve handling for unmapped GPU resources - Fixed a memory tracking bug that would set protection on empty PTEs - When a texture's memory is (partially) unmapped, all pool references are forcibly removed and the texture must be rediscovered to draw with it. This will also force the texture discovery to always compare the texture's range for a match. - RegionHandles now know if they are unmapped, and automatically unset their dirty flag when unmapped. - Partial texture sync now loads only the region of texture that has been modified. Unmapped memory tracking handles cause dirty flags for a texture group handle to be ignored. This greatly improves the emulator's stability for newer UE4 games. * Address feedback, fix MultiRange slice Fixed an issue where the size of the multi-range slice would be miscalculated. * Update Ryujinx.Memory/Range/MultiRange.cs (feedback) Co-authored-by: Mary <thog@protonmail.com> Co-authored-by: Mary <thog@protonmail.com>
This commit is contained in:
@ -74,6 +74,14 @@ namespace Ryujinx.Memory.Tracking
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
VirtualRegion region = results[i];
|
||||
|
||||
// If the region has been fully remapped, signal that it has been mapped again.
|
||||
bool remapped = _memoryManager.IsRangeMapped(region.Address, region.Size);
|
||||
if (remapped)
|
||||
{
|
||||
region.SignalMappingChanged(true);
|
||||
}
|
||||
|
||||
region.RecalculatePhysicalChildren();
|
||||
region.UpdateProtection();
|
||||
}
|
||||
@ -99,6 +107,7 @@ namespace Ryujinx.Memory.Tracking
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
VirtualRegion region = results[i];
|
||||
region.SignalMappingChanged(false);
|
||||
region.RecalculatePhysicalChildren();
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ namespace Ryujinx.Memory.Tracking
|
||||
public class RegionHandle : IRegionHandle, IRange
|
||||
{
|
||||
public bool Dirty { get; private set; }
|
||||
public bool Unmapped { get; private set; }
|
||||
|
||||
public ulong Address { get; }
|
||||
public ulong Size { get; }
|
||||
@ -37,10 +38,11 @@ namespace Ryujinx.Memory.Tracking
|
||||
/// <param name="tracking">Tracking object for the target memory block</param>
|
||||
/// <param name="address">Virtual address of the region to track</param>
|
||||
/// <param name="size">Size of the region to track</param>
|
||||
/// <param name="dirty">Initial value of the dirty flag</param>
|
||||
internal RegionHandle(MemoryTracking tracking, ulong address, ulong size, bool dirty = true)
|
||||
/// <param name="mapped">True if the region handle starts mapped</param>
|
||||
internal RegionHandle(MemoryTracking tracking, ulong address, ulong size, bool mapped = true)
|
||||
{
|
||||
Dirty = dirty;
|
||||
Dirty = mapped;
|
||||
Unmapped = !mapped;
|
||||
Address = address;
|
||||
Size = size;
|
||||
EndAddress = address + size;
|
||||
@ -128,6 +130,23 @@ namespace Ryujinx.Memory.Tracking
|
||||
_regions.Add(region);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Signal that this handle has been mapped or unmapped.
|
||||
/// </summary>
|
||||
/// <param name="mapped">True if the handle has been mapped, false if unmapped</param>
|
||||
internal void SignalMappingChanged(bool mapped)
|
||||
{
|
||||
if (Unmapped == mapped)
|
||||
{
|
||||
Unmapped = !mapped;
|
||||
|
||||
if (Unmapped)
|
||||
{
|
||||
Dirty = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if this region overlaps with another.
|
||||
/// </summary>
|
||||
|
@ -66,6 +66,18 @@ namespace Ryujinx.Memory.Tracking
|
||||
UpdatePhysicalChildren();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Signal that this region has been mapped or unmapped.
|
||||
/// </summary>
|
||||
/// <param name="mapped">True if the region has been mapped, false if unmapped</param>
|
||||
public void SignalMappingChanged(bool mapped)
|
||||
{
|
||||
foreach (RegionHandle handle in Handles)
|
||||
{
|
||||
handle.SignalMappingChanged(mapped);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the strictest permission that the child handles demand. Assumes that the tracking lock has been obtained.
|
||||
/// </summary>
|
||||
|
Reference in New Issue
Block a user