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 --- Ryujinx.Graphics.Gpu/Engine/Types/Boolean32.cs | 17 +++ Ryujinx.Graphics.Gpu/Engine/Types/ColorFormat.cs | 134 +++++++++++++++++++++ Ryujinx.Graphics.Gpu/Engine/Types/GpuVa.cs | 22 ++++ Ryujinx.Graphics.Gpu/Engine/Types/MemoryLayout.cs | 37 ++++++ Ryujinx.Graphics.Gpu/Engine/Types/PrimitiveType.cs | 99 +++++++++++++++ Ryujinx.Graphics.Gpu/Engine/Types/SamplerIndex.cs | 11 ++ Ryujinx.Graphics.Gpu/Engine/Types/SbDescriptor.cs | 20 +++ Ryujinx.Graphics.Gpu/Engine/Types/ZetaFormat.cs | 42 +++++++ 8 files changed, 382 insertions(+) create mode 100644 Ryujinx.Graphics.Gpu/Engine/Types/Boolean32.cs create mode 100644 Ryujinx.Graphics.Gpu/Engine/Types/ColorFormat.cs create mode 100644 Ryujinx.Graphics.Gpu/Engine/Types/GpuVa.cs create mode 100644 Ryujinx.Graphics.Gpu/Engine/Types/MemoryLayout.cs create mode 100644 Ryujinx.Graphics.Gpu/Engine/Types/PrimitiveType.cs create mode 100644 Ryujinx.Graphics.Gpu/Engine/Types/SamplerIndex.cs create mode 100644 Ryujinx.Graphics.Gpu/Engine/Types/SbDescriptor.cs create mode 100644 Ryujinx.Graphics.Gpu/Engine/Types/ZetaFormat.cs (limited to 'Ryujinx.Graphics.Gpu/Engine/Types') diff --git a/Ryujinx.Graphics.Gpu/Engine/Types/Boolean32.cs b/Ryujinx.Graphics.Gpu/Engine/Types/Boolean32.cs new file mode 100644 index 00000000..c982347a --- /dev/null +++ b/Ryujinx.Graphics.Gpu/Engine/Types/Boolean32.cs @@ -0,0 +1,17 @@ +namespace Ryujinx.Graphics.Gpu.Engine.Types +{ + /// + /// Boolean value, stored as a 32-bits integer in memory. + /// + struct Boolean32 + { +#pragma warning disable CS0649 + private uint _value; +#pragma warning restore CS0649 + + public static implicit operator bool(Boolean32 value) + { + return (value._value & 1) != 0; + } + } +} diff --git a/Ryujinx.Graphics.Gpu/Engine/Types/ColorFormat.cs b/Ryujinx.Graphics.Gpu/Engine/Types/ColorFormat.cs new file mode 100644 index 00000000..e780ec23 --- /dev/null +++ b/Ryujinx.Graphics.Gpu/Engine/Types/ColorFormat.cs @@ -0,0 +1,134 @@ +using Ryujinx.Graphics.GAL; +using Ryujinx.Graphics.Gpu.Image; + +namespace Ryujinx.Graphics.Gpu.Engine.Types +{ + /// + /// Color texture format. + /// + enum ColorFormat + { + R32G32B32A32Float = 0xc0, + R32G32B32A32Sint = 0xc1, + R32G32B32A32Uint = 0xc2, + R32G32B32X32Float = 0xc3, + R32G32B32X32Sint = 0xc4, + R32G32B32X32Uint = 0xc5, + R16G16B16X16Unorm = 0xc6, + R16G16B16X16Snorm = 0xc7, + R16G16B16X16Sint = 0xc8, + R16G16B16X16Uint = 0xc9, + R16G16B16A16Float = 0xca, + R32G32Float = 0xcb, + R32G32Sint = 0xcc, + R32G32Uint = 0xcd, + R16G16B16X16Float = 0xce, + B8G8R8A8Unorm = 0xcf, + B8G8R8A8Srgb = 0xd0, + R10G10B10A2Unorm = 0xd1, + R10G10B10A2Uint = 0xd2, + R8G8B8A8Unorm = 0xd5, + R8G8B8A8Srgb = 0xd6, + R8G8B8X8Snorm = 0xd7, + R8G8B8X8Sint = 0xd8, + R8G8B8X8Uint = 0xd9, + R16G16Unorm = 0xda, + R16G16Snorm = 0xdb, + R16G16Sint = 0xdc, + R16G16Uint = 0xdd, + R16G16Float = 0xde, + R11G11B10Float = 0xe0, + R32Sint = 0xe3, + R32Uint = 0xe4, + R32Float = 0xe5, + B8G8R8X8Unorm = 0xe6, + B8G8R8X8Srgb = 0xe7, + B5G6R5Unorm = 0xe8, + B5G5R5A1Unorm = 0xe9, + R8G8Unorm = 0xea, + R8G8Snorm = 0xeb, + R8G8Sint = 0xec, + R8G8Uint = 0xed, + R16Unorm = 0xee, + R16Snorm = 0xef, + R16Sint = 0xf0, + R16Uint = 0xf1, + R16Float = 0xf2, + R8Unorm = 0xf3, + R8Snorm = 0xf4, + R8Sint = 0xf5, + R8Uint = 0xf6, + B5G5R5X1Unorm = 0xf8, + R8G8B8X8Unorm = 0xf9, + R8G8B8X8Srgb = 0xfa + } + + static class ColorFormatConverter + { + /// + /// Converts the color texture format to a host compatible format. + /// + /// Color format + /// Host compatible format enum value + public static FormatInfo Convert(this ColorFormat format) + { + return format switch + { + ColorFormat.R32G32B32A32Float => new FormatInfo(Format.R32G32B32A32Float, 1, 1, 16, 4), + ColorFormat.R32G32B32A32Sint => new FormatInfo(Format.R32G32B32A32Sint, 1, 1, 16, 4), + ColorFormat.R32G32B32A32Uint => new FormatInfo(Format.R32G32B32A32Uint, 1, 1, 16, 4), + ColorFormat.R32G32B32X32Float => new FormatInfo(Format.R32G32B32A32Float, 1, 1, 16, 4), + ColorFormat.R32G32B32X32Sint => new FormatInfo(Format.R32G32B32A32Sint, 1, 1, 16, 4), + ColorFormat.R32G32B32X32Uint => new FormatInfo(Format.R32G32B32A32Uint, 1, 1, 16, 4), + ColorFormat.R16G16B16X16Unorm => new FormatInfo(Format.R16G16B16A16Unorm, 1, 1, 8, 4), + ColorFormat.R16G16B16X16Snorm => new FormatInfo(Format.R16G16B16A16Snorm, 1, 1, 8, 4), + ColorFormat.R16G16B16X16Sint => new FormatInfo(Format.R16G16B16A16Sint, 1, 1, 8, 4), + ColorFormat.R16G16B16X16Uint => new FormatInfo(Format.R16G16B16A16Uint, 1, 1, 8, 4), + ColorFormat.R16G16B16A16Float => new FormatInfo(Format.R16G16B16A16Float, 1, 1, 8, 4), + ColorFormat.R32G32Float => new FormatInfo(Format.R32G32Float, 1, 1, 8, 2), + ColorFormat.R32G32Sint => new FormatInfo(Format.R32G32Sint, 1, 1, 8, 2), + ColorFormat.R32G32Uint => new FormatInfo(Format.R32G32Uint, 1, 1, 8, 2), + ColorFormat.R16G16B16X16Float => new FormatInfo(Format.R16G16B16A16Float, 1, 1, 8, 4), + ColorFormat.B8G8R8A8Unorm => new FormatInfo(Format.B8G8R8A8Unorm, 1, 1, 4, 4), + ColorFormat.B8G8R8A8Srgb => new FormatInfo(Format.B8G8R8A8Srgb, 1, 1, 4, 4), + ColorFormat.R10G10B10A2Unorm => new FormatInfo(Format.R10G10B10A2Unorm, 1, 1, 4, 4), + ColorFormat.R10G10B10A2Uint => new FormatInfo(Format.R10G10B10A2Uint, 1, 1, 4, 4), + ColorFormat.R8G8B8A8Unorm => new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4, 4), + ColorFormat.R8G8B8A8Srgb => new FormatInfo(Format.R8G8B8A8Srgb, 1, 1, 4, 4), + ColorFormat.R8G8B8X8Snorm => new FormatInfo(Format.R8G8B8A8Snorm, 1, 1, 4, 4), + ColorFormat.R8G8B8X8Sint => new FormatInfo(Format.R8G8B8A8Sint, 1, 1, 4, 4), + ColorFormat.R8G8B8X8Uint => new FormatInfo(Format.R8G8B8A8Uint, 1, 1, 4, 4), + ColorFormat.R16G16Unorm => new FormatInfo(Format.R16G16Unorm, 1, 1, 4, 2), + ColorFormat.R16G16Snorm => new FormatInfo(Format.R16G16Snorm, 1, 1, 4, 2), + ColorFormat.R16G16Sint => new FormatInfo(Format.R16G16Sint, 1, 1, 4, 2), + ColorFormat.R16G16Uint => new FormatInfo(Format.R16G16Uint, 1, 1, 4, 2), + ColorFormat.R16G16Float => new FormatInfo(Format.R16G16Float, 1, 1, 4, 2), + ColorFormat.R11G11B10Float => new FormatInfo(Format.R11G11B10Float, 1, 1, 4, 3), + ColorFormat.R32Sint => new FormatInfo(Format.R32Sint, 1, 1, 4, 1), + ColorFormat.R32Uint => new FormatInfo(Format.R32Uint, 1, 1, 4, 1), + ColorFormat.R32Float => new FormatInfo(Format.R32Float, 1, 1, 4, 1), + ColorFormat.B8G8R8X8Unorm => new FormatInfo(Format.B8G8R8A8Unorm, 1, 1, 4, 4), + ColorFormat.B8G8R8X8Srgb => new FormatInfo(Format.B8G8R8A8Srgb, 1, 1, 4, 4), + ColorFormat.B5G6R5Unorm => new FormatInfo(Format.B5G6R5Unorm, 1, 1, 2, 3), + ColorFormat.B5G5R5A1Unorm => new FormatInfo(Format.B5G5R5A1Unorm, 1, 1, 2, 4), + ColorFormat.R8G8Unorm => new FormatInfo(Format.R8G8Unorm, 1, 1, 2, 2), + ColorFormat.R8G8Snorm => new FormatInfo(Format.R8G8Snorm, 1, 1, 2, 2), + ColorFormat.R8G8Sint => new FormatInfo(Format.R8G8Sint, 1, 1, 2, 2), + ColorFormat.R8G8Uint => new FormatInfo(Format.R8G8Uint, 1, 1, 2, 2), + ColorFormat.R16Unorm => new FormatInfo(Format.R16Unorm, 1, 1, 2, 1), + ColorFormat.R16Snorm => new FormatInfo(Format.R16Snorm, 1, 1, 2, 1), + ColorFormat.R16Sint => new FormatInfo(Format.R16Sint, 1, 1, 2, 1), + ColorFormat.R16Uint => new FormatInfo(Format.R16Uint, 1, 1, 2, 1), + ColorFormat.R16Float => new FormatInfo(Format.R16Float, 1, 1, 2, 1), + ColorFormat.R8Unorm => new FormatInfo(Format.R8Unorm, 1, 1, 1, 1), + ColorFormat.R8Snorm => new FormatInfo(Format.R8Snorm, 1, 1, 1, 1), + ColorFormat.R8Sint => new FormatInfo(Format.R8Sint, 1, 1, 1, 1), + ColorFormat.R8Uint => new FormatInfo(Format.R8Uint, 1, 1, 1, 1), + ColorFormat.B5G5R5X1Unorm => new FormatInfo(Format.B5G5R5X1Unorm, 1, 1, 2, 4), + ColorFormat.R8G8B8X8Unorm => new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4, 4), + ColorFormat.R8G8B8X8Srgb => new FormatInfo(Format.R8G8B8A8Srgb, 1, 1, 4, 4), + _ => FormatInfo.Default + }; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Gpu/Engine/Types/GpuVa.cs b/Ryujinx.Graphics.Gpu/Engine/Types/GpuVa.cs new file mode 100644 index 00000000..839faac9 --- /dev/null +++ b/Ryujinx.Graphics.Gpu/Engine/Types/GpuVa.cs @@ -0,0 +1,22 @@ +namespace Ryujinx.Graphics.Gpu.Engine.Types +{ + /// + /// Split GPU virtual address. + /// + struct GpuVa + { +#pragma warning disable CS0649 + public uint High; + public uint Low; +#pragma warning restore CS0649 + + /// + /// Packs the split address into a 64-bits address value. + /// + /// The 64-bits address value + public ulong Pack() + { + return Low | ((ulong)High << 32); + } + } +} diff --git a/Ryujinx.Graphics.Gpu/Engine/Types/MemoryLayout.cs b/Ryujinx.Graphics.Gpu/Engine/Types/MemoryLayout.cs new file mode 100644 index 00000000..6da96bd4 --- /dev/null +++ b/Ryujinx.Graphics.Gpu/Engine/Types/MemoryLayout.cs @@ -0,0 +1,37 @@ +namespace Ryujinx.Graphics.Gpu.Engine.Types +{ + /// + /// Memory layout parameters, for block linear textures. + /// + struct MemoryLayout + { +#pragma warning disable CS0649 + public uint Packed; +#pragma warning restore CS0649 + + public int UnpackGobBlocksInX() + { + return 1 << (int)(Packed & 0xf); + } + + public int UnpackGobBlocksInY() + { + return 1 << (int)((Packed >> 4) & 0xf); + } + + public int UnpackGobBlocksInZ() + { + return 1 << (int)((Packed >> 8) & 0xf); + } + + public bool UnpackIsLinear() + { + return (Packed & 0x1000) != 0; + } + + public bool UnpackIsTarget3D() + { + return (Packed & 0x10000) != 0; + } + } +} diff --git a/Ryujinx.Graphics.Gpu/Engine/Types/PrimitiveType.cs b/Ryujinx.Graphics.Gpu/Engine/Types/PrimitiveType.cs new file mode 100644 index 00000000..dae63124 --- /dev/null +++ b/Ryujinx.Graphics.Gpu/Engine/Types/PrimitiveType.cs @@ -0,0 +1,99 @@ +using Ryujinx.Graphics.GAL; + +namespace Ryujinx.Graphics.Gpu.Engine.Types +{ + /// + /// Draw primitive type. + /// + enum PrimitiveType + { + Points, + Lines, + LineLoop, + LineStrip, + Triangles, + TriangleStrip, + TriangleFan, + Quads, + QuadStrip, + Polygon, + LinesAdjacency, + LineStripAdjacency, + TrianglesAdjacency, + TriangleStripAdjacency, + Patches + } + + /// + /// Alternative primitive type that might override . + /// + enum PrimitiveTypeOverride + { + Points = 1, + Lines = 2, + LineStrip = 3, + Triangles = 4, + TriangleStrip = 5, + TriangleFan = 0x1015, + LinesAdjacency = 10, + LineStripAdjacency = 11, + TrianglesAdjacency = 12, + TriangleStripAdjacency = 13, + Patches = 14 + } + + static class PrimitiveTypeConverter + { + /// + /// Converts the primitive type into something that can be used with the host API. + /// + /// The primitive type to convert + /// A host compatible enum value + public static PrimitiveTopology Convert(this PrimitiveType type) + { + return type switch + { + PrimitiveType.Points => PrimitiveTopology.Points, + PrimitiveType.Lines => PrimitiveTopology.Lines, + PrimitiveType.LineLoop => PrimitiveTopology.LineLoop, + PrimitiveType.LineStrip => PrimitiveTopology.LineStrip, + PrimitiveType.Triangles => PrimitiveTopology.Triangles, + PrimitiveType.TriangleStrip => PrimitiveTopology.TriangleStrip, + PrimitiveType.TriangleFan => PrimitiveTopology.TriangleFan, + PrimitiveType.Quads => PrimitiveTopology.Quads, + PrimitiveType.QuadStrip => PrimitiveTopology.QuadStrip, + PrimitiveType.Polygon => PrimitiveTopology.Polygon, + PrimitiveType.LinesAdjacency => PrimitiveTopology.LinesAdjacency, + PrimitiveType.LineStripAdjacency => PrimitiveTopology.LineStripAdjacency, + PrimitiveType.TrianglesAdjacency => PrimitiveTopology.TrianglesAdjacency, + PrimitiveType.TriangleStripAdjacency => PrimitiveTopology.TriangleStripAdjacency, + PrimitiveType.Patches => PrimitiveTopology.Patches, + _ => PrimitiveTopology.Triangles + }; + } + + /// + /// Converts the primitive type into something that can be used with the host API. + /// + /// The primitive type to convert + /// A host compatible enum value + public static PrimitiveTopology Convert(this PrimitiveTypeOverride type) + { + return type switch + { + PrimitiveTypeOverride.Points => PrimitiveTopology.Points, + PrimitiveTypeOverride.Lines => PrimitiveTopology.Lines, + PrimitiveTypeOverride.LineStrip => PrimitiveTopology.LineStrip, + PrimitiveTypeOverride.Triangles => PrimitiveTopology.Triangles, + PrimitiveTypeOverride.TriangleStrip => PrimitiveTopology.TriangleStrip, + PrimitiveTypeOverride.TriangleFan => PrimitiveTopology.TriangleFan, + PrimitiveTypeOverride.LinesAdjacency => PrimitiveTopology.LinesAdjacency, + PrimitiveTypeOverride.LineStripAdjacency => PrimitiveTopology.LineStripAdjacency, + PrimitiveTypeOverride.TrianglesAdjacency => PrimitiveTopology.TrianglesAdjacency, + PrimitiveTypeOverride.TriangleStripAdjacency => PrimitiveTopology.TriangleStripAdjacency, + PrimitiveTypeOverride.Patches => PrimitiveTopology.Patches, + _ => PrimitiveTopology.Triangles + }; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Gpu/Engine/Types/SamplerIndex.cs b/Ryujinx.Graphics.Gpu/Engine/Types/SamplerIndex.cs new file mode 100644 index 00000000..839a4d0a --- /dev/null +++ b/Ryujinx.Graphics.Gpu/Engine/Types/SamplerIndex.cs @@ -0,0 +1,11 @@ +namespace Ryujinx.Graphics.Gpu.Engine.Types +{ + /// + /// Sampler pool indexing mode. + /// + enum SamplerIndex + { + Independently = 0, + ViaHeaderIndex = 1 + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Gpu/Engine/Types/SbDescriptor.cs b/Ryujinx.Graphics.Gpu/Engine/Types/SbDescriptor.cs new file mode 100644 index 00000000..c457dbf9 --- /dev/null +++ b/Ryujinx.Graphics.Gpu/Engine/Types/SbDescriptor.cs @@ -0,0 +1,20 @@ +namespace Ryujinx.Graphics.Gpu.Engine.Types +{ + /// + /// Storage buffer address and size information. + /// + struct SbDescriptor + { +#pragma warning disable CS0649 + public uint AddressLow; + public uint AddressHigh; + public int Size; + public int Padding; +#pragma warning restore CS0649 + + public ulong PackAddress() + { + return AddressLow | ((ulong)AddressHigh << 32); + } + } +} diff --git a/Ryujinx.Graphics.Gpu/Engine/Types/ZetaFormat.cs b/Ryujinx.Graphics.Gpu/Engine/Types/ZetaFormat.cs new file mode 100644 index 00000000..2de38fd2 --- /dev/null +++ b/Ryujinx.Graphics.Gpu/Engine/Types/ZetaFormat.cs @@ -0,0 +1,42 @@ +using Ryujinx.Graphics.GAL; +using Ryujinx.Graphics.Gpu.Image; + +namespace Ryujinx.Graphics.Gpu.Engine.Types +{ + /// + /// Depth-stencil texture format. + /// + enum ZetaFormat + { + D32Float = 0xa, + D16Unorm = 0x13, + D24UnormS8Uint = 0x14, + D24Unorm = 0x15, + S8UintD24Unorm = 0x16, + S8Uint = 0x17, + D32FloatS8Uint = 0x19 + } + + static class ZetaFormatConverter + { + /// + /// Converts the depth-stencil texture format to a host compatible format. + /// + /// Depth-stencil format + /// Host compatible format enum value + public static FormatInfo Convert(this ZetaFormat format) + { + return format switch + { + ZetaFormat.D32Float => new FormatInfo(Format.D32Float, 1, 1, 4, 1), + ZetaFormat.D16Unorm => new FormatInfo(Format.D16Unorm, 1, 1, 2, 1), + ZetaFormat.D24UnormS8Uint => new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4, 2), + ZetaFormat.D24Unorm => new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4, 1), + ZetaFormat.S8UintD24Unorm => new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4, 2), + ZetaFormat.S8Uint => new FormatInfo(Format.S8Uint, 1, 1, 1, 1), + ZetaFormat.D32FloatS8Uint => new FormatInfo(Format.D32FloatS8Uint, 1, 1, 8, 2), + _ => FormatInfo.Default + }; + } + } +} -- cgit v1.2.3