aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Gpu/Engine/Threed
diff options
context:
space:
mode:
authorriperiperi <rhy3756547@hotmail.com>2023-10-06 23:55:07 +0100
committerGitHub <noreply@github.com>2023-10-06 19:55:07 -0300
commitf460ecc1829c1b34f2198cc41528b1c6de99d976 (patch)
treeed18225f62b90b2f74ce8a940d9235e08b2517e3 /src/Ryujinx.Graphics.Gpu/Engine/Threed
parent086564c3c88d8006670199b3aba5977c07f16261 (diff)
GPU: Add HLE macros for popular NVN macros (#5761)
* GPU: Add HLE macros for popular NVN macros * Remove non-vector equality check The case where it's not hardware accelerated will do the check integer-wise anyways. * Whitespace :pensive: * Address Feedback
Diffstat (limited to 'src/Ryujinx.Graphics.Gpu/Engine/Threed')
-rw-r--r--src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs2
-rw-r--r--src/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClass.cs207
-rw-r--r--src/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClassState.cs7
3 files changed, 213 insertions, 3 deletions
diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs
index 37e41c51..1ff82156 100644
--- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs
+++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs
@@ -17,9 +17,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
class StateUpdater
{
public const int ShaderStateIndex = 26;
+ public const int RtColorMaskIndex = 14;
public const int RasterizerStateIndex = 15;
public const int ScissorStateIndex = 16;
public const int VertexBufferStateIndex = 0;
+ public const int BlendStateIndex = 2;
public const int IndexBufferStateIndex = 23;
public const int PrimitiveRestartStateIndex = 12;
public const int RenderTargetStateIndex = 27;
diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClass.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClass.cs
index 7bc2970f..df9d1f5c 100644
--- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClass.cs
+++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClass.cs
@@ -1,12 +1,15 @@
-using Ryujinx.Graphics.Device;
+using Ryujinx.Common.Memory;
+using Ryujinx.Graphics.Device;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Gpu.Engine.GPFifo;
using Ryujinx.Graphics.Gpu.Engine.InlineToMemory;
using Ryujinx.Graphics.Gpu.Engine.Threed.Blender;
+using Ryujinx.Graphics.Gpu.Engine.Types;
using Ryujinx.Graphics.Gpu.Synchronization;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
namespace Ryujinx.Graphics.Gpu.Engine.Threed
{
@@ -26,6 +29,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
private readonly ConstantBufferUpdater _cbUpdater;
private readonly StateUpdater _stateUpdater;
+ private SetMmeShadowRamControlMode ShadowMode => _state.State.SetMmeShadowRamControlMode;
+
/// <summary>
/// Creates a new instance of the 3D engine class.
/// </summary>
@@ -229,6 +234,206 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
}
/// <summary>
+ /// Test if two 32 byte structs are equal.
+ /// </summary>
+ /// <typeparam name="T">Type of the 32-byte struct</typeparam>
+ /// <param name="lhs">First struct</param>
+ /// <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
+ {
+ if (Vector256.IsHardwareAccelerated)
+ {
+ return Vector256.EqualsAll(
+ Unsafe.As<T, Vector256<uint>>(ref lhs),
+ Unsafe.As<T, Vector256<uint>>(ref rhs)
+ );
+ }
+ else
+ {
+ ref var lhsVec = ref Unsafe.As<T, Vector128<uint>>(ref lhs);
+ ref var rhsVec = ref Unsafe.As<T, Vector128<uint>>(ref rhs);
+
+ return Vector128.EqualsAll(lhsVec, rhsVec) &&
+ Vector128.EqualsAll(Unsafe.Add(ref lhsVec, 1), Unsafe.Add(ref rhsVec, 1));
+ }
+ }
+
+ /// <summary>
+ /// Updates blend enable. Respects current shadow mode.
+ /// </summary>
+ /// <param name="masks">Blend enable</param>
+ public void UpdateBlendEnable(ref Array8<Boolean32> enable)
+ {
+ var shadow = ShadowMode;
+ ref var state = ref _state.State.BlendEnable;
+
+ if (shadow.IsReplay())
+ {
+ enable = _state.ShadowState.BlendEnable;
+ }
+
+ if (!UnsafeEquals32Byte(ref enable, ref state))
+ {
+ state = enable;
+
+ _stateUpdater.ForceDirty(StateUpdater.BlendStateIndex);
+ }
+
+ if (shadow.IsTrack())
+ {
+ _state.ShadowState.BlendEnable = enable;
+ }
+ }
+
+ /// <summary>
+ /// Updates color masks. Respects current shadow mode.
+ /// </summary>
+ /// <param name="masks">Color masks</param>
+ public void UpdateColorMasks(ref Array8<RtColorMask> masks)
+ {
+ var shadow = ShadowMode;
+ ref var state = ref _state.State.RtColorMask;
+
+ if (shadow.IsReplay())
+ {
+ masks = _state.ShadowState.RtColorMask;
+ }
+
+ if (!UnsafeEquals32Byte(ref masks, ref state))
+ {
+ state = masks;
+
+ _stateUpdater.ForceDirty(StateUpdater.RtColorMaskIndex);
+ }
+
+ if (shadow.IsTrack())
+ {
+ _state.ShadowState.RtColorMask = masks;
+ }
+ }
+
+ /// <summary>
+ /// Updates index buffer state for an indexed draw. Respects current shadow mode.
+ /// </summary>
+ /// <param name="addrHigh">High part of the address</param>
+ /// <param name="addrLow">Low part of the address</param>
+ /// <param name="type">Type of the binding</param>
+ public void UpdateIndexBuffer(uint addrHigh, uint addrLow, IndexType type)
+ {
+ var shadow = ShadowMode;
+ ref var state = ref _state.State.IndexBufferState;
+
+ if (shadow.IsReplay())
+ {
+ ref var shadowState = ref _state.ShadowState.IndexBufferState;
+ addrHigh = shadowState.Address.High;
+ addrLow = shadowState.Address.Low;
+ type = shadowState.Type;
+ }
+
+ if (state.Address.High != addrHigh || state.Address.Low != addrLow || state.Type != type)
+ {
+ state.Address.High = addrHigh;
+ state.Address.Low = addrLow;
+ state.Type = type;
+
+ _stateUpdater.ForceDirty(StateUpdater.IndexBufferStateIndex);
+ }
+
+ if (shadow.IsTrack())
+ {
+ ref var shadowState = ref _state.ShadowState.IndexBufferState;
+ shadowState.Address.High = addrHigh;
+ shadowState.Address.Low = addrLow;
+ shadowState.Type = type;
+ }
+ }
+
+ /// <summary>
+ /// Updates uniform buffer state for update or bind. Respects current shadow mode.
+ /// </summary>
+ /// <param name="size">Size of the binding</param>
+ /// <param name="addrHigh">High part of the addrsss</param>
+ /// <param name="addrLow">Low part of the address</param>
+ public void UpdateUniformBufferState(int size, uint addrHigh, uint addrLow)
+ {
+ var shadow = ShadowMode;
+ ref var state = ref _state.State.UniformBufferState;
+
+ if (shadow.IsReplay())
+ {
+ ref var shadowState = ref _state.ShadowState.UniformBufferState;
+ size = shadowState.Size;
+ addrHigh = shadowState.Address.High;
+ addrLow = shadowState.Address.Low;
+ }
+
+ state.Size = size;
+ state.Address.High = addrHigh;
+ state.Address.Low = addrLow;
+
+ if (shadow.IsTrack())
+ {
+ ref var shadowState = ref _state.ShadowState.UniformBufferState;
+ shadowState.Size = size;
+ shadowState.Address.High = addrHigh;
+ shadowState.Address.Low = addrLow;
+ }
+ }
+
+ /// <summary>
+ /// Updates a shader offset. Respects current shadow mode.
+ /// </summary>
+ /// <param name="index">Index of the shader to update</param>
+ /// <param name="offset">Offset to update with</param>
+ public void SetShaderOffset(int index, uint offset)
+ {
+ var shadow = ShadowMode;
+ ref var shaderState = ref _state.State.ShaderState[index];
+
+ if (shadow.IsReplay())
+ {
+ offset = _state.ShadowState.ShaderState[index].Offset;
+ }
+
+ if (shaderState.Offset != offset)
+ {
+ shaderState.Offset = offset;
+
+ _stateUpdater.ForceDirty(StateUpdater.ShaderStateIndex);
+ }
+
+ if (shadow.IsTrack())
+ {
+ _state.ShadowState.ShaderState[index].Offset = offset;
+ }
+ }
+
+ /// <summary>
+ /// Updates uniform buffer state for update. Respects current shadow mode.
+ /// </summary>
+ /// <param name="ubState">Uniform buffer state</param>
+ public void UpdateUniformBufferState(UniformBufferState ubState)
+ {
+ var shadow = ShadowMode;
+ ref var state = ref _state.State.UniformBufferState;
+
+ if (shadow.IsReplay())
+ {
+ ubState = _state.ShadowState.UniformBufferState;
+ }
+
+ state = ubState;
+
+ if (shadow.IsTrack())
+ {
+ _state.ShadowState.UniformBufferState = ubState;
+ }
+ }
+
+ /// <summary>
/// Launches the Inline-to-Memory DMA copy operation.
/// </summary>
/// <param name="argument">Method call argument</param>
diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClassState.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClassState.cs
index f2997678..45284525 100644
--- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClassState.cs
+++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClassState.cs
@@ -590,9 +590,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
/// </summary>
struct RtColorMask
{
-#pragma warning disable CS0649 // Field is never assigned to
public uint Packed;
-#pragma warning restore CS0649
+
+ public RtColorMask(uint packed)
+ {
+ Packed = packed;
+ }
/// <summary>
/// Unpacks red channel enable.