diff options
author | Mary <me@thog.eu> | 2020-12-01 22:48:31 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-01 22:48:31 +0100 |
commit | f6d88558b1780df25088042771a75ab174f0a06c (patch) | |
tree | e3e1d1ece3b20be6a7b460226eb1e920f78e2087 /Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs | |
parent | 5e6dc37aed22bd596db6a0e9c9a0527fc2a8e5b5 (diff) |
salieri: Fix missing guest GPU accessor missing on hashes (#1759)
This adds the guest GPU accessor to hashes computation.
As this change all the hashes from the cache, I added some migration
logic.
This is required for #1755.
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs')
-rw-r--r-- | Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs | 209 |
1 files changed, 10 insertions, 199 deletions
diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs index b469aab5..a04affc2 100644 --- a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs +++ b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs @@ -9,9 +9,6 @@ using Ryujinx.Graphics.Shader.Translation; using System; using System.Collections.Generic; using System.Diagnostics; -using System.IO; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; namespace Ryujinx.Graphics.Gpu.Shader { @@ -37,7 +34,7 @@ namespace Ryujinx.Graphics.Gpu.Shader /// <summary> /// Version of the codegen (to be changed when codegen or guest format change). /// </summary> - private const ulong ShaderCodeGenVersion = 1717; + private const ulong ShaderCodeGenVersion = 1759; /// <summary> /// Creates a new instance of the shader cache. @@ -165,7 +162,7 @@ namespace Ryujinx.Graphics.Gpu.Shader ShaderCodeHolder[] shaders = new ShaderCodeHolder[cachedShaderEntries.Length]; List<ShaderProgram> shaderPrograms = new List<ShaderProgram>(); - TransformFeedbackDescriptor[] tfd = ReadTransformationFeedbackInformations(ref guestProgramReadOnlySpan, fileHeader); + TransformFeedbackDescriptor[] tfd = CacheHelper.ReadTransformationFeedbackInformations(ref guestProgramReadOnlySpan, fileHeader); TranslationFlags flags = DefaultFlags; @@ -347,14 +344,14 @@ namespace Ryujinx.Graphics.Gpu.Shader bool isShaderCacheEnabled = _cacheManager != null; - byte[] programCode = null; Hash128 programCodeHash = default; - GuestShaderCacheEntryHeader[] shaderCacheEntries = null; + GuestShaderCacheEntry[] shaderCacheEntries = null; if (isShaderCacheEnabled) { // Compute hash and prepare data for shader disk cache comparison. - GetProgramInformations(null, shaderContexts, out programCode, out programCodeHash, out shaderCacheEntries); + shaderCacheEntries = CacheHelper.CreateShaderCacheEntries(_context.MemoryManager, shaderContexts); + programCodeHash = CacheHelper.ComputeGuestHashFromCache(shaderCacheEntries); } ShaderBundle cpShader; @@ -381,7 +378,7 @@ namespace Ryujinx.Graphics.Gpu.Shader if (isShaderCacheEnabled) { _cpProgramsDiskCache.Add(programCodeHash, cpShader); - _cacheManager.SaveProgram(ref programCodeHash, CreateGuestProgramDump(programCode, shaderCacheEntries, null), hostProgramBinary); + _cacheManager.SaveProgram(ref programCodeHash, CacheHelper.CreateGuestProgramDump(shaderCacheEntries), hostProgramBinary); } } @@ -451,14 +448,14 @@ namespace Ryujinx.Graphics.Gpu.Shader bool isShaderCacheEnabled = _cacheManager != null; - byte[] programCode = null; Hash128 programCodeHash = default; - GuestShaderCacheEntryHeader[] shaderCacheEntries = null; + GuestShaderCacheEntry[] shaderCacheEntries = null; if (isShaderCacheEnabled) { // Compute hash and prepare data for shader disk cache comparison. - GetProgramInformations(tfd, shaderContexts, out programCode, out programCodeHash, out shaderCacheEntries); + shaderCacheEntries = CacheHelper.CreateShaderCacheEntries(_context.MemoryManager, shaderContexts); + programCodeHash = CacheHelper.ComputeGuestHashFromCache(shaderCacheEntries, tfd); } ShaderBundle gpShaders; @@ -507,7 +504,7 @@ namespace Ryujinx.Graphics.Gpu.Shader if (isShaderCacheEnabled) { _gpProgramsDiskCache.Add(programCodeHash, gpShaders); - _cacheManager.SaveProgram(ref programCodeHash, CreateGuestProgramDump(programCode, shaderCacheEntries, tfd), hostProgramBinary); + _cacheManager.SaveProgram(ref programCodeHash, CacheHelper.CreateGuestProgramDump(shaderCacheEntries, tfd), hostProgramBinary); } } @@ -766,191 +763,5 @@ namespace Ryujinx.Graphics.Gpu.Shader _cacheManager?.Dispose(); } - - /// <summary> - /// Create a guest shader program. - /// </summary> - /// <param name="programCode">The program code of the shader code</param> - /// <param name="shaderCacheEntries">The resulting guest shader entries header</param> - /// <param name="tfd">The transform feedback descriptors in use</param> - /// <returns>The resulting guest shader program</returns> - private static byte[] CreateGuestProgramDump(ReadOnlySpan<byte> programCode, GuestShaderCacheEntryHeader[] shaderCacheEntries, TransformFeedbackDescriptor[] tfd) - { - using (MemoryStream resultStream = new MemoryStream()) - { - BinaryWriter resultStreamWriter = new BinaryWriter(resultStream); - - byte transformFeedbackCount = 0; - - if (tfd != null) - { - transformFeedbackCount = (byte)tfd.Length; - } - - // Header - resultStreamWriter.WriteStruct(new GuestShaderCacheHeader((byte)shaderCacheEntries.Length, transformFeedbackCount)); - - // Write all entries header - foreach (GuestShaderCacheEntryHeader entry in shaderCacheEntries) - { - resultStreamWriter.WriteStruct(entry); - } - - // Finally, write all program code and all transform feedback information. - resultStreamWriter.Write(programCode); - - return resultStream.ToArray(); - } - } - - /// <summary> - /// Write transform feedback guest information to the given stream. - /// </summary> - /// <param name="stream">The stream to write data to</param> - /// <param name="tfd">The current transform feedback descriptors used</param> - private static void WriteTransformationFeedbackInformation(Stream stream, TransformFeedbackDescriptor[] tfd) - { - if (tfd != null) - { - BinaryWriter writer = new BinaryWriter(stream); - - foreach (TransformFeedbackDescriptor transform in tfd) - { - writer.WriteStruct(new GuestShaderCacheTransformFeedbackHeader(transform.BufferIndex, transform.Stride, transform.VaryingLocations.Length)); - writer.Write(transform.VaryingLocations); - } - } - } - - /// <summary> - /// Read transform feedback descriptors from guest. - /// </summary> - /// <param name="data">The raw guest transform feedback descriptors</param> - /// <param name="header">The guest shader program header</param> - /// <returns>The transform feedback descriptors read from guest</returns> - private static TransformFeedbackDescriptor[] ReadTransformationFeedbackInformations(ref ReadOnlySpan<byte> data, GuestShaderCacheHeader header) - { - if (header.TransformFeedbackCount != 0) - { - TransformFeedbackDescriptor[] result = new TransformFeedbackDescriptor[header.TransformFeedbackCount]; - - for (int i = 0; i < result.Length; i++) - { - GuestShaderCacheTransformFeedbackHeader feedbackHeader = MemoryMarshal.Read<GuestShaderCacheTransformFeedbackHeader>(data); - - result[i] = new TransformFeedbackDescriptor(feedbackHeader.BufferIndex, feedbackHeader.Stride, data.Slice(Unsafe.SizeOf<GuestShaderCacheTransformFeedbackHeader>(), feedbackHeader.VaryingLocationsLength).ToArray()); - - data = data.Slice(Unsafe.SizeOf<GuestShaderCacheTransformFeedbackHeader>() + feedbackHeader.VaryingLocationsLength); - } - - return result; - } - - return null; - } - - /// <summary> - /// Create a new instance of <see cref="GuestGpuAccessorHeader"/> from an gpu accessor. - /// </summary> - /// <param name="gpuAccessor">The gpu accessor</param> - /// <returns>a new instance of <see cref="GuestGpuAccessorHeader"/></returns> - private static GuestGpuAccessorHeader CreateGuestGpuAccessorCache(IGpuAccessor gpuAccessor) - { - return new GuestGpuAccessorHeader - { - ComputeLocalSizeX = gpuAccessor.QueryComputeLocalSizeX(), - ComputeLocalSizeY = gpuAccessor.QueryComputeLocalSizeY(), - ComputeLocalSizeZ = gpuAccessor.QueryComputeLocalSizeZ(), - ComputeLocalMemorySize = gpuAccessor.QueryComputeLocalMemorySize(), - ComputeSharedMemorySize = gpuAccessor.QueryComputeSharedMemorySize(), - PrimitiveTopology = gpuAccessor.QueryPrimitiveTopology(), - }; - } - - /// <summary> - /// Write the guest GpuAccessor informations to the given stream. - /// </summary> - /// <param name="stream">The stream to write the guest GpuAcessor</param> - /// <param name="shaderContext">The shader tranlator context in use</param> - /// <returns>The guest gpu accessor header</returns> - private static GuestGpuAccessorHeader WriteGuestGpuAccessorCache(Stream stream, TranslatorContext shaderContext) - { - BinaryWriter writer = new BinaryWriter(stream); - - GuestGpuAccessorHeader header = CreateGuestGpuAccessorCache(shaderContext.GpuAccessor); - - // If we have a full gpu accessor, cache textures descriptors - if (shaderContext.GpuAccessor is GpuAccessor gpuAccessor) - { - HashSet<int> textureHandlesInUse = shaderContext.TextureHandlesForCache; - - header.TextureDescriptorCount = textureHandlesInUse.Count; - - foreach (int textureHandle in textureHandlesInUse) - { - GuestTextureDescriptor textureDescriptor = ((Image.TextureDescriptor)gpuAccessor.GetTextureDescriptor(textureHandle)).ToCache(); - - textureDescriptor.Handle = (uint)textureHandle; - - writer.WriteStruct(textureDescriptor); - } - } - - return header; - } - - /// <summary> - /// Get the shader program information for use on the shader cache. - /// </summary> - /// <param name="tfd">The current transform feedback descriptors used</param> - /// <param name="shaderContexts">The shader translators context in use</param> - /// <param name="programCode">The resulting raw shader program code</param> - /// <param name="programCodeHash">The resulting raw shader program code hash</param> - /// <param name="entries">The resulting guest shader entries header</param> - private void GetProgramInformations(TransformFeedbackDescriptor[] tfd, ReadOnlySpan<TranslatorContext> shaderContexts, out byte[] programCode, out Hash128 programCodeHash, out GuestShaderCacheEntryHeader[] entries) - { - GuestShaderCacheEntryHeader ComputeStage(Stream stream, TranslatorContext context) - { - if (context == null) - { - return new GuestShaderCacheEntryHeader(); - } - - ReadOnlySpan<byte> data = _context.MemoryManager.GetSpan(context.Address, context.Size); - - stream.Write(data); - - int size = data.Length; - int sizeA = 0; - - if (context.AddressA != 0) - { - data = _context.MemoryManager.GetSpan(context.AddressA, context.SizeA); - - sizeA = data.Length; - - stream.Write(data); - } - - GuestGpuAccessorHeader gpuAccessorHeader = WriteGuestGpuAccessorCache(stream, context); - - return new GuestShaderCacheEntryHeader(context.Stage, size, sizeA, gpuAccessorHeader); - } - - entries = new GuestShaderCacheEntryHeader[shaderContexts.Length]; - - using (MemoryStream stream = new MemoryStream()) - { - for (int i = 0; i < shaderContexts.Length; i++) - { - entries[i] = ComputeStage(stream, shaderContexts[i]); - } - - WriteTransformationFeedbackInformation(stream, tfd); - - programCode = stream.ToArray(); - programCodeHash = _cacheManager.ComputeHash(programCode); - } - } } }
\ No newline at end of file |