From 40b21cc3c4d2622bbd4f88d43073341854d9a671 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sun, 11 Jul 2021 17:20:40 -0300 Subject: Separate GPU engines (part 2/2) (#2440) * 3D engine now uses DeviceState too, plus new state modification tracking * Remove old methods code * Remove GpuState and friends * Optimize DeviceState, force inline some functions * This change was not supposed to go in * Proper channel initialization * Optimize state read/write methods even more * Fix debug build * Do not dirty state if the write is redundant * The YControl register should dirty either the viewport or front face state too, to update the host origin * Avoid redundant vertex buffer updates * Move state and get rid of the Ryujinx.Graphics.Gpu.State namespace * Comments and nits * Fix rebase * PR feedback * Move changed = false to improve codegen * PR feedback * Carry RyuJIT a bit more --- .../Engine/DeviceStateWithShadow.cs | 95 ++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 Ryujinx.Graphics.Gpu/Engine/DeviceStateWithShadow.cs (limited to 'Ryujinx.Graphics.Gpu/Engine/DeviceStateWithShadow.cs') diff --git a/Ryujinx.Graphics.Gpu/Engine/DeviceStateWithShadow.cs b/Ryujinx.Graphics.Gpu/Engine/DeviceStateWithShadow.cs new file mode 100644 index 00000000..3a06bc2a --- /dev/null +++ b/Ryujinx.Graphics.Gpu/Engine/DeviceStateWithShadow.cs @@ -0,0 +1,95 @@ +using Ryujinx.Graphics.Device; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.CompilerServices; + +namespace Ryujinx.Graphics.Gpu.Engine +{ + /// + /// State interface with a shadow memory control register. + /// + interface IShadowState + { + /// + /// MME shadow ram control mode. + /// + SetMmeShadowRamControlMode SetMmeShadowRamControlMode { get; } + } + + /// + /// Represents a device's state, with a additional shadow state. + /// + /// Type of the state + class DeviceStateWithShadow : IDeviceState where TState : unmanaged, IShadowState + { + private readonly DeviceState _state; + private readonly DeviceState _shadowState; + + /// + /// Current device state. + /// + public ref TState State => ref _state.State; + + /// + /// Creates a new instance of the device state, with shadow state. + /// + /// Optional that will be called if a register specified by name is read or written + /// Optional callback to be used for debug log messages + public DeviceStateWithShadow(IReadOnlyDictionary callbacks = null, Action debugLogCallback = null) + { + _state = new DeviceState(callbacks, debugLogCallback); + _shadowState = new DeviceState(); + } + + /// + /// Reads a value from a register. + /// + /// Register offset in bytes + /// Value stored on the register + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Read(int offset) + { + return _state.Read(offset); + } + + /// + /// Writes a value to a register. + /// + /// Register offset in bytes + /// Value to be written + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Write(int offset, int value) + { + WriteWithRedundancyCheck(offset, value, out _); + } + + /// + /// Writes a value to a register, returning a value indicating if + /// is different from the current value on the register. + /// + /// Register offset in bytes + /// Value to be written + /// True if the value was changed, false otherwise + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void WriteWithRedundancyCheck(int offset, int value, out bool changed) + { + var shadowRamControl = _state.State.SetMmeShadowRamControlMode; + if (shadowRamControl == SetMmeShadowRamControlMode.MethodPassthrough || offset < 0x200) + { + _state.WriteWithRedundancyCheck(offset, value, out changed); + } + else if (shadowRamControl == SetMmeShadowRamControlMode.MethodTrack || + shadowRamControl == SetMmeShadowRamControlMode.MethodTrackWithFilter) + { + _shadowState.Write(offset, value); + _state.WriteWithRedundancyCheck(offset, value, out changed); + } + else /* if (shadowRamControl == SetMmeShadowRamControlMode.MethodReplay) */ + { + Debug.Assert(shadowRamControl == SetMmeShadowRamControlMode.MethodReplay); + _state.WriteWithRedundancyCheck(offset, _shadowState.Read(offset), out changed); + } + } + } +} -- cgit v1.2.3