From 29e8576b0d056a9c3a32b93bf47cafbb073e9f9c Mon Sep 17 00:00:00 2001 From: Thog Date: Sun, 12 Jan 2020 03:14:27 +0100 Subject: [PATCH] MapBufferEx: take page size into account (#873) Fix #744 --- Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs | 5 +++-- .../NvHostAsGpu/NvHostAsGpuDeviceFile.cs | 21 +++++++++++++------ .../NvHostAsGpu/Types/AddressSpaceContext.cs | 6 +++--- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs b/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs index 2fc315c3..ffca6f33 100644 --- a/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs +++ b/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs @@ -66,12 +66,13 @@ namespace Ryujinx.Graphics.Gpu.Memory /// /// CPU virtual address to map into /// Size in bytes of the mapping + /// Required alignment of the GPU virtual address in bytes /// GPU virtual address where the range was mapped, or an all ones mask in case of failure - public ulong Map(ulong pa, ulong size) + public ulong MapAllocate(ulong pa, ulong size, ulong alignment) { lock (_pageTable) { - ulong va = GetFreePosition(size); + ulong va = GetFreePosition(size, alignment); if (va != PteUnmapped) { diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/NvHostAsGpuDeviceFile.cs b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/NvHostAsGpuDeviceFile.cs index 008c6059..6653c0f0 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/NvHostAsGpuDeviceFile.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/NvHostAsGpuDeviceFile.cs @@ -1,10 +1,12 @@ -using Ryujinx.Common.Logging; +using Ryujinx.Common; +using Ryujinx.Common.Logging; using Ryujinx.Graphics.Gpu.Memory; using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu.Types; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap; using System; using System.Collections.Concurrent; +using System.Diagnostics; namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu { @@ -165,7 +167,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu private NvInternalResult MapBufferEx(ref MapBufferExArguments arguments) { - const string mapErrorMsg = "Failed to map fixed buffer with offset 0x{0:x16} and size 0x{1:x16}!"; + const string mapErrorMsg = "Failed to map fixed buffer with offset 0x{0:x16}, size 0x{1:x16} and alignment 0x{2:x16}!"; AddressSpaceContext addressSpaceContext = GetAddressSpaceContext(Context); @@ -178,6 +180,13 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu return NvInternalResult.InvalidInput; } + ulong pageSize = (ulong)arguments.PageSize; + + if (pageSize == 0) + { + pageSize = (ulong)map.Align; + } + long physicalAddress; if ((arguments.Flags & AddressSpaceFlags.RemapSubRange) != 0) @@ -192,7 +201,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu if ((long)addressSpaceContext.Gmm.Map((ulong)physicalAddress, (ulong)virtualAddress, (ulong)arguments.MappingSize) < 0) { - string message = string.Format(mapErrorMsg, virtualAddress, arguments.MappingSize); + string message = string.Format(mapErrorMsg, virtualAddress, arguments.MappingSize, pageSize); Logger.PrintWarning(LogClass.ServiceNv, message); @@ -229,13 +238,13 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu if (!virtualAddressAllocated) { - if (addressSpaceContext.ValidateFixedBuffer(arguments.Offset, size)) + if (addressSpaceContext.ValidateFixedBuffer(arguments.Offset, size, pageSize)) { arguments.Offset = (long)addressSpaceContext.Gmm.Map((ulong)physicalAddress, (ulong)arguments.Offset, (ulong)size); } else { - string message = string.Format(mapErrorMsg, arguments.Offset, size); + string message = string.Format(mapErrorMsg, arguments.Offset, size, pageSize); Logger.PrintWarning(LogClass.ServiceNv, message); @@ -244,7 +253,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu } else { - arguments.Offset = (long)addressSpaceContext.Gmm.Map((ulong)physicalAddress, (ulong)size); + arguments.Offset = (long)addressSpaceContext.Gmm.MapAllocate((ulong)physicalAddress, (ulong)size, pageSize); } if (arguments.Offset < 0) diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/Types/AddressSpaceContext.cs b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/Types/AddressSpaceContext.cs index 951994ef..d39be297 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/Types/AddressSpaceContext.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/Types/AddressSpaceContext.cs @@ -48,7 +48,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu.Types _reservations = new SortedList(); } - public bool ValidateFixedBuffer(long position, long size) + public bool ValidateFixedBuffer(long position, long size, ulong alignment) { long mapEnd = position + size; @@ -58,8 +58,8 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu.Types return false; } - // Check if address is page aligned. - if ((position & (long)MemoryManager.PageMask) != 0) + // Check if address is aligned. + if ((position & (long)(alignment - 1)) != 0) { return false; }