From 7016d95eb17ee572fd6fe373f2b4c05e4a576dd6 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sun, 7 Feb 2021 20:23:56 -0300 Subject: [PATCH 1/6] Implement ETC2 (RGB) texture format (#2000) * Implement ETC2 format * Fix component counts for compressed formats --- Ryujinx.Graphics.GAL/Format.cs | 2 + Ryujinx.Graphics.Gpu/Image/FormatTable.cs | 2 + Ryujinx.Graphics.OpenGL/FormatTable.cs | 90 ++++++++++++----------- 3 files changed, 50 insertions(+), 44 deletions(-) diff --git a/Ryujinx.Graphics.GAL/Format.cs b/Ryujinx.Graphics.GAL/Format.cs index 15cf5f4f0..1d034921f 100644 --- a/Ryujinx.Graphics.GAL/Format.cs +++ b/Ryujinx.Graphics.GAL/Format.cs @@ -82,7 +82,9 @@ namespace Ryujinx.Graphics.GAL Bc7Srgb, Bc6HSfloat, Bc6HUfloat, + Etc2RgbUnorm, Etc2RgbaUnorm, + Etc2RgbSrgb, Etc2RgbaSrgb, R8Uscaled, R8Sscaled, diff --git a/Ryujinx.Graphics.Gpu/Image/FormatTable.cs b/Ryujinx.Graphics.Gpu/Image/FormatTable.cs index a1911d568..b4b881792 100644 --- a/Ryujinx.Graphics.Gpu/Image/FormatTable.cs +++ b/Ryujinx.Graphics.Gpu/Image/FormatTable.cs @@ -78,7 +78,9 @@ namespace Ryujinx.Graphics.Gpu.Image { 0xa4917, new FormatInfo(Format.Bc7Srgb, 4, 4, 16, 4) }, { 0x7ff90, new FormatInfo(Format.Bc6HSfloat, 4, 4, 16, 4) }, { 0x7ff91, new FormatInfo(Format.Bc6HUfloat, 4, 4, 16, 4) }, + { 0x24906, new FormatInfo(Format.Etc2RgbUnorm, 4, 4, 8, 3) }, { 0x2490b, new FormatInfo(Format.Etc2RgbaUnorm, 4, 4, 16, 4) }, + { 0xa4906, new FormatInfo(Format.Etc2RgbSrgb, 4, 4, 8, 3) }, { 0xa490b, new FormatInfo(Format.Etc2RgbaSrgb, 4, 4, 16, 4) }, { 0x24940, new FormatInfo(Format.Astc4x4Unorm, 4, 4, 16, 4) }, { 0x24950, new FormatInfo(Format.Astc5x4Unorm, 5, 4, 16, 4) }, diff --git a/Ryujinx.Graphics.OpenGL/FormatTable.cs b/Ryujinx.Graphics.OpenGL/FormatTable.cs index 52da3efd3..8c926fc28 100644 --- a/Ryujinx.Graphics.OpenGL/FormatTable.cs +++ b/Ryujinx.Graphics.OpenGL/FormatTable.cs @@ -80,24 +80,26 @@ namespace Ryujinx.Graphics.OpenGL Add(Format.R10G10B10A2Uint, new FormatInfo(4, false, false, All.Rgb10A2ui, PixelFormat.RgbaInteger, PixelType.UnsignedInt2101010Reversed)); Add(Format.R11G11B10Float, new FormatInfo(3, false, false, All.R11fG11fB10f, PixelFormat.Rgb, PixelType.UnsignedInt10F11F11FRev)); Add(Format.R9G9B9E5Float, new FormatInfo(3, false, false, All.Rgb9E5, PixelFormat.Rgb, PixelType.UnsignedInt5999Rev)); - Add(Format.Bc1RgbUnorm, new FormatInfo(2, true, false, All.CompressedRgbS3tcDxt1Ext)); - Add(Format.Bc1RgbaUnorm, new FormatInfo(1, true, false, All.CompressedRgbaS3tcDxt1Ext)); - Add(Format.Bc2Unorm, new FormatInfo(1, true, false, All.CompressedRgbaS3tcDxt3Ext)); - Add(Format.Bc3Unorm, new FormatInfo(1, true, false, All.CompressedRgbaS3tcDxt5Ext)); - Add(Format.Bc1RgbSrgb, new FormatInfo(2, false, false, All.CompressedSrgbS3tcDxt1Ext)); - Add(Format.Bc1RgbaSrgb, new FormatInfo(1, true, false, All.CompressedSrgbAlphaS3tcDxt1Ext)); - Add(Format.Bc2Srgb, new FormatInfo(1, false, false, All.CompressedSrgbAlphaS3tcDxt3Ext)); - Add(Format.Bc3Srgb, new FormatInfo(1, false, false, All.CompressedSrgbAlphaS3tcDxt5Ext)); + Add(Format.Bc1RgbUnorm, new FormatInfo(3, true, false, All.CompressedRgbS3tcDxt1Ext)); + Add(Format.Bc1RgbaUnorm, new FormatInfo(4, true, false, All.CompressedRgbaS3tcDxt1Ext)); + Add(Format.Bc2Unorm, new FormatInfo(4, true, false, All.CompressedRgbaS3tcDxt3Ext)); + Add(Format.Bc3Unorm, new FormatInfo(4, true, false, All.CompressedRgbaS3tcDxt5Ext)); + Add(Format.Bc1RgbSrgb, new FormatInfo(3, false, false, All.CompressedSrgbS3tcDxt1Ext)); + Add(Format.Bc1RgbaSrgb, new FormatInfo(4, true, false, All.CompressedSrgbAlphaS3tcDxt1Ext)); + Add(Format.Bc2Srgb, new FormatInfo(4, false, false, All.CompressedSrgbAlphaS3tcDxt3Ext)); + Add(Format.Bc3Srgb, new FormatInfo(4, false, false, All.CompressedSrgbAlphaS3tcDxt5Ext)); Add(Format.Bc4Unorm, new FormatInfo(1, true, false, All.CompressedRedRgtc1)); Add(Format.Bc4Snorm, new FormatInfo(1, true, false, All.CompressedSignedRedRgtc1)); - Add(Format.Bc5Unorm, new FormatInfo(1, true, false, All.CompressedRgRgtc2)); - Add(Format.Bc5Snorm, new FormatInfo(1, true, false, All.CompressedSignedRgRgtc2)); - Add(Format.Bc7Unorm, new FormatInfo(1, true, false, All.CompressedRgbaBptcUnorm)); - Add(Format.Bc7Srgb, new FormatInfo(1, false, false, All.CompressedSrgbAlphaBptcUnorm)); - Add(Format.Bc6HSfloat, new FormatInfo(1, false, false, All.CompressedRgbBptcSignedFloat)); - Add(Format.Bc6HUfloat, new FormatInfo(1, false, false, All.CompressedRgbBptcUnsignedFloat)); - Add(Format.Etc2RgbaUnorm, new FormatInfo(1, false, false, All.CompressedRgba8Etc2Eac)); - Add(Format.Etc2RgbaSrgb, new FormatInfo(1, false, false, All.CompressedSrgb8Alpha8Etc2Eac)); + Add(Format.Bc5Unorm, new FormatInfo(2, true, false, All.CompressedRgRgtc2)); + Add(Format.Bc5Snorm, new FormatInfo(2, true, false, All.CompressedSignedRgRgtc2)); + Add(Format.Bc7Unorm, new FormatInfo(4, true, false, All.CompressedRgbaBptcUnorm)); + Add(Format.Bc7Srgb, new FormatInfo(4, false, false, All.CompressedSrgbAlphaBptcUnorm)); + Add(Format.Bc6HSfloat, new FormatInfo(4, false, false, All.CompressedRgbBptcSignedFloat)); + Add(Format.Bc6HUfloat, new FormatInfo(4, false, false, All.CompressedRgbBptcUnsignedFloat)); + Add(Format.Etc2RgbUnorm, new FormatInfo(3, false, false, All.CompressedRgb8Etc2)); + Add(Format.Etc2RgbaUnorm, new FormatInfo(4, false, false, All.CompressedRgba8Etc2Eac)); + Add(Format.Etc2RgbSrgb, new FormatInfo(3, false, false, All.CompressedSrgb8Etc2)); + Add(Format.Etc2RgbaSrgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Etc2Eac)); Add(Format.R8Uscaled, new FormatInfo(1, false, true, All.R8ui, PixelFormat.RedInteger, PixelType.UnsignedByte)); Add(Format.R8Sscaled, new FormatInfo(1, false, true, All.R8i, PixelFormat.RedInteger, PixelType.Byte)); Add(Format.R16Uscaled, new FormatInfo(1, false, true, All.R16ui, PixelFormat.RedInteger, PixelType.UnsignedShort)); @@ -138,34 +140,34 @@ namespace Ryujinx.Graphics.OpenGL Add(Format.R32G32B32X32Float, new FormatInfo(4, false, false, All.Rgb32f, PixelFormat.Rgba, PixelType.Float)); Add(Format.R32G32B32X32Uint, new FormatInfo(4, false, false, All.Rgb32ui, PixelFormat.RgbaInteger, PixelType.UnsignedInt)); Add(Format.R32G32B32X32Sint, new FormatInfo(4, false, false, All.Rgb32i, PixelFormat.RgbaInteger, PixelType.Int)); - Add(Format.Astc4x4Unorm, new FormatInfo(1, true, false, All.CompressedRgbaAstc4X4Khr)); - Add(Format.Astc5x4Unorm, new FormatInfo(1, true, false, All.CompressedRgbaAstc5X4Khr)); - Add(Format.Astc5x5Unorm, new FormatInfo(1, true, false, All.CompressedRgbaAstc5X5Khr)); - Add(Format.Astc6x5Unorm, new FormatInfo(1, true, false, All.CompressedRgbaAstc6X5Khr)); - Add(Format.Astc6x6Unorm, new FormatInfo(1, true, false, All.CompressedRgbaAstc6X6Khr)); - Add(Format.Astc8x5Unorm, new FormatInfo(1, true, false, All.CompressedRgbaAstc8X5Khr)); - Add(Format.Astc8x6Unorm, new FormatInfo(1, true, false, All.CompressedRgbaAstc8X6Khr)); - Add(Format.Astc8x8Unorm, new FormatInfo(1, true, false, All.CompressedRgbaAstc8X8Khr)); - Add(Format.Astc10x5Unorm, new FormatInfo(1, true, false, All.CompressedRgbaAstc10X5Khr)); - Add(Format.Astc10x6Unorm, new FormatInfo(1, true, false, All.CompressedRgbaAstc10X6Khr)); - Add(Format.Astc10x8Unorm, new FormatInfo(1, true, false, All.CompressedRgbaAstc10X8Khr)); - Add(Format.Astc10x10Unorm, new FormatInfo(1, true, false, All.CompressedRgbaAstc10X10Khr)); - Add(Format.Astc12x10Unorm, new FormatInfo(1, true, false, All.CompressedRgbaAstc12X10Khr)); - Add(Format.Astc12x12Unorm, new FormatInfo(1, true, false, All.CompressedRgbaAstc12X12Khr)); - Add(Format.Astc4x4Srgb, new FormatInfo(1, false, false, All.CompressedSrgb8Alpha8Astc4X4Khr)); - Add(Format.Astc5x4Srgb, new FormatInfo(1, false, false, All.CompressedSrgb8Alpha8Astc5X4Khr)); - Add(Format.Astc5x5Srgb, new FormatInfo(1, false, false, All.CompressedSrgb8Alpha8Astc5X5Khr)); - Add(Format.Astc6x5Srgb, new FormatInfo(1, false, false, All.CompressedSrgb8Alpha8Astc6X5Khr)); - Add(Format.Astc6x6Srgb, new FormatInfo(1, false, false, All.CompressedSrgb8Alpha8Astc6X6Khr)); - Add(Format.Astc8x5Srgb, new FormatInfo(1, false, false, All.CompressedSrgb8Alpha8Astc8X5Khr)); - Add(Format.Astc8x6Srgb, new FormatInfo(1, false, false, All.CompressedSrgb8Alpha8Astc8X6Khr)); - Add(Format.Astc8x8Srgb, new FormatInfo(1, false, false, All.CompressedSrgb8Alpha8Astc8X8Khr)); - Add(Format.Astc10x5Srgb, new FormatInfo(1, false, false, All.CompressedSrgb8Alpha8Astc10X5Khr)); - Add(Format.Astc10x6Srgb, new FormatInfo(1, false, false, All.CompressedSrgb8Alpha8Astc10X6Khr)); - Add(Format.Astc10x8Srgb, new FormatInfo(1, false, false, All.CompressedSrgb8Alpha8Astc10X8Khr)); - Add(Format.Astc10x10Srgb, new FormatInfo(1, false, false, All.CompressedSrgb8Alpha8Astc10X10Khr)); - Add(Format.Astc12x10Srgb, new FormatInfo(1, false, false, All.CompressedSrgb8Alpha8Astc12X10Khr)); - Add(Format.Astc12x12Srgb, new FormatInfo(1, false, false, All.CompressedSrgb8Alpha8Astc12X12Khr)); + Add(Format.Astc4x4Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc4X4Khr)); + Add(Format.Astc5x4Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc5X4Khr)); + Add(Format.Astc5x5Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc5X5Khr)); + Add(Format.Astc6x5Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc6X5Khr)); + Add(Format.Astc6x6Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc6X6Khr)); + Add(Format.Astc8x5Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc8X5Khr)); + Add(Format.Astc8x6Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc8X6Khr)); + Add(Format.Astc8x8Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc8X8Khr)); + Add(Format.Astc10x5Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc10X5Khr)); + Add(Format.Astc10x6Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc10X6Khr)); + Add(Format.Astc10x8Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc10X8Khr)); + Add(Format.Astc10x10Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc10X10Khr)); + Add(Format.Astc12x10Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc12X10Khr)); + Add(Format.Astc12x12Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc12X12Khr)); + Add(Format.Astc4x4Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc4X4Khr)); + Add(Format.Astc5x4Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc5X4Khr)); + Add(Format.Astc5x5Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc5X5Khr)); + Add(Format.Astc6x5Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc6X5Khr)); + Add(Format.Astc6x6Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc6X6Khr)); + Add(Format.Astc8x5Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc8X5Khr)); + Add(Format.Astc8x6Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc8X6Khr)); + Add(Format.Astc8x8Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc8X8Khr)); + Add(Format.Astc10x5Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc10X5Khr)); + Add(Format.Astc10x6Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc10X6Khr)); + Add(Format.Astc10x8Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc10X8Khr)); + Add(Format.Astc10x10Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc10X10Khr)); + Add(Format.Astc12x10Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc12X10Khr)); + Add(Format.Astc12x12Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc12X12Khr)); Add(Format.B5G6R5Unorm, new FormatInfo(3, true, false, All.Rgb565, PixelFormat.Rgb, PixelType.UnsignedShort565)); Add(Format.B5G5R5X1Unorm, new FormatInfo(4, true, false, All.Rgb5, PixelFormat.Bgra, PixelType.UnsignedShort5551)); Add(Format.B5G5R5A1Unorm, new FormatInfo(4, true, false, All.Rgb5A1, PixelFormat.Bgra, PixelType.UnsignedShort5551)); From ee28ccebf4e8a2ad84c2fcba2d6436473103def8 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sun, 7 Feb 2021 20:25:14 -0300 Subject: [PATCH 2/6] Disable partial JIT invalidation on unmap (#1991) --- ARMeilleure/Translation/TranslatedFunction.cs | 5 ++ ARMeilleure/Translation/Translator.cs | 50 ++++++++----------- 2 files changed, 26 insertions(+), 29 deletions(-) diff --git a/ARMeilleure/Translation/TranslatedFunction.cs b/ARMeilleure/Translation/TranslatedFunction.cs index 54c050f6e..8b0759289 100644 --- a/ARMeilleure/Translation/TranslatedFunction.cs +++ b/ARMeilleure/Translation/TranslatedFunction.cs @@ -33,5 +33,10 @@ namespace ARMeilleure.Translation { return !HighCq && Interlocked.Increment(ref _callCount) == MinCallsForRejit; } + + public void ResetCallCount() + { + Interlocked.Exchange(ref _callCount, 0); + } } } \ No newline at end of file diff --git a/ARMeilleure/Translation/Translator.cs b/ARMeilleure/Translation/Translator.cs index 2c32e9f00..ac96475f9 100644 --- a/ARMeilleure/Translation/Translator.cs +++ b/ARMeilleure/Translation/Translator.cs @@ -390,33 +390,10 @@ namespace ARMeilleure.Translation public void InvalidateJitCacheRegion(ulong address, ulong size) { - static bool OverlapsWith(ulong funcAddress, ulong funcSize, ulong address, ulong size) - { - return funcAddress < address + size && address < funcAddress + funcSize; - } + // If rejit is running, stop it as it may be trying to rejit a function on the invalidated region. + ClearRejitQueue(allowRequeue: true); - // Make a copy of all overlapping functions, as we can't otherwise - // remove elements from the collection we are iterating. - // Doing that before clearing the rejit queue is fine, even - // if a function is translated after this, it would only replace - // a existing function, as rejit is only triggered on functions - // that were already executed before. - var toDelete = _funcs.Where(x => OverlapsWith(x.Key, x.Value.GuestSize, address, size)).ToArray(); - - if (toDelete.Length != 0) - { - // If rejit is running, stop it as it may be trying to rejit the functions we are - // supposed to remove. - ClearRejitQueue(); - } - - foreach (var kv in toDelete) - { - if (_funcs.TryRemove(kv.Key, out TranslatedFunction func)) - { - EnqueueForDeletion(kv.Key, func); - } - } + // TODO: Completely remove functions overlapping the specified range from the cache. } private void EnqueueForDeletion(ulong guestAddress, TranslatedFunction func) @@ -427,7 +404,7 @@ namespace ARMeilleure.Translation private void ClearJitCache() { // Ensure no attempt will be made to compile new functions due to rejit. - ClearRejitQueue(); + ClearRejitQueue(allowRequeue: false); foreach (var kv in _funcs) { @@ -442,10 +419,25 @@ namespace ARMeilleure.Translation } } - private void ClearRejitQueue() + private void ClearRejitQueue(bool allowRequeue) { _backgroundTranslatorLock.AcquireWriterLock(Timeout.Infinite); - _backgroundStack.Clear(); + + if (allowRequeue) + { + while (_backgroundStack.TryPop(out var request)) + { + if (_funcs.TryGetValue(request.Address, out var func)) + { + func.ResetCallCount(); + } + } + } + else + { + _backgroundStack.Clear(); + } + _backgroundTranslatorLock.ReleaseWriterLock(); } } From 1319eda8b72caaa035c9097207b29dae402e16d1 Mon Sep 17 00:00:00 2001 From: edisionnano Date: Mon, 8 Feb 2021 01:27:12 +0200 Subject: [PATCH 3/6] Fix Updater Icon On Linux (#1995) * Fix Linux Icon * Fix identation * Move the icon to the private constructor --- Ryujinx/Modules/Updater/UpdateDialog.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Ryujinx/Modules/Updater/UpdateDialog.cs b/Ryujinx/Modules/Updater/UpdateDialog.cs index 0b6757859..54ffc0a9b 100644 --- a/Ryujinx/Modules/Updater/UpdateDialog.cs +++ b/Ryujinx/Modules/Updater/UpdateDialog.cs @@ -5,6 +5,7 @@ using Ryujinx.Ui; using System; using System.Diagnostics; using System.Linq; +using System.Reflection; using System.Runtime.InteropServices; namespace Ryujinx.Modules @@ -32,6 +33,7 @@ namespace Ryujinx.Modules _mainWindow = mainWindow; _buildUrl = buildUrl; + Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.Resources.Logo_Ryujinx.png"); MainText.Text = "Do you want to update Ryujinx to the latest version?"; SecondaryText.Text = $"{Program.Version} -> {newVersion}"; @@ -86,4 +88,4 @@ namespace Ryujinx.Modules Dispose(); } } -} \ No newline at end of file +} From 4047477866a8ed7e375c0ebe5de254d61860936d Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sun, 7 Feb 2021 20:42:17 -0300 Subject: [PATCH 4/6] Simplify handling of shader vertex A (#1999) * Simplify handling of shader vertex A * Theres no transformation feedback, its transform * Merge TextureHandlesForCache --- .../Shader/Cache/CacheHelper.cs | 20 +++--- .../Shader/Cache/CacheMigration.cs | 2 +- Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs | 62 ++++++++----------- Ryujinx.Graphics.Shader/ShaderProgram.cs | 7 +-- .../Translation/Translator.cs | 19 +----- .../Translation/TranslatorContext.cs | 36 +++-------- 6 files changed, 52 insertions(+), 94 deletions(-) diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/CacheHelper.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/CacheHelper.cs index d109f1cd6..1ec4ab74c 100644 --- a/Ryujinx.Graphics.Gpu/Shader/Cache/CacheHelper.cs +++ b/Ryujinx.Graphics.Gpu/Shader/Cache/CacheHelper.cs @@ -280,7 +280,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache } } - // Transformation feedback + // Transform feedback if (tfd != null) { foreach (TransformFeedbackDescriptor transform in tfd) @@ -311,7 +311,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache /// The raw guest transform feedback descriptors /// The guest shader program header /// The transform feedback descriptors read from guest - public static TransformFeedbackDescriptor[] ReadTransformationFeedbackInformations(ref ReadOnlySpan data, GuestShaderCacheHeader header) + public static TransformFeedbackDescriptor[] ReadTransformFeedbackInformation(ref ReadOnlySpan data, GuestShaderCacheHeader header) { if (header.TransformFeedbackCount != 0) { @@ -376,9 +376,11 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache /// Guest shader cahe entries from the runtime contexts public static GuestShaderCacheEntry[] CreateShaderCacheEntries(MemoryManager memoryManager, ReadOnlySpan shaderContexts) { - GuestShaderCacheEntry[] entries = new GuestShaderCacheEntry[shaderContexts.Length]; + int startIndex = shaderContexts.Length > 1 ? 1 : 0; - for (int i = 0; i < shaderContexts.Length; i++) + GuestShaderCacheEntry[] entries = new GuestShaderCacheEntry[shaderContexts.Length - startIndex]; + + for (int i = startIndex; i < shaderContexts.Length; i++) { TranslatorContext context = shaderContexts[i]; @@ -387,15 +389,17 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache continue; } - int sizeA = context.AddressA == 0 ? 0 : context.SizeA; + TranslatorContext translatorContext2 = i == 1 ? shaderContexts[0] : null; + + int sizeA = translatorContext2 != null ? translatorContext2.Size : 0; byte[] code = new byte[context.Size + sizeA]; memoryManager.GetSpan(context.Address, context.Size).CopyTo(code); - if (context.AddressA != 0) + if (translatorContext2 != null) { - memoryManager.GetSpan(context.AddressA, context.SizeA).CopyTo(code.AsSpan().Slice(context.Size, context.SizeA)); + memoryManager.GetSpan(translatorContext2.Address, sizeA).CopyTo(code.AsSpan().Slice(context.Size, sizeA)); } GuestGpuAccessorHeader gpuAccessorHeader = CreateGuestGpuAccessorCache(context.GpuAccessor); @@ -421,7 +425,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache } } - entries[i] = entry; + entries[i - startIndex] = entry; } return entries; diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/CacheMigration.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/CacheMigration.cs index 839853c07..e726bc2c0 100644 --- a/Ryujinx.Graphics.Gpu/Shader/Cache/CacheMigration.cs +++ b/Ryujinx.Graphics.Gpu/Shader/Cache/CacheMigration.cs @@ -103,7 +103,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache ReadOnlySpan cachedShaderEntries = GuestShaderCacheEntry.Parse(ref guestProgramReadOnlySpan, out GuestShaderCacheHeader fileHeader); - TransformFeedbackDescriptor[] tfd = CacheHelper.ReadTransformationFeedbackInformations(ref guestProgramReadOnlySpan, fileHeader); + TransformFeedbackDescriptor[] tfd = CacheHelper.ReadTransformFeedbackInformation(ref guestProgramReadOnlySpan, fileHeader); Hash128 newHash = CacheHelper.ComputeGuestHashFromCache(cachedShaderEntries, tfd); diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs index f266bbb44..6a3971df2 100644 --- a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs +++ b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs @@ -128,7 +128,7 @@ namespace Ryujinx.Graphics.Gpu.Shader // Reconstruct code holder. if (isHostProgramValid) { - program = new ShaderProgram(entry.Header.Stage, "", entry.Header.Size, entry.Header.SizeA); + program = new ShaderProgram(entry.Header.Stage, ""); shaderProgramInfo = hostShaderEntries[0].ToShaderProgramInfo(); } else @@ -176,7 +176,7 @@ namespace Ryujinx.Graphics.Gpu.Shader ShaderCodeHolder[] shaders = new ShaderCodeHolder[cachedShaderEntries.Length]; List shaderPrograms = new List(); - TransformFeedbackDescriptor[] tfd = CacheHelper.ReadTransformationFeedbackInformations(ref guestProgramReadOnlySpan, fileHeader); + TransformFeedbackDescriptor[] tfd = CacheHelper.ReadTransformFeedbackInformation(ref guestProgramReadOnlySpan, fileHeader); TranslationFlags flags = DefaultFlags; @@ -217,14 +217,17 @@ namespace Ryujinx.Graphics.Gpu.Shader if (isHostProgramValid) { - program = new ShaderProgram(entry.Header.Stage, "", entry.Header.Size, entry.Header.SizeA); + program = new ShaderProgram(entry.Header.Stage, ""); shaderProgramInfo = hostShaderEntries[i].ToShaderProgramInfo(); } else { IGpuAccessor gpuAccessor = new CachedGpuAccessor(_context, entry.Code, entry.Header.GpuAccessorHeader, entry.TextureDescriptors); - program = Translator.CreateContext((ulong)entry.Header.Size, 0, gpuAccessor, flags, counts).Translate(out shaderProgramInfo); + TranslatorContext translatorContext = Translator.CreateContext(0, gpuAccessor, flags, counts); + TranslatorContext translatorContext2 = Translator.CreateContext((ulong)entry.Header.Size, gpuAccessor, flags | TranslationFlags.VertexA, counts); + + program = translatorContext.Translate(out shaderProgramInfo, translatorContext2); } // NOTE: Vertex B comes first in the shader cache. @@ -239,7 +242,7 @@ namespace Ryujinx.Graphics.Gpu.Shader if (isHostProgramValid) { - program = new ShaderProgram(entry.Header.Stage, "", entry.Header.Size, entry.Header.SizeA); + program = new ShaderProgram(entry.Header.Stage, ""); shaderProgramInfo = hostShaderEntries[i].ToShaderProgramInfo(); } else @@ -446,7 +449,7 @@ namespace Ryujinx.Graphics.Gpu.Shader } } - TranslatorContext[] shaderContexts = new TranslatorContext[Constants.ShaderStages]; + TranslatorContext[] shaderContexts = new TranslatorContext[Constants.ShaderStages + 1]; TransformFeedbackDescriptor[] tfd = GetTransformFeedbackDescriptors(state); @@ -461,17 +464,14 @@ namespace Ryujinx.Graphics.Gpu.Shader if (addresses.VertexA != 0) { - shaderContexts[0] = DecodeGraphicsShader(state, counts, flags, ShaderStage.Vertex, addresses.Vertex, addresses.VertexA); - } - else - { - shaderContexts[0] = DecodeGraphicsShader(state, counts, flags, ShaderStage.Vertex, addresses.Vertex); + shaderContexts[0] = DecodeGraphicsShader(state, counts, flags | TranslationFlags.VertexA, ShaderStage.Vertex, addresses.VertexA); } - shaderContexts[1] = DecodeGraphicsShader(state, counts, flags, ShaderStage.TessellationControl, addresses.TessControl); - shaderContexts[2] = DecodeGraphicsShader(state, counts, flags, ShaderStage.TessellationEvaluation, addresses.TessEvaluation); - shaderContexts[3] = DecodeGraphicsShader(state, counts, flags, ShaderStage.Geometry, addresses.Geometry); - shaderContexts[4] = DecodeGraphicsShader(state, counts, flags, ShaderStage.Fragment, addresses.Fragment); + shaderContexts[1] = DecodeGraphicsShader(state, counts, flags, ShaderStage.Vertex, addresses.Vertex); + shaderContexts[2] = DecodeGraphicsShader(state, counts, flags, ShaderStage.TessellationControl, addresses.TessControl); + shaderContexts[3] = DecodeGraphicsShader(state, counts, flags, ShaderStage.TessellationEvaluation, addresses.TessEvaluation); + shaderContexts[4] = DecodeGraphicsShader(state, counts, flags, ShaderStage.Geometry, addresses.Geometry); + shaderContexts[5] = DecodeGraphicsShader(state, counts, flags, ShaderStage.Fragment, addresses.Fragment); bool isShaderCacheEnabled = _cacheManager != null; bool isShaderCacheReadOnly = false; @@ -501,11 +501,11 @@ namespace Ryujinx.Graphics.Gpu.Shader // The shader isn't currently cached, translate it and compile it. ShaderCodeHolder[] shaders = new ShaderCodeHolder[Constants.ShaderStages]; - shaders[0] = TranslateShader(shaderContexts[0]); - shaders[1] = TranslateShader(shaderContexts[1]); - shaders[2] = TranslateShader(shaderContexts[2]); - shaders[3] = TranslateShader(shaderContexts[3]); - shaders[4] = TranslateShader(shaderContexts[4]); + shaders[0] = TranslateShader(shaderContexts[1], shaderContexts[0]); + shaders[1] = TranslateShader(shaderContexts[2]); + shaders[2] = TranslateShader(shaderContexts[3]); + shaders[3] = TranslateShader(shaderContexts[4]); + shaders[4] = TranslateShader(shaderContexts[5]); List hostShaders = new List(); @@ -696,15 +696,13 @@ namespace Ryujinx.Graphics.Gpu.Shader /// Flags that controls shader translation /// Shader stage /// GPU virtual address of the shader code - /// Optional GPU virtual address of the "Vertex A" shader code /// The generated translator context private TranslatorContext DecodeGraphicsShader( GpuState state, TranslationCounts counts, TranslationFlags flags, ShaderStage stage, - ulong gpuVa, - ulong gpuVaA = 0) + ulong gpuVa) { if (gpuVa == 0) { @@ -713,37 +711,31 @@ namespace Ryujinx.Graphics.Gpu.Shader GpuAccessor gpuAccessor = new GpuAccessor(_context, state, (int)stage - 1); - if (gpuVaA != 0) - { - return Translator.CreateContext(gpuVaA, gpuVa, gpuAccessor, flags, counts); - } - else - { - return Translator.CreateContext(gpuVa, gpuAccessor, flags, counts); - } + return Translator.CreateContext(gpuVa, gpuAccessor, flags, counts); } /// /// Translates a previously generated translator context to something that the host API accepts. /// /// Current translator context to translate + /// Optional translator context of the shader that should be combined /// Compiled graphics shader code - private ShaderCodeHolder TranslateShader(TranslatorContext translatorContext) + private ShaderCodeHolder TranslateShader(TranslatorContext translatorContext, TranslatorContext translatorContext2 = null) { if (translatorContext == null) { return null; } - if (translatorContext.AddressA != 0) + if (translatorContext2 != null) { - byte[] codeA = _context.MemoryManager.GetSpan(translatorContext.AddressA, translatorContext.SizeA).ToArray(); + byte[] codeA = _context.MemoryManager.GetSpan(translatorContext2.Address, translatorContext2.Size).ToArray(); byte[] codeB = _context.MemoryManager.GetSpan(translatorContext.Address, translatorContext.Size).ToArray(); _dumper.Dump(codeA, compute: false, out string fullPathA, out string codePathA); _dumper.Dump(codeB, compute: false, out string fullPathB, out string codePathB); - ShaderProgram program = translatorContext.Translate(out ShaderProgramInfo shaderProgramInfo); + ShaderProgram program = translatorContext.Translate(out ShaderProgramInfo shaderProgramInfo, translatorContext2); if (fullPathA != null && fullPathB != null && codePathA != null && codePathB != null) { diff --git a/Ryujinx.Graphics.Shader/ShaderProgram.cs b/Ryujinx.Graphics.Shader/ShaderProgram.cs index 0e037fc9c..4a6bfea9f 100644 --- a/Ryujinx.Graphics.Shader/ShaderProgram.cs +++ b/Ryujinx.Graphics.Shader/ShaderProgram.cs @@ -8,15 +8,10 @@ namespace Ryujinx.Graphics.Shader public string Code { get; private set; } - public int SizeA { get; } - public int Size { get; } - - public ShaderProgram(ShaderStage stage, string code, int size, int sizeA) + public ShaderProgram(ShaderStage stage, string code) { Stage = stage; Code = code; - SizeA = sizeA; - Size = size; } public void Prepend(string line) diff --git a/Ryujinx.Graphics.Shader/Translation/Translator.cs b/Ryujinx.Graphics.Shader/Translation/Translator.cs index e52c1ccf4..0d64bccc4 100644 --- a/Ryujinx.Graphics.Shader/Translation/Translator.cs +++ b/Ryujinx.Graphics.Shader/Translation/Translator.cs @@ -36,22 +36,7 @@ namespace Ryujinx.Graphics.Shader.Translation return new TranslatorContext(address, cfg, config); } - public static TranslatorContext CreateContext( - ulong addressA, - ulong addressB, - IGpuAccessor gpuAccessor, - TranslationFlags flags, - TranslationCounts counts = null) - { - counts ??= new TranslationCounts(); - - Block[][] cfgA = DecodeShader(addressA, gpuAccessor, flags | TranslationFlags.VertexA, counts, out ShaderConfig configA); - Block[][] cfgB = DecodeShader(addressB, gpuAccessor, flags, counts, out ShaderConfig configB); - - return new TranslatorContext(addressA, addressB, cfgA, cfgB, configA, configB); - } - - internal static ShaderProgram Translate(FunctionCode[] functions, ShaderConfig config, out ShaderProgramInfo shaderProgramInfo, int sizeA = 0) + internal static ShaderProgram Translate(FunctionCode[] functions, ShaderConfig config, out ShaderProgramInfo shaderProgramInfo) { var cfgs = new ControlFlowGraph[functions.Length]; var frus = new RegisterUsage.FunctionRegisterUsage[functions.Length]; @@ -113,7 +98,7 @@ namespace Ryujinx.Graphics.Shader.Translation string glslCode = program.Code; - return new ShaderProgram(config.Stage, glslCode, config.Size, sizeA); + return new ShaderProgram(config.Stage, glslCode); } private static Block[][] DecodeShader( diff --git a/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs b/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs index 3092e0776..501f78807 100644 --- a/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs +++ b/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs @@ -10,16 +10,12 @@ namespace Ryujinx.Graphics.Shader.Translation public class TranslatorContext { private readonly Block[][] _cfg; - private readonly Block[][] _cfgA; private ShaderConfig _config; - private ShaderConfig _configA; public ulong Address { get; } - public ulong AddressA { get; } public ShaderStage Stage => _config.Stage; public int Size => _config.Size; - public int SizeA => _configA != null ? _configA.Size : 0; public HashSet TextureHandlesForCache => _config.TextureHandlesForCache; @@ -27,22 +23,9 @@ namespace Ryujinx.Graphics.Shader.Translation internal TranslatorContext(ulong address, Block[][] cfg, ShaderConfig config) { - Address = address; - AddressA = 0; - _config = config; - _configA = null; - _cfg = cfg; - _cfgA = null; - } - - internal TranslatorContext(ulong addressA, ulong addressB, Block[][] cfgA, Block[][] cfgB, ShaderConfig configA, ShaderConfig configB) - { - Address = addressB; - AddressA = addressA; - _config = configB; - _configA = configA; - _cfg = cfgB; - _cfgA = cfgA; + Address = address; + _config = config; + _cfg = cfg; } private static bool IsUserAttribute(Operand operand) @@ -141,20 +124,19 @@ namespace Ryujinx.Graphics.Shader.Translation return output; } - public ShaderProgram Translate(out ShaderProgramInfo shaderProgramInfo) + public ShaderProgram Translate(out ShaderProgramInfo shaderProgramInfo, TranslatorContext other = null) { FunctionCode[] code = EmitShader(_cfg, _config); - if (_configA != null) + if (other != null) { - FunctionCode[] codeA = EmitShader(_cfgA, _configA); + _config.SetUsedFeature(other._config.UsedFeatures); + TextureHandlesForCache.UnionWith(other.TextureHandlesForCache); - _config.SetUsedFeature(_configA.UsedFeatures); - - code = Combine(codeA, code); + code = Combine(EmitShader(other._cfg, other._config), code); } - return Translator.Translate(code, _config, out shaderProgramInfo, SizeA); + return Translator.Translate(code, _config, out shaderProgramInfo); } } } From 40797a1283ce9119f5f132693089c42442a4aa71 Mon Sep 17 00:00:00 2001 From: sharmander Date: Sun, 7 Feb 2021 18:49:46 -0500 Subject: [PATCH 5/6] Optimization | Modify Add (Integer) Instruction to use LEA instead. (#1971) * Optimization | Modify Add Instruction to use LEA instead. Currently, the add instruction requires 4 registers to take place. By using LEA, we can effectively perform the same working using 3 registers, reducing memory spills and improving translation efficiency. * Fix IsSameOperandDestSrc1 Check for Add * Use LEA if Dest != SRC1 * Update IsSameOperandDestSrc1 to account for Cases where Dest and Src1 can be same for add * Fix error in logic * Typo * Add paranthesis for clarity * Compare registers as requested. * Cleanup if statement, use same comparison method as generateCopy * Make change as recommended by gdk * Perform check only when Add calls are made * use ensure sametype for lea, fix else * Update comment * Update version # --- ARMeilleure/CodeGen/X86/CodeGenerator.cs | 49 +++++++++++++++++++----- ARMeilleure/CodeGen/X86/PreAllocator.cs | 1 + ARMeilleure/Translation/PTC/Ptc.cs | 2 +- 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/ARMeilleure/CodeGen/X86/CodeGenerator.cs b/ARMeilleure/CodeGen/X86/CodeGenerator.cs index 5f41ff790..ca1f1ceb6 100644 --- a/ARMeilleure/CodeGen/X86/CodeGenerator.cs +++ b/ARMeilleure/CodeGen/X86/CodeGenerator.cs @@ -514,19 +514,50 @@ namespace ARMeilleure.CodeGen.X86 Operand src1 = operation.GetSource(0); Operand src2 = operation.GetSource(1); - ValidateBinOp(dest, src1, src2); - if (dest.Type.IsInteger()) { - context.Assembler.Add(dest, src2, dest.Type); + // If Destination and Source 1 Operands are the same, perform a standard add as there are no benefits to using LEA. + if (dest.Kind == src1.Kind && dest.Value == src1.Value) + { + ValidateBinOp(dest, src1, src2); + + context.Assembler.Add(dest, src2, dest.Type); + } + else + { + EnsureSameType(dest, src1, src2); + + int offset; + Operand index; + + if (src2.Kind == OperandKind.Constant) + { + offset = src2.AsInt32(); + index = null; + } + else + { + offset = 0; + index = src2; + } + + MemoryOperand memOp = MemoryOp(dest.Type, src1, index, Multiplier.x1, offset); + + context.Assembler.Lea(dest, memOp, dest.Type); + } } - else if (dest.Type == OperandType.FP32) + else { - context.Assembler.Addss(dest, src1, src2); - } - else /* if (dest.Type == OperandType.FP64) */ - { - context.Assembler.Addsd(dest, src1, src2); + ValidateBinOp(dest, src1, src2); + + if (dest.Type == OperandType.FP32) + { + context.Assembler.Addss(dest, src1, src2); + } + else /* if (dest.Type == OperandType.FP64) */ + { + context.Assembler.Addsd(dest, src1, src2); + } } } diff --git a/ARMeilleure/CodeGen/X86/PreAllocator.cs b/ARMeilleure/CodeGen/X86/PreAllocator.cs index 55bc778b2..cb2476b48 100644 --- a/ARMeilleure/CodeGen/X86/PreAllocator.cs +++ b/ARMeilleure/CodeGen/X86/PreAllocator.cs @@ -1273,6 +1273,7 @@ namespace ARMeilleure.CodeGen.X86 switch (operation.Instruction) { case Instruction.Add: + return !HardwareCapabilities.SupportsVexEncoding && !operation.Destination.Type.IsInteger(); case Instruction.Multiply: case Instruction.Subtract: return !HardwareCapabilities.SupportsVexEncoding || operation.Destination.Type.IsInteger(); diff --git a/ARMeilleure/Translation/PTC/Ptc.cs b/ARMeilleure/Translation/PTC/Ptc.cs index fd69077b0..846c01cde 100644 --- a/ARMeilleure/Translation/PTC/Ptc.cs +++ b/ARMeilleure/Translation/PTC/Ptc.cs @@ -22,7 +22,7 @@ namespace ARMeilleure.Translation.PTC { private const string HeaderMagic = "PTChd"; - private const int InternalVersion = 1943; //! To be incremented manually for each change to the ARMeilleure project. + private const int InternalVersion = 1971; //! To be incremented manually for each change to the ARMeilleure project. private const string ActualDir = "0"; private const string BackupDir = "1"; From 5ea7d77981df75f4eede220bf25926af177ef808 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sun, 7 Feb 2021 20:54:49 -0300 Subject: [PATCH 6/6] Fix inter-process data copy on non-contiguous physical regions (#1988) --- .../HOS/Kernel/Memory/KMemoryManager.cs | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryManager.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryManager.cs index 5a8e8e3b2..5b6df53ba 100644 --- a/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryManager.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryManager.cs @@ -1506,15 +1506,33 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory { KProcess currentProcess = KernelStatic.GetCurrentProcess(); - serverAddress = currentProcess.MemoryManager.GetDramAddressFromVa(serverAddress); + while (size > 0) + { + ulong copySize = Math.Min(PageSize - (serverAddress & (PageSize - 1)), PageSize - (clientAddress & (PageSize - 1))); - if (toServer) - { - _context.Memory.Copy(serverAddress, GetDramAddressFromVa(clientAddress), size); - } - else - { - _context.Memory.Copy(GetDramAddressFromVa(clientAddress), serverAddress, size); + if (copySize > size) + { + copySize = size; + } + + ulong serverDramAddr = currentProcess.MemoryManager.GetDramAddressFromVa(serverAddress); + ulong clientDramAddr = GetDramAddressFromVa(clientAddress); + + if (serverDramAddr != clientDramAddr) + { + if (toServer) + { + _context.Memory.Copy(serverDramAddr, clientDramAddr, copySize); + } + else + { + _context.Memory.Copy(clientDramAddr, serverDramAddr, copySize); + } + } + + serverAddress += copySize; + clientAddress += copySize; + size -= copySize; } return KernelResult.Success;