示例#1
0
 public void make_intptr()
 {
     Assert.AreEqual(BitUtils.MakeIntPtr(0x1234, 0x5678), (IntPtr)0x56781234U);
     Assert.AreEqual(BitUtils.MakeIntPtr(0x1234, 0x8678), (IntPtr) unchecked ((int)0x86781234));
 }
示例#2
0
        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");
            }
        }
示例#3
0
        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);
        }
示例#4
0
 public static uint _ext_impl(uint data, int pos, int size) => BitUtils.Extract(data, pos, size);
示例#5
0
        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));
        }
示例#6
0
        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);
                }
            }
        }
示例#7
0
        public OpCodeSimdShImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
        {
            Imm = (opCode >> 16) & 0x7f;

            Size = BitUtils.HighestBitSetNibble(Imm >> 3);
        }
示例#8
0
 public void ThrowsOnInvalidCharacter()
 {
     Assert.Throws <FormatException>(() => BitUtils.FromHexString("zzzz"))
     .WithMessage(String.Format(CoreResources.Input_Not_Valid_Hex_String, "zzzz"));
 }
示例#9
0
        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");
            }
        }
示例#10
0
        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.")
            };
        }
示例#11
0
        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);
        }
示例#12
0
        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));
 }
示例#14
0
 public static int MiColsAlignedToSb(int nMis)
 {
     return(BitUtils.AlignPowerOfTwo(nMis, Constants.MiBlockSizeLog2));
 }
示例#15
0
        /// <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);
        }
示例#16
0
        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);
        }
示例#17
0
        // 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);
            }
        }
示例#18
0
        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);
        }
示例#19
0
        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;
            }
示例#20
0
        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);
        }
示例#21
0
 public static float _vh2f_1(uint a) => HalfFloat.ToFloat((int)BitUtils.Extract(a, 16, 16));
示例#22
0
        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);
        }
示例#23
0
 public static uint _ins_impl(uint initialData, uint data, int pos, int size) =>
 BitUtils.Insert(initialData, pos, size, data);
示例#24
0
        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);
        }
示例#25
0
        /// <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>());
        }
示例#26
0
 public bool IsKindOf(CharInfo c)
 {
     return(BitUtils.CompareAnd(this.bits, c.bits, 0, 18));
 }
示例#27
0
        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);
            }
        }
示例#28
0
        /// <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));
        }
示例#29
0
        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);
        }
示例#30
0
        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);
        }