Memory Changes part 2 (ryubing/ryujinx!123)

See merge request ryubing/ryujinx!123
This commit is contained in:
LotP
2025-08-25 17:44:15 -05:00
parent d499449f57
commit 50ab108ee1
90 changed files with 2133 additions and 1159 deletions

View File

@@ -219,13 +219,14 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
state.Write(LogicOpOffset, 0);
Array8<Boolean32> enable = new();
Span<Boolean32> enableSpan = enable.AsSpan();
for (int i = 0; i < 8; i++)
{
enable[i] = new Boolean32((uint)(arg0 >> (i + 8)) & 1);
enableSpan[i] = new Boolean32((uint)(arg0 >> (i + 8)) & 1);
}
_processor.ThreedClass.UpdateBlendEnable(ref enable);
_processor.ThreedClass.UpdateBlendEnable(enableSpan);
}
/// <summary>
@@ -236,13 +237,14 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
private void UpdateColorMasks(IDeviceState state, int arg0)
{
Array8<RtColorMask> masks = new();
Span<RtColorMask> masksSpan = masks.AsSpan();
int index = 0;
for (int i = 0; i < 4; i++)
{
masks[index++] = new RtColorMask((uint)arg0 & 0x1fff);
masks[index++] = new RtColorMask(((uint)arg0 >> 16) & 0x1fff);
masksSpan[index++] = new RtColorMask((uint)arg0 & 0x1fff);
masksSpan[index++] = new RtColorMask(((uint)arg0 >> 16) & 0x1fff);
if (i != 3)
{
@@ -250,7 +252,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
}
}
_processor.ThreedClass.UpdateColorMasks(ref masks);
_processor.ThreedClass.UpdateColorMasks(masksSpan);
}
/// <summary>

View File

@@ -75,10 +75,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.Blender
{
bool constantsMatch = true;
Span<RgbHalf> blendUcodeConstantsSpan = _state.State.BlendUcodeConstants.AsSpan();
for (int i = 0; i < entry.Constants.Length; i++)
{
RgbFloat constant = entry.Constants[i];
RgbHalf constant2 = _state.State.BlendUcodeConstants[i];
RgbHalf constant2 = blendUcodeConstantsSpan[i];
if ((Half)constant.R != constant2.UnpackR() ||
(Half)constant.G != constant2.UnpackG() ||

View File

@@ -1,6 +1,7 @@
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Gpu.Memory;
using Ryujinx.Graphics.Shader;
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -76,9 +77,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
/// <param name="componentCount">Number of components that the format has</param>
public void SetVertexStride(int index, int stride, int componentCount)
{
if (_data.VertexStrides[index].X != stride)
Span<Vector4<int>> vertexStridesSpan = _data.VertexStrides.AsSpan();
if (vertexStridesSpan[index].X != stride)
{
_data.VertexStrides[index].X = stride;
vertexStridesSpan[index].X = stride;
MarkDirty(VertexInfoBuffer.VertexStridesOffset + index * Unsafe.SizeOf<Vector4<int>>(), sizeof(int));
}
@@ -86,7 +89,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
{
int value = c < componentCount ? 1 : 0;
ref int currentValue = ref GetElementRef(ref _data.VertexStrides[index], c);
ref int currentValue = ref GetElementRef(ref vertexStridesSpan[index], c);
if (currentValue != value)
{
@@ -104,15 +107,17 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
/// <param name="divisor">If the draw is instanced, should have the vertex divisor value, otherwise should be zero</param>
public void SetVertexOffset(int index, int offset, int divisor)
{
if (_data.VertexOffsets[index].X != offset)
Span<Vector4<int>> vertexOffsetsSpan = _data.VertexOffsets.AsSpan();
if (vertexOffsetsSpan[index].X != offset)
{
_data.VertexOffsets[index].X = offset;
vertexOffsetsSpan[index].X = offset;
MarkDirty(VertexInfoBuffer.VertexOffsetsOffset + index * Unsafe.SizeOf<Vector4<int>>(), sizeof(int));
}
if (_data.VertexOffsets[index].Y != divisor)
if (vertexOffsetsSpan[index].Y != divisor)
{
_data.VertexOffsets[index].Y = divisor;
vertexOffsetsSpan[index].Y = divisor;
MarkDirty(VertexInfoBuffer.VertexOffsetsOffset + index * Unsafe.SizeOf<Vector4<int>>() + sizeof(int), sizeof(int));
}
}

View File

@@ -125,9 +125,14 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
_vacContext.VertexInfoBufferUpdater.SetVertexCounts(_count, _instanceCount, _firstVertex, _firstInstance);
_vacContext.VertexInfoBufferUpdater.SetGeometryCounts(primitivesCount);
Span<VertexAttribState> vertexAttribStateSpan = _state.State.VertexAttribState.AsSpan();
Span<GpuVa> vertexBufferEndAddressSpan = _state.State.VertexBufferEndAddress.AsSpan();
Span<VertexBufferState> vertexBufferStateSpan = _state.State.VertexBufferState.AsSpan();
Span<Boolean32> vertexBufferInstancedSpan = _state.State.VertexBufferInstanced.AsSpan();
for (int index = 0; index < Constants.TotalVertexAttribs; index++)
{
VertexAttribState vertexAttrib = _state.State.VertexAttribState[index];
VertexAttribState vertexAttrib = vertexAttribStateSpan[index];
if (!FormatTable.TryGetSingleComponentAttribFormat(vertexAttrib.UnpackFormat(), out Format format, out int componentsCount))
{
@@ -153,9 +158,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
int bufferIndex = vertexAttrib.UnpackBufferIndex();
GpuVa endAddress = _state.State.VertexBufferEndAddress[bufferIndex];
VertexBufferState vertexBuffer = _state.State.VertexBufferState[bufferIndex];
bool instanced = _state.State.VertexBufferInstanced[bufferIndex];
GpuVa endAddress = vertexBufferEndAddressSpan[bufferIndex];
VertexBufferState vertexBuffer = vertexBufferStateSpan[bufferIndex];
bool instanced = vertexBufferInstancedSpan[bufferIndex];
ulong address = vertexBuffer.Address.Pack();

View File

@@ -821,6 +821,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
// on the screen scissor state, then we need to force only one texture to be bound to avoid
// host clipping.
ScreenScissorState screenScissorState = _state.State.ScreenScissorState;
Span<ScissorState> scissorStateSpan = _state.State.ScissorState.AsSpan();
bool clearAffectedByStencilMask = (_state.State.ClearFlags & 1) != 0;
bool clearAffectedByScissor = (_state.State.ClearFlags & 0x100) != 0;
@@ -831,9 +833,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
bool fullClear = screenScissorState.X == 0 && screenScissorState.Y == 0;
if (fullClear && clearAffectedByScissor && _state.State.ScissorState[0].Enable)
if (fullClear && clearAffectedByScissor && scissorStateSpan[0].Enable)
{
ref ScissorState scissorState = ref _state.State.ScissorState[0];
ref ScissorState scissorState = ref scissorStateSpan[0];
fullClear = scissorState.X1 == screenScissorState.X &&
scissorState.Y1 == screenScissorState.Y &&
@@ -892,9 +894,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
int scissorW = screenScissorState.Width;
int scissorH = screenScissorState.Height;
if (clearAffectedByScissor && _state.State.ScissorState[0].Enable)
if (clearAffectedByScissor && scissorStateSpan[0].Enable)
{
ref ScissorState scissorState = ref _state.State.ScissorState[0];
ref ScissorState scissorState = ref scissorStateSpan[0];
scissorX = Math.Max(scissorX, scissorState.X1);
scissorY = Math.Max(scissorY, scissorState.Y1);

View File

@@ -3,6 +3,7 @@ using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Gpu.Engine.Types;
using Ryujinx.Graphics.Gpu.Shader;
using Ryujinx.Graphics.Shader;
using System;
namespace Ryujinx.Graphics.Gpu.Engine.Threed
{
@@ -214,10 +215,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
/// Updates the type of the vertex attributes consumed by the shader.
/// </summary>
/// <param name="state">The new state</param>
public void SetAttributeTypes(ref Array32<VertexAttribState> state)
public void SetAttributeTypes(ReadOnlySpan<VertexAttribState> state)
{
bool changed = false;
ref Array32<AttributeType> attributeTypes = ref _graphics.AttributeTypes;
// ref Array32<AttributeType> attributeTypes = ref _graphics.AttributeTypes;
Span<AttributeType> attributeTypesSpan = _graphics.AttributeTypes.AsSpan();
bool mayConvertVtgToCompute = ShaderCache.MayConvertVtgToCompute(ref _context.Capabilities);
bool supportsScaledFormats = _context.Capabilities.SupportsScaledVertexFormats && !mayConvertVtgToCompute;
@@ -261,9 +263,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
}
}
if (attributeTypes[location] != value)
if (attributeTypesSpan[location] != value)
{
attributeTypes[location] = value;
attributeTypesSpan[location] = value;
changed = true;
}
}
@@ -279,10 +281,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
/// </summary>
/// <param name="rtControl">The render target control register</param>
/// <param name="state">The color attachment state</param>
public void SetFragmentOutputTypes(RtControl rtControl, ref Array8<RtColorState> state)
public void SetFragmentOutputTypes(RtControl rtControl, ReadOnlySpan<RtColorState> state)
{
bool changed = false;
int count = rtControl.UnpackCount();
Span<AttributeType> fragmentOutputTypesSpan = _graphics.FragmentOutputTypes.AsSpan();
for (int index = 0; index < Constants.TotalRenderTargets; index++)
{
@@ -296,9 +300,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
AttributeType type = format.IsInteger() ? (format.IsSint() ? AttributeType.Sint : AttributeType.Uint) : AttributeType.Float;
if (type != _graphics.FragmentOutputTypes[index])
if (type != fragmentOutputTypesSpan[index])
{
_graphics.FragmentOutputTypes[index] = type;
fragmentOutputTypesSpan[index] = type;
changed = true;
}
}

View File

@@ -423,9 +423,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
/// </summary>
private void UpdateTfBufferState()
{
Span<TfBufferState> tfBufferStateSpan = _state.State.TfBufferState.AsSpan();
for (int index = 0; index < Constants.TotalTransformFeedbackBuffers; index++)
{
TfBufferState tfb = _state.State.TfBufferState[index];
TfBufferState tfb = tfBufferStateSpan[index];
if (!tfb.Enable)
{
@@ -466,10 +468,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
MemoryManager memoryManager = _channel.MemoryManager;
RtControl rtControl = _state.State.RtControl;
bool useControl = updateFlags.HasFlag(RenderTargetUpdateFlags.UseControl);
bool layered = updateFlags.HasFlag(RenderTargetUpdateFlags.Layered);
bool singleColor = updateFlags.HasFlag(RenderTargetUpdateFlags.SingleColor);
bool discard = updateFlags.HasFlag(RenderTargetUpdateFlags.DiscardClip);
bool useControl = (updateFlags & RenderTargetUpdateFlags.UseControl) == RenderTargetUpdateFlags.UseControl;
bool layered = (updateFlags & RenderTargetUpdateFlags.Layered) == RenderTargetUpdateFlags.Layered;
bool singleColor = (updateFlags & RenderTargetUpdateFlags.SingleColor) == RenderTargetUpdateFlags.SingleColor;
bool discard = (updateFlags & RenderTargetUpdateFlags.DiscardClip) == RenderTargetUpdateFlags.DiscardClip;
int count = useControl ? rtControl.UnpackCount() : Constants.TotalRenderTargets;
@@ -487,11 +489,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
bool changedScale = false;
uint rtNoAlphaMask = 0;
Span<RtColorState> rtColorStateSpan = _state.State.RtColorState.AsSpan();
for (int index = 0; index < Constants.TotalRenderTargets; index++)
{
int rtIndex = useControl ? rtControl.UnpackPermutationIndex(index) : index;
RtColorState colorState = _state.State.RtColorState[rtIndex];
RtColorState colorState = rtColorStateSpan[rtIndex];
if (index >= count || !IsRtEnabled(colorState) || (singleColor && index != singleUse))
{
@@ -539,7 +543,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
Image.Texture depthStencil = null;
if (dsEnable && updateFlags.HasFlag(RenderTargetUpdateFlags.UpdateDepthStencil))
if (dsEnable && (updateFlags & RenderTargetUpdateFlags.UpdateDepthStencil) == RenderTargetUpdateFlags.UpdateDepthStencil)
{
RtDepthStencilState dsState = _state.State.RtDepthStencilState;
Size3D dsSize = _state.State.RtDepthStencilSize;
@@ -599,7 +603,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
/// </summary>
public void UpdateRenderTargetSpecialization()
{
_currentSpecState.SetFragmentOutputTypes(_state.State.RtControl, ref _state.State.RtColorState);
_currentSpecState.SetFragmentOutputTypes(_state.State.RtControl, _state.State.RtColorState.AsSpan());
}
/// <summary>
@@ -624,10 +628,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
const int MaxH = 0xffff;
Span<Rectangle<int>> regions = stackalloc Rectangle<int>[Constants.TotalViewports];
Span<ScissorState> scissorStateSpan = _state.State.ScissorState.AsSpan();
for (int index = 0; index < Constants.TotalViewports; index++)
{
ScissorState scissor = _state.State.ScissorState[index];
ScissorState scissor = scissorStateSpan[index];
bool enable = scissor.Enable && (scissor.X1 != MinX ||
scissor.Y1 != MinY ||
@@ -731,6 +736,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
UpdateDepthMode();
Span<Viewport> viewports = stackalloc Viewport[Constants.TotalViewports];
Span<ViewportTransform> viewportTransformSpan = _state.State.ViewportTransform.AsSpan();
Span<ViewportExtents> viewportExtentsSpan = _state.State.ViewportExtents.AsSpan();
for (int index = 0; index < Constants.TotalViewports; index++)
{
@@ -745,8 +752,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
continue;
}
ref ViewportTransform transform = ref _state.State.ViewportTransform[index];
ref ViewportExtents extents = ref _state.State.ViewportExtents[index];
ref ViewportTransform transform = ref viewportTransformSpan[index];
ref ViewportExtents extents = ref viewportExtentsSpan[index];
float scaleX = MathF.Abs(transform.ScaleX);
float scaleY = transform.ScaleY;
@@ -968,10 +975,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
uint vbEnableMask = _vbEnableMask;
Span<VertexAttribDescriptor> vertexAttribs = stackalloc VertexAttribDescriptor[Constants.TotalVertexAttribs];
Span<VertexAttribState> vertexAttribStateSpan = _state.State.VertexAttribState.AsSpan();
for (int index = 0; index < Constants.TotalVertexAttribs; index++)
{
VertexAttribState vertexAttrib = _state.State.VertexAttribState[index];
VertexAttribState vertexAttrib = vertexAttribStateSpan[index];
int bufferIndex = vertexAttrib.UnpackBufferIndex();
@@ -1015,7 +1023,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
_pipeline.SetVertexAttribs(vertexAttribs);
_context.Renderer.Pipeline.SetVertexAttribs(vertexAttribs);
_currentSpecState.SetAttributeTypes(ref _state.State.VertexAttribState);
_currentSpecState.SetAttributeTypes(_state.State.VertexAttribState.AsSpan());
}
/// <summary>
@@ -1113,20 +1121,25 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
int drawFirstVertex = _drawState.DrawFirstVertex;
int drawVertexCount = _drawState.DrawVertexCount;
uint vbEnableMask = 0;
Span<VertexBufferState> vertexBufferStateSpan = _state.State.VertexBufferState.AsSpan();
Span<BufferPipelineDescriptor> vertexBuffersSpan = _pipeline.VertexBuffers.AsSpan();
Span<GpuVa> vertexBufferEndAddressSpan = _state.State.VertexBufferEndAddress.AsSpan();
Span<Boolean32> vertexBufferInstancedSpan = _state.State.VertexBufferInstanced.AsSpan();
for (int index = 0; index < Constants.TotalVertexBuffers; index++)
{
VertexBufferState vertexBuffer = _state.State.VertexBufferState[index];
VertexBufferState vertexBuffer = vertexBufferStateSpan[index];
if (!vertexBuffer.UnpackEnable())
{
_pipeline.VertexBuffers[index] = new BufferPipelineDescriptor(false, 0, 0);
vertexBuffersSpan[index] = new BufferPipelineDescriptor(false, 0, 0);
_channel.BufferManager.SetVertexBuffer(index, 0, 0, 0, 0);
continue;
}
GpuVa endAddress = _state.State.VertexBufferEndAddress[index];
GpuVa endAddress = vertexBufferEndAddressSpan[index];
ulong address = vertexBuffer.Address.Pack();
@@ -1137,7 +1150,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
int stride = vertexBuffer.UnpackStride();
bool instanced = _state.State.VertexBufferInstanced[index];
bool instanced = vertexBufferInstancedSpan[index];
int divisor = instanced ? vertexBuffer.Divisor : 0;
@@ -1184,7 +1197,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
size = Math.Min(vbSize, (ulong)((firstInstance + drawFirstVertex + drawVertexCount) * stride));
}
_pipeline.VertexBuffers[index] = new BufferPipelineDescriptor(_channel.MemoryManager.IsMapped(address), stride, divisor);
vertexBuffersSpan[index] = new BufferPipelineDescriptor(_channel.MemoryManager.IsMapped(address), stride, divisor);
_channel.BufferManager.SetVertexBuffer(index, address, size, stride, divisor);
}
@@ -1237,10 +1250,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
bool rtColorMaskShared = _state.State.RtColorMaskShared;
Span<uint> componentMasks = stackalloc uint[Constants.TotalRenderTargets];
Span<RtColorMask> rtColorMaskSpan = _state.State.RtColorMask.AsSpan();
Span<uint> colorWriteMaskSpan = _pipeline.ColorWriteMask.AsSpan();
for (int index = 0; index < Constants.TotalRenderTargets; index++)
{
RtColorMask colorMask = _state.State.RtColorMask[rtColorMaskShared ? 0 : index];
RtColorMask colorMask = rtColorMaskSpan[rtColorMaskShared ? 0 : index];
uint componentMask;
@@ -1250,7 +1265,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
componentMask |= (colorMask.UnpackAlpha() ? 8u : 0u);
componentMasks[index] = componentMask;
_pipeline.ColorWriteMask[index] = componentMask;
colorWriteMaskSpan[index] = componentMask;
}
_context.Renderer.Pipeline.SetRenderTargetColorMasks(componentMasks);
@@ -1282,10 +1297,14 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
if (blendIndependent)
{
Span<Boolean32> blendEnableSpan = _state.State.BlendEnable.AsSpan();
Span<BlendState> blendStateSpan = _state.State.BlendState.AsSpan();
Span<BlendDescriptor> blendDescriptorsSpan = _pipeline.BlendDescriptors.AsSpan();
for (int index = 0; index < Constants.TotalRenderTargets; index++)
{
bool enable = _state.State.BlendEnable[index];
BlendState blend = _state.State.BlendState[index];
bool enable = blendEnableSpan[index];
BlendState blend = blendStateSpan[index];
BlendDescriptor descriptor = new(
enable,
@@ -1306,7 +1325,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
dualSourceBlendEnabled = true;
}
_pipeline.BlendDescriptors[index] = descriptor;
blendDescriptorsSpan[index] = descriptor;
_context.Renderer.Pipeline.SetBlendState(index, descriptor);
}
}
@@ -1333,10 +1352,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
{
dualSourceBlendEnabled = true;
}
Span<BlendDescriptor> blendDescriptorsSpan = _pipeline.BlendDescriptors.AsSpan();
for (int index = 0; index < Constants.TotalRenderTargets; index++)
{
_pipeline.BlendDescriptors[index] = descriptor;
blendDescriptorsSpan[index] = descriptor;
_context.Renderer.Pipeline.SetBlendState(index, descriptor);
}
}
@@ -1422,12 +1443,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
ShaderAddresses addresses = new();
Span<ulong> addressesSpan = addresses.AsSpan();
Span<ShaderState> shaderStateSpan = _state.State.ShaderState.AsSpan();
ulong baseAddress = _state.State.ShaderBaseAddress.Pack();
for (int index = 0; index < 6; index++)
{
ShaderState shader = _state.State.ShaderState[index];
ShaderState shader = shaderStateSpan[index];
if (!shader.UnpackEnable() && index != 1)
{
continue;

View File

@@ -242,22 +242,22 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
/// <param name="rhs">Second struct</param>
/// <returns>True if equal, false otherwise</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool UnsafeEquals32Byte<T>(ref T lhs, ref T rhs) where T : unmanaged
private static bool UnsafeEquals32Byte<T>(Span<T> lhs, Span<T> rhs) where T : unmanaged
{
if (Vector256.IsHardwareAccelerated)
{
return Vector256.EqualsAll(
Unsafe.As<T, Vector256<uint>>(ref lhs),
Unsafe.As<T, Vector256<uint>>(ref rhs)
Unsafe.As<Span<T>, ReadOnlySpan<Vector256<uint>>>(ref lhs)[0],
Unsafe.As<Span<T>, ReadOnlySpan<Vector256<uint>>>(ref rhs)[0]
);
}
else
{
ref Vector128<uint> lhsVec = ref Unsafe.As<T, Vector128<uint>>(ref lhs);
ref Vector128<uint> rhsVec = ref Unsafe.As<T, Vector128<uint>>(ref rhs);
ReadOnlySpan<Vector128<uint>> lhsVec = Unsafe.As<Span<T>, ReadOnlySpan<Vector128<uint>>>(ref lhs);
ReadOnlySpan<Vector128<uint>> rhsVec = Unsafe.As<Span<T>, ReadOnlySpan<Vector128<uint>>>(ref rhs);
return Vector128.EqualsAll(lhsVec, rhsVec) &&
Vector128.EqualsAll(Unsafe.Add(ref lhsVec, 1), Unsafe.Add(ref rhsVec, 1));
return Vector128.EqualsAll(lhsVec[0], rhsVec[0]) &&
Vector128.EqualsAll(lhsVec[1], rhsVec[1]);
}
}
@@ -265,26 +265,26 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
/// Updates blend enable. Respects current shadow mode.
/// </summary>
/// <param name="masks">Blend enable</param>
public void UpdateBlendEnable(ref Array8<Boolean32> enable)
public void UpdateBlendEnable(Span<Boolean32> enable)
{
SetMmeShadowRamControlMode shadow = ShadowMode;
ref Array8<Boolean32> state = ref _state.State.BlendEnable;
Span<Boolean32> state = _state.State.BlendEnable.AsSpan();
if (shadow.IsReplay())
{
enable = _state.ShadowState.BlendEnable;
state.CopyTo(enable);
}
if (!UnsafeEquals32Byte(ref enable, ref state))
if (!UnsafeEquals32Byte(enable, state))
{
state = enable;
enable.CopyTo(state);
_stateUpdater.ForceDirty(StateUpdater.BlendStateIndex);
}
if (shadow.IsTrack())
{
_state.ShadowState.BlendEnable = enable;
enable.CopyTo(state);
}
}
@@ -292,26 +292,26 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
/// Updates color masks. Respects current shadow mode.
/// </summary>
/// <param name="masks">Color masks</param>
public void UpdateColorMasks(ref Array8<RtColorMask> masks)
public void UpdateColorMasks(Span<RtColorMask> masks)
{
SetMmeShadowRamControlMode shadow = ShadowMode;
ref Array8<RtColorMask> state = ref _state.State.RtColorMask;
Span<RtColorMask> state = _state.State.RtColorMask.AsSpan();
if (shadow.IsReplay())
{
masks = _state.ShadowState.RtColorMask;
state.CopyTo(masks);
}
if (!UnsafeEquals32Byte(ref masks, ref state))
if (!UnsafeEquals32Byte(masks, state))
{
state = masks;
masks.CopyTo(state);
_stateUpdater.ForceDirty(StateUpdater.RtColorMaskIndex);
}
if (shadow.IsTrack())
{
_state.ShadowState.RtColorMask = masks;
masks.CopyTo(state);
}
}

View File

@@ -72,7 +72,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// </summary>
class BufferModifiedRangeList : NonOverlappingRangeList<BufferModifiedRange>
{
private new const int BackingInitialSize = 8;
private const int BackingInitialSize = 8;
private readonly GpuContext _context;
private readonly Buffer _parent;
@@ -80,6 +80,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
private BufferMigration _source;
private BufferModifiedRangeList _migrationTarget;
private List<RangeItem<BufferModifiedRange>> _overlaps;
/// <summary>
/// Whether the modified range list has any entries or not.
@@ -106,6 +108,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
_context = context;
_parent = parent;
_flushAction = flushAction;
_overlaps = [];
}
/// <summary>
@@ -295,23 +298,24 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// <param name="rangeAction">The action to call for each modified range</param>
public void GetRanges(ulong address, ulong size, Action<ulong, ulong> rangeAction)
{
List<RangeItem<BufferModifiedRange>> overlaps = [];
// We use the non-span method here because keeping the lock will cause a deadlock.
Lock.EnterReadLock();
_overlaps.Clear();
(RangeItem<BufferModifiedRange> first, RangeItem<BufferModifiedRange> last) = FindOverlaps(address, size);
RangeItem<BufferModifiedRange> current = first;
while (last != null && current != last.Next)
{
overlaps.Add(current);
_overlaps.Add(current);
current = current.Next;
}
Lock.ExitReadLock();
for (int i = 0; i < overlaps.Count; i++)
for (int i = 0; i < _overlaps.Count; i++)
{
BufferModifiedRange overlap = overlaps[i].Value;
BufferModifiedRange overlap = _overlaps[i].Value;
rangeAction(overlap.Address, overlap.Size);
}
}

View File

@@ -54,7 +54,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static BufferStage FromUsage(BufferUsageFlags flags)
{
if (flags.HasFlag(BufferUsageFlags.Write))
if ((flags & BufferUsageFlags.Write) == BufferUsageFlags.Write)
{
return BufferStage.StorageWrite;
}
@@ -67,7 +67,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static BufferStage FromUsage(TextureUsageFlags flags)
{
if (flags.HasFlag(TextureUsageFlags.ImageStore))
if ((flags & TextureUsageFlags.ImageStore) == TextureUsageFlags.ImageStore)
{
return BufferStage.StorageWrite;
}

View File

@@ -1,5 +1,6 @@
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Shader;
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -104,9 +105,11 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// <param name="scale">Scale value</param>
public void UpdateRenderScale(int index, float scale)
{
if (_data.RenderScale[1 + index].X != scale)
Span<Vector4<float>> renderScaleSpan = _data.RenderScale.AsSpan();
if (renderScaleSpan[1 + index].X != scale)
{
_data.RenderScale[1 + index].X = scale;
renderScaleSpan[1 + index].X = scale;
DirtyRenderScale(1 + index, 1);
}
}
@@ -133,11 +136,13 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// <param name="isBgra">True if the format is BGRA< false otherwise</param>
public void SetRenderTargetIsBgra(int index, bool isBgra)
{
bool isBgraChanged = _data.FragmentIsBgra[index].X != 0 != isBgra;
Span<Vector4<int>> fragmentIsBgraSpan = _data.FragmentIsBgra.AsSpan();
bool isBgraChanged = fragmentIsBgraSpan[index].X != 0 != isBgra;
if (isBgraChanged)
{
_data.FragmentIsBgra[index].X = isBgra ? 1 : 0;
fragmentIsBgraSpan[index].X = isBgra ? 1 : 0;
DirtyFragmentIsBgra(index, 1);
}
}

View File

@@ -1,5 +1,6 @@
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Gpu.Engine.Threed;
using Ryujinx.Graphics.Gpu.Engine.Types;
@@ -258,21 +259,25 @@ namespace Ryujinx.Graphics.Gpu.Shader
int count = rtControl.UnpackCount();
Span<RtColorState> rtColorStateSpan = state.RtColorState.AsSpan();
Span<bool> attachmentEnableSpan = pipeline.AttachmentEnable.AsSpan();
Span<Format> attachmentFormatsSpan = pipeline.AttachmentFormats.AsSpan();
for (int index = 0; index < Constants.TotalRenderTargets; index++)
{
int rtIndex = rtControl.UnpackPermutationIndex(index);
var colorState = state.RtColorState[rtIndex];
var colorState = rtColorStateSpan[rtIndex];
if (index >= count || colorState.Format == 0 || colorState.WidthOrStride == 0)
{
pipeline.AttachmentEnable[index] = false;
pipeline.AttachmentFormats[index] = Format.R8G8B8A8Unorm;
attachmentEnableSpan[index] = false;
attachmentFormatsSpan[index] = Format.R8G8B8A8Unorm;
}
else
{
pipeline.AttachmentEnable[index] = true;
pipeline.AttachmentFormats[index] = colorState.Format.Convert().Format;
attachmentEnableSpan[index] = true;
attachmentFormatsSpan[index] = colorState.Format.Convert().Format;
}
}
@@ -580,15 +585,18 @@ namespace Ryujinx.Graphics.Gpu.Shader
TransformFeedbackDescriptor[] descs = new TransformFeedbackDescriptor[Constants.TotalTransformFeedbackBuffers];
Span<TfState> tfStateSpan = state.TfState.AsSpan();
Span<Array32<uint>> tfVaryingLocationsSpan = state.TfVaryingLocations.AsSpan();
for (int i = 0; i < Constants.TotalTransformFeedbackBuffers; i++)
{
var tf = state.TfState[i];
var tf = tfStateSpan[i];
descs[i] = new TransformFeedbackDescriptor(
tf.BufferIndex,
tf.Stride,
tf.VaryingsCount,
ref state.TfVaryingLocations[i]);
ref tfVaryingLocationsSpan[i]);
}
return descs;

View File

@@ -580,10 +580,13 @@ namespace Ryujinx.Graphics.Gpu.Shader
if (ShaderCache.MayConvertVtgToCompute(ref channel.Capabilities) && !vertexAsCompute)
{
for (int index = 0; index < graphicsState.AttributeTypes.Length; index++)
Span<AttributeType> attributeTypesSpan = graphicsState.AttributeTypes.AsSpan();
Span<AttributeType> gAttributeTypesSpan = GraphicsState.AttributeTypes.AsSpan();
for (int index = 0; index < attributeTypesSpan.Length; index++)
{
AttributeType lType = FilterAttributeType(channel, graphicsState.AttributeTypes[index]);
AttributeType rType = FilterAttributeType(channel, GraphicsState.AttributeTypes[index]);
AttributeType lType = FilterAttributeType(channel, attributeTypesSpan[index]);
AttributeType rType = FilterAttributeType(channel, gAttributeTypesSpan[index]);
if (lType != rType)
{
@@ -729,6 +732,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
{
int constantBufferUsePerStageMask = _constantBufferUsePerStage;
Span<uint> constantBufferUseSpan = ConstantBufferUse.AsSpan();
while (constantBufferUsePerStageMask != 0)
{
int index = BitOperations.TrailingZeroCount(constantBufferUsePerStageMask);
@@ -737,7 +742,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
? channel.BufferManager.GetComputeUniformBufferUseMask()
: channel.BufferManager.GetGraphicsUniformBufferUseMask(index);
if (ConstantBufferUse[index] != useMask)
if (constantBufferUseSpan[index] != useMask)
{
return false;
}
@@ -801,7 +806,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
{
if (specializationState != null)
{
if (specializationState.Value.QueriedFlags.HasFlag(QueriedTextureStateFlags.CoordNormalized) &&
if ((specializationState.Value.QueriedFlags & QueriedTextureStateFlags.CoordNormalized) == QueriedTextureStateFlags.CoordNormalized &&
specializationState.Value.CoordNormalized != descriptor.UnpackTextureCoordNormalized())
{
return false;
@@ -877,10 +882,12 @@ namespace Ryujinx.Graphics.Gpu.Shader
int constantBufferUsePerStageMask = specState._constantBufferUsePerStage;
Span<uint> constantBufferUseSpan = specState.ConstantBufferUse.AsSpan();
while (constantBufferUsePerStageMask != 0)
{
int index = BitOperations.TrailingZeroCount(constantBufferUsePerStageMask);
dataReader.Read(ref specState.ConstantBufferUse[index]);
dataReader.Read(ref constantBufferUseSpan[index]);
constantBufferUsePerStageMask &= ~(1 << index);
}
@@ -979,11 +986,13 @@ namespace Ryujinx.Graphics.Gpu.Shader
dataWriter.Write(ref _constantBufferUsePerStage);
int constantBufferUsePerStageMask = _constantBufferUsePerStage;
Span<uint> constantBufferUseSpan = ConstantBufferUse.AsSpan();
while (constantBufferUsePerStageMask != 0)
{
int index = BitOperations.TrailingZeroCount(constantBufferUsePerStageMask);
dataWriter.Write(ref ConstantBufferUse[index]);
dataWriter.Write(ref constantBufferUseSpan[index]);
constantBufferUsePerStageMask &= ~(1 << index);
}