diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2024-04-22 15:05:55 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-04-22 15:05:55 -0300 |
| commit | c6f8bfed904e30f7c5d890a2f0ef531eb9e298e5 (patch) | |
| tree | e1c048d390867e8c9403904498184e3a64277e49 /src/Ryujinx.Graphics.Gpu/Shader | |
| parent | 9b94662b4bb2ebf846e1baf45ba8097fcd7da684 (diff) | |
Add support for bindless textures from shader input (vertex buffer) on Vulkan (#6577)
* Add support for bindless textures from shader input (vertex buffer)
* Shader cache version bump
* Format whitespace
* Remove cache entries on pool removal, disable for OpenGL
* PR feedback
Diffstat (limited to 'src/Ryujinx.Graphics.Gpu/Shader')
10 files changed, 187 insertions, 28 deletions
diff --git a/src/Ryujinx.Graphics.Gpu/Shader/CachedShaderBindings.cs b/src/Ryujinx.Graphics.Gpu/Shader/CachedShaderBindings.cs index 6e36753e..a80dcbc8 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/CachedShaderBindings.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/CachedShaderBindings.cs @@ -58,7 +58,7 @@ namespace Ryujinx.Graphics.Gpu.Shader TextureBindings[i] = stage.Info.Textures.Select(descriptor => { - Target target = ShaderTexture.GetTarget(descriptor.Type); + Target target = descriptor.Type != SamplerType.None ? ShaderTexture.GetTarget(descriptor.Type) : default; var result = new TextureBindingInfo( target, @@ -66,7 +66,8 @@ namespace Ryujinx.Graphics.Gpu.Shader descriptor.ArrayLength, descriptor.CbufSlot, descriptor.HandleIndex, - descriptor.Flags); + descriptor.Flags, + descriptor.Type == SamplerType.None); if (descriptor.ArrayLength <= 1) { diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGpuAccessor.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGpuAccessor.cs index 681838a9..45f32e2d 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGpuAccessor.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGpuAccessor.cs @@ -110,6 +110,13 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache } /// <inheritdoc/> + /// <exception cref="DiskCacheLoadException">Pool length is not available on the cache</exception> + public int QuerySamplerArrayLengthFromPool() + { + return QueryArrayLengthFromPool(isSampler: true); + } + + /// <inheritdoc/> public SamplerType QuerySamplerType(int handle, int cbufSlot) { _newSpecState.RecordTextureSamplerType(_stageIndex, handle, cbufSlot); @@ -117,6 +124,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache } /// <inheritdoc/> + /// <exception cref="DiskCacheLoadException">Constant buffer derived length is not available on the cache</exception> public int QueryTextureArrayLengthFromBuffer(int slot) { if (!_oldSpecState.TextureArrayFromBufferRegistered(_stageIndex, 0, slot)) @@ -131,6 +139,13 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache } /// <inheritdoc/> + /// <exception cref="DiskCacheLoadException">Pool length is not available on the cache</exception> + public int QueryTextureArrayLengthFromPool() + { + return QueryArrayLengthFromPool(isSampler: false); + } + + /// <inheritdoc/> public TextureFormat QueryTextureFormat(int handle, int cbufSlot) { _newSpecState.RecordTextureFormat(_stageIndex, handle, cbufSlot); @@ -170,6 +185,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache } /// <inheritdoc/> + /// <exception cref="DiskCacheLoadException">Texture information is not available on the cache</exception> public void RegisterTexture(int handle, int cbufSlot) { if (!_oldSpecState.TextureRegistered(_stageIndex, handle, cbufSlot)) @@ -182,5 +198,24 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache bool coordNormalized = _oldSpecState.GetCoordNormalized(_stageIndex, handle, cbufSlot); _newSpecState.RegisterTexture(_stageIndex, handle, cbufSlot, format, formatSrgb, target, coordNormalized); } + + /// <summary> + /// Gets the cached texture or sampler pool capacity. + /// </summary> + /// <param name="isSampler">True to get sampler pool length, false for texture pool length</param> + /// <returns>Pool length</returns> + /// <exception cref="DiskCacheLoadException">Pool length is not available on the cache</exception> + private int QueryArrayLengthFromPool(bool isSampler) + { + if (!_oldSpecState.TextureArrayFromPoolRegistered(isSampler)) + { + throw new DiskCacheLoadException(DiskCacheLoadResult.MissingTextureArrayLength); + } + + int arrayLength = _oldSpecState.GetTextureArrayFromPoolLength(isSampler); + _newSpecState.RegisterTextureArrayLengthFromPool(isSampler, arrayLength); + + return arrayLength; + } } } diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs index b6a277a2..2c19cc4b 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs @@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache private const ushort FileFormatVersionMajor = 1; private const ushort FileFormatVersionMinor = 2; private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor; - private const uint CodeGenVersion = 6489; + private const uint CodeGenVersion = 6577; private const string SharedTocFileName = "shared.toc"; private const string SharedDataFileName = "shared.data"; diff --git a/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs b/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs index 1d22ab93..04949690 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs @@ -121,6 +121,15 @@ namespace Ryujinx.Graphics.Gpu.Shader } /// <inheritdoc/> + public int QuerySamplerArrayLengthFromPool() + { + int length = _state.SamplerPoolMaximumId + 1; + _state.SpecializationState?.RegisterTextureArrayLengthFromPool(isSampler: true, length); + + return length; + } + + /// <inheritdoc/> public SamplerType QuerySamplerType(int handle, int cbufSlot) { _state.SpecializationState?.RecordTextureSamplerType(_stageIndex, handle, cbufSlot); @@ -141,6 +150,15 @@ namespace Ryujinx.Graphics.Gpu.Shader return arrayLength; } + /// <inheritdoc/> + public int QueryTextureArrayLengthFromPool() + { + int length = _state.PoolState.TexturePoolMaximumId + 1; + _state.SpecializationState?.RegisterTextureArrayLengthFromPool(isSampler: false, length); + + return length; + } + //// <inheritdoc/> public TextureFormat QueryTextureFormat(int handle, int cbufSlot) { diff --git a/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessorBase.cs b/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessorBase.cs index 06e5edf1..0d562b0d 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessorBase.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessorBase.cs @@ -213,6 +213,8 @@ namespace Ryujinx.Graphics.Gpu.Shader public bool QueryHostSupportsScaledVertexFormats() => _context.Capabilities.SupportsScaledVertexFormats; + public bool QueryHostSupportsSeparateSampler() => _context.Capabilities.SupportsSeparateSampler; + public bool QueryHostSupportsShaderBallot() => _context.Capabilities.SupportsShaderBallot; public bool QueryHostSupportsShaderBarrierDivergence() => _context.Capabilities.SupportsShaderBarrierDivergence; diff --git a/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessorState.cs b/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessorState.cs index cfc4a2cc..808bf185 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessorState.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessorState.cs @@ -6,6 +6,11 @@ namespace Ryujinx.Graphics.Gpu.Shader class GpuAccessorState { /// <summary> + /// Maximum ID that a sampler pool entry may have. + /// </summary> + public readonly int SamplerPoolMaximumId; + + /// <summary> /// GPU texture pool state. /// </summary> public readonly GpuChannelPoolState PoolState; @@ -38,18 +43,21 @@ namespace Ryujinx.Graphics.Gpu.Shader /// <summary> /// Creates a new GPU accessor state. /// </summary> + /// <param name="samplerPoolMaximumId">Maximum ID that a sampler pool entry may have</param> /// <param name="poolState">GPU texture pool state</param> /// <param name="computeState">GPU compute state, for compute shaders</param> /// <param name="graphicsState">GPU graphics state, for vertex, tessellation, geometry and fragment shaders</param> /// <param name="specializationState">Shader specialization state (shared by all stages)</param> /// <param name="transformFeedbackDescriptors">Transform feedback information, if the shader uses transform feedback. Otherwise, should be null</param> public GpuAccessorState( + int samplerPoolMaximumId, GpuChannelPoolState poolState, GpuChannelComputeState computeState, GpuChannelGraphicsState graphicsState, ShaderSpecializationState specializationState, TransformFeedbackDescriptor[] transformFeedbackDescriptors = null) { + SamplerPoolMaximumId = samplerPoolMaximumId; PoolState = poolState; GraphicsState = graphicsState; ComputeState = computeState; diff --git a/src/Ryujinx.Graphics.Gpu/Shader/GpuChannelPoolState.cs b/src/Ryujinx.Graphics.Gpu/Shader/GpuChannelPoolState.cs index ddb45152..a2ab9933 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/GpuChannelPoolState.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/GpuChannelPoolState.cs @@ -2,7 +2,6 @@ using System; namespace Ryujinx.Graphics.Gpu.Shader { -#pragma warning disable CS0659 // Class overrides Object.Equals(object o) but does not override Object.GetHashCode() /// <summary> /// State used by the <see cref="GpuAccessor"/>. /// </summary> @@ -52,6 +51,10 @@ namespace Ryujinx.Graphics.Gpu.Shader { return obj is GpuChannelPoolState state && Equals(state); } + + public override int GetHashCode() + { + return HashCode.Combine(TexturePoolGpuVa, TexturePoolMaximumId, TextureBufferIndex); + } } -#pragma warning restore CS0659 } diff --git a/src/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs b/src/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs index 0b17af8b..31cc94a2 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs @@ -192,12 +192,14 @@ namespace Ryujinx.Graphics.Gpu.Shader /// This automatically translates, compiles and adds the code to the cache if not present. /// </remarks> /// <param name="channel">GPU channel</param> + /// <param name="samplerPoolMaximumId">Maximum ID that an entry in the sampler pool may have</param> /// <param name="poolState">Texture pool state</param> /// <param name="computeState">Compute engine state</param> /// <param name="gpuVa">GPU virtual address of the binary shader code</param> /// <returns>Compiled compute shader code</returns> public CachedShaderProgram GetComputeShader( GpuChannel channel, + int samplerPoolMaximumId, GpuChannelPoolState poolState, GpuChannelComputeState computeState, ulong gpuVa) @@ -214,7 +216,7 @@ namespace Ryujinx.Graphics.Gpu.Shader } ShaderSpecializationState specState = new(ref computeState); - GpuAccessorState gpuAccessorState = new(poolState, computeState, default, specState); + GpuAccessorState gpuAccessorState = new(samplerPoolMaximumId, poolState, computeState, default, specState); GpuAccessor gpuAccessor = new(_context, channel, gpuAccessorState); gpuAccessor.InitializeReservedCounts(tfEnabled: false, vertexAsCompute: false); @@ -291,6 +293,7 @@ namespace Ryujinx.Graphics.Gpu.Shader /// <param name="state">GPU state</param> /// <param name="pipeline">Pipeline state</param> /// <param name="channel">GPU channel</param> + /// <param name="samplerPoolMaximumId">Maximum ID that an entry in the sampler pool may have</param> /// <param name="poolState">Texture pool state</param> /// <param name="graphicsState">3D engine state</param> /// <param name="addresses">Addresses of the shaders for each stage</param> @@ -299,6 +302,7 @@ namespace Ryujinx.Graphics.Gpu.Shader ref ThreedClassState state, ref ProgramPipelineState pipeline, GpuChannel channel, + int samplerPoolMaximumId, ref GpuChannelPoolState poolState, ref GpuChannelGraphicsState graphicsState, ShaderAddresses addresses) @@ -319,7 +323,7 @@ namespace Ryujinx.Graphics.Gpu.Shader UpdatePipelineInfo(ref state, ref pipeline, graphicsState, channel); ShaderSpecializationState specState = new(ref graphicsState, ref pipeline, transformFeedbackDescriptors); - GpuAccessorState gpuAccessorState = new(poolState, default, graphicsState, specState, transformFeedbackDescriptors); + GpuAccessorState gpuAccessorState = new(samplerPoolMaximumId, poolState, default, graphicsState, specState, transformFeedbackDescriptors); ReadOnlySpan<ulong> addressesSpan = addresses.AsSpan(); diff --git a/src/Ryujinx.Graphics.Gpu/Shader/ShaderInfoBuilder.cs b/src/Ryujinx.Graphics.Gpu/Shader/ShaderInfoBuilder.cs index ea8f164f..ed56db3b 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/ShaderInfoBuilder.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/ShaderInfoBuilder.cs @@ -185,11 +185,7 @@ namespace Ryujinx.Graphics.Gpu.Shader { if (texture.ArrayLength > 1) { - bool isBuffer = (texture.Type & SamplerType.Mask) == SamplerType.TextureBuffer; - - ResourceType type = isBuffer - ? (isImage ? ResourceType.BufferImage : ResourceType.BufferTexture) - : (isImage ? ResourceType.Image : ResourceType.TextureAndSampler); + ResourceType type = GetTextureResourceType(texture, isImage); _resourceDescriptors[setIndex].Add(new ResourceDescriptor(texture.Binding, texture.ArrayLength, type, stages)); } @@ -242,16 +238,38 @@ namespace Ryujinx.Graphics.Gpu.Shader { foreach (TextureDescriptor texture in textures) { - bool isBuffer = (texture.Type & SamplerType.Mask) == SamplerType.TextureBuffer; - - ResourceType type = isBuffer - ? (isImage ? ResourceType.BufferImage : ResourceType.BufferTexture) - : (isImage ? ResourceType.Image : ResourceType.TextureAndSampler); + ResourceType type = GetTextureResourceType(texture, isImage); _resourceUsages[setIndex].Add(new ResourceUsage(texture.Binding, texture.ArrayLength, type, stages)); } } + private static ResourceType GetTextureResourceType(TextureDescriptor texture, bool isImage) + { + bool isBuffer = (texture.Type & SamplerType.Mask) == SamplerType.TextureBuffer; + + if (isBuffer) + { + return isImage ? ResourceType.BufferImage : ResourceType.BufferTexture; + } + else if (isImage) + { + return ResourceType.Image; + } + else if (texture.Type == SamplerType.None) + { + return ResourceType.Sampler; + } + else if (texture.Separate) + { + return ResourceType.Texture; + } + else + { + return ResourceType.TextureAndSampler; + } + } + /// <summary> /// Creates a new shader information structure from the added information. /// </summary> diff --git a/src/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs b/src/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs index c90a0b8f..98acb6f2 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs @@ -31,6 +31,7 @@ namespace Ryujinx.Graphics.Gpu.Shader PrimitiveTopology = 1 << 1, TransformFeedback = 1 << 3, TextureArrayFromBuffer = 1 << 4, + TextureArrayFromPool = 1 << 5, } private QueriedStateFlags _queriedState; @@ -154,7 +155,8 @@ namespace Ryujinx.Graphics.Gpu.Shader } private readonly Dictionary<TextureKey, Box<TextureSpecializationState>> _textureSpecialization; - private readonly Dictionary<TextureKey, int> _textureArraySpecialization; + private readonly Dictionary<TextureKey, int> _textureArrayFromBufferSpecialization; + private readonly Dictionary<bool, int> _textureArrayFromPoolSpecialization; private KeyValuePair<TextureKey, Box<TextureSpecializationState>>[] _allTextures; private Box<TextureSpecializationState>[][] _textureByBinding; private Box<TextureSpecializationState>[][] _imageByBinding; @@ -165,7 +167,8 @@ namespace Ryujinx.Graphics.Gpu.Shader private ShaderSpecializationState() { _textureSpecialization = new Dictionary<TextureKey, Box<TextureSpecializationState>>(); - _textureArraySpecialization = new Dictionary<TextureKey, int>(); + _textureArrayFromBufferSpecialization = new Dictionary<TextureKey, int>(); + _textureArrayFromPoolSpecialization = new Dictionary<bool, int>(); } /// <summary> @@ -327,7 +330,7 @@ namespace Ryujinx.Graphics.Gpu.Shader } /// <summary> - /// Indicates that the coordinate normalization state of a given texture was used during the shader translation process. + /// Registers the length of a texture array calculated from a constant buffer size. /// </summary> /// <param name="stageIndex">Shader stage where the texture is used</param> /// <param name="handle">Offset in words of the texture handle on the texture buffer</param> @@ -335,11 +338,22 @@ namespace Ryujinx.Graphics.Gpu.Shader /// <param name="length">Number of elements in the texture array</param> public void RegisterTextureArrayLengthFromBuffer(int stageIndex, int handle, int cbufSlot, int length) { - _textureArraySpecialization[new TextureKey(stageIndex, handle, cbufSlot)] = length; + _textureArrayFromBufferSpecialization[new TextureKey(stageIndex, handle, cbufSlot)] = length; _queriedState |= QueriedStateFlags.TextureArrayFromBuffer; } /// <summary> + /// Registers the length of a texture array calculated from a texture or sampler pool capacity. + /// </summary> + /// <param name="isSampler">True for sampler pool, false for texture pool</param> + /// <param name="length">Number of elements in the texture array</param> + public void RegisterTextureArrayLengthFromPool(bool isSampler, int length) + { + _textureArrayFromPoolSpecialization[isSampler] = length; + _queriedState |= QueriedStateFlags.TextureArrayFromPool; + } + + /// <summary> /// Indicates that the format of a given texture was used during the shader translation process. /// </summary> /// <param name="stageIndex">Shader stage where the texture is used</param> @@ -385,7 +399,7 @@ namespace Ryujinx.Graphics.Gpu.Shader } /// <summary> - /// Checks if a given texture was registerd on this specialization state. + /// Checks if a given texture was registered on this specialization state. /// </summary> /// <param name="stageIndex">Shader stage where the texture is used</param> /// <param name="handle">Offset in words of the texture handle on the texture buffer</param> @@ -396,14 +410,25 @@ namespace Ryujinx.Graphics.Gpu.Shader } /// <summary> - /// Checks if a given texture array (from constant buffer) was registerd on this specialization state. + /// Checks if a given texture array (from constant buffer) was registered on this specialization state. /// </summary> /// <param name="stageIndex">Shader stage where the texture is used</param> /// <param name="handle">Offset in words of the texture handle on the texture buffer</param> /// <param name="cbufSlot">Slot of the texture buffer constant buffer</param> + /// <returns>True if the length for the given buffer and stage exists, false otherwise</returns> public bool TextureArrayFromBufferRegistered(int stageIndex, int handle, int cbufSlot) { - return _textureArraySpecialization.ContainsKey(new TextureKey(stageIndex, handle, cbufSlot)); + return _textureArrayFromBufferSpecialization.ContainsKey(new TextureKey(stageIndex, handle, cbufSlot)); + } + + /// <summary> + /// Checks if a given texture array (from a sampler pool or texture pool) was registered on this specialization state. + /// </summary> + /// <param name="isSampler">True for sampler pool, false for texture pool</param> + /// <returns>True if the length for the given pool, false otherwise</returns> + public bool TextureArrayFromPoolRegistered(bool isSampler) + { + return _textureArrayFromPoolSpecialization.ContainsKey(isSampler); } /// <summary> @@ -412,6 +437,7 @@ namespace Ryujinx.Graphics.Gpu.Shader /// <param name="stageIndex">Shader stage where the texture is used</param> /// <param name="handle">Offset in words of the texture handle on the texture buffer</param> /// <param name="cbufSlot">Slot of the texture buffer constant buffer</param> + /// <returns>Format and sRGB tuple</returns> public (uint, bool) GetFormat(int stageIndex, int handle, int cbufSlot) { TextureSpecializationState state = GetTextureSpecState(stageIndex, handle, cbufSlot).Value; @@ -424,6 +450,7 @@ namespace Ryujinx.Graphics.Gpu.Shader /// <param name="stageIndex">Shader stage where the texture is used</param> /// <param name="handle">Offset in words of the texture handle on the texture buffer</param> /// <param name="cbufSlot">Slot of the texture buffer constant buffer</param> + /// <returns>Texture target</returns> public TextureTarget GetTextureTarget(int stageIndex, int handle, int cbufSlot) { return GetTextureSpecState(stageIndex, handle, cbufSlot).Value.TextureTarget; @@ -435,6 +462,7 @@ namespace Ryujinx.Graphics.Gpu.Shader /// <param name="stageIndex">Shader stage where the texture is used</param> /// <param name="handle">Offset in words of the texture handle on the texture buffer</param> /// <param name="cbufSlot">Slot of the texture buffer constant buffer</param> + /// <returns>True if coordinates are normalized, false otherwise</returns> public bool GetCoordNormalized(int stageIndex, int handle, int cbufSlot) { return GetTextureSpecState(stageIndex, handle, cbufSlot).Value.CoordNormalized; @@ -446,9 +474,20 @@ namespace Ryujinx.Graphics.Gpu.Shader /// <param name="stageIndex">Shader stage where the texture is used</param> /// <param name="handle">Offset in words of the texture handle on the texture buffer</param> /// <param name="cbufSlot">Slot of the texture buffer constant buffer</param> + /// <returns>Texture array length</returns> public int GetTextureArrayFromBufferLength(int stageIndex, int handle, int cbufSlot) { - return _textureArraySpecialization[new TextureKey(stageIndex, handle, cbufSlot)]; + return _textureArrayFromBufferSpecialization[new TextureKey(stageIndex, handle, cbufSlot)]; + } + + /// <summary> + /// Gets the recorded length of a given texture array (from a sampler or texture pool). + /// </summary> + /// <param name="isSampler">True to get the sampler pool length, false to get the texture pool length</param> + /// <returns>Texture array length</returns> + public int GetTextureArrayFromPoolLength(bool isSampler) + { + return _textureArrayFromPoolSpecialization[isSampler]; } /// <summary> @@ -894,7 +933,23 @@ namespace Ryujinx.Graphics.Gpu.Shader dataReader.ReadWithMagicAndSize(ref textureKey, TexkMagic); dataReader.Read(ref length); - specState._textureArraySpecialization[textureKey] = length; + specState._textureArrayFromBufferSpecialization[textureKey] = length; + } + } + + if (specState._queriedState.HasFlag(QueriedStateFlags.TextureArrayFromPool)) + { + dataReader.Read(ref count); + + for (int index = 0; index < count; index++) + { + bool textureKey = default; + int length = 0; + + dataReader.ReadWithMagicAndSize(ref textureKey, TexkMagic); + dataReader.Read(ref length); + + specState._textureArrayFromPoolSpecialization[textureKey] = length; } } @@ -965,10 +1020,25 @@ namespace Ryujinx.Graphics.Gpu.Shader if (_queriedState.HasFlag(QueriedStateFlags.TextureArrayFromBuffer)) { - count = (ushort)_textureArraySpecialization.Count; + count = (ushort)_textureArrayFromBufferSpecialization.Count; + dataWriter.Write(ref count); + + foreach (var kv in _textureArrayFromBufferSpecialization) + { + var textureKey = kv.Key; + var length = kv.Value; + + dataWriter.WriteWithMagicAndSize(ref textureKey, TexkMagic); + dataWriter.Write(ref length); + } + } + + if (_queriedState.HasFlag(QueriedStateFlags.TextureArrayFromPool)) + { + count = (ushort)_textureArrayFromPoolSpecialization.Count; dataWriter.Write(ref count); - foreach (var kv in _textureArraySpecialization) + foreach (var kv in _textureArrayFromPoolSpecialization) { var textureKey = kv.Key; var length = kv.Value; |
