Replace old ArrayN uses with new InlineArray structs

This commit is contained in:
Gabriel A 2023-11-17 20:33:02 -03:00
parent 82a638230e
commit 0d8e6dd4f8
49 changed files with 3484 additions and 686 deletions

View file

@ -76,7 +76,7 @@ namespace Ryujinx.Audio.Renderer.Dsp
if (!info.DecodingBehaviour.HasFlag(DecodingBehaviour.SkipPitchAndSampleRateConversion)) if (!info.DecodingBehaviour.HasFlag(DecodingBehaviour.SkipPitchAndSampleRateConversion))
{ {
voiceState.Pitch.AsSpan()[..pitchMaxLength].CopyTo(tempBuffer); voiceState.Pitch[..pitchMaxLength].CopyTo(tempBuffer);
tempBufferIndex += pitchMaxLength; tempBufferIndex += pitchMaxLength;
} }
@ -239,7 +239,7 @@ namespace Ryujinx.Audio.Renderer.Dsp
ResamplerHelper.Resample(outputBuffer, tempBuffer, sampleRateRatio, ref fraction, sampleCountToProcess, info.SrcQuality, y != sourceSampleCountToProcess || info.Pitch != 1.0f); ResamplerHelper.Resample(outputBuffer, tempBuffer, sampleRateRatio, ref fraction, sampleCountToProcess, info.SrcQuality, y != sourceSampleCountToProcess || info.Pitch != 1.0f);
tempBuffer.Slice(sampleCountToDecode, pitchMaxLength).CopyTo(voiceState.Pitch.AsSpan()); tempBuffer.Slice(sampleCountToDecode, pitchMaxLength).CopyTo(voiceState.Pitch);
} }
i += sampleCountToProcess; i += sampleCountToProcess;

View file

@ -71,7 +71,7 @@ namespace Ryujinx.Audio.Renderer.Dsp
return; return;
} }
float DoFilterBank(ref UpsamplerBufferState state, in Array20<float> bank) float DoFilterBank(ref UpsamplerBufferState state, ReadOnlySpan<float> bank)
{ {
float result = 0.0f; float result = 0.0f;
@ -87,8 +87,8 @@ namespace Ryujinx.Audio.Renderer.Dsp
while (curIdx < stopIdx) while (curIdx < stopIdx)
{ {
result += Vector.Dot( result += Vector.Dot(
new Vector<float>(bank.AsSpan().Slice(curIdx, Vector<float>.Count)), new Vector<float>(bank.Slice(curIdx, Vector<float>.Count)),
new Vector<float>(state.History.AsSpan().Slice(curIdx, Vector<float>.Count))); new Vector<float>(((Span<float>)state.History).Slice(curIdx, Vector<float>.Count)));
curIdx += Vector<float>.Count; curIdx += Vector<float>.Count;
} }
} }
@ -105,7 +105,7 @@ namespace Ryujinx.Audio.Renderer.Dsp
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
void NextInput(ref UpsamplerBufferState state, float input) void NextInput(ref UpsamplerBufferState state, float input)
{ {
state.History.AsSpan()[1..].CopyTo(state.History.AsSpan()); state.History[1..].CopyTo(state.History);
state.History[HistoryLength - 1] = input; state.History[HistoryLength - 1] = input;
} }

View file

@ -1,4 +1,5 @@
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Ryujinx.Audio.Renderer.Parameter.Effect namespace Ryujinx.Audio.Renderer.Parameter.Effect
@ -24,8 +25,8 @@ namespace Ryujinx.Audio.Renderer.Parameter.Effect
/// </summary> /// </summary>
public void Reset() public void Reset()
{ {
InputMax.AsSpan().Clear(); ((Span<float>)InputMax).Clear();
CompressionGainMin.AsSpan().Fill(1.0f); ((Span<float>)CompressionGainMin).Fill(1.0f);
} }
} }
} }

View file

@ -141,7 +141,7 @@ namespace Ryujinx.Audio.Renderer.Server
Memory<byte> biquadStateRawMemory = SpanMemoryManager<byte>.Cast(state)[..(VoiceUpdateState.BiquadStateSize * Constants.VoiceBiquadFilterCount)]; Memory<byte> biquadStateRawMemory = SpanMemoryManager<byte>.Cast(state)[..(VoiceUpdateState.BiquadStateSize * Constants.VoiceBiquadFilterCount)];
Memory<BiquadFilterState> stateMemory = SpanMemoryManager<BiquadFilterState>.Cast(biquadStateRawMemory); Memory<BiquadFilterState> stateMemory = SpanMemoryManager<BiquadFilterState>.Cast(biquadStateRawMemory);
_commandBuffer.GenerateGroupedBiquadFilter(baseIndex, voiceState.BiquadFilters.AsSpan(), stateMemory, bufferOffset, bufferOffset, voiceState.BiquadFilterNeedInitialization, nodeId); _commandBuffer.GenerateGroupedBiquadFilter(baseIndex, voiceState.BiquadFilters, stateMemory, bufferOffset, bufferOffset, voiceState.BiquadFilterNeedInitialization, nodeId);
} }
else else
{ {
@ -337,8 +337,8 @@ namespace Ryujinx.Audio.Renderer.Server
GeneratePerformance(ref performanceEntry, PerformanceCommand.Type.Start, nodeId); GeneratePerformance(ref performanceEntry, PerformanceCommand.Type.Start, nodeId);
} }
GenerateVoiceMix(channelResource.Mix.AsSpan(), GenerateVoiceMix(channelResource.Mix,
channelResource.PreviousMix.AsSpan(), channelResource.PreviousMix,
dspStateMemory, dspStateMemory,
mix.BufferOffset, mix.BufferOffset,
mix.BufferCount, mix.BufferCount,
@ -507,8 +507,8 @@ namespace Ryujinx.Audio.Renderer.Server
Enable = true, Enable = true,
}; };
effect.Parameter.Denominator.AsSpan().CopyTo(parameter.Denominator.AsSpan()); ((Span<short>)effect.Parameter.Denominator).CopyTo(parameter.Denominator);
effect.Parameter.Numerator.AsSpan().CopyTo(parameter.Numerator.AsSpan()); ((Span<short>)effect.Parameter.Numerator).CopyTo(parameter.Numerator);
for (int i = 0; i < effect.Parameter.ChannelCount; i++) for (int i = 0; i < effect.Parameter.ChannelCount; i++)
{ {
@ -939,8 +939,8 @@ namespace Ryujinx.Audio.Renderer.Server
if (useCustomDownMixingCommand) if (useCustomDownMixingCommand)
{ {
_commandBuffer.GenerateDownMixSurroundToStereo(finalMix.BufferOffset, _commandBuffer.GenerateDownMixSurroundToStereo(finalMix.BufferOffset,
sink.Parameter.Input.AsSpan(), sink.Parameter.Input,
sink.Parameter.Input.AsSpan(), sink.Parameter.Input,
sink.DownMixCoefficients, sink.DownMixCoefficients,
Constants.InvalidNodeId); Constants.InvalidNodeId);
} }
@ -948,8 +948,8 @@ namespace Ryujinx.Audio.Renderer.Server
else if (_rendererContext.ChannelCount == 2 && sink.Parameter.InputCount == 6) else if (_rendererContext.ChannelCount == 2 && sink.Parameter.InputCount == 6)
{ {
_commandBuffer.GenerateDownMixSurroundToStereo(finalMix.BufferOffset, _commandBuffer.GenerateDownMixSurroundToStereo(finalMix.BufferOffset,
sink.Parameter.Input.AsSpan(), sink.Parameter.Input,
sink.Parameter.Input.AsSpan(), sink.Parameter.Input,
Constants.DefaultSurroundToStereoCoefficients, Constants.DefaultSurroundToStereoCoefficients,
Constants.InvalidNodeId); Constants.InvalidNodeId);
} }
@ -961,7 +961,7 @@ namespace Ryujinx.Audio.Renderer.Server
_commandBuffer.GenerateUpsample(finalMix.BufferOffset, _commandBuffer.GenerateUpsample(finalMix.BufferOffset,
sink.UpsamplerState, sink.UpsamplerState,
sink.Parameter.InputCount, sink.Parameter.InputCount,
sink.Parameter.Input.AsSpan(), sink.Parameter.Input,
commandList.BufferCount, commandList.BufferCount,
commandList.SampleCount, commandList.SampleCount,
commandList.SampleRate, commandList.SampleRate,

View file

@ -63,10 +63,10 @@ namespace Ryujinx.Audio.Renderer.Server.Sink
else else
{ {
Parameter.DownMixParameterEnabled = inputDeviceParameter.DownMixParameterEnabled; Parameter.DownMixParameterEnabled = inputDeviceParameter.DownMixParameterEnabled;
inputDeviceParameter.DownMixParameter.AsSpan().CopyTo(Parameter.DownMixParameter.AsSpan()); ((Span<float>)inputDeviceParameter.DownMixParameter).CopyTo(Parameter.DownMixParameter);
} }
Parameter.DownMixParameter.AsSpan().CopyTo(DownMixCoefficients.AsSpan()); ((Span<float>)Parameter.DownMixParameter).CopyTo(DownMixCoefficients.AsSpan());
errorInfo = new BehaviourParameter.ErrorInfo(); errorInfo = new BehaviourParameter.ErrorInfo();
outStatus = new SinkOutStatus(); outStatus = new SinkOutStatus();

View file

@ -120,7 +120,7 @@ namespace Ryujinx.Audio.Renderer.Server
ref VoiceChannelResource resource = ref context.GetChannelResource(i); ref VoiceChannelResource resource = ref context.GetChannelResource(i);
resource.Id = parameter.Id; resource.Id = parameter.Id;
parameter.Mix.AsSpan().CopyTo(resource.Mix.AsSpan()); ((Span<float>)parameter.Mix).CopyTo(resource.Mix);
resource.IsUsed = parameter.IsUsed; resource.IsUsed = parameter.IsUsed;
} }
@ -565,7 +565,7 @@ namespace Ryujinx.Audio.Renderer.Server
{ {
ref BehaviourErrorInfoOutStatus outStatus = ref SpanIOHelper.GetWriteRef<BehaviourErrorInfoOutStatus>(ref _output)[0]; ref BehaviourErrorInfoOutStatus outStatus = ref SpanIOHelper.GetWriteRef<BehaviourErrorInfoOutStatus>(ref _output)[0];
_behaviourContext.CopyErrorInfo(outStatus.ErrorInfos.AsSpan(), out outStatus.ErrorInfosCount); _behaviourContext.CopyErrorInfo(outStatus.ErrorInfos, out outStatus.ErrorInfosCount);
OutputHeader.BehaviourSize = (uint)Unsafe.SizeOf<BehaviourErrorInfoOutStatus>(); OutputHeader.BehaviourSize = (uint)Unsafe.SizeOf<BehaviourErrorInfoOutStatus>();
OutputHeader.TotalSize += OutputHeader.BehaviourSize; OutputHeader.TotalSize += OutputHeader.BehaviourSize;

View file

@ -1,4 +1,5 @@
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Ryujinx.Audio.Renderer.Server.Voice namespace Ryujinx.Audio.Renderer.Server.Voice
@ -34,7 +35,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
public void UpdateState() public void UpdateState()
{ {
Mix.AsSpan().CopyTo(PreviousMix.AsSpan()); ((Span<float>)Mix).CopyTo(PreviousMix);
} }
} }
} }

View file

@ -204,7 +204,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
Pitch = 0.0f; Pitch = 0.0f;
Volume = 0.0f; Volume = 0.0f;
PreviousVolume = 0.0f; PreviousVolume = 0.0f;
BiquadFilters.AsSpan().Clear(); ((Span<BiquadFilterParameter>)BiquadFilters).Clear();
WaveBuffersCount = 0; WaveBuffersCount = 0;
WaveBuffersIndex = 0; WaveBuffersIndex = 0;
MixId = Constants.UnusedMixId; MixId = Constants.UnusedMixId;
@ -290,7 +290,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
ChannelsCount = parameter.ChannelCount; ChannelsCount = parameter.ChannelCount;
Pitch = parameter.Pitch; Pitch = parameter.Pitch;
Volume = parameter.Volume; Volume = parameter.Volume;
parameter.BiquadFilters.AsSpan().CopyTo(BiquadFilters.AsSpan()); ((Span<BiquadFilterParameter>)parameter.BiquadFilters).CopyTo(BiquadFilters);
WaveBuffersCount = parameter.WaveBuffersCount; WaveBuffersCount = parameter.WaveBuffersCount;
WaveBuffersIndex = parameter.WaveBuffersIndex; WaveBuffersIndex = parameter.WaveBuffersIndex;
@ -310,7 +310,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
SplitterId = Constants.UnusedSplitterId; SplitterId = Constants.UnusedSplitterId;
} }
parameter.ChannelResourceIds.AsSpan().CopyTo(ChannelResourceIds.AsSpan()); ((Span<int>)parameter.ChannelResourceIds).CopyTo(ChannelResourceIds);
DecodingBehaviour behaviour = DecodingBehaviour.Default; DecodingBehaviour behaviour = DecodingBehaviour.Default;
@ -640,7 +640,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
voiceUpdateState.Offset = 0; voiceUpdateState.Offset = 0;
voiceUpdateState.PlayedSampleCount = 0; voiceUpdateState.PlayedSampleCount = 0;
voiceUpdateState.Pitch.AsSpan().Clear(); ((Span<short>)voiceUpdateState.Pitch).Clear();
voiceUpdateState.Fraction = 0; voiceUpdateState.Fraction = 0;
voiceUpdateState.LoopContext = new AdpcmLoopContext(); voiceUpdateState.LoopContext = new AdpcmLoopContext();
} }
@ -652,7 +652,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
case PlayState.Stopped: case PlayState.Stopped:
case PlayState.Paused: case PlayState.Paused:
foreach (ref WaveBuffer wavebuffer in WaveBuffers.AsSpan()) foreach (ref WaveBuffer wavebuffer in WaveBuffers)
{ {
wavebuffer.BufferAddressInfo.GetReference(true); wavebuffer.BufferAddressInfo.GetReference(true);
wavebuffer.ContextAddressInfo.GetReference(true); wavebuffer.ContextAddressInfo.GetReference(true);

View file

@ -129,7 +129,7 @@ namespace Ryujinx.Common.Memory.PartialUnmaps
const uint ExitCodeStillActive = 259; const uint ExitCodeStillActive = 259;
const int ThreadQueryInformation = 0x40; const int ThreadQueryInformation = 0x40;
Span<int> ids = LocalCounts.ThreadIds.AsSpan(); Span<int> ids = LocalCounts.ThreadIds;
for (int i = 0; i < ids.Length; i++) for (int i = 0; i < ids.Length; i++)
{ {

View file

@ -1,4 +1,5 @@
using System.Runtime.InteropServices; using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using static Ryujinx.Common.Memory.PartialUnmaps.PartialUnmapHelpers; using static Ryujinx.Common.Memory.PartialUnmaps.PartialUnmapHelpers;
@ -74,6 +75,7 @@ namespace Ryujinx.Common.Memory.PartialUnmaps
/// </summary> /// </summary>
/// <param name="index">Index of the entry</param> /// <param name="index">Index of the entry</param>
/// <returns>A reference to the struct value</returns> /// <returns>A reference to the struct value</returns>
[UnscopedRef]
public ref T GetValue(int index) public ref T GetValue(int index)
{ {
return ref Structs[index]; return ref Structs[index];

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,6 @@
using System; using System;
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices;
namespace Ryujinx.Graphics.Device namespace Ryujinx.Graphics.Device
{ {
@ -28,6 +29,14 @@ namespace Ryujinx.Graphics.Device
return type.StructLayoutAttribute.Size; return type.StructLayoutAttribute.Size;
} }
// If the struct has the InlineArray attribute, the size is specified on the attribute, and the first field has the type.
if (type.GetCustomAttribute<InlineArrayAttribute>() is InlineArrayAttribute attribute)
{
Type field0Type = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)[0].FieldType;
return attribute.Length * SizeOf(field0Type);
}
// Otherwise we calculate the sum of the sizes of all fields. // Otherwise we calculate the sum of the sizes of all fields.
int size = 0; int size = 0;
var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

View file

@ -13,13 +13,13 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands
public void Set(int vertices, ReadOnlySpan<float> defaultOuterLevel, ReadOnlySpan<float> defaultInnerLevel) public void Set(int vertices, ReadOnlySpan<float> defaultOuterLevel, ReadOnlySpan<float> defaultInnerLevel)
{ {
_vertices = vertices; _vertices = vertices;
defaultOuterLevel.CopyTo(_defaultOuterLevel.AsSpan()); defaultOuterLevel.CopyTo(_defaultOuterLevel);
defaultInnerLevel.CopyTo(_defaultInnerLevel.AsSpan()); defaultInnerLevel.CopyTo(_defaultInnerLevel);
} }
public static void Run(ref SetPatchParametersCommand command, ThreadedRenderer threaded, IRenderer renderer) public static void Run(ref SetPatchParametersCommand command, ThreadedRenderer threaded, IRenderer renderer)
{ {
renderer.Pipeline.SetPatchParameters(command._vertices, command._defaultOuterLevel.AsSpan(), command._defaultInnerLevel.AsSpan()); renderer.Pipeline.SetPatchParameters(command._vertices, command._defaultOuterLevel, command._defaultInnerLevel);
} }
} }
} }

View file

@ -68,7 +68,7 @@ namespace Ryujinx.Graphics.GAL
public void SetVertexAttribs(ReadOnlySpan<VertexAttribDescriptor> vertexAttribs) public void SetVertexAttribs(ReadOnlySpan<VertexAttribDescriptor> vertexAttribs)
{ {
VertexAttribCount = vertexAttribs.Length; VertexAttribCount = vertexAttribs.Length;
vertexAttribs.CopyTo(VertexAttribs.AsSpan()); vertexAttribs.CopyTo(VertexAttribs);
} }
public void SetLogicOpState(bool enable, LogicalOp op) public void SetLogicOpState(bool enable, LogicalOp op)

View file

@ -392,8 +392,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
_context.Renderer.Pipeline.SetPatchParameters( _context.Renderer.Pipeline.SetPatchParameters(
_state.State.PatchVertices, _state.State.PatchVertices,
_state.State.TessOuterLevel.AsSpan(), _state.State.TessOuterLevel,
_state.State.TessInnerLevel.AsSpan()); _state.State.TessInnerLevel);
_currentSpecState.SetTessellationMode(_state.State.TessMode); _currentSpecState.SetTessellationMode(_state.State.TessMode);
} }

View file

@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
public SupportBufferUpdater(IRenderer renderer) : base(renderer) public SupportBufferUpdater(IRenderer renderer) : base(renderer)
{ {
var defaultScale = new Vector4<float> { X = 1f, Y = 0f, Z = 0f, W = 0f }; var defaultScale = new Vector4<float> { X = 1f, Y = 0f, Z = 0f, W = 0f };
_data.RenderScale.AsSpan().Fill(defaultScale); ((Span<Vector4<float>>)_data.RenderScale).Fill(defaultScale);
DirtyRenderScale(0, SupportBuffer.RenderScaleMaxCount); DirtyRenderScale(0, SupportBuffer.RenderScaleMaxCount);
} }

View file

@ -139,7 +139,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
/// <inheritdoc/> /// <inheritdoc/>
public ReadOnlySpan<byte> QueryTransformFeedbackVaryingLocations(int bufferIndex) public ReadOnlySpan<byte> QueryTransformFeedbackVaryingLocations(int bufferIndex)
{ {
return _oldSpecState.TransformFeedbackDescriptors[bufferIndex].AsSpan(); return MemoryMarshal.Cast<uint, byte>(_oldSpecState.TransformFeedbackDescriptors[bufferIndex].VaryingLocations);
} }
/// <inheritdoc/> /// <inheritdoc/>

View file

@ -179,7 +179,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// <inheritdoc/> /// <inheritdoc/>
public ReadOnlySpan<byte> QueryTransformFeedbackVaryingLocations(int bufferIndex) public ReadOnlySpan<byte> QueryTransformFeedbackVaryingLocations(int bufferIndex)
{ {
return _state.TransformFeedbackDescriptors[bufferIndex].AsSpan(); return MemoryMarshal.Cast<uint, byte>(_state.TransformFeedbackDescriptors[bufferIndex].VaryingLocations);
} }
/// <inheritdoc/> /// <inheritdoc/>

View file

@ -514,7 +514,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
} }
else else
{ {
if (!graphicsState.AttributeTypes.AsSpan().SequenceEqual(GraphicsState.AttributeTypes.AsSpan())) if (!((Span<AttributeType>)graphicsState.AttributeTypes).SequenceEqual(GraphicsState.AttributeTypes))
{ {
return false; return false;
} }
@ -530,7 +530,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
return false; return false;
} }
if (channel.Capabilities.NeedsFragmentOutputSpecialization && !graphicsState.FragmentOutputTypes.AsSpan().SequenceEqual(GraphicsState.FragmentOutputTypes.AsSpan())) if (channel.Capabilities.NeedsFragmentOutputSpecialization &&
!((Span<AttributeType>)graphicsState.FragmentOutputTypes).SequenceEqual(GraphicsState.FragmentOutputTypes))
{ {
return false; return false;
} }

View file

@ -29,7 +29,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// <summary> /// <summary>
/// Location of varyings to be written into the buffer. Each byte is one location. /// Location of varyings to be written into the buffer. Each byte is one location.
/// </summary> /// </summary>
public Array32<uint> VaryingLocations; // Making this readonly breaks AsSpan public Array32<uint> VaryingLocations;
/// <summary> /// <summary>
/// Creates a new transform feedback descriptor. /// Creates a new transform feedback descriptor.
@ -45,14 +45,5 @@ namespace Ryujinx.Graphics.Gpu.Shader
VaryingCount = varyingCount; VaryingCount = varyingCount;
VaryingLocations = varyingLocations; VaryingLocations = varyingLocations;
} }
/// <summary>
/// Gets a span of the <see cref="VaryingLocations"/>.
/// </summary>
/// <returns>Span of varying locations</returns>
public ReadOnlySpan<byte> AsSpan()
{
return MemoryMarshal.Cast<uint, byte>(VaryingLocations.AsSpan())[..Math.Min(128, VaryingCount)];
}
} }
} }

View file

@ -138,7 +138,7 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg.H264
3 + 1 * 4, 3 + 2 * 4, 2 + 3 * 4, 3 + 3 * 4, 3 + 1 * 4, 3 + 2 * 4, 2 + 3 * 4, 3 + 3 * 4,
}; };
private static void WriteScalingList(ref H264BitStreamWriter writer, IArray<byte> list) private static void WriteScalingList(ref H264BitStreamWriter writer, Span<byte> list)
{ {
ReadOnlySpan<byte> scan = list.Length == 16 ? ZigZagScan : ZigZagDirect; ReadOnlySpan<byte> scan = list.Length == 16 ? ZigZagScan : ZigZagDirect;

View file

@ -1295,12 +1295,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
GetTileBuffers(ref cm, data, tileCols, ref tileBuffers); GetTileBuffers(ref cm, data, tileCols, ref tileBuffers);
tileBuffers.AsSpan()[..tileCols].Sort(CompareTileBuffers); tileBuffers[..tileCols].Sort(CompareTileBuffers);
if (numWorkers == tileCols) if (numWorkers == tileCols)
{ {
TileBuffer largest = tileBuffers[0]; TileBuffer largest = tileBuffers[0];
Span<TileBuffer> buffers = tileBuffers.AsSpan(); Span<TileBuffer> buffers = tileBuffers;
buffers[1..].CopyTo(buffers[..(tileBuffers.Length - 1)]); buffers[1..].CopyTo(buffers[..(tileBuffers.Length - 1)]);
tileBuffers[tileCols - 1] = largest; tileBuffers[tileCols - 1] = largest;
} }

View file

@ -19,7 +19,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private static PredictionMode ReadIntraModeY(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, int sizeGroup) private static PredictionMode ReadIntraModeY(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, int sizeGroup)
{ {
PredictionMode yMode = ReadIntraMode(ref r, cm.Fc.Value.YModeProb[sizeGroup].AsSpan()); PredictionMode yMode = ReadIntraMode(ref r, cm.Fc.Value.YModeProb[sizeGroup]);
if (!xd.Counts.IsNull) if (!xd.Counts.IsNull)
{ {
++xd.Counts.Value.YMode[sizeGroup][(int)yMode]; ++xd.Counts.Value.YMode[sizeGroup][(int)yMode];
@ -30,7 +30,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private static PredictionMode ReadIntraModeUv(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, byte yMode) private static PredictionMode ReadIntraModeUv(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, byte yMode)
{ {
PredictionMode uvMode = ReadIntraMode(ref r, cm.Fc.Value.UvModeProb[yMode].AsSpan()); PredictionMode uvMode = ReadIntraMode(ref r, cm.Fc.Value.UvModeProb[yMode]);
if (!xd.Counts.IsNull) if (!xd.Counts.IsNull)
{ {
++xd.Counts.Value.UvMode[yMode][(int)uvMode]; ++xd.Counts.Value.UvMode[yMode][(int)uvMode];
@ -41,7 +41,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private static PredictionMode ReadInterMode(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, int ctx) private static PredictionMode ReadInterMode(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, int ctx)
{ {
int mode = r.ReadTree(Luts.Vp9InterModeTree, cm.Fc.Value.InterModeProb[ctx].AsSpan()); int mode = r.ReadTree(Luts.Vp9InterModeTree, cm.Fc.Value.InterModeProb[ctx]);
if (!xd.Counts.IsNull) if (!xd.Counts.IsNull)
{ {
++xd.Counts.Value.InterMode[ctx][mode]; ++xd.Counts.Value.InterMode[ctx][mode];
@ -52,7 +52,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private static int ReadSegmentId(ref Reader r, ref Array7<byte> segTreeProbs) private static int ReadSegmentId(ref Reader r, ref Array7<byte> segTreeProbs)
{ {
return r.ReadTree(Luts.Vp9SegmentTree, segTreeProbs.AsSpan()); return r.ReadTree(Luts.Vp9SegmentTree, segTreeProbs);
} }
private static ReadOnlySpan<byte> GetTxProbs(ref Vp9EntropyProbs fc, TxSize maxTxSize, int ctx) private static ReadOnlySpan<byte> GetTxProbs(ref Vp9EntropyProbs fc, TxSize maxTxSize, int ctx)
@ -60,11 +60,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
switch (maxTxSize) switch (maxTxSize)
{ {
case TxSize.Tx8x8: case TxSize.Tx8x8:
return fc.Tx8x8Prob[ctx].AsSpan(); return fc.Tx8x8Prob[ctx];
case TxSize.Tx16x16: case TxSize.Tx16x16:
return fc.Tx16x16Prob[ctx].AsSpan(); return fc.Tx16x16Prob[ctx];
case TxSize.Tx32x32: case TxSize.Tx32x32:
return fc.Tx32x32Prob[ctx].AsSpan(); return fc.Tx32x32Prob[ctx];
default: default:
Debug.Assert(false, "Invalid maxTxSize."); Debug.Assert(false, "Invalid maxTxSize.");
@ -77,11 +77,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
switch (maxTxSize) switch (maxTxSize)
{ {
case TxSize.Tx8x8: case TxSize.Tx8x8:
return counts.Tx8x8[ctx].AsSpan(); return counts.Tx8x8[ctx];
case TxSize.Tx16x16: case TxSize.Tx16x16:
return counts.Tx16x16[ctx].AsSpan(); return counts.Tx16x16[ctx];
case TxSize.Tx32x32: case TxSize.Tx32x32:
return counts.Tx32x32[ctx].AsSpan(); return counts.Tx32x32[ctx];
default: default:
Debug.Assert(false, "Invalid maxTxSize."); Debug.Assert(false, "Invalid maxTxSize.");
@ -264,7 +264,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
int mag, d, fr, hp; int mag, d, fr, hp;
bool sign = r.Read(fc.Sign[mvcomp]) != 0; bool sign = r.Read(fc.Sign[mvcomp]) != 0;
MvClassType mvClass = (MvClassType)r.ReadTree(Luts.Vp9MvClassTree, fc.Classes[mvcomp].AsSpan()); MvClassType mvClass = (MvClassType)r.ReadTree(Luts.Vp9MvClassTree, fc.Classes[mvcomp]);
bool class0 = mvClass == MvClassType.MvClass0; bool class0 = mvClass == MvClassType.MvClass0;
// Integer part // Integer part
@ -288,7 +288,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
// Fractional part // Fractional part
fr = r.ReadTree(Luts.Vp9MvFPTree, class0 ? fc.Class0Fp[mvcomp][d].AsSpan() : fc.Fp[mvcomp].AsSpan()); fr = r.ReadTree(Luts.Vp9MvFPTree, class0 ? (Span<byte>)fc.Class0Fp[mvcomp][d] : (Span<byte>)fc.Fp[mvcomp]);
// High precision part (if hp is not used, the default value of the hp is 1) // High precision part (if hp is not used, the default value of the hp is 1)
hp = usehp ? r.Read(class0 ? fc.Class0Hp[mvcomp] : fc.Hp[mvcomp]) : 1; hp = usehp ? r.Read(class0 ? fc.Class0Hp[mvcomp] : fc.Hp[mvcomp]) : 1;
@ -307,7 +307,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
Ptr<Vp9BackwardUpdates> counts, Ptr<Vp9BackwardUpdates> counts,
bool allowHP) bool allowHP)
{ {
MvJointType jointType = (MvJointType)r.ReadTree(Luts.Vp9MvJointTree, fc.Joints.AsSpan()); MvJointType jointType = (MvJointType)r.ReadTree(Luts.Vp9MvJointTree, fc.Joints);
bool useHP = allowHP && refr.UseMvHp(); bool useHP = allowHP && refr.UseMvHp();
Mv diff = new(); Mv diff = new();
@ -412,7 +412,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private static byte ReadSwitchableInterpFilter(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r) private static byte ReadSwitchableInterpFilter(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r)
{ {
int ctx = xd.GetPredContextSwitchableInterp(); int ctx = xd.GetPredContextSwitchableInterp();
byte type = (byte)r.ReadTree(Luts.Vp9SwitchableInterpTree, cm.Fc.Value.SwitchableInterpProb[ctx].AsSpan()); byte type = (byte)r.ReadTree(Luts.Vp9SwitchableInterpTree, cm.Fc.Value.SwitchableInterpProb[ctx]);
if (!xd.Counts.IsNull) if (!xd.Counts.IsNull)
{ {
++xd.Counts.Value.SwitchableInterp[ctx][type]; ++xd.Counts.Value.SwitchableInterp[ctx][type];
@ -1076,7 +1076,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
PredictionMode above = AboveBlockMode(mi, aboveMi, block); PredictionMode above = AboveBlockMode(mi, aboveMi, block);
PredictionMode left = LeftBlockMode(mi, leftMi, block); PredictionMode left = LeftBlockMode(mi, leftMi, block);
return fc.KfYModeProb[(int)above][(int)left].AsSpan(); return fc.KfYModeProb[(int)above][(int)left];
} }
private static void ReadIntraFrameModeInfo( private static void ReadIntraFrameModeInfo(
@ -1129,7 +1129,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
break; break;
} }
mi.Value.UvMode = ReadIntraMode(ref r, cm.Fc.Value.KfUvModeProb[(int)mi.Value.Mode].AsSpan()); mi.Value.UvMode = ReadIntraMode(ref r, cm.Fc.Value.KfUvModeProb[(int)mi.Value.Mode]);
} }
private static void CopyRefFramePair(ref Array2<sbyte> dst, ref Array2<sbyte> src) private static void CopyRefFramePair(ref Array2<sbyte> dst, ref Array2<sbyte> src)

View file

@ -349,8 +349,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
blockInsideLimit = 1; blockInsideLimit = 1;
} }
lfi.Lfthr[lvl].Lim.AsSpan().Fill((byte)blockInsideLimit); ((Span<byte>)lfi.Lfthr[lvl].Lim).Fill((byte)blockInsideLimit);
lfi.Lfthr[lvl].Mblim.AsSpan().Fill((byte)(2 * (lvl + 2) + blockInsideLimit)); ((Span<byte>)lfi.Lfthr[lvl].Mblim).Fill((byte)(2 * (lvl + 2) + blockInsideLimit));
} }
} }
@ -385,7 +385,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
// We could get rid of this if we assume that deltas are set to // We could get rid of this if we assume that deltas are set to
// zero when not in use; encoder always uses deltas // zero when not in use; encoder always uses deltas
MemoryMarshal.Cast<Array2<byte>, byte>(lfi.Lvl[segId].AsSpan()).Fill((byte)lvlSeg); MemoryMarshal.Cast<Array2<byte>, byte>(lfi.Lvl[segId]).Fill((byte)lvlSeg);
} }
else else
{ {

View file

@ -333,7 +333,7 @@ namespace Ryujinx.Graphics.Vic.Image
bool isField = frameFormat.IsField(); bool isField = frameFormat.IsField();
bool isTopField = frameFormat.IsTopField(isLuma); bool isTopField = frameFormat.IsTopField(isLuma);
int stride = GetPitch(width, bytesPerPixel); int stride = GetPitch(width, bytesPerPixel);
uint offset = GetOffset(ref offsets[0], plane); uint offset = GetOffset(offsets[0], plane);
int dstStart = 0; int dstStart = 0;
int dstStride = stride; int dstStride = stride;
@ -362,12 +362,12 @@ namespace Ryujinx.Graphics.Vic.Image
if (config.PrevFieldEnable) if (config.PrevFieldEnable)
{ {
prevBuffer = ReadBufferNoDeinterlace(rm, ref offsets[1], linear, plane, width, height, bytesPerPixel, gobBlocksInY); prevBuffer = ReadBufferNoDeinterlace(rm, offsets[1], linear, plane, width, height, bytesPerPixel, gobBlocksInY);
} }
if (config.NextFieldEnable) if (config.NextFieldEnable)
{ {
nextBuffer = ReadBufferNoDeinterlace(rm, ref offsets[2], linear, plane, width, height, bytesPerPixel, gobBlocksInY); nextBuffer = ReadBufferNoDeinterlace(rm, offsets[2], linear, plane, width, height, bytesPerPixel, gobBlocksInY);
} }
int w = width * bytesPerPixel; int w = width * bytesPerPixel;
@ -410,7 +410,7 @@ namespace Ryujinx.Graphics.Vic.Image
return buffer; return buffer;
} }
private static uint GetOffset(ref PlaneOffsets offsets, int plane) private static uint GetOffset(PlaneOffsets offsets, int plane)
{ {
return plane switch return plane switch
{ {
@ -423,7 +423,7 @@ namespace Ryujinx.Graphics.Vic.Image
private static RentedBuffer ReadBufferNoDeinterlace( private static RentedBuffer ReadBufferNoDeinterlace(
ResourceManager rm, ResourceManager rm,
ref PlaneOffsets offsets, PlaneOffsets offsets,
bool linear, bool linear,
int plane, int plane,
int width, int width,
@ -432,7 +432,7 @@ namespace Ryujinx.Graphics.Vic.Image
int gobBlocksInY) int gobBlocksInY)
{ {
int stride = GetPitch(width, bytesPerPixel); int stride = GetPitch(width, bytesPerPixel);
uint offset = GetOffset(ref offsets, plane); uint offset = GetOffset(offsets, plane);
if (linear) if (linear)
{ {

View file

@ -9,21 +9,21 @@ namespace Ryujinx.Graphics.Vulkan
void BitMapSignal(int index, int count); void BitMapSignal(int index, int count);
} }
struct BitMapStruct<T> where T : IArray<long> struct BitMapStruct
{ {
public const int IntSize = 64; public const int IntSize = 64;
private const int IntShift = 6; private const int IntShift = 6;
private const int IntMask = IntSize - 1; private const int IntMask = IntSize - 1;
private T _masks; private Array2<long> _masks;
public BitMapStruct() public BitMapStruct()
{ {
_masks = default; _masks = default;
} }
public bool BecomesUnsetFrom(in BitMapStruct<T> from, ref BitMapStruct<T> into) public readonly bool BecomesUnsetFrom(in BitMapStruct from, ref BitMapStruct into)
{ {
bool result = false; bool result = false;
@ -40,9 +40,9 @@ namespace Ryujinx.Graphics.Vulkan
return result; return result;
} }
public void SetAndSignalUnset<T2>(in BitMapStruct<T> from, ref T2 listener) where T2 : struct, IBitMapListener public void SetAndSignalUnset<T2>(in BitMapStruct from, ref T2 listener) where T2 : struct, IBitMapListener
{ {
BitMapStruct<T> result = new(); BitMapStruct result = new();
if (BecomesUnsetFrom(from, ref result)) if (BecomesUnsetFrom(from, ref result))
{ {
@ -50,7 +50,7 @@ namespace Ryujinx.Graphics.Vulkan
int offset = 0; int offset = 0;
int masks = _masks.Length; int masks = _masks.Length;
ref T resultMasks = ref result._masks; ref Array2<long> resultMasks = ref result._masks;
for (int i = 0; i < masks; i++) for (int i = 0; i < masks; i++)
{ {
long value = resultMasks[i]; long value = resultMasks[i];
@ -70,7 +70,7 @@ namespace Ryujinx.Graphics.Vulkan
_masks = from._masks; _masks = from._masks;
} }
public void SignalSet(Action<int, int> action) public readonly void SignalSet(Action<int, int> action)
{ {
// Iterate the set bits in the result, and signal them. // Iterate the set bits in the result, and signal them.
@ -92,7 +92,7 @@ namespace Ryujinx.Graphics.Vulkan
} }
} }
public bool AnySet() public readonly bool AnySet()
{ {
for (int i = 0; i < _masks.Length; i++) for (int i = 0; i < _masks.Length; i++)
{ {
@ -105,7 +105,7 @@ namespace Ryujinx.Graphics.Vulkan
return false; return false;
} }
public bool IsSet(int bit) public readonly bool IsSet(int bit)
{ {
int wordIndex = bit >> IntShift; int wordIndex = bit >> IntShift;
int wordBit = bit & IntMask; int wordBit = bit & IntMask;
@ -218,9 +218,9 @@ namespace Ryujinx.Graphics.Vulkan
} }
} }
public BitMapStruct<T> Union(BitMapStruct<T> other) public BitMapStruct Union(BitMapStruct other)
{ {
var result = new BitMapStruct<T>(); var result = new BitMapStruct();
ref var masks = ref _masks; ref var masks = ref _masks;
ref var otherMasks = ref other._masks; ref var otherMasks = ref other._masks;

View file

@ -54,10 +54,10 @@ namespace Ryujinx.Graphics.Vulkan
private readonly BufferView[] _bufferTextures; private readonly BufferView[] _bufferTextures;
private readonly BufferView[] _bufferImages; private readonly BufferView[] _bufferImages;
private BitMapStruct<Array2<long>> _uniformSet; private BitMapStruct _uniformSet;
private BitMapStruct<Array2<long>> _storageSet; private BitMapStruct _storageSet;
private BitMapStruct<Array2<long>> _uniformMirrored; private BitMapStruct _uniformMirrored;
private BitMapStruct<Array2<long>> _storageMirrored; private BitMapStruct _storageMirrored;
private bool _updateDescriptorCacheCbIndex; private bool _updateDescriptorCacheCbIndex;

View file

@ -1462,7 +1462,7 @@ namespace Ryujinx.Graphics.Vulkan
protected void UpdatePipelineAttachmentFormats() protected void UpdatePipelineAttachmentFormats()
{ {
var dstAttachmentFormats = _newState.Internal.AttachmentFormats.AsSpan(); var dstAttachmentFormats = _newState.Internal.AttachmentFormats;
FramebufferParams.AttachmentFormats.CopyTo(dstAttachmentFormats); FramebufferParams.AttachmentFormats.CopyTo(dstAttachmentFormats);
_newState.Internal.AttachmentIntegerFormatMask = FramebufferParams.AttachmentIntegerFormatMask; _newState.Internal.AttachmentIntegerFormatMask = FramebufferParams.AttachmentIntegerFormatMask;

View file

@ -136,7 +136,7 @@ namespace Ryujinx.Graphics.Vulkan
private void RecordBlend(Vk api, CommandBuffer commandBuffer) private void RecordBlend(Vk api, CommandBuffer commandBuffer)
{ {
api.CmdSetBlendConstants(commandBuffer, _blendConstants.AsSpan()); api.CmdSetBlendConstants(commandBuffer, _blendConstants);
} }
private readonly void RecordDepthBias(Vk api, CommandBuffer commandBuffer) private readonly void RecordDepthBias(Vk api, CommandBuffer commandBuffer)
@ -148,7 +148,7 @@ namespace Ryujinx.Graphics.Vulkan
{ {
if (ScissorsCount != 0) if (ScissorsCount != 0)
{ {
api.CmdSetScissor(commandBuffer, 0, (uint)ScissorsCount, _scissors.AsSpan()); api.CmdSetScissor(commandBuffer, 0, (uint)ScissorsCount, _scissors);
} }
} }
@ -166,7 +166,7 @@ namespace Ryujinx.Graphics.Vulkan
{ {
if (ViewportsCount != 0) if (ViewportsCount != 0)
{ {
api.CmdSetViewport(commandBuffer, 0, ViewportsCount, Viewports.AsSpan()); api.CmdSetViewport(commandBuffer, 0, ViewportsCount, Viewports);
} }
} }
} }

View file

@ -49,22 +49,22 @@ namespace Ryujinx.Graphics.Vulkan
return false; return false;
} }
if (!SequenceEqual<VertexInputAttributeDescription>(VertexAttributeDescriptions.AsSpan(), other.VertexAttributeDescriptions.AsSpan(), VertexAttributeDescriptionsCount)) if (!SequenceEqual<VertexInputAttributeDescription>(VertexAttributeDescriptions, other.VertexAttributeDescriptions, VertexAttributeDescriptionsCount))
{ {
return false; return false;
} }
if (!SequenceEqual<VertexInputBindingDescription>(VertexBindingDescriptions.AsSpan(), other.VertexBindingDescriptions.AsSpan(), VertexBindingDescriptionsCount)) if (!SequenceEqual<VertexInputBindingDescription>(VertexBindingDescriptions, other.VertexBindingDescriptions, VertexBindingDescriptionsCount))
{ {
return false; return false;
} }
if (!SequenceEqual<PipelineColorBlendAttachmentState>(ColorBlendAttachmentState.AsSpan(), other.ColorBlendAttachmentState.AsSpan(), ColorBlendAttachmentStateCount)) if (!SequenceEqual<PipelineColorBlendAttachmentState>(ColorBlendAttachmentState, other.ColorBlendAttachmentState, ColorBlendAttachmentStateCount))
{ {
return false; return false;
} }
if (!SequenceEqual<Format>(AttachmentFormats.AsSpan(), other.AttachmentFormats.AsSpan(), ColorBlendAttachmentStateCount + (HasDepthStencil ? 1u : 0u))) if (!SequenceEqual<Format>(AttachmentFormats, other.AttachmentFormats, ColorBlendAttachmentStateCount + (HasDepthStencil ? 1u : 0u)))
{ {
return false; return false;
} }

View file

@ -117,7 +117,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio
OpusMultiStreamParametersEx parameters = context.Memory.Read<OpusMultiStreamParametersEx>(parametersAddress); OpusMultiStreamParametersEx parameters = context.Memory.Read<OpusMultiStreamParametersEx>(parametersAddress);
byte[] mappings = MemoryMarshal.Cast<uint, byte>(parameters.ChannelMappings.AsSpan()).ToArray(); byte[] mappings = MemoryMarshal.Cast<uint, byte>(parameters.ChannelMappings).ToArray();
// UseLargeFrameSize can be ignored due to not relying on fixed size buffers for storing the decoded result. // UseLargeFrameSize can be ignored due to not relying on fixed size buffers for storing the decoded result.
MakeObject(context, new IHardwareOpusDecoder( MakeObject(context, new IHardwareOpusDecoder(

View file

@ -292,7 +292,7 @@ namespace Ryujinx.HLE.HOS.Services.Friend.ServiceCreator
Array16<byte> randomGuid = new(); Array16<byte> randomGuid = new();
Guid.NewGuid().ToByteArray().AsSpan().CopyTo(randomGuid.AsSpan()); Guid.NewGuid().ToByteArray().AsSpan().CopyTo(randomGuid);
PlayHistoryRegistrationKey playHistoryRegistrationKey = new() PlayHistoryRegistrationKey playHistoryRegistrationKey = new()
{ {

View file

@ -26,7 +26,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
SamplingNumber = previousEntry.SamplingNumber + 1, SamplingNumber = previousEntry.SamplingNumber + 1,
}; };
keyState.Keys.AsSpan().CopyTo(newState.Keys.RawData.AsSpan()); keyState.Keys.AsSpan().CopyTo(newState.Keys.RawData);
newState.Modifiers = (KeyboardModifier)keyState.Modifier; newState.Modifiers = (KeyboardModifier)keyState.Modifier;
lifo.Write(ref newState); lifo.Write(ref newState);

View file

@ -549,7 +549,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
Attributes = SixAxisSensorAttribute.IsConnected, Attributes = SixAxisSensorAttribute.IsConnected,
}; };
state.Orientation.AsSpan().CopyTo(newState.Direction.AsSpan()); state.Orientation.AsSpan().CopyTo(newState.Direction);
ref RingLifo<SixAxisSensorState> lifo = ref GetSixAxisSensorLifo(ref currentNpad, isRightPair); ref RingLifo<SixAxisSensorState> lifo = ref GetSixAxisSensorLifo(ref currentNpad, isRightPair);

View file

@ -1,5 +1,6 @@
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System; using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Threading; using System.Threading;
@ -37,6 +38,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common
return (index + 1) % MaxEntries; return (index + 1) % MaxEntries;
} }
[UnscopedRef]
public ref AtomicStorage<T> GetCurrentAtomicEntryRef() public ref AtomicStorage<T> GetCurrentAtomicEntryRef()
{ {
ulong countAvailaible = Math.Min(Math.Max(0, ReadCurrentCount()), 1); ulong countAvailaible = Math.Min(Math.Max(0, ReadCurrentCount()), 1);
@ -73,6 +75,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common
} }
} }
[UnscopedRef]
public ref T GetCurrentEntryRef() public ref T GetCurrentEntryRef()
{ {
return ref GetCurrentAtomicEntryRef().Object; return ref GetCurrentAtomicEntryRef().Object;

View file

@ -102,7 +102,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnMitm
{ {
Length = LdnConst.SsidLengthMax, Length = LdnConst.SsidLengthMax,
}; };
_random.NextBytes(_fakeSsid.Name.AsSpan()[..32]); _random.NextBytes(_fakeSsid.Name[..32]);
_protocol = new LanProtocol(this); _protocol = new LanProtocol(this);
_protocol.Accept += OnConnect; _protocol.Accept += OnConnect;
@ -203,7 +203,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnMitm
return false; return false;
} }
data.CopyTo(NetworkInfo.Ldn.AdvertiseData.AsSpan()); data.CopyTo(NetworkInfo.Ldn.AdvertiseData);
NetworkInfo.Ldn.AdvertiseDataSize = (ushort)data.Length; NetworkInfo.Ldn.AdvertiseDataSize = (ushort)data.Length;
// NOTE: Otherwise this results in SessionKeepFailed or MasterDisconnected // NOTE: Otherwise this results in SessionKeepFailed or MasterDisconnected
@ -245,7 +245,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnMitm
byte[] ip = address.GetAddressBytes(); byte[] ip = address.GetAddressBytes();
var macAddress = new Array6<byte>(); var macAddress = new Array6<byte>();
new byte[] { 0x02, 0x00, ip[0], ip[1], ip[2], ip[3] }.CopyTo(macAddress.AsSpan()); new byte[] { 0x02, 0x00, ip[0], ip[1], ip[2], ip[3] }.CopyTo(macAddress);
return macAddress; return macAddress;
} }
@ -356,7 +356,10 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnMitm
if (filter.Flag.HasFlag(ScanFilterFlag.SessionId)) if (filter.Flag.HasFlag(ScanFilterFlag.SessionId))
{ {
copy &= filter.NetworkId.SessionId.AsSpan().SequenceEqual(item.Value.NetworkId.SessionId.AsSpan()); Array16<byte> lSessionId = filter.NetworkId.SessionId;
Array16<byte> rSessionId = item.Value.NetworkId.SessionId;
copy &= ((Span<byte>)lSessionId).SequenceEqual(rSessionId);
} }
if (filter.Flag.HasFlag(ScanFilterFlag.NetworkType)) if (filter.Flag.HasFlag(ScanFilterFlag.NetworkType))
@ -366,8 +369,10 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnMitm
if (filter.Flag.HasFlag(ScanFilterFlag.Ssid)) if (filter.Flag.HasFlag(ScanFilterFlag.Ssid))
{ {
Span<byte> gameSsid = item.Value.Common.Ssid.Name.AsSpan()[item.Value.Common.Ssid.Length..]; Array33<byte> ssidName = item.Value.Common.Ssid.Name;
Span<byte> scanSsid = filter.Ssid.Name.AsSpan()[filter.Ssid.Length..]; ReadOnlySpan<byte> gameSsid = ssidName[item.Value.Common.Ssid.Length..];
ReadOnlySpan<byte> scanSsid = filter.Ssid.Name[filter.Ssid.Length..];
copy &= gameSsid.SequenceEqual(scanSsid); copy &= gameSsid.SequenceEqual(scanSsid);
} }
@ -486,7 +491,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnMitm
NetworkInfo.Common.Channel = networkConfig.Channel == 0 ? (ushort)6 : networkConfig.Channel; NetworkInfo.Common.Channel = networkConfig.Channel == 0 ? (ushort)6 : networkConfig.Channel;
NetworkInfo.NetworkId.SessionId = new Array16<byte>(); NetworkInfo.NetworkId.SessionId = new Array16<byte>();
_random.NextBytes(NetworkInfo.NetworkId.SessionId.AsSpan()); _random.NextBytes(NetworkInfo.NetworkId.SessionId);
NetworkInfo.NetworkId.IntentId = networkConfig.IntentId; NetworkInfo.NetworkId.IntentId = networkConfig.IntentId;
NetworkInfo.Ldn.Nodes[0] = GetNodeInfo(NetworkInfo.Ldn.Nodes[0], userConfig, networkConfig.LocalCommunicationVersion); NetworkInfo.Ldn.Nodes[0] = GetNodeInfo(NetworkInfo.Ldn.Nodes[0], userConfig, networkConfig.LocalCommunicationVersion);

View file

@ -86,7 +86,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnMitm.Proxy
{ {
Span<byte> mac = stackalloc byte[8]; Span<byte> mac = stackalloc byte[8];
info.Common.MacAddress.AsSpan().CopyTo(mac); ((Span<byte>)info.Common.MacAddress).CopyTo(mac);
lock (_scanLock) lock (_scanLock)
{ {

View file

@ -1,5 +1,6 @@
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System; using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using static Ryujinx.HLE.HOS.Services.Mii.Types.RandomMiiConstants; using static Ryujinx.HLE.HOS.Services.Mii.Types.RandomMiiConstants;
@ -13,7 +14,8 @@ namespace Ryujinx.HLE.HOS.Services.Mii.Types
private Array48<byte> _storage; private Array48<byte> _storage;
public Span<byte> Storage => _storage.AsSpan(); [UnscopedRef]
public Span<byte> Storage => _storage;
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 0x18)] [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 0x18)]
public struct ElementInfo public struct ElementInfo
@ -373,6 +375,7 @@ namespace Ryujinx.HLE.HOS.Services.Mii.Types
set => SetValue(ElementInfoIndex.MoleScale, value); set => SetValue(ElementInfoIndex.MoleScale, value);
} }
[UnscopedRef]
public Span<byte> GetNicknameStorage() public Span<byte> GetNicknameStorage()
{ {
return Storage[0x1c..]; return Storage[0x1c..];

View file

@ -1,5 +1,6 @@
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System; using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
@ -16,8 +17,10 @@ namespace Ryujinx.HLE.HOS.Services.Mii.Types
public static Nickname Default => FromString("no name"); public static Nickname Default => FromString("no name");
public static Nickname Question => FromString("???"); public static Nickname Question => FromString("???");
public Span<byte> Raw => _storage.AsSpan(); [UnscopedRef]
public Span<byte> Raw => _storage;
[UnscopedRef]
private ReadOnlySpan<ushort> Characters => MemoryMarshal.Cast<byte, ushort>(Raw); private ReadOnlySpan<ushort> Characters => MemoryMarshal.Cast<byte, ushort>(Raw);
private int GetEndCharacterIndex() private int GetEndCharacterIndex()

View file

@ -1,5 +1,6 @@
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System; using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Ryujinx.HLE.HOS.Services.Mii.Types namespace Ryujinx.HLE.HOS.Services.Mii.Types
@ -35,7 +36,8 @@ namespace Ryujinx.HLE.HOS.Services.Mii.Types
private Array47<int> _values; private Array47<int> _values;
public ReadOnlySpan<int> Values => _values.AsSpan()[..ValuesCount]; [UnscopedRef]
public ReadOnlySpan<int> Values => _values[..ValuesCount];
} }
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 0xC8)] [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 0xC8)]
@ -48,7 +50,8 @@ namespace Ryujinx.HLE.HOS.Services.Mii.Types
private Array47<int> _values; private Array47<int> _values;
public ReadOnlySpan<int> Values => _values.AsSpan()[..ValuesCount]; [UnscopedRef]
public ReadOnlySpan<int> Values => _values[..ValuesCount];
} }
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 0xC4)] [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 0xC4)]
@ -60,7 +63,8 @@ namespace Ryujinx.HLE.HOS.Services.Mii.Types
private Array47<int> _values; private Array47<int> _values;
public ReadOnlySpan<int> Values => _values.AsSpan()[..ValuesCount]; [UnscopedRef]
public ReadOnlySpan<int> Values => _values[..ValuesCount];
} }
public static ReadOnlySpan<RandomMiiData4> RandomMiiFacelineArray => MemoryMarshal.Cast<byte, RandomMiiData4>(RandomMiiFacelineRawArray); public static ReadOnlySpan<RandomMiiData4> RandomMiiFacelineArray => MemoryMarshal.Cast<byte, RandomMiiData4>(RandomMiiFacelineRawArray);

View file

@ -1,6 +1,7 @@
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using System; using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Ryujinx.HLE.HOS.Services.Mii.Types namespace Ryujinx.HLE.HOS.Services.Mii.Types
@ -12,7 +13,8 @@ namespace Ryujinx.HLE.HOS.Services.Mii.Types
private Array96<byte> _storage; private Array96<byte> _storage;
public Span<byte> Storage => _storage.AsSpan(); [UnscopedRef]
public Span<byte> Storage => _storage;
// TODO: define all getters/setters // TODO: define all getters/setters
} }

View file

@ -626,7 +626,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
Reserved2 = new Array6<byte>(), Reserved2 = new Array6<byte>(),
}; };
uuid.CopyTo(tagInfo.Uuid.AsSpan()); uuid.CopyTo(tagInfo.Uuid);
context.Memory.Write(outputPosition, tagInfo); context.Memory.Write(outputPosition, tagInfo);

View file

@ -85,7 +85,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
Reserved1 = new Array64<byte>(), Reserved1 = new Array64<byte>(),
Reserved2 = new Array58<byte>(), Reserved2 = new Array58<byte>(),
}; };
"Ryujinx"u8.CopyTo(registerInfo.Nickname.AsSpan()); "Ryujinx"u8.CopyTo(registerInfo.Nickname);
return registerInfo; return registerInfo;
} }

View file

@ -84,7 +84,7 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
networkProfile.IpSettingData.IpAddressSetting = new IpAddressSetting(interfaceProperties, unicastAddress); networkProfile.IpSettingData.IpAddressSetting = new IpAddressSetting(interfaceProperties, unicastAddress);
networkProfile.IpSettingData.DnsSetting = new DnsSetting(interfaceProperties); networkProfile.IpSettingData.DnsSetting = new DnsSetting(interfaceProperties);
"RyujinxNetwork"u8.CopyTo(networkProfile.Name.AsSpan()); "RyujinxNetwork"u8.CopyTo(networkProfile.Name);
context.Memory.Write(networkProfileDataPosition, networkProfile); context.Memory.Write(networkProfileDataPosition, networkProfile);

View file

@ -16,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Types
public IPEndPoint ToIPEndPoint() public IPEndPoint ToIPEndPoint()
{ {
IPAddress address = new(Address.AsSpan()); IPAddress address = new(Address);
int port = (ushort)IPAddress.NetworkToHostOrder((short)Port); int port = (ushort)IPAddress.NetworkToHostOrder((short)Port);
return new IPEndPoint(address, port); return new IPEndPoint(address, port);
@ -31,7 +31,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Types
Port = (ushort)IPAddress.HostToNetworkOrder((short)endpoint.Port), Port = (ushort)IPAddress.HostToNetworkOrder((short)endpoint.Port),
}; };
endpoint.Address.GetAddressBytes().AsSpan().CopyTo(result.Address.AsSpan()); endpoint.Address.GetAddressBytes().AsSpan().CopyTo(result.Address);
return result; return result;
} }

View file

@ -23,7 +23,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres.Types
Port = IPAddress.HostToNetworkOrder(port); Port = IPAddress.HostToNetworkOrder(port);
Address = new Array4<byte>(); Address = new Array4<byte>();
address.TryWriteBytes(Address.AsSpan(), out _); address.TryWriteBytes(Address, out _);
} }
public void ToNetworkOrder() public void ToNetworkOrder()
@ -44,7 +44,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres.Types
{ {
if (BitConverter.IsLittleEndian) if (BitConverter.IsLittleEndian)
{ {
address.AsSpan().Reverse(); ((Span<byte>)address).Reverse();
} }
} }
} }

View file

@ -1442,7 +1442,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
int timeZoneSize = Math.Min(StringUtils.LengthCstr(timeZoneAbbreviation), 8); int timeZoneSize = Math.Min(StringUtils.LengthCstr(timeZoneAbbreviation), 8);
timeZoneAbbreviation[..timeZoneSize].CopyTo(calendarAdditionalInfo.TimezoneName.AsSpan()); timeZoneAbbreviation[..timeZoneSize].CopyTo(calendarAdditionalInfo.TimezoneName);
} }
return result; return result;

View file

@ -49,7 +49,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
Height = height, Height = height,
}; };
Encoding.ASCII.GetBytes(name).AsSpan().CopyTo(displayInfo.Name.AsSpan()); Encoding.ASCII.GetBytes(name).AsSpan().CopyTo(displayInfo.Name);
_displayInfo.Add(displayInfo); _displayInfo.Add(displayInfo);
} }
@ -171,7 +171,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
return ResultCode.InvalidValue; return ResultCode.InvalidValue;
} }
int displayId = _displayInfo.FindIndex(display => Encoding.ASCII.GetString(display.Name.AsSpan()).Trim('\0') == name); int displayId = _displayInfo.FindIndex(display => Encoding.ASCII.GetString(display.Name).Trim('\0') == name);
if (displayId == -1) if (displayId == -1)
{ {

View file

@ -400,10 +400,10 @@ namespace Ryujinx.Input.Motion.CemuHook
writer.Seek(6, SeekOrigin.Begin); writer.Seek(6, SeekOrigin.Begin);
writer.Write(header.Length); writer.Write(header.Length);
Crc32.Hash(stream.ToArray(), header.Crc32.AsSpan()); Crc32.Hash(stream.ToArray(), header.Crc32);
writer.Seek(8, SeekOrigin.Begin); writer.Seek(8, SeekOrigin.Begin);
writer.Write(header.Crc32.AsSpan()); writer.Write(header.Crc32);
byte[] data = stream.ToArray(); byte[] data = stream.ToArray();
@ -438,10 +438,10 @@ namespace Ryujinx.Input.Motion.CemuHook
writer.Seek(6, SeekOrigin.Begin); writer.Seek(6, SeekOrigin.Begin);
writer.Write(header.Length); writer.Write(header.Length);
Crc32.Hash(stream.ToArray(), header.Crc32.AsSpan()); Crc32.Hash(stream.ToArray(), header.Crc32);
writer.Seek(8, SeekOrigin.Begin); writer.Seek(8, SeekOrigin.Begin);
writer.Write(header.Crc32.AsSpan()); writer.Write(header.Crc32);
byte[] data = stream.ToArray(); byte[] data = stream.ToArray();