Example #1
0
        public ResultCode UpdateMemoryPools(Span <MemoryPoolState> memoryPools)
        {
            PoolMapper mapper = new PoolMapper(_processHandle, _behaviourContext.IsMemoryPoolForceMappingEnabled());

            if (memoryPools.Length * Unsafe.SizeOf <MemoryPoolInParameter>() != _inputHeader.MemoryPoolsSize)
            {
                return(ResultCode.InvalidUpdateInfo);
            }

            foreach (ref MemoryPoolState memoryPool in memoryPools)
            {
                MemoryPoolInParameter parameter = SpanIOHelper.Read <MemoryPoolInParameter>(ref _input);

                ref MemoryPoolOutStatus outStatus = ref SpanIOHelper.GetWriteRef <MemoryPoolOutStatus>(ref _output)[0];

                PoolMapper.UpdateResult updateResult = mapper.Update(ref memoryPool, ref parameter, ref outStatus);

                if (updateResult != PoolMapper.UpdateResult.Success &&
                    updateResult != PoolMapper.UpdateResult.MapError &&
                    updateResult != PoolMapper.UpdateResult.UnmapError)
                {
                    if (updateResult != PoolMapper.UpdateResult.InvalidParameter)
                    {
                        throw new InvalidOperationException($"{updateResult}");
                    }

                    return(ResultCode.InvalidUpdateInfo);
                }
            }
Example #2
0
        public void TestGetProcessHandle()
        {
            PoolMapper      poolMapper    = new PoolMapper(DummyProcessHandle, true);
            MemoryPoolState memoryPoolDsp = MemoryPoolState.Create(MemoryPoolState.LocationType.Dsp);
            MemoryPoolState memoryPoolCpu = MemoryPoolState.Create(MemoryPoolState.LocationType.Cpu);

            Assert.AreEqual(0xFFFF8001, poolMapper.GetProcessHandle(ref memoryPoolCpu));
            Assert.AreEqual(DummyProcessHandle, poolMapper.GetProcessHandle(ref memoryPoolDsp));
        }
Example #3
0
 /// <summary>
 /// Force unmap all the work buffers.
 /// </summary>
 /// <param name="mapper">The mapper to use.</param>
 public void ForceUnmapBuffers(PoolMapper mapper)
 {
     foreach (ref AddressInfo info in WorkBuffers.AsSpan())
     {
         if (info.GetReference(false) != 0)
         {
             mapper.ForceUnmap(ref info);
         }
     }
 }
Example #4
0
        internal static Pool GetPool(short id)
        {
            const string spName = "GetPool";

            using (var conn = new SqlConnection(cs))
            {
                conn.Open();
                using (var r = conn.ExecuteReader(spName, id, commandType: CommandType.StoredProcedure))
                {
                    var mapper = new PoolMapper();
                    var result = mapper.Map(r);
                    return(result.FirstOrDefault());
                }
            }
        }
Example #5
0
        public void TestInitializeSystemPool()
        {
            PoolMapper      poolMapper    = new PoolMapper(DummyProcessHandle, true);
            MemoryPoolState memoryPoolDsp = MemoryPoolState.Create(MemoryPoolState.LocationType.Dsp);
            MemoryPoolState memoryPoolCpu = MemoryPoolState.Create(MemoryPoolState.LocationType.Cpu);

            const CpuAddress CpuAddress = 0x20000;
            const DspAddress DspAddress = CpuAddress; // TODO: DSP LLE
            const ulong      CpuSize    = 0x1000;

            Assert.IsFalse(poolMapper.InitializeSystemPool(ref memoryPoolCpu, CpuAddress, CpuSize));
            Assert.IsTrue(poolMapper.InitializeSystemPool(ref memoryPoolDsp, CpuAddress, CpuSize));

            Assert.AreEqual(CpuAddress, memoryPoolDsp.CpuAddress);
            Assert.AreEqual(CpuSize, memoryPoolDsp.Size);
            Assert.AreEqual(DspAddress, memoryPoolDsp.DspAddress);
        }
Example #6
0
        public void TestMappings()
        {
            PoolMapper      poolMapper    = new PoolMapper(DummyProcessHandle, true);
            MemoryPoolState memoryPoolDsp = MemoryPoolState.Create(MemoryPoolState.LocationType.Dsp);
            MemoryPoolState memoryPoolCpu = MemoryPoolState.Create(MemoryPoolState.LocationType.Cpu);

            const CpuAddress CpuAddress = 0x20000;
            const DspAddress DspAddress = CpuAddress; // TODO: DSP LLE
            const ulong      CpuSize    = 0x1000;

            memoryPoolDsp.SetCpuAddress(CpuAddress, CpuSize);
            memoryPoolCpu.SetCpuAddress(CpuAddress, CpuSize);

            Assert.AreEqual(DspAddress, poolMapper.Map(ref memoryPoolCpu));
            Assert.AreEqual(DspAddress, poolMapper.Map(ref memoryPoolDsp));
            Assert.AreEqual(DspAddress, memoryPoolDsp.DspAddress);
            Assert.IsTrue(poolMapper.Unmap(ref memoryPoolCpu));

            memoryPoolDsp.IsUsed = true;
            Assert.IsFalse(poolMapper.Unmap(ref memoryPoolDsp));
            memoryPoolDsp.IsUsed = false;
            Assert.IsTrue(poolMapper.Unmap(ref memoryPoolDsp));
        }
Example #7
0
 public override void Update(out BehaviourParameter.ErrorInfo updateErrorInfo, ref EffectInParameterVersion2 parameter, PoolMapper mapper)
 {
     Update(out updateErrorInfo, ref parameter, mapper);
 }
Example #8
0
        /// <summary>
        /// Update the internal state from a user parameter.
        /// </summary>
        /// <param name="updateErrorInfo">The possible <see cref="ErrorInfo"/> that was generated.</param>
        /// <param name="parameter">The user parameter.</param>
        /// <param name="mapper">The mapper to use.</param>
        public virtual void Update(out ErrorInfo updateErrorInfo, ref EffectInParameter parameter, PoolMapper mapper)
        {
            Debug.Assert(IsTypeValid(ref parameter));

            updateErrorInfo = new ErrorInfo();
        }
Example #9
0
        public void Update <T>(out BehaviourParameter.ErrorInfo updateErrorInfo, ref T parameter, PoolMapper mapper) where T : unmanaged, IEffectInParameter
        {
            Debug.Assert(IsTypeValid(ref parameter));

            UpdateParameterBase(ref parameter);

            Parameter = MemoryMarshal.Cast <byte, AuxiliaryBufferParameter>(parameter.SpecificData)[0];
            IsEnabled = parameter.IsEnabled;

            updateErrorInfo = new BehaviourParameter.ErrorInfo();

            if (BufferUnmapped || parameter.IsNew)
            {
                ulong bufferSize = (ulong)Unsafe.SizeOf <int>() * Parameter.BufferStorageSize + (ulong)Unsafe.SizeOf <AuxiliaryBufferHeader>();

                bool sendBufferUnmapped   = !mapper.TryAttachBuffer(out updateErrorInfo, ref WorkBuffers[0], Parameter.SendBufferInfoAddress, bufferSize);
                bool returnBufferUnmapped = !mapper.TryAttachBuffer(out updateErrorInfo, ref WorkBuffers[1], Parameter.ReturnBufferInfoAddress, bufferSize);

                BufferUnmapped = sendBufferUnmapped && returnBufferUnmapped;

                if (!BufferUnmapped)
                {
                    DspAddress sendDspAddress   = WorkBuffers[0].GetReference(false);
                    DspAddress returnDspAddress = WorkBuffers[1].GetReference(false);

                    State.SendBufferInfo     = sendDspAddress + (uint)Unsafe.SizeOf <AuxiliaryBufferInfo>();
                    State.SendBufferInfoBase = sendDspAddress + (uint)Unsafe.SizeOf <AuxiliaryBufferHeader>();

                    State.ReturnBufferInfo     = returnDspAddress + (uint)Unsafe.SizeOf <AuxiliaryBufferInfo>();
                    State.ReturnBufferInfoBase = returnDspAddress + (uint)Unsafe.SizeOf <AuxiliaryBufferHeader>();
                }
            }
        }
Example #10
0
        public override void Update(out BehaviourParameter.ErrorInfo errorInfo, ref SinkInParameter parameter, ref SinkOutStatus outStatus, PoolMapper mapper)
        {
            errorInfo = new BehaviourParameter.ErrorInfo();
            outStatus = new SinkOutStatus();

            Debug.Assert(IsTypeValid(ref parameter));

            ref CircularBufferParameter inputDeviceParameter = ref MemoryMarshal.Cast <byte, CircularBufferParameter>(parameter.SpecificData)[0];
Example #11
0
        /// <summary>
        /// Update the internal state from a user parameter.
        /// </summary>
        /// <param name="outErrorInfo">The possible <see cref="ErrorInfo"/> that was generated.</param>
        /// <param name="parameter">The user parameter.</param>
        /// <param name="poolMapper">The mapper to use.</param>
        /// <param name="behaviourContext">The behaviour context.</param>
        public void UpdateParameters(out ErrorInfo outErrorInfo, ref VoiceInParameter parameter, ref PoolMapper poolMapper, ref BehaviourContext behaviourContext)
        {
            InUse  = parameter.InUse;
            Id     = parameter.Id;
            NodeId = parameter.NodeId;

            UpdatePlayState(parameter.PlayState);

            SrcQuality = parameter.SrcQuality;

            Priority      = parameter.Priority;
            SortingOrder  = parameter.SortingOrder;
            SampleRate    = parameter.SampleRate;
            SampleFormat  = parameter.SampleFormat;
            ChannelsCount = parameter.ChannelCount;
            Pitch         = parameter.Pitch;
            Volume        = parameter.Volume;
            parameter.BiquadFilters.ToSpan().CopyTo(BiquadFilters.ToSpan());
            WaveBuffersCount = parameter.WaveBuffersCount;
            WaveBuffersIndex = parameter.WaveBuffersIndex;

            if (behaviourContext.IsFlushVoiceWaveBuffersSupported())
            {
                FlushWaveBufferCount += parameter.FlushWaveBufferCount;
            }

            MixId = parameter.MixId;

            if (behaviourContext.IsSplitterSupported())
            {
                SplitterId = parameter.SplitterId;
            }
            else
            {
                SplitterId = RendererConstants.UnusedSplitterId;
            }

            parameter.ChannelResourceIds.ToSpan().CopyTo(ChannelResourceIds.ToSpan());

            DecodingBehaviour behaviour = DecodingBehaviour.Default;

            if (behaviourContext.IsDecodingBehaviourFlagSupported())
            {
                behaviour = parameter.DecodingBehaviourFlags;
            }

            DecodingBehaviour = behaviour;

            if (parameter.ResetVoiceDropFlag)
            {
                VoiceDropFlag = false;
            }

            if (ShouldUpdateParameters(ref parameter))
            {
                DataSourceStateUnmapped = !poolMapper.TryAttachBuffer(out outErrorInfo, ref DataSourceStateAddressInfo, parameter.DataSourceStateAddress, parameter.DataSourceStateSize);
            }
            else
            {
                outErrorInfo = new ErrorInfo();
            }
        }
Example #12
0
        public override void Update(out BehaviourParameter.ErrorInfo updateErrorInfo, ref EffectInParameter parameter, PoolMapper mapper)
        {
            Debug.Assert(IsTypeValid(ref parameter));

            UpdateParameterBase(ref parameter);

            Parameter = MemoryMarshal.Cast <byte, BiquadFilterEffectParameter>(parameter.SpecificData)[0];
            IsEnabled = parameter.IsEnabled;

            updateErrorInfo = new BehaviourParameter.ErrorInfo();
        }
Example #13
0
        public void Update <T>(out BehaviourParameter.ErrorInfo updateErrorInfo, ref T parameter, PoolMapper mapper) where T : unmanaged, IEffectInParameter
        {
            Debug.Assert(IsTypeValid(ref parameter));

            UpdateParameterBase(ref parameter);

            Parameter = MemoryMarshal.Cast <byte, AuxiliaryBufferParameter>(parameter.SpecificData)[0];
            IsEnabled = parameter.IsEnabled;

            updateErrorInfo = new BehaviourParameter.ErrorInfo();

            if (BufferUnmapped || parameter.IsNew)
            {
                ulong bufferSize = (ulong)Unsafe.SizeOf <int>() * Parameter.BufferStorageSize + (ulong)Unsafe.SizeOf <AuxiliaryBufferHeader>();

                bool sendBufferUnmapped = !mapper.TryAttachBuffer(out updateErrorInfo, ref WorkBuffers[0], Parameter.SendBufferInfoAddress, bufferSize);

                BufferUnmapped = sendBufferUnmapped;

                if (!BufferUnmapped)
                {
                    DspAddress sendDspAddress = WorkBuffers[0].GetReference(false);

                    // NOTE: Nintendo directly interact with the CPU side structure in the processing of the DSP command.
                    State.SendBufferInfo       = sendDspAddress;
                    State.SendBufferInfoBase   = sendDspAddress + (ulong)Unsafe.SizeOf <AuxiliaryBufferHeader>();
                    State.ReturnBufferInfo     = 0;
                    State.ReturnBufferInfoBase = 0;
                }
            }
        }
Example #14
0
        public void TestTryAttachBuffer()
        {
            const CpuAddress CpuAddress = 0x20000;
            const DspAddress DspAddress = CpuAddress; // TODO: DSP LLE
            const ulong      CpuSize    = 0x1000;

            const int        MemoryPoolStateArraySize = 0x10;
            const CpuAddress CpuAddressRegionEnding   = CpuAddress * MemoryPoolStateArraySize;

            MemoryPoolState[] memoryPoolStateArray = new MemoryPoolState[MemoryPoolStateArraySize];

            for (int i = 0; i < memoryPoolStateArray.Length; i++)
            {
                memoryPoolStateArray[i] = MemoryPoolState.Create(MemoryPoolState.LocationType.Cpu);
                memoryPoolStateArray[i].SetCpuAddress(CpuAddress + (ulong)i * CpuSize, CpuSize);
            }

            ErrorInfo errorInfo;

            AddressInfo addressInfo = AddressInfo.Create();

            PoolMapper poolMapper = new PoolMapper(DummyProcessHandle, true);

            Assert.IsTrue(poolMapper.TryAttachBuffer(out errorInfo, ref addressInfo, 0, 0));

            Assert.AreEqual(ResultCode.InvalidAddressInfo, errorInfo.ErrorCode);
            Assert.AreEqual(0, errorInfo.ExtraErrorInfo);
            Assert.AreEqual(0, addressInfo.ForceMappedDspAddress);

            Assert.IsTrue(poolMapper.TryAttachBuffer(out errorInfo, ref addressInfo, CpuAddress, CpuSize));

            Assert.AreEqual(ResultCode.InvalidAddressInfo, errorInfo.ErrorCode);
            Assert.AreEqual(CpuAddress, errorInfo.ExtraErrorInfo);
            Assert.AreEqual(DspAddress, addressInfo.ForceMappedDspAddress);

            poolMapper = new PoolMapper(DummyProcessHandle, false);

            Assert.IsFalse(poolMapper.TryAttachBuffer(out errorInfo, ref addressInfo, 0, 0));

            addressInfo.ForceMappedDspAddress = 0;

            Assert.IsFalse(poolMapper.TryAttachBuffer(out errorInfo, ref addressInfo, CpuAddress, CpuSize));

            Assert.AreEqual(ResultCode.InvalidAddressInfo, errorInfo.ErrorCode);
            Assert.AreEqual(CpuAddress, errorInfo.ExtraErrorInfo);
            Assert.AreEqual(0, addressInfo.ForceMappedDspAddress);

            poolMapper = new PoolMapper(DummyProcessHandle, memoryPoolStateArray.AsMemory(), false);

            Assert.IsFalse(poolMapper.TryAttachBuffer(out errorInfo, ref addressInfo, CpuAddressRegionEnding, CpuSize));

            Assert.AreEqual(ResultCode.InvalidAddressInfo, errorInfo.ErrorCode);
            Assert.AreEqual(CpuAddressRegionEnding, errorInfo.ExtraErrorInfo);
            Assert.AreEqual(0, addressInfo.ForceMappedDspAddress);
            Assert.IsFalse(addressInfo.HasMemoryPoolState);

            Assert.IsTrue(poolMapper.TryAttachBuffer(out errorInfo, ref addressInfo, CpuAddress, CpuSize));

            Assert.AreEqual(ResultCode.Success, errorInfo.ErrorCode);
            Assert.AreEqual(0, errorInfo.ExtraErrorInfo);
            Assert.AreEqual(0, addressInfo.ForceMappedDspAddress);
            Assert.IsTrue(addressInfo.HasMemoryPoolState);
        }
Example #15
0
        public void Update <T>(out BehaviourParameter.ErrorInfo updateErrorInfo, ref T parameter, PoolMapper mapper) where T : unmanaged, IEffectInParameter
        {
            Debug.Assert(IsTypeValid(ref parameter));

            UpdateParameterBase(ref parameter);

            Parameter = MemoryMarshal.Cast <byte, BufferMixParameter>(parameter.SpecificData)[0];
            IsEnabled = parameter.IsEnabled;

            updateErrorInfo = new BehaviourParameter.ErrorInfo();
        }
Example #16
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;
            }
Example #17
0
        public void Update <T>(out BehaviourParameter.ErrorInfo updateErrorInfo, ref T parameter, PoolMapper mapper) where T : unmanaged, IEffectInParameter
        {
            Debug.Assert(IsTypeValid(ref parameter));

            ref LimiterParameter limiterParameter = ref MemoryMarshal.Cast <byte, LimiterParameter>(parameter.SpecificData)[0];
Example #18
0
        public override void Update(out BehaviourParameter.ErrorInfo updateErrorInfo, ref EffectInParameter parameter, PoolMapper mapper)
        {
            Debug.Assert(IsTypeValid(ref parameter));

            ref Reverb3dParameter reverbParameter = ref MemoryMarshal.Cast <byte, Reverb3dParameter>(parameter.SpecificData)[0];
Example #19
0
        /// <summary>
        /// Update the internal state from user parameter.
        /// </summary>
        /// <param name="errorInfo">The possible <see cref="ErrorInfo"/> that was generated.</param>
        /// <param name="parameter">The user parameter.</param>
        /// <param name="outStatus">The user output status.</param>
        /// <param name="mapper">The mapper to use.</param>
        public virtual void Update(out ErrorInfo errorInfo, ref SinkInParameter parameter, ref SinkOutStatus outStatus, PoolMapper mapper)
        {
            Debug.Assert(IsTypeValid(ref parameter));

            errorInfo = new ErrorInfo();
        }