public void make_intptr() { Assert.AreEqual(BitUtils.MakeIntPtr(0x1234, 0x5678), (IntPtr)0x56781234U); Assert.AreEqual(BitUtils.MakeIntPtr(0x1234, 0x8678), (IntPtr) unchecked ((int)0x86781234)); }
public static void Declare(CodeGenContext context, StructuredProgramInfo info) { context.AppendLine("#version 450 core"); context.AppendLine("#extension GL_ARB_gpu_shader_int64 : enable"); context.AppendLine("#extension GL_ARB_shader_ballot : enable"); context.AppendLine("#extension GL_ARB_shader_group_vote : enable"); context.AppendLine("#extension GL_EXT_shader_image_load_formatted : enable"); if (context.Config.Stage == ShaderStage.Compute) { context.AppendLine("#extension GL_ARB_compute_shader : enable"); } if (context.Config.GpPassthrough) { context.AppendLine("#extension GL_NV_geometry_shader_passthrough : enable"); } context.AppendLine("#pragma optionNV(fastmath off)"); context.AppendLine(); context.AppendLine($"const int {DefaultNames.UndefinedName} = 0;"); context.AppendLine(); if (context.Config.Stage == ShaderStage.Compute) { int localMemorySize = BitUtils.DivRoundUp(context.Config.GpuAccessor.QueryComputeLocalMemorySize(), 4); if (localMemorySize != 0) { string localMemorySizeStr = NumberFormatter.FormatInt(localMemorySize); context.AppendLine($"uint {DefaultNames.LocalMemoryName}[{localMemorySizeStr}];"); context.AppendLine(); } int sharedMemorySize = BitUtils.DivRoundUp(context.Config.GpuAccessor.QueryComputeSharedMemorySize(), 4); if (sharedMemorySize != 0) { string sharedMemorySizeStr = NumberFormatter.FormatInt(sharedMemorySize); context.AppendLine($"shared uint {DefaultNames.SharedMemoryName}[{sharedMemorySizeStr}];"); context.AppendLine(); } } else if (context.Config.LocalMemorySize != 0) { int localMemorySize = BitUtils.DivRoundUp(context.Config.LocalMemorySize, 4); string localMemorySizeStr = NumberFormatter.FormatInt(localMemorySize); context.AppendLine($"uint {DefaultNames.LocalMemoryName}[{localMemorySizeStr}];"); context.AppendLine(); } var cBufferDescriptors = context.Config.GetConstantBufferDescriptors(); if (cBufferDescriptors.Length != 0) { DeclareUniforms(context, cBufferDescriptors); context.AppendLine(); } var sBufferDescriptors = context.Config.GetStorageBufferDescriptors(); if (sBufferDescriptors.Length != 0) { DeclareStorages(context, sBufferDescriptors); context.AppendLine(); } var textureDescriptors = context.Config.GetTextureDescriptors(); if (textureDescriptors.Length != 0) { DeclareSamplers(context, textureDescriptors); context.AppendLine(); } var imageDescriptors = context.Config.GetImageDescriptors(); if (imageDescriptors.Length != 0) { DeclareImages(context, imageDescriptors); context.AppendLine(); } if (context.Config.Stage != ShaderStage.Compute) { if (context.Config.Stage == ShaderStage.Geometry) { string inPrimitive = context.Config.GpuAccessor.QueryPrimitiveTopology().ToGlslString(); context.AppendLine($"layout ({inPrimitive}) in;"); if (context.Config.GpPassthrough) { context.AppendLine($"layout (passthrough) in gl_PerVertex"); context.EnterScope(); context.AppendLine("vec4 gl_Position;"); context.AppendLine("float gl_PointSize;"); context.AppendLine("float gl_ClipDistance[];"); context.LeaveScope(";"); } else { string outPrimitive = context.Config.OutputTopology.ToGlslString(); int maxOutputVertices = context.Config.MaxOutputVertices; context.AppendLine($"layout ({outPrimitive}, max_vertices = {maxOutputVertices}) out;"); } context.AppendLine(); } if (info.IAttributes.Count != 0) { DeclareInputAttributes(context, info); context.AppendLine(); } if (info.OAttributes.Count != 0 || context.Config.Stage != ShaderStage.Fragment) { DeclareOutputAttributes(context, info); context.AppendLine(); } } else { string localSizeX = NumberFormatter.FormatInt(context.Config.GpuAccessor.QueryComputeLocalSizeX()); string localSizeY = NumberFormatter.FormatInt(context.Config.GpuAccessor.QueryComputeLocalSizeY()); string localSizeZ = NumberFormatter.FormatInt(context.Config.GpuAccessor.QueryComputeLocalSizeZ()); context.AppendLine( "layout (" + $"local_size_x = {localSizeX}, " + $"local_size_y = {localSizeY}, " + $"local_size_z = {localSizeZ}) in;"); context.AppendLine(); } if (context.Config.Stage == ShaderStage.Fragment || context.Config.Stage == ShaderStage.Compute) { if (context.Config.Stage == ShaderStage.Fragment) { if (context.Config.GpuAccessor.QueryEarlyZForce()) { context.AppendLine("layout(early_fragment_tests) in;"); context.AppendLine(); } context.AppendLine($"uniform bool {DefaultNames.IsBgraName}[8];"); context.AppendLine(); } if (DeclareRenderScale(context)) { context.AppendLine(); } } if ((info.HelperFunctionsMask & HelperFunctionsMask.AtomicMinMaxS32Shared) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/AtomicMinMaxS32Shared.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.AtomicMinMaxS32Storage) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/AtomicMinMaxS32Storage.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.MultiplyHighS32) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/MultiplyHighS32.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.MultiplyHighU32) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/MultiplyHighU32.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.Shuffle) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/Shuffle.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.ShuffleDown) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleDown.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.ShuffleUp) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleUp.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.ShuffleXor) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleXor.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.SwizzleAdd) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/SwizzleAdd.glsl"); } }
public static bool LoadStaticObjects( Horizon system, Npdm metaData, IExecutable[] staticObjects, byte[] arguments = null) { if (!metaData.Is64Bits) { Logger.PrintWarning(LogClass.Loader, "32-bits application detected!"); } ulong argsStart = 0; int argsSize = 0; ulong codeStart = metaData.Is64Bits ? 0x8000000UL : 0x200000UL; int codeSize = 0; ulong[] nsoBase = new ulong[staticObjects.Length]; for (int index = 0; index < staticObjects.Length; index++) { IExecutable staticObject = staticObjects[index]; int textEnd = staticObject.TextOffset + staticObject.Text.Length; int roEnd = staticObject.RoOffset + staticObject.Ro.Length; int dataEnd = staticObject.DataOffset + staticObject.Data.Length + staticObject.BssSize; int nsoSize = textEnd; if ((uint)nsoSize < (uint)roEnd) { nsoSize = roEnd; } if ((uint)nsoSize < (uint)dataEnd) { nsoSize = dataEnd; } nsoSize = BitUtils.AlignUp(nsoSize, KMemoryManager.PageSize); nsoBase[index] = codeStart + (ulong)codeSize; codeSize += nsoSize; if (arguments != null && argsSize == 0) { argsStart = (ulong)codeSize; argsSize = BitUtils.AlignDown(arguments.Length * 2 + ArgsTotalSize - 1, KMemoryManager.PageSize); codeSize += argsSize; } } int codePagesCount = codeSize / KMemoryManager.PageSize; int personalMmHeapPagesCount = metaData.PersonalMmHeapSize / KMemoryManager.PageSize; ProcessCreationInfo creationInfo = new ProcessCreationInfo( metaData.TitleName, metaData.ProcessCategory, metaData.Aci0.TitleId, codeStart, codePagesCount, metaData.MmuFlags, 0, personalMmHeapPagesCount); KernelResult result; KResourceLimit resourceLimit = new KResourceLimit(system); long applicationRgSize = (long)system.MemoryRegions[(int)MemoryRegion.Application].Size; result = resourceLimit.SetLimitValue(LimitableResource.Memory, applicationRgSize); result |= resourceLimit.SetLimitValue(LimitableResource.Thread, 608); result |= resourceLimit.SetLimitValue(LimitableResource.Event, 700); result |= resourceLimit.SetLimitValue(LimitableResource.TransferMemory, 128); result |= resourceLimit.SetLimitValue(LimitableResource.Session, 894); if (result != KernelResult.Success) { Logger.PrintError(LogClass.Loader, $"Process initialization failed setting resource limit values."); return(false); } KProcess process = new KProcess(system); MemoryRegion memoryRegion = (MemoryRegion)((metaData.Acid.Flags >> 2) & 0xf); if (memoryRegion > MemoryRegion.NvServices) { Logger.PrintError(LogClass.Loader, $"Process initialization failed due to invalid ACID flags."); return(false); } result = process.Initialize( creationInfo, metaData.Aci0.KernelAccessControl.Capabilities, resourceLimit, memoryRegion); if (result != KernelResult.Success) { Logger.PrintError(LogClass.Loader, $"Process initialization returned error \"{result}\"."); return(false); } for (int index = 0; index < staticObjects.Length; index++) { Logger.PrintInfo(LogClass.Loader, $"Loading image {index} at 0x{nsoBase[index]:x16}..."); result = LoadIntoMemory(process, staticObjects[index], nsoBase[index]); if (result != KernelResult.Success) { Logger.PrintError(LogClass.Loader, $"Process initialization returned error \"{result}\"."); return(false); } } process.DefaultCpuCore = metaData.DefaultCpuId; result = process.Start(metaData.MainThreadPriority, (ulong)metaData.MainThreadStackSize); if (result != KernelResult.Success) { Logger.PrintError(LogClass.Loader, $"Process start returned error \"{result}\"."); return(false); } system.Processes.Add(process.Pid, process); return(true); }
public static uint _ext_impl(uint data, int pos, int size) => BitUtils.Extract(data, pos, size);
public void ExtractBitTest() { Assert.AreEqual(0, BitUtils.ExtractBit(0x00000000u, 0)); Assert.AreEqual(0, BitUtils.ExtractBit(0x00000000u, 1)); Assert.AreEqual(0, BitUtils.ExtractBit(0x00000000u, 31)); Assert.AreEqual(1, BitUtils.ExtractBit(0xFFFFFFFFu, 0)); Assert.AreEqual(1, BitUtils.ExtractBit(0xFFFFFFFFu, 1)); Assert.AreEqual(1, BitUtils.ExtractBit(0xFFFFFFFFu, 31)); Assert.AreEqual(0, BitUtils.ExtractBit(0x4B603B9Au, 0)); Assert.AreEqual(1, BitUtils.ExtractBit(0x4B603B9Au, 1)); Assert.AreEqual(0, BitUtils.ExtractBit(0x4B603B9Au, 2)); Assert.AreEqual(1, BitUtils.ExtractBit(0x4B603B9Au, 3)); Assert.AreEqual(1, BitUtils.ExtractBit(0x4B603B9Au, 4)); Assert.AreEqual(0, BitUtils.ExtractBit(0x4B603B9Au, 5)); Assert.AreEqual(0, BitUtils.ExtractBit(0x4B603B9Au, 6)); Assert.AreEqual(1, BitUtils.ExtractBit(0x4B603B9Au, 7)); Assert.AreEqual(1, BitUtils.ExtractBit(0x4B603B9Au, 8)); Assert.AreEqual(1, BitUtils.ExtractBit(0x4B603B9Au, 9)); Assert.AreEqual(0, BitUtils.ExtractBit(0x4B603B9Au, 10)); Assert.AreEqual(1, BitUtils.ExtractBit(0x4B603B9Au, 11)); Assert.AreEqual(1, BitUtils.ExtractBit(0x4B603B9Au, 12)); Assert.AreEqual(1, BitUtils.ExtractBit(0x4B603B9Au, 13)); Assert.AreEqual(0, BitUtils.ExtractBit(0x4B603B9Au, 14)); Assert.AreEqual(0, BitUtils.ExtractBit(0x4B603B9Au, 15)); Assert.AreEqual(0, BitUtils.ExtractBit(0x4B603B9Au, 16)); Assert.AreEqual(0, BitUtils.ExtractBit(0x4B603B9Au, 17)); Assert.AreEqual(0, BitUtils.ExtractBit(0x4B603B9Au, 18)); Assert.AreEqual(0, BitUtils.ExtractBit(0x4B603B9Au, 19)); Assert.AreEqual(0, BitUtils.ExtractBit(0x4B603B9Au, 20)); Assert.AreEqual(1, BitUtils.ExtractBit(0x4B603B9Au, 21)); Assert.AreEqual(1, BitUtils.ExtractBit(0x4B603B9Au, 22)); Assert.AreEqual(0, BitUtils.ExtractBit(0x4B603B9Au, 23)); Assert.AreEqual(1, BitUtils.ExtractBit(0x4B603B9Au, 24)); Assert.AreEqual(1, BitUtils.ExtractBit(0x4B603B9Au, 25)); Assert.AreEqual(0, BitUtils.ExtractBit(0x4B603B9Au, 26)); Assert.AreEqual(1, BitUtils.ExtractBit(0x4B603B9Au, 27)); Assert.AreEqual(0, BitUtils.ExtractBit(0x4B603B9Au, 28)); Assert.AreEqual(0, BitUtils.ExtractBit(0x4B603B9Au, 29)); Assert.AreEqual(1, BitUtils.ExtractBit(0x4B603B9Au, 30)); Assert.AreEqual(0, BitUtils.ExtractBit(0x4B603B9Au, 31)); Assert.AreEqual(0, BitUtils.ExtractBit(0xFFFFFFFEu, 0)); Assert.AreEqual(0, BitUtils.ExtractBit(0xFFFFFFFDu, 1)); Assert.AreEqual(0, BitUtils.ExtractBit(0xFFFFFFFBu, 2)); Assert.AreEqual(0, BitUtils.ExtractBit(0xFFFFFFF7u, 3)); Assert.AreEqual(0, BitUtils.ExtractBit(0xFFFFFFEFu, 4)); Assert.AreEqual(0, BitUtils.ExtractBit(0xFFFFFFDFu, 5)); Assert.AreEqual(0, BitUtils.ExtractBit(0xFFFFFFBFu, 6)); Assert.AreEqual(0, BitUtils.ExtractBit(0xFFFFFF7Fu, 7)); Assert.AreEqual(0, BitUtils.ExtractBit(0xFFFFFEFFu, 8)); Assert.AreEqual(0, BitUtils.ExtractBit(0xFFFFFDFFu, 9)); Assert.AreEqual(0, BitUtils.ExtractBit(0xFFFFFBFFu, 10)); Assert.AreEqual(0, BitUtils.ExtractBit(0xFFFFF7FFu, 11)); Assert.AreEqual(0, BitUtils.ExtractBit(0xFFFFEFFFu, 12)); Assert.AreEqual(0, BitUtils.ExtractBit(0xFFFFDFFFu, 13)); Assert.AreEqual(0, BitUtils.ExtractBit(0xFFFFBFFFu, 14)); Assert.AreEqual(0, BitUtils.ExtractBit(0xFFFF7FFFu, 15)); Assert.AreEqual(0, BitUtils.ExtractBit(0xFFFEFFFFu, 16)); Assert.AreEqual(0, BitUtils.ExtractBit(0xFFFDFFFFu, 17)); Assert.AreEqual(0, BitUtils.ExtractBit(0xFFFBFFFFu, 18)); Assert.AreEqual(0, BitUtils.ExtractBit(0xFFF7FFFFu, 19)); Assert.AreEqual(0, BitUtils.ExtractBit(0xFFEFFFFFu, 20)); Assert.AreEqual(0, BitUtils.ExtractBit(0xFFDFFFFFu, 21)); Assert.AreEqual(0, BitUtils.ExtractBit(0xFFBFFFFFu, 22)); Assert.AreEqual(0, BitUtils.ExtractBit(0xFF7FFFFFu, 23)); Assert.AreEqual(0, BitUtils.ExtractBit(0xFEFFFFFFu, 24)); Assert.AreEqual(0, BitUtils.ExtractBit(0xFDFFFFFFu, 25)); Assert.AreEqual(0, BitUtils.ExtractBit(0xFBFFFFFFu, 26)); Assert.AreEqual(0, BitUtils.ExtractBit(0xF7FFFFFFu, 27)); Assert.AreEqual(0, BitUtils.ExtractBit(0xEFFFFFFFu, 28)); Assert.AreEqual(0, BitUtils.ExtractBit(0xDFFFFFFFu, 29)); Assert.AreEqual(0, BitUtils.ExtractBit(0xBFFFFFFFu, 30)); Assert.AreEqual(0, BitUtils.ExtractBit(0x7FFFFFFFu, 31)); Assert.AreEqual(1, BitUtils.ExtractBit(0x00000001u, 0)); Assert.AreEqual(1, BitUtils.ExtractBit(0x00000002u, 1)); Assert.AreEqual(1, BitUtils.ExtractBit(0x00000004u, 2)); Assert.AreEqual(1, BitUtils.ExtractBit(0x00000008u, 3)); Assert.AreEqual(1, BitUtils.ExtractBit(0x00000010u, 4)); Assert.AreEqual(1, BitUtils.ExtractBit(0x00000020u, 5)); Assert.AreEqual(1, BitUtils.ExtractBit(0x00000040u, 6)); Assert.AreEqual(1, BitUtils.ExtractBit(0x00000080u, 7)); Assert.AreEqual(1, BitUtils.ExtractBit(0x00000100u, 8)); Assert.AreEqual(1, BitUtils.ExtractBit(0x00000200u, 9)); Assert.AreEqual(1, BitUtils.ExtractBit(0x00000400u, 10)); Assert.AreEqual(1, BitUtils.ExtractBit(0x00000800u, 11)); Assert.AreEqual(1, BitUtils.ExtractBit(0x00001000u, 12)); Assert.AreEqual(1, BitUtils.ExtractBit(0x00002000u, 13)); Assert.AreEqual(1, BitUtils.ExtractBit(0x00004000u, 14)); Assert.AreEqual(1, BitUtils.ExtractBit(0x00008000u, 15)); Assert.AreEqual(1, BitUtils.ExtractBit(0x00010000u, 16)); Assert.AreEqual(1, BitUtils.ExtractBit(0x00020000u, 17)); Assert.AreEqual(1, BitUtils.ExtractBit(0x00040000u, 18)); Assert.AreEqual(1, BitUtils.ExtractBit(0x00080000u, 19)); Assert.AreEqual(1, BitUtils.ExtractBit(0x00100000u, 20)); Assert.AreEqual(1, BitUtils.ExtractBit(0x00200000u, 21)); Assert.AreEqual(1, BitUtils.ExtractBit(0x00400000u, 22)); Assert.AreEqual(1, BitUtils.ExtractBit(0x00800000u, 23)); Assert.AreEqual(1, BitUtils.ExtractBit(0x01000000u, 24)); Assert.AreEqual(1, BitUtils.ExtractBit(0x02000000u, 25)); Assert.AreEqual(1, BitUtils.ExtractBit(0x04000000u, 26)); Assert.AreEqual(1, BitUtils.ExtractBit(0x08000000u, 27)); Assert.AreEqual(1, BitUtils.ExtractBit(0x10000000u, 28)); Assert.AreEqual(1, BitUtils.ExtractBit(0x20000000u, 29)); Assert.AreEqual(1, BitUtils.ExtractBit(0x40000000u, 30)); Assert.AreEqual(1, BitUtils.ExtractBit(0x80000000u, 31)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0x0000000000000000u, 0)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0x0000000000000000u, 1)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0x0000000000000000u, 63)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0xFFFFFFFFFFFFFFFFu, 0)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0xFFFFFFFFFFFFFFFFu, 1)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0xFFFFFFFFFFFFFFFFu, 63)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFFFFFFFFEu, 0)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFFFFFFFFDu, 1)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFFFFFFFFBu, 2)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFFFFFFFF7u, 3)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFFFFFFFEFu, 4)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFFFFFFFDFu, 5)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFFFFFFFBFu, 6)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFFFFFFF7Fu, 7)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFFFFFFEFFu, 8)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFFFFFFDFFu, 9)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFFFFFFBFFu, 10)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFFFFFF7FFu, 11)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFFFFFEFFFu, 12)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFFFFFDFFFu, 13)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFFFFFBFFFu, 14)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFFFFF7FFFu, 15)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFFFFEFFFFu, 16)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFFFFDFFFFu, 17)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFFFFBFFFFu, 18)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFFFF7FFFFu, 19)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFFFEFFFFFu, 20)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFFFDFFFFFu, 21)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFFFBFFFFFu, 22)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFFF7FFFFFu, 23)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFFEFFFFFFu, 24)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFFDFFFFFFu, 25)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFFBFFFFFFu, 26)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFF7FFFFFFu, 27)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFEFFFFFFFu, 28)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFDFFFFFFFu, 29)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFFBFFFFFFFu, 30)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFF7FFFFFFFu, 31)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFEFFFFFFFFu, 32)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFDFFFFFFFFu, 33)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFFBFFFFFFFFu, 34)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFF7FFFFFFFFu, 35)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFEFFFFFFFFFu, 36)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFDFFFFFFFFFu, 37)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFFBFFFFFFFFFu, 38)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFF7FFFFFFFFFu, 39)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFEFFFFFFFFFFu, 40)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFDFFFFFFFFFFu, 41)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFFBFFFFFFFFFFu, 42)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFF7FFFFFFFFFFu, 43)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFEFFFFFFFFFFFu, 44)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFDFFFFFFFFFFFu, 45)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFFBFFFFFFFFFFFu, 46)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFF7FFFFFFFFFFFu, 47)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFEFFFFFFFFFFFFu, 48)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFDFFFFFFFFFFFFu, 49)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFFBFFFFFFFFFFFFu, 50)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFF7FFFFFFFFFFFFu, 51)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFEFFFFFFFFFFFFFu, 52)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFDFFFFFFFFFFFFFu, 53)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFFBFFFFFFFFFFFFFu, 54)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFF7FFFFFFFFFFFFFu, 55)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFEFFFFFFFFFFFFFFu, 56)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFDFFFFFFFFFFFFFFu, 57)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xFBFFFFFFFFFFFFFFu, 58)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xF7FFFFFFFFFFFFFFu, 59)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xEFFFFFFFFFFFFFFFu, 60)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xDFFFFFFFFFFFFFFFu, 61)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0xBFFFFFFFFFFFFFFFu, 62)); Assert.AreEqual(0, BitUtils.ExtractBit((ulong)0x7FFFFFFFFFFFFFFFu, 63)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000000000001u, 0)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000000000002u, 1)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000000000004u, 2)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000000000008u, 3)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000000000010u, 4)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000000000020u, 5)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000000000040u, 6)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000000000080u, 7)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000000000100u, 8)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000000000200u, 9)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000000000400u, 10)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000000000800u, 11)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000000001000u, 12)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000000002000u, 13)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000000004000u, 14)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000000008000u, 15)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000000010000u, 16)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000000020000u, 17)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000000040000u, 18)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000000080000u, 19)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000000100000u, 20)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000000200000u, 21)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000000400000u, 22)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000000800000u, 23)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000001000000u, 24)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000002000000u, 25)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000004000000u, 26)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000008000000u, 27)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000010000000u, 28)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000020000000u, 29)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000040000000u, 30)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000080000000u, 31)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000100000000u, 32)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000200000000u, 33)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000400000000u, 34)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000000800000000u, 35)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000001000000000u, 36)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000002000000000u, 37)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000004000000000u, 38)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000008000000000u, 39)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000010000000000u, 40)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000020000000000u, 41)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000040000000000u, 42)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000080000000000u, 43)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000100000000000u, 44)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000200000000000u, 45)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000400000000000u, 46)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0000800000000000u, 47)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0001000000000000u, 48)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0002000000000000u, 49)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0004000000000000u, 50)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0008000000000000u, 51)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0010000000000000u, 52)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0020000000000000u, 53)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0040000000000000u, 54)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0080000000000000u, 55)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0100000000000000u, 56)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0200000000000000u, 57)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0400000000000000u, 58)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x0800000000000000u, 59)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x1000000000000000u, 60)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x2000000000000000u, 61)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x4000000000000000u, 62)); Assert.AreEqual(1, BitUtils.ExtractBit((ulong)0x8000000000000000u, 63)); }
public static void Copy( TextureCreateInfo srcInfo, TextureCreateInfo dstInfo, int srcHandle, int dstHandle, int srcLayer, int dstLayer, int srcLevel, int dstLevel) { int srcWidth = srcInfo.Width; int srcHeight = srcInfo.Height; int srcDepth = srcInfo.GetDepthOrLayers(); int srcLevels = srcInfo.Levels; int dstWidth = dstInfo.Width; int dstHeight = dstInfo.Height; int dstDepth = dstInfo.GetDepthOrLayers(); int dstLevels = dstInfo.Levels; dstWidth = Math.Max(1, dstWidth >> dstLevel); dstHeight = Math.Max(1, dstHeight >> dstLevel); if (dstInfo.Target == Target.Texture3D) { dstDepth = Math.Max(1, dstDepth >> dstLevel); } // When copying from a compressed to a non-compressed format, // the non-compressed texture will have the size of the texture // in blocks (not in texels), so we must adjust that size to // match the size in texels of the compressed texture. if (!srcInfo.IsCompressed && dstInfo.IsCompressed) { dstWidth = BitUtils.DivRoundUp(dstWidth, dstInfo.BlockWidth); dstHeight = BitUtils.DivRoundUp(dstHeight, dstInfo.BlockHeight); } else if (srcInfo.IsCompressed && !dstInfo.IsCompressed) { dstWidth *= srcInfo.BlockWidth; dstHeight *= srcInfo.BlockHeight; } int width = Math.Min(srcWidth, dstWidth); int height = Math.Min(srcHeight, dstHeight); int depth = Math.Min(srcDepth, dstDepth); int levels = Math.Min(srcLevels, dstLevels); for (int level = 0; level < levels; level++) { // Stop copy if we are already out of the levels range. if (level >= srcInfo.Levels || dstLevel + level >= dstInfo.Levels) { break; } GL.CopyImageSubData( srcHandle, srcInfo.Target.ConvertToImageTarget(), srcLevel + level, 0, 0, srcLayer, dstHandle, dstInfo.Target.ConvertToImageTarget(), dstLevel + level, 0, 0, dstLayer, width, height, depth); width = Math.Max(1, width >> 1); height = Math.Max(1, height >> 1); if (srcInfo.Target == Target.Texture3D) { depth = Math.Max(1, depth >> 1); } } }
public OpCodeSimdShImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) { Imm = (opCode >> 16) & 0x7f; Size = BitUtils.HighestBitSetNibble(Imm >> 3); }
public void ThrowsOnInvalidCharacter() { Assert.Throws <FormatException>(() => BitUtils.FromHexString("zzzz")) .WithMessage(String.Format(CoreResources.Input_Not_Valid_Hex_String, "zzzz")); }
public static void Declare(CodeGenContext context, StructuredProgramInfo info) { context.AppendLine("#version 420 core"); context.AppendLine("#extension GL_ARB_gpu_shader_int64 : enable"); context.AppendLine("#extension GL_ARB_shader_ballot : enable"); context.AppendLine("#extension GL_ARB_shader_group_vote : enable"); context.AppendLine("#extension GL_ARB_shader_storage_buffer_object : enable"); if (context.Config.Stage == ShaderStage.Compute) { context.AppendLine("#extension GL_ARB_compute_shader : enable"); } context.AppendLine("#pragma optionNV(fastmath off)"); context.AppendLine(); context.AppendLine($"const int {DefaultNames.UndefinedName} = 0;"); context.AppendLine(); if (context.Config.Stage == ShaderStage.Geometry) { string inPrimitive = ((InputTopology)context.Config.QueryInfo(QueryInfoName.PrimitiveTopology)).ToGlslString(); context.AppendLine($"layout ({inPrimitive}) in;"); string outPrimitive = context.Config.OutputTopology.ToGlslString(); int maxOutputVertices = context.Config.MaxOutputVertices; context.AppendLine($"layout ({outPrimitive}, max_vertices = {maxOutputVertices}) out;"); context.AppendLine(); } if (context.Config.Stage == ShaderStage.Compute) { int localMemorySize = BitUtils.DivRoundUp(context.Config.QueryInfo(QueryInfoName.ComputeLocalMemorySize), 4); if (localMemorySize != 0) { string localMemorySizeStr = NumberFormatter.FormatInt(localMemorySize); context.AppendLine($"uint {DefaultNames.LocalMemoryName}[{localMemorySizeStr}];"); context.AppendLine(); } int sharedMemorySize = BitUtils.DivRoundUp(context.Config.QueryInfo(QueryInfoName.ComputeSharedMemorySize), 4); if (sharedMemorySize != 0) { string sharedMemorySizeStr = NumberFormatter.FormatInt(sharedMemorySize); context.AppendLine($"shared uint {DefaultNames.SharedMemoryName}[{sharedMemorySizeStr}];"); context.AppendLine(); } } else if (context.Config.LocalMemorySize != 0) { int localMemorySize = BitUtils.DivRoundUp(context.Config.LocalMemorySize, 4); string localMemorySizeStr = NumberFormatter.FormatInt(localMemorySize); context.AppendLine($"uint {DefaultNames.LocalMemoryName}[{localMemorySizeStr}];"); context.AppendLine(); } if (info.CBuffers.Count != 0) { DeclareUniforms(context, info); context.AppendLine(); } if (info.SBuffers.Count != 0) { DeclareStorages(context, info); context.AppendLine(); } if (info.Samplers.Count != 0) { DeclareSamplers(context, info); context.AppendLine(); } if (info.Images.Count != 0) { DeclareImages(context, info); context.AppendLine(); } if (context.Config.Stage != ShaderStage.Compute) { if (info.IAttributes.Count != 0) { DeclareInputAttributes(context, info); context.AppendLine(); } if (info.OAttributes.Count != 0 || context.Config.Stage != ShaderStage.Fragment) { DeclareOutputAttributes(context, info); context.AppendLine(); } } else { string localSizeX = NumberFormatter.FormatInt(context.Config.QueryInfo(QueryInfoName.ComputeLocalSizeX)); string localSizeY = NumberFormatter.FormatInt(context.Config.QueryInfo(QueryInfoName.ComputeLocalSizeY)); string localSizeZ = NumberFormatter.FormatInt(context.Config.QueryInfo(QueryInfoName.ComputeLocalSizeZ)); context.AppendLine( "layout (" + $"local_size_x = {localSizeX}, " + $"local_size_y = {localSizeY}, " + $"local_size_z = {localSizeZ}) in;"); context.AppendLine(); } if ((info.HelperFunctionsMask & HelperFunctionsMask.MultiplyHighS32) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/MultiplyHighS32.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.MultiplyHighU32) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/MultiplyHighU32.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.Shuffle) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/Shuffle.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.ShuffleDown) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleDown.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.ShuffleUp) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleUp.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.ShuffleXor) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleXor.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.SwizzleAdd) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/SwizzleAdd.glsl"); } }
public static void ConvertLinearToBlockLinear( Span <byte> dst, int width, int height, int stride, int bytesPerPixel, int gobBlocksInY, ReadOnlySpan <byte> data) { int gobHeight = gobBlocksInY * GobHeight; int strideTrunc = BitUtils.AlignDown(width * bytesPerPixel, 16); int strideTrunc64 = BitUtils.AlignDown(width * bytesPerPixel, 64); int xStart = strideTrunc / bytesPerPixel; int inStrideGap = stride - width * bytesPerPixel; int alignment = GobStride / bytesPerPixel; int wAligned = BitUtils.AlignUp(width, alignment); BlockLinearLayout layoutConverter = new BlockLinearLayout(wAligned, height, gobBlocksInY, 1, bytesPerPixel); unsafe bool Convert <T>(Span <byte> output, ReadOnlySpan <byte> data) where T : unmanaged { fixed(byte *outputPtr = output, dataPtr = data) { byte *inPtr = dataPtr; for (int y = 0; y < height; y++) { layoutConverter.SetY(y); for (int x = 0; x < strideTrunc64; x += 64, inPtr += 64) { byte *offset = outputPtr + layoutConverter.GetOffsetWithLineOffset64(x); byte *offset2 = offset + 0x20; byte *offset3 = offset + 0x100; byte *offset4 = offset + 0x120; Vector128 <byte> value = *(Vector128 <byte> *)inPtr; Vector128 <byte> value2 = *(Vector128 <byte> *)(inPtr + 16); Vector128 <byte> value3 = *(Vector128 <byte> *)(inPtr + 32); Vector128 <byte> value4 = *(Vector128 <byte> *)(inPtr + 48); *(Vector128 <byte> *)offset = value; *(Vector128 <byte> *)offset2 = value2; *(Vector128 <byte> *)offset3 = value3; *(Vector128 <byte> *)offset4 = value4; } for (int x = strideTrunc64; x < strideTrunc; x += 16, inPtr += 16) { byte *offset = outputPtr + layoutConverter.GetOffsetWithLineOffset16(x); *(Vector128 <byte> *)offset = *(Vector128 <byte> *)inPtr; } for (int x = xStart; x < width; x++, inPtr += bytesPerPixel) { byte *offset = outputPtr + layoutConverter.GetOffset(x); *(T *)offset = *(T *)inPtr; } inPtr += inStrideGap; } } return(true); } bool _ = bytesPerPixel switch { 1 => Convert <byte>(dst, data), 2 => Convert <ushort>(dst, data), 4 => Convert <uint>(dst, data), 8 => Convert <ulong>(dst, data), 12 => Convert <Bpp12Pixel>(dst, data), 16 => Convert <Vector128 <byte> >(dst, data), _ => throw new NotSupportedException($"Unable to convert ${bytesPerPixel} bpp pixel format.") }; }
public static Span <byte> ConvertBlockLinearToLinear( int width, int height, int depth, int sliceDepth, int levels, int layers, int blockWidth, int blockHeight, int bytesPerPixel, int gobBlocksInY, int gobBlocksInZ, int gobBlocksInTileX, SizeInfo sizeInfo, ReadOnlySpan <byte> data) { int outSize = GetTextureSize( width, height, depth, levels, layers, blockWidth, blockHeight, bytesPerPixel); Span <byte> output = new byte[outSize]; int outOffs = 0; int mipGobBlocksInY = gobBlocksInY; int mipGobBlocksInZ = gobBlocksInZ; int gobWidth = (GobStride / bytesPerPixel) * gobBlocksInTileX; int gobHeight = gobBlocksInY * GobHeight; for (int level = 0; level < levels; level++) { int w = Math.Max(1, width >> level); int h = Math.Max(1, height >> level); int d = Math.Max(1, depth >> level); w = BitUtils.DivRoundUp(w, blockWidth); h = BitUtils.DivRoundUp(h, blockHeight); while (h <= (mipGobBlocksInY >> 1) * GobHeight && mipGobBlocksInY != 1) { mipGobBlocksInY >>= 1; } while (d <= (mipGobBlocksInZ >> 1) && mipGobBlocksInZ != 1) { mipGobBlocksInZ >>= 1; } int strideTrunc = BitUtils.AlignDown(w * bytesPerPixel, 16); int strideTrunc64 = BitUtils.AlignDown(w * bytesPerPixel, 64); int xStart = strideTrunc / bytesPerPixel; int stride = BitUtils.AlignUp(w * bytesPerPixel, HostStrideAlignment); int outStrideGap = stride - w * bytesPerPixel; int alignment = gobWidth; if (d < gobBlocksInZ || w <= gobWidth || h <= gobHeight) { alignment = GobStride / bytesPerPixel; } int wAligned = BitUtils.AlignUp(w, alignment); BlockLinearLayout layoutConverter = new BlockLinearLayout( wAligned, h, mipGobBlocksInY, mipGobBlocksInZ, bytesPerPixel); int sd = Math.Max(1, sliceDepth >> level); unsafe bool Convert <T>(Span <byte> output, ReadOnlySpan <byte> data) where T : unmanaged { fixed(byte *outputPtr = output, dataPtr = data) { byte *outPtr = outputPtr + outOffs; for (int layer = 0; layer < layers; layer++) { byte *inBaseOffset = dataPtr + (layer * sizeInfo.LayerSize + sizeInfo.GetMipOffset(level)); for (int z = 0; z < sd; z++) { layoutConverter.SetZ(z); for (int y = 0; y < h; y++) { layoutConverter.SetY(y); for (int x = 0; x < strideTrunc64; x += 64, outPtr += 64) { byte *offset = inBaseOffset + layoutConverter.GetOffsetWithLineOffset64(x); byte *offset2 = offset + 0x20; byte *offset3 = offset + 0x100; byte *offset4 = offset + 0x120; Vector128 <byte> value = *(Vector128 <byte> *)offset; Vector128 <byte> value2 = *(Vector128 <byte> *)offset2; Vector128 <byte> value3 = *(Vector128 <byte> *)offset3; Vector128 <byte> value4 = *(Vector128 <byte> *)offset4; *(Vector128 <byte> *)outPtr = value; *(Vector128 <byte> *)(outPtr + 16) = value2; *(Vector128 <byte> *)(outPtr + 32) = value3; *(Vector128 <byte> *)(outPtr + 48) = value4; } for (int x = strideTrunc64; x < strideTrunc; x += 16, outPtr += 16) { byte *offset = inBaseOffset + layoutConverter.GetOffsetWithLineOffset16(x); *(Vector128 <byte> *)outPtr = *(Vector128 <byte> *)offset; } for (int x = xStart; x < w; x++, outPtr += bytesPerPixel) { byte *offset = inBaseOffset + layoutConverter.GetOffset(x); *(T *)outPtr = *(T *)offset; } outPtr += outStrideGap; } } } outOffs += stride * h * d * layers; } return(true); } bool _ = bytesPerPixel switch { 1 => Convert <byte>(output, data), 2 => Convert <ushort>(output, data), 4 => Convert <uint>(output, data), 8 => Convert <ulong>(output, data), 12 => Convert <Bpp12Pixel>(output, data), 16 => Convert <Vector128 <byte> >(output, data), _ => throw new NotSupportedException($"Unable to convert ${bytesPerPixel} bpp pixel format.") }; } return(output); }
public static void Compress(BinaryWriter writer, long[] values, int index, int count, Helper helper) { writer.Write(VERSION); if (count == 0) { return; } long value = values[index]; CountCompression.Serialize(writer, (ulong)value); if (count == 1) { return; } Debug.Assert(count == helper.Count); if (!helper.IsReady) { helper.Prepare(); } index++; count--; int maxIndex = index + count - 1; helper.Serialize(writer); if (helper.Type == HelperType.Raw) { while (index <= maxIndex) { writer.Write(values[index++]); } return; } if (helper.Type == HelperType.OneStep) { return; } ulong maxDelta = helper.Delta; bool alwaysUseDelta = helper.AlwaysUseDelta; int bitCount = BitUtils.GetBitBounds(maxDelta); bool writeSign = helper.Type == HelperType.Delta; CommonArray common = new CommonArray(); int sizeBits = helper.SizeBits > 0 ? helper.SizeBits : (1 + 1 + 64) * (count - 1); common.ByteArray = new byte[(int)Math.Ceiling(sizeBits / 8.0)]; ulong[] data = common.UInt64Array; int bitIndex = 0; ulong delta; bool sign; //false - positive, true - negative for (; index <= maxIndex; index++) { long newValue = values[index]; if (newValue >= value) { sign = false; delta = (ulong)(newValue - value); } else { sign = true; delta = (ulong)(value - newValue); } if (alwaysUseDelta || delta <= maxDelta) { if (!alwaysUseDelta) { SetFlag(data, bitIndex /*, true*/); //use delta bitIndex++; } if (writeSign) { if (sign) { SetFlag(data, bitIndex /*, sign*/); } bitIndex++; } SetBits(data, bitIndex, delta, bitCount); bitIndex += bitCount; } else { //SetFlag(data, bitIndex, false); //don't use delta bitIndex++; SetValue(data, bitIndex, (ulong)newValue); bitIndex += 64; } value = newValue; } int bytesCount = (int)Math.Ceiling(bitIndex / 8.0); CountCompression.Serialize(writer, (ulong)bytesCount); writer.Write(common.ByteArray, 0, bytesCount); }
private static int Align4(int value) { return(BitUtils.AlignUp(value, 4)); }
public static int MiColsAlignedToSb(int nMis) { return(BitUtils.AlignPowerOfTwo(nMis, Constants.MiBlockSizeLog2)); }
/// <summary> /// Determines if a given texture is "safe" for upscaling from its info. /// Note that this is different from being compatible - this elilinates targets that would have detrimental effects when scaled. /// </summary> /// <param name="info">The texture info to check</param> /// <returns>True if safe</returns> public bool UpscaleSafeMode(TextureInfo info) { // While upscaling works for all targets defined by IsUpscaleCompatible, we additionally blacklist targets here that // may have undesirable results (upscaling blur textures) or simply waste GPU resources (upscaling texture atlas). if (info.Levels > 3) { // Textures with more than 3 levels are likely to be game textures, rather than render textures. // Small textures with full mips are likely to be removed by the next check. return(false); } if (info.Width < 8 || info.Height < 8) { // Discount textures with small dimensions. return(false); } if (!(info.FormatInfo.Format.IsDepthOrStencil() || info.FormatInfo.Components == 1)) { // Discount square textures that aren't depth-stencil like. (excludes game textures, cubemap faces, most 3D texture LUT, texture atlas) // Detect if the texture is possibly square. Widths may be aligned, so to remove the uncertainty we align both the width and height. int widthAlignment = (info.IsLinear ? 32 : 64) / info.FormatInfo.BytesPerPixel; bool possiblySquare = BitUtils.AlignUp(info.Width, widthAlignment) == BitUtils.AlignUp(info.Height, widthAlignment); if (possiblySquare) { return(false); } } int aspect = (int)Math.Round((info.Width / (float)info.Height) * 9); if (aspect == 16 && info.Height < 360) { // Targets that are roughly 16:9 can only be rescaled if they're equal to or above 360p. (excludes blur and bloom textures) return(false); } return(true); }
private KernelResult GetReceiveListAddress( PointerBufferDesc descriptor, Message message, uint recvListType, uint messageSizeInWords, ulong[] receiveList, ref uint dstOffset, out ulong address) { ulong recvListBufferAddress = address = 0; if (recvListType == 0) { return(KernelResult.OutOfResource); } else if (recvListType == 1 || recvListType == 2) { ulong recvListBaseAddr; ulong recvListEndAddr; if (recvListType == 1) { recvListBaseAddr = message.Address + messageSizeInWords * 4; recvListEndAddr = message.Address + message.Size; } else /* if (recvListType == 2) */ { ulong packed = receiveList[0]; recvListBaseAddr = packed & 0x7fffffffff; uint size = (uint)(packed >> 48); if (size == 0) { return(KernelResult.OutOfResource); } recvListEndAddr = recvListBaseAddr + size; } recvListBufferAddress = BitUtils.AlignUp(recvListBaseAddr + dstOffset, 0x10); ulong endAddress = recvListBufferAddress + descriptor.BufferSize; dstOffset = (uint)endAddress - (uint)recvListBaseAddr; if (recvListBufferAddress + descriptor.BufferSize <= recvListBufferAddress || recvListBufferAddress + descriptor.BufferSize > recvListEndAddr) { return(KernelResult.OutOfResource); } } else /* if (recvListType > 2) */ { if (descriptor.ReceiveIndex >= receiveList.Length) { return(KernelResult.OutOfResource); } ulong packed = receiveList[descriptor.ReceiveIndex]; recvListBufferAddress = packed & 0x7fffffffff; uint size = (uint)(packed >> 48); if (recvListBufferAddress == 0 || size == 0 || size < descriptor.BufferSize) { return(KernelResult.OutOfResource); } } address = recvListBufferAddress; return(KernelResult.Success); }
// GetWorkBufferSize(nn::audio::detail::AudioRendererParameterInternal) -> u64 public ResultCode GetAudioRendererWorkBufferSize(ServiceCtx context) { AudioRendererParameter parameters = GetAudioRendererParameter(context); if (AudioRendererCommon.CheckValidRevision(parameters)) { BehaviorInfo behaviorInfo = new BehaviorInfo(); behaviorInfo.SetUserLibRevision(parameters.Revision); long size; int totalMixCount = parameters.SubMixCount + 1; size = BitUtils.AlignUp(parameters.MixBufferCount * 4, AudioRendererConsts.BufferAlignment) + parameters.SubMixCount * 0x400 + totalMixCount * 0x940 + parameters.VoiceCount * 0x3F0 + BitUtils.AlignUp(totalMixCount * 8, 16) + BitUtils.AlignUp(parameters.VoiceCount * 8, 16) + BitUtils.AlignUp(((parameters.SinkCount + parameters.SubMixCount) * 0x3C0 + parameters.SampleCount * 4) * (parameters.MixBufferCount + 6), AudioRendererConsts.BufferAlignment) + (parameters.SinkCount + parameters.SubMixCount) * 0x2C0 + (parameters.EffectCount + parameters.VoiceCount * 4) * 0x30 + 0x50; if (behaviorInfo.IsSplitterSupported()) { size += BitUtils.AlignUp(NodeStates.GetWorkBufferSize(totalMixCount) + EdgeMatrix.GetWorkBufferSize(totalMixCount), 16); } size = parameters.SinkCount * 0x170 + (parameters.SinkCount + parameters.SubMixCount) * 0x280 + parameters.EffectCount * 0x4C0 + ((size + SplitterContext.CalcWorkBufferSize(behaviorInfo, parameters) + 0x30 * parameters.EffectCount + (4 * parameters.VoiceCount) + 0x8F) & ~0x3FL) + ((parameters.VoiceCount << 8) | 0x40); if (parameters.PerformanceManagerCount >= 1) { size += (PerformanceManager.GetRequiredBufferSizeForPerformanceMetricsPerFrame(behaviorInfo, parameters) * (parameters.PerformanceManagerCount + 1) + 0xFF) & ~0x3FL; } if (behaviorInfo.IsVariadicCommandBufferSizeSupported()) { size += CommandGenerator.CalculateCommandBufferSize(parameters) + 0x7E; } else { size += 0x1807E; } size = BitUtils.AlignUp(size, 0x1000); context.ResponseData.Write(size); Logger.PrintDebug(LogClass.ServiceAudio, $"WorkBufferSize is 0x{size:x16}."); return(ResultCode.Success); } else { context.ResponseData.Write(0L); Logger.PrintWarning(LogClass.ServiceAudio, $"Library Revision REV{AudioRendererCommon.GetRevisionVersion(parameters.Revision)} is not supported!"); return(ResultCode.UnsupportedRevision); } }
private KernelResult CopyToClient(KMemoryManager memoryManager, List <KBufferDescriptor> list) { foreach (KBufferDescriptor desc in list) { MemoryState stateMask; switch (desc.State) { case MemoryState.IpcBuffer0: stateMask = MemoryState.IpcSendAllowedType0; break; case MemoryState.IpcBuffer1: stateMask = MemoryState.IpcSendAllowedType1; break; case MemoryState.IpcBuffer3: stateMask = MemoryState.IpcSendAllowedType3; break; default: return(KernelResult.InvalidCombination); } MemoryAttribute attributeMask = MemoryAttribute.Borrowed | MemoryAttribute.Uncached; if (desc.State == MemoryState.IpcBuffer0) { attributeMask |= MemoryAttribute.DeviceMapped; } ulong clientAddrTruncated = BitUtils.AlignDown(desc.ClientAddress, KMemoryManager.PageSize); ulong clientAddrRounded = BitUtils.AlignUp(desc.ClientAddress, KMemoryManager.PageSize); // Check if address is not aligned, in this case we need to perform 2 copies. if (clientAddrTruncated != clientAddrRounded) { ulong copySize = clientAddrRounded - desc.ClientAddress; if (copySize > desc.Size) { copySize = desc.Size; } KernelResult result = memoryManager.CopyDataFromCurrentProcess( desc.ClientAddress, copySize, stateMask, stateMask, MemoryPermission.ReadAndWrite, attributeMask, MemoryAttribute.None, desc.ServerAddress); if (result != KernelResult.Success) { return(result); } } ulong clientEndAddr = desc.ClientAddress + desc.Size; ulong serverEndAddr = desc.ServerAddress + desc.Size; ulong clientEndAddrTruncated = BitUtils.AlignDown(clientEndAddr, KMemoryManager.PageSize); ulong clientEndAddrRounded = BitUtils.AlignUp(clientEndAddr, KMemoryManager.PageSize); ulong serverEndAddrTruncated = BitUtils.AlignDown(serverEndAddr, KMemoryManager.PageSize); if (clientEndAddrTruncated < clientEndAddrRounded && (clientAddrTruncated == clientAddrRounded || clientAddrTruncated < clientEndAddrTruncated)) { KernelResult result = memoryManager.CopyDataFromCurrentProcess( clientEndAddrTruncated, clientEndAddr - clientEndAddrTruncated, stateMask, stateMask, MemoryPermission.ReadAndWrite, attributeMask, MemoryAttribute.None, serverEndAddrTruncated); if (result != KernelResult.Success) { return(result); } } } return(KernelResult.Success); }
public ResultCode Initialize(ref AudioRendererConfiguration parameter, uint processHandle, CpuAddress workBuffer, ulong workBufferSize, int sessionId, ulong appletResourceId, IVirtualMemoryManager memoryManager) { if (!BehaviourContext.CheckValidRevision(parameter.Revision)) { return(ResultCode.OperationFailed); } if (GetWorkBufferSize(ref parameter) > workBufferSize) { return(ResultCode.WorkBufferTooSmall); } Debug.Assert(parameter.RenderingDevice == AudioRendererRenderingDevice.Dsp && parameter.ExecutionMode == AudioRendererExecutionMode.Auto); Logger.Info?.Print(LogClass.AudioRenderer, $"Initializing with REV{BehaviourContext.GetRevisionNumber(parameter.Revision)}"); _behaviourContext.SetUserRevision(parameter.Revision); _sampleRate = parameter.SampleRate; _sampleCount = parameter.SampleCount; _mixBufferCount = parameter.MixBufferCount; _voiceChannelCountMax = Constants.VoiceChannelCountMax; _upsamplerCount = parameter.SinkCount + parameter.SubMixBufferCount; _appletResourceId = appletResourceId; _memoryPoolCount = parameter.EffectCount + parameter.VoiceCount * Constants.VoiceWaveBufferCount; _executionMode = parameter.ExecutionMode; _sessionId = sessionId; MemoryManager = memoryManager; if (memoryManager is IRefCounted rc) { rc.IncrementReferenceCount(); } WorkBufferAllocator workBufferAllocator; _workBufferRegion = MemoryManager.GetWritableRegion(workBuffer, (int)workBufferSize); _workBufferRegion.Memory.Span.Fill(0); _workBufferMemoryPin = _workBufferRegion.Memory.Pin(); workBufferAllocator = new WorkBufferAllocator(_workBufferRegion.Memory); PoolMapper poolMapper = new PoolMapper(processHandle, false); poolMapper.InitializeSystemPool(ref _dspMemoryPoolState, workBuffer, workBufferSize); _mixBuffer = workBufferAllocator.Allocate <float>(_sampleCount * (_voiceChannelCountMax + _mixBufferCount), 0x10); if (_mixBuffer.IsEmpty) { return(ResultCode.WorkBufferTooSmall); } Memory <float> upSamplerWorkBuffer = workBufferAllocator.Allocate <float>(Constants.TargetSampleCount * (_voiceChannelCountMax + _mixBufferCount) * _upsamplerCount, 0x10); if (upSamplerWorkBuffer.IsEmpty) { return(ResultCode.WorkBufferTooSmall); } _depopBuffer = workBufferAllocator.Allocate <float>((ulong)BitUtils.AlignUp(parameter.MixBufferCount, Constants.BufferAlignment), Constants.BufferAlignment); if (_depopBuffer.IsEmpty) { return(ResultCode.WorkBufferTooSmall); } // Invalidate DSP cache on what was currently allocated with workBuffer. AudioProcessorMemoryManager.InvalidateDspCache(_dspMemoryPoolState.Translate(workBuffer, workBufferAllocator.Offset), workBufferAllocator.Offset); Debug.Assert((workBufferAllocator.Offset % Constants.BufferAlignment) == 0); Memory <VoiceState> voices = workBufferAllocator.Allocate <VoiceState>(parameter.VoiceCount, VoiceState.Alignment); if (voices.IsEmpty) { return(ResultCode.WorkBufferTooSmall); } foreach (ref VoiceState voice in voices.Span) { voice.Initialize(); } // A pain to handle as we can't have VoiceState*, use indices to be a bit more safe Memory <int> sortedVoices = workBufferAllocator.Allocate <int>(parameter.VoiceCount, 0x10); if (sortedVoices.IsEmpty) { return(ResultCode.WorkBufferTooSmall); } // Clear memory (use -1 as it's an invalid index) sortedVoices.Span.Fill(-1); Memory <VoiceChannelResource> voiceChannelResources = workBufferAllocator.Allocate <VoiceChannelResource>(parameter.VoiceCount, VoiceChannelResource.Alignment); if (voiceChannelResources.IsEmpty) { return(ResultCode.WorkBufferTooSmall); } for (uint id = 0; id < voiceChannelResources.Length; id++) { ref VoiceChannelResource voiceChannelResource = ref voiceChannelResources.Span[(int)id]; voiceChannelResource.Id = id; voiceChannelResource.IsUsed = false; }
public static byte[] DecodeBC3(ReadOnlySpan <byte> data, int width, int height, int depth, int levels, int layers) { int size = 0; for (int l = 0; l < levels; l++) { size += Math.Max(1, width >> l) * Math.Max(1, height >> l) * Math.Max(1, depth >> l) * layers * 4; } byte[] output = new byte[size]; Span <byte> tile = stackalloc byte[BlockWidth * BlockHeight * 4]; Span <byte> rPal = stackalloc byte[8]; Span <uint> tileAsUint = MemoryMarshal.Cast <byte, uint>(tile); Span <uint> outputAsUint = MemoryMarshal.Cast <byte, uint>(output); Span <Vector128 <byte> > tileAsVector128 = MemoryMarshal.Cast <byte, Vector128 <byte> >(tile); Span <Vector128 <byte> > outputLine0 = default; Span <Vector128 <byte> > outputLine1 = default; Span <Vector128 <byte> > outputLine2 = default; Span <Vector128 <byte> > outputLine3 = default; int imageBaseOOffs = 0; for (int l = 0; l < levels; l++) { int w = BitUtils.DivRoundUp(width, BlockWidth); int h = BitUtils.DivRoundUp(height, BlockHeight); for (int l2 = 0; l2 < layers; l2++) { for (int z = 0; z < depth; z++) { for (int y = 0; y < h; y++) { int baseY = y * BlockHeight; int copyHeight = Math.Min(BlockHeight, height - baseY); int lineBaseOOffs = imageBaseOOffs + baseY * width; if (copyHeight == 4) { outputLine0 = MemoryMarshal.Cast <uint, Vector128 <byte> >(outputAsUint.Slice(lineBaseOOffs)); outputLine1 = MemoryMarshal.Cast <uint, Vector128 <byte> >(outputAsUint.Slice(lineBaseOOffs + width)); outputLine2 = MemoryMarshal.Cast <uint, Vector128 <byte> >(outputAsUint.Slice(lineBaseOOffs + width * 2)); outputLine3 = MemoryMarshal.Cast <uint, Vector128 <byte> >(outputAsUint.Slice(lineBaseOOffs + width * 3)); } for (int x = 0; x < w; x++) { int baseX = x * BlockWidth; int copyWidth = Math.Min(BlockWidth, width - baseX); BC23DecodeTileRgb(tile, data.Slice(8)); ulong block = BinaryPrimitives.ReadUInt64LittleEndian(data); rPal[0] = (byte)block; rPal[1] = (byte)(block >> 8); BCnLerpAlphaUnorm(rPal); BCnDecodeTileAlphaRgba(tile, rPal, block >> 16); if ((copyWidth | copyHeight) == 4) { outputLine0[x] = tileAsVector128[0]; outputLine1[x] = tileAsVector128[1]; outputLine2[x] = tileAsVector128[2]; outputLine3[x] = tileAsVector128[3]; } else { int pixelBaseOOffs = lineBaseOOffs + baseX; for (int tY = 0; tY < copyHeight; tY++) { tileAsUint.Slice(tY * 4, copyWidth).CopyTo(outputAsUint.Slice(pixelBaseOOffs + width * tY, copyWidth)); } } data = data.Slice(16); } } imageBaseOOffs += width * height; } } width = Math.Max(1, width >> 1); height = Math.Max(1, height >> 1); depth = Math.Max(1, depth >> 1); } return(output); }
public static float _vh2f_1(uint a) => HalfFloat.ToFloat((int)BitUtils.Extract(a, 16, 16));
public static byte[] DecodeBC4(ReadOnlySpan <byte> data, int width, int height, int depth, int levels, int layers, bool signed) { int size = 0; for (int l = 0; l < levels; l++) { size += BitUtils.AlignUp(Math.Max(1, width >> l), 4) * Math.Max(1, height >> l) * Math.Max(1, depth >> l) * layers; } // Backends currently expect a stride alignment of 4 bytes, so output width must be aligned. int alignedWidth = BitUtils.AlignUp(width, 4); byte[] output = new byte[size]; Span <byte> outputSpan = new Span <byte>(output); ReadOnlySpan <ulong> data64 = MemoryMarshal.Cast <byte, ulong>(data); Span <byte> tile = stackalloc byte[BlockWidth * BlockHeight]; Span <byte> rPal = stackalloc byte[8]; Span <uint> tileAsUint = MemoryMarshal.Cast <byte, uint>(tile); Span <uint> outputLine0 = default; Span <uint> outputLine1 = default; Span <uint> outputLine2 = default; Span <uint> outputLine3 = default; int imageBaseOOffs = 0; for (int l = 0; l < levels; l++) { int w = BitUtils.DivRoundUp(width, BlockWidth); int h = BitUtils.DivRoundUp(height, BlockHeight); for (int l2 = 0; l2 < layers; l2++) { for (int z = 0; z < depth; z++) { for (int y = 0; y < h; y++) { int baseY = y * BlockHeight; int copyHeight = Math.Min(BlockHeight, height - baseY); int lineBaseOOffs = imageBaseOOffs + baseY * alignedWidth; if (copyHeight == 4) { outputLine0 = MemoryMarshal.Cast <byte, uint>(outputSpan.Slice(lineBaseOOffs)); outputLine1 = MemoryMarshal.Cast <byte, uint>(outputSpan.Slice(lineBaseOOffs + alignedWidth)); outputLine2 = MemoryMarshal.Cast <byte, uint>(outputSpan.Slice(lineBaseOOffs + alignedWidth * 2)); outputLine3 = MemoryMarshal.Cast <byte, uint>(outputSpan.Slice(lineBaseOOffs + alignedWidth * 3)); } for (int x = 0; x < w; x++) { int baseX = x * BlockWidth; int copyWidth = Math.Min(BlockWidth, width - baseX); ulong block = data64[0]; rPal[0] = (byte)block; rPal[1] = (byte)(block >> 8); if (signed) { BCnLerpAlphaSnorm(rPal); } else { BCnLerpAlphaUnorm(rPal); } BCnDecodeTileAlpha(tile, rPal, block >> 16); if ((copyWidth | copyHeight) == 4) { outputLine0[x] = tileAsUint[0]; outputLine1[x] = tileAsUint[1]; outputLine2[x] = tileAsUint[2]; outputLine3[x] = tileAsUint[3]; } else { int pixelBaseOOffs = lineBaseOOffs + baseX; for (int tY = 0; tY < copyHeight; tY++) { tile.Slice(tY * 4, copyWidth).CopyTo(outputSpan.Slice(pixelBaseOOffs + alignedWidth * tY, copyWidth)); } } data64 = data64.Slice(1); } } imageBaseOOffs += alignedWidth * height; } } width = Math.Max(1, width >> 1); height = Math.Max(1, height >> 1); depth = Math.Max(1, depth >> 1); alignedWidth = BitUtils.AlignUp(width, 4); } return(output); }
public static uint _ins_impl(uint initialData, uint data, int pos, int size) => BitUtils.Insert(initialData, pos, size, data);
public static byte[] DecodeBC5(ReadOnlySpan <byte> data, int width, int height, int depth, int levels, int layers, bool signed) { int size = 0; for (int l = 0; l < levels; l++) { size += BitUtils.AlignUp(Math.Max(1, width >> l), 2) * Math.Max(1, height >> l) * Math.Max(1, depth >> l) * layers * 2; } // Backends currently expect a stride alignment of 4 bytes, so output width must be aligned. int alignedWidth = BitUtils.AlignUp(width, 2); byte[] output = new byte[size]; ReadOnlySpan <ulong> data64 = MemoryMarshal.Cast <byte, ulong>(data); Span <byte> rTile = stackalloc byte[BlockWidth * BlockHeight * 2]; Span <byte> gTile = stackalloc byte[BlockWidth * BlockHeight * 2]; Span <byte> rPal = stackalloc byte[8]; Span <byte> gPal = stackalloc byte[8]; Span <ushort> outputAsUshort = MemoryMarshal.Cast <byte, ushort>(output); Span <uint> rTileAsUint = MemoryMarshal.Cast <byte, uint>(rTile); Span <uint> gTileAsUint = MemoryMarshal.Cast <byte, uint>(gTile); Span <ulong> outputLine0 = default; Span <ulong> outputLine1 = default; Span <ulong> outputLine2 = default; Span <ulong> outputLine3 = default; int imageBaseOOffs = 0; for (int l = 0; l < levels; l++) { int w = BitUtils.DivRoundUp(width, BlockWidth); int h = BitUtils.DivRoundUp(height, BlockHeight); for (int l2 = 0; l2 < layers; l2++) { for (int z = 0; z < depth; z++) { for (int y = 0; y < h; y++) { int baseY = y * BlockHeight; int copyHeight = Math.Min(BlockHeight, height - baseY); int lineBaseOOffs = imageBaseOOffs + baseY * alignedWidth; if (copyHeight == 4) { outputLine0 = MemoryMarshal.Cast <ushort, ulong>(outputAsUshort.Slice(lineBaseOOffs)); outputLine1 = MemoryMarshal.Cast <ushort, ulong>(outputAsUshort.Slice(lineBaseOOffs + alignedWidth)); outputLine2 = MemoryMarshal.Cast <ushort, ulong>(outputAsUshort.Slice(lineBaseOOffs + alignedWidth * 2)); outputLine3 = MemoryMarshal.Cast <ushort, ulong>(outputAsUshort.Slice(lineBaseOOffs + alignedWidth * 3)); } for (int x = 0; x < w; x++) { int baseX = x * BlockWidth; int copyWidth = Math.Min(BlockWidth, width - baseX); ulong blockL = data64[0]; ulong blockH = data64[1]; rPal[0] = (byte)blockL; rPal[1] = (byte)(blockL >> 8); gPal[0] = (byte)blockH; gPal[1] = (byte)(blockH >> 8); if (signed) { BCnLerpAlphaSnorm(rPal); BCnLerpAlphaSnorm(gPal); } else { BCnLerpAlphaUnorm(rPal); BCnLerpAlphaUnorm(gPal); } BCnDecodeTileAlpha(rTile, rPal, blockL >> 16); BCnDecodeTileAlpha(gTile, gPal, blockH >> 16); if ((copyWidth | copyHeight) == 4) { outputLine0[x] = InterleaveBytes(rTileAsUint[0], gTileAsUint[0]); outputLine1[x] = InterleaveBytes(rTileAsUint[1], gTileAsUint[1]); outputLine2[x] = InterleaveBytes(rTileAsUint[2], gTileAsUint[2]); outputLine3[x] = InterleaveBytes(rTileAsUint[3], gTileAsUint[3]); } else { int pixelBaseOOffs = lineBaseOOffs + baseX; for (int tY = 0; tY < copyHeight; tY++) { int line = pixelBaseOOffs + alignedWidth * tY; for (int tX = 0; tX < copyWidth; tX++) { int texel = tY * BlockWidth + tX; outputAsUshort[line + tX] = (ushort)(rTile[texel] | (gTile[texel] << 8)); } } } data64 = data64.Slice(2); } } imageBaseOOffs += alignedWidth * height; } } width = Math.Max(1, width >> 1); height = Math.Max(1, height >> 1); depth = Math.Max(1, depth >> 1); alignedWidth = BitUtils.AlignUp(width, 2); } return(output); }
/// <summary> /// Get the required work buffer size memory needed for the <see cref="EdgeMatrix"/>. /// </summary> /// <param name="nodeCount">The count of nodes.</param> /// <returns>The size required for the given <paramref name="nodeCount"/>.</returns> public static int GetWorkBufferSize(int nodeCount) { int size = BitUtils.AlignUp(nodeCount * nodeCount, RendererConstants.BufferAlignment); return(size / Unsafe.SizeOf <byte>()); }
public bool IsKindOf(CharInfo c) { return(BitUtils.CompareAnd(this.bits, c.bits, 0, 18)); }
public KernelResult Start(int mainThreadPriority, ulong stackSize) { lock (_processLock) { if (State > ProcessState.CreatedAttached) { return(KernelResult.InvalidState); } if (ResourceLimit != null && !ResourceLimit.Reserve(LimitableResource.Thread, 1)) { return(KernelResult.ResLimitExceeded); } KResourceLimit threadResourceLimit = ResourceLimit; KResourceLimit memoryResourceLimit = null; if (_mainThreadStackSize != 0) { throw new InvalidOperationException("Trying to start a process with a invalid state!"); } ulong stackSizeRounded = BitUtils.AlignUp(stackSize, KPageTableBase.PageSize); ulong neededSize = stackSizeRounded + _imageSize; // Check if the needed size for the code and the stack will fit on the // memory usage capacity of this Process. Also check for possible overflow // on the above addition. if (neededSize > _memoryUsageCapacity || neededSize < stackSizeRounded) { threadResourceLimit?.Release(LimitableResource.Thread, 1); return(KernelResult.OutOfMemory); } if (stackSizeRounded != 0 && ResourceLimit != null) { memoryResourceLimit = ResourceLimit; if (!memoryResourceLimit.Reserve(LimitableResource.Memory, stackSizeRounded)) { threadResourceLimit?.Release(LimitableResource.Thread, 1); return(KernelResult.ResLimitExceeded); } } KernelResult result; KThread mainThread = null; ulong stackTop = 0; void CleanUpForError() { HandleTable.Destroy(); mainThread?.DecrementReferenceCount(); if (_mainThreadStackSize != 0) { ulong stackBottom = stackTop - _mainThreadStackSize; ulong stackPagesCount = _mainThreadStackSize / KPageTableBase.PageSize; MemoryManager.UnmapForKernel(stackBottom, stackPagesCount, MemoryState.Stack); _mainThreadStackSize = 0; } memoryResourceLimit?.Release(LimitableResource.Memory, stackSizeRounded); threadResourceLimit?.Release(LimitableResource.Thread, 1); } if (stackSizeRounded != 0) { ulong stackPagesCount = stackSizeRounded / KPageTableBase.PageSize; ulong regionStart = MemoryManager.StackRegionStart; ulong regionSize = MemoryManager.StackRegionEnd - regionStart; ulong regionPagesCount = regionSize / KPageTableBase.PageSize; result = MemoryManager.MapPages( stackPagesCount, KPageTableBase.PageSize, 0, false, regionStart, regionPagesCount, MemoryState.Stack, KMemoryPermission.ReadAndWrite, out ulong stackBottom); if (result != KernelResult.Success) { CleanUpForError(); return(result); } _mainThreadStackSize += stackSizeRounded; stackTop = stackBottom + stackSizeRounded; } ulong heapCapacity = _memoryUsageCapacity - _mainThreadStackSize - _imageSize; result = MemoryManager.SetHeapCapacity(heapCapacity); if (result != KernelResult.Success) { CleanUpForError(); return(result); } HandleTable = new KHandleTable(KernelContext); result = HandleTable.Initialize(Capabilities.HandleTableSize); if (result != KernelResult.Success) { CleanUpForError(); return(result); } mainThread = new KThread(KernelContext); result = mainThread.Initialize( _entrypoint, 0, stackTop, mainThreadPriority, DefaultCpuCore, this, ThreadType.User, _customThreadStart); if (result != KernelResult.Success) { CleanUpForError(); return(result); } result = HandleTable.GenerateHandle(mainThread, out int mainThreadHandle); if (result != KernelResult.Success) { CleanUpForError(); return(result); } mainThread.SetEntryArguments(0, mainThreadHandle); ProcessState oldState = State; ProcessState newState = State != ProcessState.Created ? ProcessState.Attached : ProcessState.Started; SetState(newState); result = mainThread.Start(); if (result != KernelResult.Success) { SetState(oldState); CleanUpForError(); } if (result == KernelResult.Success) { mainThread.IncrementReferenceCount(); } mainThread.DecrementReferenceCount(); return(result); } }
/// <summary> /// Adjusts the size of the texture information for a given mipmap level, /// based on the size of a parent texture. /// </summary> /// <param name="parent">The parent texture</param> /// <param name="info">The texture information to be adjusted</param> /// <param name="firstLevel">The first level of the texture view</param> /// <returns>The adjusted texture information with the new size</returns> private static TextureInfo AdjustSizes(Texture parent, TextureInfo info, int firstLevel) { // When the texture is used as view of another texture, we must // ensure that the sizes are valid, otherwise data uploads would fail // (and the size wouldn't match the real size used on the host API). // Given a parent texture from where the view is created, we have the // following rules: // - The view size must be equal to the parent size, divided by (2 ^ l), // where l is the first mipmap level of the view. The division result must // be rounded down, and the result must be clamped to 1. // - If the parent format is compressed, and the view format isn't, the // view size is calculated as above, but the width and height of the // view must be also divided by the compressed format block width and height. // - If the parent format is not compressed, and the view is, the view // size is calculated as described on the first point, but the width and height // of the view must be also multiplied by the block width and height. int width = Math.Max(1, parent.Info.Width >> firstLevel); int height = Math.Max(1, parent.Info.Height >> firstLevel); if (parent.Info.FormatInfo.IsCompressed && !info.FormatInfo.IsCompressed) { width = BitUtils.DivRoundUp(width, parent.Info.FormatInfo.BlockWidth); height = BitUtils.DivRoundUp(height, parent.Info.FormatInfo.BlockHeight); } else if (!parent.Info.FormatInfo.IsCompressed && info.FormatInfo.IsCompressed) { width *= info.FormatInfo.BlockWidth; height *= info.FormatInfo.BlockHeight; } int depthOrLayers; if (info.Target == Target.Texture3D) { depthOrLayers = Math.Max(1, parent.Info.DepthOrLayers >> firstLevel); } else { depthOrLayers = info.DepthOrLayers; } return(new TextureInfo( info.GpuAddress, width, height, depthOrLayers, info.Levels, info.SamplesInX, info.SamplesInY, info.Stride, info.IsLinear, info.GobBlocksInY, info.GobBlocksInZ, info.GobBlocksInTileX, info.Target, info.FormatInfo, info.DepthStencilMode, info.SwizzleR, info.SwizzleG, info.SwizzleB, info.SwizzleA)); }
public static bool LoadKernelInitalProcess(Horizon system, KernelInitialProcess kip) { int endOffset = kip.DataOffset + kip.Data.Length; if (kip.BssSize != 0) { endOffset = kip.BssOffset + kip.BssSize; } int codeSize = BitUtils.AlignUp(kip.TextOffset + endOffset, KMemoryManager.PageSize); int codePagesCount = codeSize / KMemoryManager.PageSize; ulong codeBaseAddress = kip.Addr39Bits ? 0x8000000UL : 0x200000UL; ulong codeAddress = codeBaseAddress + (ulong)kip.TextOffset; int mmuFlags = 0; if (AslrEnabled) { // TODO: Randomization. mmuFlags |= 0x20; } if (kip.Addr39Bits) { mmuFlags |= (int)AddressSpaceType.Addr39Bits << 1; } if (kip.Is64Bits) { mmuFlags |= 1; } ProcessCreationInfo creationInfo = new ProcessCreationInfo( kip.Name, kip.ProcessCategory, kip.TitleId, codeAddress, codePagesCount, mmuFlags, 0, 0); MemoryRegion memoryRegion = kip.IsService ? MemoryRegion.Service : MemoryRegion.Application; KMemoryRegionManager region = system.MemoryRegions[(int)memoryRegion]; KernelResult result = region.AllocatePages((ulong)codePagesCount, false, out KPageList pageList); if (result != KernelResult.Success) { Logger.PrintError(LogClass.Loader, $"Process initialization returned error \"{result}\"."); return(false); } KProcess process = new KProcess(system); result = process.InitializeKip( creationInfo, kip.Capabilities, pageList, system.ResourceLimit, memoryRegion); if (result != KernelResult.Success) { Logger.PrintError(LogClass.Loader, $"Process initialization returned error \"{result}\"."); return(false); } result = LoadIntoMemory(process, kip, codeBaseAddress); if (result != KernelResult.Success) { Logger.PrintError(LogClass.Loader, $"Process initialization returned error \"{result}\"."); return(false); } process.DefaultCpuCore = kip.DefaultProcessorId; result = process.Start(kip.MainThreadPriority, (ulong)kip.MainThreadStackSize); if (result != KernelResult.Success) { Logger.PrintError(LogClass.Loader, $"Process start returned error \"{result}\"."); return(false); } system.Processes.Add(process.Pid, process); return(true); }
private KernelResult ParseCapability(int cap, ref int mask0, ref int mask1, KMemoryManager memoryManager) { int code = (cap + 1) & ~cap; if (code == 1) { return(KernelResult.InvalidCapability); } else if (code == 0) { return(KernelResult.Success); } int codeMask = 1 << (32 - BitUtils.CountLeadingZeros32(code + 1)); //Check if the property was already set. if (((mask0 & codeMask) & 0x1e008) != 0) { return(KernelResult.InvalidCombination); } mask0 |= codeMask; switch (code) { case 8: { if (AllowedCpuCoresMask != 0 || AllowedThreadPriosMask != 0) { return(KernelResult.InvalidCapability); } int lowestCpuCore = (cap >> 16) & 0xff; int highestCpuCore = (cap >> 24) & 0xff; if (lowestCpuCore > highestCpuCore) { return(KernelResult.InvalidCombination); } int highestThreadPrio = (cap >> 4) & 0x3f; int lowestThreadPrio = (cap >> 10) & 0x3f; if (lowestThreadPrio > highestThreadPrio) { return(KernelResult.InvalidCombination); } if (highestCpuCore >= KScheduler.CpuCoresCount) { return(KernelResult.InvalidCpuCore); } AllowedCpuCoresMask = GetMaskFromMinMax(lowestCpuCore, highestCpuCore); AllowedThreadPriosMask = GetMaskFromMinMax(lowestThreadPrio, highestThreadPrio); break; } case 0x10: { int slot = (cap >> 29) & 7; int svcSlotMask = 1 << slot; if ((mask1 & svcSlotMask) != 0) { return(KernelResult.InvalidCombination); } mask1 |= svcSlotMask; int svcMask = (cap >> 5) & 0xffffff; int baseSvc = slot * 24; for (int index = 0; index < 24; index++) { if (((svcMask >> index) & 1) == 0) { continue; } int svcId = baseSvc + index; if (svcId > 0x7f) { return(KernelResult.MaximumExceeded); } SvcAccessMask[svcId / 8] |= (byte)(1 << (svcId & 7)); } break; } case 0x80: { long address = ((long)(uint)cap << 4) & 0xffffff000; memoryManager.MapIoMemory(address, KMemoryManager.PageSize, MemoryPermission.ReadAndWrite); break; } case 0x800: { //TODO: GIC distributor check. int irq0 = (cap >> 12) & 0x3ff; int irq1 = (cap >> 22) & 0x3ff; if (irq0 != 0x3ff) { IrqAccessMask[irq0 / 8] |= (byte)(1 << (irq0 & 7)); } if (irq1 != 0x3ff) { IrqAccessMask[irq1 / 8] |= (byte)(1 << (irq1 & 7)); } break; } case 0x2000: { int applicationType = cap >> 14; if ((uint)applicationType > 7) { return(KernelResult.ReservedValue); } ApplicationType = applicationType; break; } case 0x4000: { //Note: This check is bugged on kernel too, we are just replicating the bug here. if ((KernelReleaseVersion >> 17) != 0 || cap < 0x80000) { return(KernelResult.ReservedValue); } KernelReleaseVersion = cap; break; } case 0x8000: { int handleTableSize = cap >> 26; if ((uint)handleTableSize > 0x3ff) { return(KernelResult.ReservedValue); } HandleTableSize = handleTableSize; break; } case 0x10000: { int debuggingFlags = cap >> 19; if ((uint)debuggingFlags > 3) { return(KernelResult.ReservedValue); } DebuggingFlags &= ~3; DebuggingFlags |= debuggingFlags; break; } default: return(KernelResult.InvalidCapability); } return(KernelResult.Success); }