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); } }
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)); }
/// <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); } } }
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()); } } }
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); }
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)); }
public override void Update(out BehaviourParameter.ErrorInfo updateErrorInfo, ref EffectInParameterVersion2 parameter, PoolMapper mapper) { Update(out updateErrorInfo, ref parameter, mapper); }
/// <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(); }
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>(); } } }
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];
/// <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(); } }
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(); }
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; } } }
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); }
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(); }
public ResultCode Initialize(ref AudioRendererConfiguration parameter, uint processHandle, CpuAddress workBuffer, ulong workBufferSize, int sessionId, ulong appletResourceId, IVirtualMemoryManager memoryManager) { if (!BehaviourContext.CheckValidRevision(parameter.Revision)) { return(ResultCode.OperationFailed); } if (GetWorkBufferSize(ref parameter) > workBufferSize) { return(ResultCode.WorkBufferTooSmall); } Debug.Assert(parameter.RenderingDevice == AudioRendererRenderingDevice.Dsp && parameter.ExecutionMode == AudioRendererExecutionMode.Auto); Logger.Info?.Print(LogClass.AudioRenderer, $"Initializing with REV{BehaviourContext.GetRevisionNumber(parameter.Revision)}"); _behaviourContext.SetUserRevision(parameter.Revision); _sampleRate = parameter.SampleRate; _sampleCount = parameter.SampleCount; _mixBufferCount = parameter.MixBufferCount; _voiceChannelCountMax = Constants.VoiceChannelCountMax; _upsamplerCount = parameter.SinkCount + parameter.SubMixBufferCount; _appletResourceId = appletResourceId; _memoryPoolCount = parameter.EffectCount + parameter.VoiceCount * Constants.VoiceWaveBufferCount; _executionMode = parameter.ExecutionMode; _sessionId = sessionId; MemoryManager = memoryManager; if (memoryManager is IRefCounted rc) { rc.IncrementReferenceCount(); } WorkBufferAllocator workBufferAllocator; _workBufferRegion = MemoryManager.GetWritableRegion(workBuffer, (int)workBufferSize); _workBufferRegion.Memory.Span.Fill(0); _workBufferMemoryPin = _workBufferRegion.Memory.Pin(); workBufferAllocator = new WorkBufferAllocator(_workBufferRegion.Memory); PoolMapper poolMapper = new PoolMapper(processHandle, false); poolMapper.InitializeSystemPool(ref _dspMemoryPoolState, workBuffer, workBufferSize); _mixBuffer = workBufferAllocator.Allocate <float>(_sampleCount * (_voiceChannelCountMax + _mixBufferCount), 0x10); if (_mixBuffer.IsEmpty) { return(ResultCode.WorkBufferTooSmall); } Memory <float> upSamplerWorkBuffer = workBufferAllocator.Allocate <float>(Constants.TargetSampleCount * (_voiceChannelCountMax + _mixBufferCount) * _upsamplerCount, 0x10); if (upSamplerWorkBuffer.IsEmpty) { return(ResultCode.WorkBufferTooSmall); } _depopBuffer = workBufferAllocator.Allocate <float>((ulong)BitUtils.AlignUp(parameter.MixBufferCount, Constants.BufferAlignment), Constants.BufferAlignment); if (_depopBuffer.IsEmpty) { return(ResultCode.WorkBufferTooSmall); } // Invalidate DSP cache on what was currently allocated with workBuffer. AudioProcessorMemoryManager.InvalidateDspCache(_dspMemoryPoolState.Translate(workBuffer, workBufferAllocator.Offset), workBufferAllocator.Offset); Debug.Assert((workBufferAllocator.Offset % Constants.BufferAlignment) == 0); Memory <VoiceState> voices = workBufferAllocator.Allocate <VoiceState>(parameter.VoiceCount, VoiceState.Alignment); if (voices.IsEmpty) { return(ResultCode.WorkBufferTooSmall); } foreach (ref VoiceState voice in voices.Span) { voice.Initialize(); } // A pain to handle as we can't have VoiceState*, use indices to be a bit more safe Memory <int> sortedVoices = workBufferAllocator.Allocate <int>(parameter.VoiceCount, 0x10); if (sortedVoices.IsEmpty) { return(ResultCode.WorkBufferTooSmall); } // Clear memory (use -1 as it's an invalid index) sortedVoices.Span.Fill(-1); Memory <VoiceChannelResource> voiceChannelResources = workBufferAllocator.Allocate <VoiceChannelResource>(parameter.VoiceCount, VoiceChannelResource.Alignment); if (voiceChannelResources.IsEmpty) { return(ResultCode.WorkBufferTooSmall); } for (uint id = 0; id < voiceChannelResources.Length; id++) { ref VoiceChannelResource voiceChannelResource = ref voiceChannelResources.Span[(int)id]; voiceChannelResource.Id = id; voiceChannelResource.IsUsed = false; }
public 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];
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];
/// <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(); }