From 57846deed53f9eacf3d47f01cdeceae3c24afddc Mon Sep 17 00:00:00 2001 From: ParantezTech <12572227+par274@users.noreply.github.com> Date: Thu, 8 Oct 2026 02:50:32 +0300 Subject: [PATCH] [ShaderCompiler] Canonicalize buffer specializations for portable descriptors --- .../Resources/ResourceMaterializationCache.cs | 9 ++++++++- .../Resources/ResourceMaterializer.cs | 12 +++++++----- .../Resources/ResourceRuntimeInputs.cs | 3 +++ 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/SharpEmu.ShaderCompiler/Resources/ResourceMaterializationCache.cs b/src/SharpEmu.ShaderCompiler/Resources/ResourceMaterializationCache.cs index 759e5bc..d3a9e8d 100644 --- a/src/SharpEmu.ShaderCompiler/Resources/ResourceMaterializationCache.cs +++ b/src/SharpEmu.ShaderCompiler/Resources/ResourceMaterializationCache.cs @@ -134,6 +134,7 @@ public sealed class ResourceMaterializationCache ReadsClean = inputs.ReadsClean, ComputeState = inputs.ComputeState, TablePhase = recorder.TablePhase, + PortableBuffers = inputs.PortableBuffers, }; if (!ResourceMaterializer.Materialize(plan, recording, ref snapshot, ref specialization, out failure)) return false; @@ -214,6 +215,7 @@ public sealed class ResourceMaterializationCache ReadResidentMemory = recorder.WrapResident(inputs.ReadResidentMemory), ReadsClean = inputs.ReadsClean, ComputeState = inputs.ComputeState, + PortableBuffers = inputs.PortableBuffers, }; var cachedTable = cached.Snapshot.FlattenedResourceTable; ReadingTable = true; @@ -249,6 +251,7 @@ public sealed class ResourceMaterializationCache UserData = cached.UserData, ShaderBase = cached.ShaderBase, ComputeState = cached.ComputeState, + PortableBuffers = cached.PortableBuffers, RangeAddresses = cached.RangeAddresses, RangeOffsets = cached.RangeOffsets, RangeLengths = cached.RangeLengths, @@ -325,6 +328,7 @@ public sealed class ResourceMaterializationCache hash.Add(RuntimeHelpers.GetHashCode(plan)); hash.Add(inputs.ShaderBase); hash.Add(inputs.ComputeState); + hash.Add(inputs.PortableBuffers); var userData = inputs.UserData; hash.Add(userData.Count); for (var index = 0; index < userData.Count; index++) @@ -387,6 +391,7 @@ public sealed class ResourceMaterializationCache public required uint[] UserData { get; init; } public required ulong ShaderBase { get; init; } public required ComputeSelectorState? ComputeState { get; init; } + public required bool PortableBuffers { get; init; } public required ulong[] RangeAddresses { get; init; } public required int[] RangeOffsets { get; init; } public required int[] RangeLengths { get; init; } @@ -403,7 +408,8 @@ public sealed class ResourceMaterializationCache public bool Matches(ShaderResourcePlan plan, ResourceRuntimeInputs inputs) { if (!ReferenceEquals(Plan, plan) || ShaderBase != inputs.ShaderBase || - !Nullable.Equals(ComputeState, inputs.ComputeState) || UserData.Length != inputs.UserData.Count) + !Nullable.Equals(ComputeState, inputs.ComputeState) || PortableBuffers != inputs.PortableBuffers || + UserData.Length != inputs.UserData.Count) return false; for (var index = 0; index < UserData.Length; index++) if (UserData[index] != inputs.UserData[index]) @@ -562,6 +568,7 @@ public sealed class ResourceMaterializationCache UserData = userData, ShaderBase = inputs.ShaderBase, ComputeState = inputs.ComputeState, + PortableBuffers = inputs.PortableBuffers, RangeAddresses = addresses, RangeOffsets = offsets, RangeLengths = lengths, diff --git a/src/SharpEmu.ShaderCompiler/Resources/ResourceMaterializer.cs b/src/SharpEmu.ShaderCompiler/Resources/ResourceMaterializer.cs index b65eb7e..42e9f65 100644 --- a/src/SharpEmu.ShaderCompiler/Resources/ResourceMaterializer.cs +++ b/src/SharpEmu.ShaderCompiler/Resources/ResourceMaterializer.cs @@ -91,7 +91,7 @@ public static class ResourceMaterializer materialized.FlattenedTable[offset + 2] = (uint)Math.Min(range.Size, uint.MaxValue); } - if (!BuildSpecialization(plan, materialized, out var nextSnapshot, out var nextSpecialization, out failure, captureIndirectImageFailure)) + if (!BuildSpecialization(plan, materialized, inputs.PortableBuffers, out var nextSnapshot, out var nextSpecialization, out failure, captureIndirectImageFailure)) { return false; } @@ -877,6 +877,7 @@ public static class ResourceMaterializer private static bool BuildSpecialization( ShaderResourcePlan plan, MaterializedSnapshot snapshot, + bool portableBuffers, out MaterializedSnapshot specializedSnapshot, out ResourceSpecialization specialization, out ResourceMaterializationFailure failure, @@ -985,10 +986,11 @@ public static class ResourceMaterializer } var formatted = info.Buffers[index].Formatted; + var runtimeFormat = portableBuffers && PortableBufferWord.ReadsFormatAtRuntime(info.Buffers[index]); buffers.Add(new BufferSpecialization( - packedStride, - formatted ? (words[3] >> 12) & 0x7F : DescriptorConstants.InvalidFormat, - formatted ? words[3] & 0xFFF : DescriptorConstants.IdentityDestinationSelect)); + portableBuffers ? 0 : packedStride, + formatted && !runtimeFormat ? (words[3] >> 12) & 0x7F : DescriptorConstants.InvalidFormat, + formatted && !runtimeFormat ? words[3] & 0xFFF : DescriptorConstants.IdentityDestinationSelect)); } for (var index = 0; index < images.Count; index++) @@ -1274,7 +1276,7 @@ public static class ResourceMaterializer packedStride &= ~(3u << 16); } - buffers.Add(new BufferSpecialization(packedStride, (words[3] >> 12) & 0x7F, words[3] & 0xFFF)); + buffers.Add(new BufferSpecialization(portableBuffers ? 0 : packedStride, (words[3] >> 12) & 0x7F, words[3] & 0xFFF)); } var mappingOffset = (uint)mappingCursor; diff --git a/src/SharpEmu.ShaderCompiler/Resources/ResourceRuntimeInputs.cs b/src/SharpEmu.ShaderCompiler/Resources/ResourceRuntimeInputs.cs index a6ee7e1..09566dd 100644 --- a/src/SharpEmu.ShaderCompiler/Resources/ResourceRuntimeInputs.cs +++ b/src/SharpEmu.ShaderCompiler/Resources/ResourceRuntimeInputs.cs @@ -26,6 +26,8 @@ public sealed class ResourceRuntimeInputs public bool ReadsClean { get; init; } + public bool PortableBuffers { get; init; } + public ResourceRuntimeInputs WithReader(GuestWordReader? reader) => new() { UserData = UserData, @@ -36,6 +38,7 @@ public sealed class ResourceRuntimeInputs TablePhase = TablePhase, ReadResidentMemory = ReadResidentMemory, ReadsClean = ReadsClean || ReferenceEquals(reader, ReadCleanMemory), + PortableBuffers = PortableBuffers, }; }