From 9e141bc3daf86ceccc4eced78edbc9be2d2efe6e Mon Sep 17 00:00:00 2001 From: Ac_K Date: Thu, 23 Jul 2020 12:25:41 +0200 Subject: [PATCH] vi: Implement GetIndirectLayerImageRequiredMemoryInfo (#1415) This implement GetIndirectLayerImageRequiredMemoryInfo call from vi service, accordingly to RE. Thanks to Thog and gdkchan for helping me to understand some GPU things. Close #942 --- Ryujinx.HLE/HOS/Services/Vi/ResultCode.cs | 1 + .../RootService/IApplicationDisplayService.cs | 50 ++++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/Ryujinx.HLE/HOS/Services/Vi/ResultCode.cs b/Ryujinx.HLE/HOS/Services/Vi/ResultCode.cs index 35ee6ae2..2c78c1a3 100644 --- a/Ryujinx.HLE/HOS/Services/Vi/ResultCode.cs +++ b/Ryujinx.HLE/HOS/Services/Vi/ResultCode.cs @@ -8,6 +8,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi Success = 0, InvalidArguments = (1 << ErrorCodeShift) | ModuleId, + InvalidLayerSize = (4 << ErrorCodeShift) | ModuleId, InvalidScalingMode = (6 << ErrorCodeShift) | ModuleId } } \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs b/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs index 8180c284..bd00fc02 100644 --- a/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs +++ b/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs @@ -1,3 +1,4 @@ +using Ryujinx.Common; using Ryujinx.Cpu; using Ryujinx.HLE.HOS.Ipc; using Ryujinx.HLE.HOS.Kernel.Common; @@ -190,7 +191,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService public ResultCode SetLayerScalingMode(ServiceCtx context) { int scalingMode = context.RequestData.ReadInt32(); - long unknown = context.RequestData.ReadInt64(); + long layerId = context.RequestData.ReadInt64(); return ResultCode.Success; } @@ -235,6 +236,53 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService return null; } + [Command(2460)] + // GetIndirectLayerImageRequiredMemoryInfo(u64 width, u64 height) -> (u64 size, u64 alignment) + public ResultCode GetIndirectLayerImageRequiredMemoryInfo(ServiceCtx context) + { + /* + // Doesn't occur in our case. + if (sizePtr == null || address_alignmentPtr == null) + { + return ResultCode.InvalidArguments; + } + */ + + int width = (int)context.RequestData.ReadUInt64(); + int height = (int)context.RequestData.ReadUInt64(); + + if (height < 0 || width < 0) + { + return ResultCode.InvalidLayerSize; + } + else + { + /* + // Doesn't occur in our case. + if (!service_initialized) + { + return ResultCode.InvalidArguments; + } + */ + + const ulong defaultAlignment = 0x1000; + const ulong defaultSize = 0x20000; + + // NOTE: The official service setup a A8B8G8R8 texture with a linear layout and then query its size. + // As we don't need this texture on the emulator, we can just simplify this logic and directly + // do a linear layout size calculation. (stride * height * bytePerPixel) + int pitch = BitUtils.AlignUp(BitUtils.DivRoundUp(width * 32, 8), 64); + int memorySize = pitch * BitUtils.AlignUp(height, 64); + ulong requiredMemorySize = (ulong)BitUtils.AlignUp(memorySize, (int)defaultAlignment); + ulong size = (requiredMemorySize + defaultSize - 1) / defaultSize * defaultSize; + + context.ResponseData.Write(size); + context.ResponseData.Write(defaultAlignment); + } + + return ResultCode.Success; + } + [Command(5202)] // GetDisplayVsyncEvent(u64) -> handle public ResultCode GetDisplayVSyncEvent(ServiceCtx context)