From a6a67a2b7add9a9dc8c4f0bab730957b8ebaf6e8 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Thu, 10 Nov 2022 13:38:38 -0300 Subject: [PATCH] Minor improvement to Vulkan pipeline state and bindings management (#3829) * Minor improvement to Vulkan pipeline state and bindings management * Clean up buffer textures too * Use glBindTextureUnit --- Ryujinx.Graphics.Gpu/Image/Texture.cs | 3 +- Ryujinx.Graphics.OpenGL/Image/TextureBase.cs | 6 + Ryujinx.Graphics.OpenGL/Pipeline.cs | 5 + .../DescriptorSetUpdater.cs | 26 +-- Ryujinx.Graphics.Vulkan/PipelineState.cs | 167 ++++++++---------- Ryujinx.Graphics.Vulkan/PipelineUid.cs | 20 +-- 6 files changed, 103 insertions(+), 124 deletions(-) diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs index 847cfbfe5e..4203cb0030 100644 --- a/Ryujinx.Graphics.Gpu/Image/Texture.cs +++ b/Ryujinx.Graphics.Gpu/Image/Texture.cs @@ -708,11 +708,12 @@ namespace Ryujinx.Graphics.Gpu.Image else { bool dataMatches = _currentData != null && data.SequenceEqual(_currentData); - _currentData = data.ToArray(); if (dataMatches) { return; } + + _currentData = data.ToArray(); } } diff --git a/Ryujinx.Graphics.OpenGL/Image/TextureBase.cs b/Ryujinx.Graphics.OpenGL/Image/TextureBase.cs index 2e70fa82a0..2ab9dffbc4 100644 --- a/Ryujinx.Graphics.OpenGL/Image/TextureBase.cs +++ b/Ryujinx.Graphics.OpenGL/Image/TextureBase.cs @@ -34,5 +34,11 @@ namespace Ryujinx.Graphics.OpenGL.Image GL.ActiveTexture(TextureUnit.Texture0 + unit); GL.BindTexture(target, Handle); } + + public static void ClearBinding(int unit) + { + GL.ActiveTexture(TextureUnit.Texture0 + unit); + GL.BindTextureUnit(unit, 0); + } } } diff --git a/Ryujinx.Graphics.OpenGL/Pipeline.cs b/Ryujinx.Graphics.OpenGL/Pipeline.cs index 5f22462530..5911758efd 100644 --- a/Ryujinx.Graphics.OpenGL/Pipeline.cs +++ b/Ryujinx.Graphics.OpenGL/Pipeline.cs @@ -919,6 +919,7 @@ namespace Ryujinx.Graphics.OpenGL if (texture == null) { + GL.BindImageTexture(binding, 0, 0, true, 0, TextureAccess.ReadWrite, SizedInternalFormat.Rgba8); return; } @@ -1275,6 +1276,10 @@ namespace Ryujinx.Graphics.OpenGL ((TextureBase)texture).Bind(binding); } } + else + { + TextureBase.ClearBinding(binding); + } Sampler glSampler = (Sampler)sampler; diff --git a/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs b/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs index 9e37231165..e0d5d28634 100644 --- a/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs +++ b/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs @@ -138,11 +138,6 @@ namespace Ryujinx.Graphics.Vulkan public void SetImage(int binding, ITexture image, GAL.Format imageFormat) { - if (image == null) - { - return; - } - if (image is TextureBuffer imageBuffer) { _bufferImageRefs[binding] = imageBuffer; @@ -152,6 +147,12 @@ namespace Ryujinx.Graphics.Vulkan { _imageRefs[binding] = view.GetView(imageFormat).GetIdentityImageView(); } + else + { + _imageRefs[binding] = null; + _bufferImageRefs[binding] = null; + _bufferImageFormats[binding] = default; + } SignalDirty(DirtyFlags.Image); } @@ -215,24 +216,23 @@ namespace Ryujinx.Graphics.Vulkan public void SetTextureAndSampler(CommandBufferScoped cbs, ShaderStage stage, int binding, ITexture texture, ISampler sampler) { - if (texture == null) - { - return; - } - if (texture is TextureBuffer textureBuffer) { _bufferTextureRefs[binding] = textureBuffer; } - else + else if (texture is TextureView view) { - TextureView view = (TextureView)texture; - view.Storage.InsertBarrier(cbs, AccessFlags.AccessShaderReadBit, stage.ConvertToPipelineStageFlags()); _textureRefs[binding] = view.GetImageView(); _samplerRefs[binding] = ((SamplerHolder)sampler)?.GetSampler(); } + else + { + _textureRefs[binding] = null; + _samplerRefs[binding] = null; + _bufferTextureRefs[binding] = null; + } SignalDirty(DirtyFlags.Texture); } diff --git a/Ryujinx.Graphics.Vulkan/PipelineState.cs b/Ryujinx.Graphics.Vulkan/PipelineState.cs index 7b6a264900..e20a664935 100644 --- a/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -81,232 +81,208 @@ namespace Ryujinx.Graphics.Vulkan set => Internal.Id5 = (Internal.Id5 & 0xFFFFFFFF) | ((ulong)(uint)BitConverter.SingleToInt32Bits(value) << 32); } - public float BlendConstantR - { - get => BitConverter.Int32BitsToSingle((int)((Internal.Id6 >> 0) & 0xFFFFFFFF)); - set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFF00000000) | ((ulong)(uint)BitConverter.SingleToInt32Bits(value) << 0); - } - - public float BlendConstantG - { - get => BitConverter.Int32BitsToSingle((int)((Internal.Id6 >> 32) & 0xFFFFFFFF)); - set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFF) | ((ulong)(uint)BitConverter.SingleToInt32Bits(value) << 32); - } - - public float BlendConstantB - { - get => BitConverter.Int32BitsToSingle((int)((Internal.Id7 >> 0) & 0xFFFFFFFF)); - set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFF00000000) | ((ulong)(uint)BitConverter.SingleToInt32Bits(value) << 0); - } - - public float BlendConstantA - { - get => BitConverter.Int32BitsToSingle((int)((Internal.Id7 >> 32) & 0xFFFFFFFF)); - set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFF) | ((ulong)(uint)BitConverter.SingleToInt32Bits(value) << 32); - } - public PolygonMode PolygonMode { - get => (PolygonMode)((Internal.Id8 >> 0) & 0x3FFFFFFF); - set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFC0000000) | ((ulong)value << 0); + get => (PolygonMode)((Internal.Id6 >> 0) & 0x3FFFFFFF); + set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFC0000000) | ((ulong)value << 0); } public uint StagesCount { - get => (byte)((Internal.Id8 >> 30) & 0xFF); - set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFC03FFFFFFF) | ((ulong)value << 30); + get => (byte)((Internal.Id6 >> 30) & 0xFF); + set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFC03FFFFFFF) | ((ulong)value << 30); } public uint VertexAttributeDescriptionsCount { - get => (byte)((Internal.Id8 >> 38) & 0xFF); - set => Internal.Id8 = (Internal.Id8 & 0xFFFFC03FFFFFFFFF) | ((ulong)value << 38); + get => (byte)((Internal.Id6 >> 38) & 0xFF); + set => Internal.Id6 = (Internal.Id6 & 0xFFFFC03FFFFFFFFF) | ((ulong)value << 38); } public uint VertexBindingDescriptionsCount { - get => (byte)((Internal.Id8 >> 46) & 0xFF); - set => Internal.Id8 = (Internal.Id8 & 0xFFC03FFFFFFFFFFF) | ((ulong)value << 46); + get => (byte)((Internal.Id6 >> 46) & 0xFF); + set => Internal.Id6 = (Internal.Id6 & 0xFFC03FFFFFFFFFFF) | ((ulong)value << 46); } public uint ViewportsCount { - get => (byte)((Internal.Id8 >> 54) & 0xFF); - set => Internal.Id8 = (Internal.Id8 & 0xC03FFFFFFFFFFFFF) | ((ulong)value << 54); + get => (byte)((Internal.Id6 >> 54) & 0xFF); + set => Internal.Id6 = (Internal.Id6 & 0xC03FFFFFFFFFFFFF) | ((ulong)value << 54); } public uint ScissorsCount { - get => (byte)((Internal.Id9 >> 0) & 0xFF); - set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFF00) | ((ulong)value << 0); + get => (byte)((Internal.Id7 >> 0) & 0xFF); + set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFFFFFFFF00) | ((ulong)value << 0); } public uint ColorBlendAttachmentStateCount { - get => (byte)((Internal.Id9 >> 8) & 0xFF); - set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFF00FF) | ((ulong)value << 8); + get => (byte)((Internal.Id7 >> 8) & 0xFF); + set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFFFFFF00FF) | ((ulong)value << 8); } public PrimitiveTopology Topology { - get => (PrimitiveTopology)((Internal.Id9 >> 16) & 0xF); - set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFF0FFFF) | ((ulong)value << 16); + get => (PrimitiveTopology)((Internal.Id7 >> 16) & 0xF); + set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFFFFF0FFFF) | ((ulong)value << 16); } public LogicOp LogicOp { - get => (LogicOp)((Internal.Id9 >> 20) & 0xF); - set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFF0FFFFF) | ((ulong)value << 20); + get => (LogicOp)((Internal.Id7 >> 20) & 0xF); + set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFFFF0FFFFF) | ((ulong)value << 20); } public CompareOp DepthCompareOp { - get => (CompareOp)((Internal.Id9 >> 24) & 0x7); - set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFF8FFFFFF) | ((ulong)value << 24); + get => (CompareOp)((Internal.Id7 >> 24) & 0x7); + set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFFF8FFFFFF) | ((ulong)value << 24); } public StencilOp StencilFrontFailOp { - get => (StencilOp)((Internal.Id9 >> 27) & 0x7); - set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFC7FFFFFF) | ((ulong)value << 27); + get => (StencilOp)((Internal.Id7 >> 27) & 0x7); + set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFFC7FFFFFF) | ((ulong)value << 27); } public StencilOp StencilFrontPassOp { - get => (StencilOp)((Internal.Id9 >> 30) & 0x7); - set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFE3FFFFFFF) | ((ulong)value << 30); + get => (StencilOp)((Internal.Id7 >> 30) & 0x7); + set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFE3FFFFFFF) | ((ulong)value << 30); } public StencilOp StencilFrontDepthFailOp { - get => (StencilOp)((Internal.Id9 >> 33) & 0x7); - set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFF1FFFFFFFF) | ((ulong)value << 33); + get => (StencilOp)((Internal.Id7 >> 33) & 0x7); + set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFF1FFFFFFFF) | ((ulong)value << 33); } public CompareOp StencilFrontCompareOp { - get => (CompareOp)((Internal.Id9 >> 36) & 0x7); - set => Internal.Id9 = (Internal.Id9 & 0xFFFFFF8FFFFFFFFF) | ((ulong)value << 36); + get => (CompareOp)((Internal.Id7 >> 36) & 0x7); + set => Internal.Id7 = (Internal.Id7 & 0xFFFFFF8FFFFFFFFF) | ((ulong)value << 36); } public StencilOp StencilBackFailOp { - get => (StencilOp)((Internal.Id9 >> 39) & 0x7); - set => Internal.Id9 = (Internal.Id9 & 0xFFFFFC7FFFFFFFFF) | ((ulong)value << 39); + get => (StencilOp)((Internal.Id7 >> 39) & 0x7); + set => Internal.Id7 = (Internal.Id7 & 0xFFFFFC7FFFFFFFFF) | ((ulong)value << 39); } public StencilOp StencilBackPassOp { - get => (StencilOp)((Internal.Id9 >> 42) & 0x7); - set => Internal.Id9 = (Internal.Id9 & 0xFFFFE3FFFFFFFFFF) | ((ulong)value << 42); + get => (StencilOp)((Internal.Id7 >> 42) & 0x7); + set => Internal.Id7 = (Internal.Id7 & 0xFFFFE3FFFFFFFFFF) | ((ulong)value << 42); } public StencilOp StencilBackDepthFailOp { - get => (StencilOp)((Internal.Id9 >> 45) & 0x7); - set => Internal.Id9 = (Internal.Id9 & 0xFFFF1FFFFFFFFFFF) | ((ulong)value << 45); + get => (StencilOp)((Internal.Id7 >> 45) & 0x7); + set => Internal.Id7 = (Internal.Id7 & 0xFFFF1FFFFFFFFFFF) | ((ulong)value << 45); } public CompareOp StencilBackCompareOp { - get => (CompareOp)((Internal.Id9 >> 48) & 0x7); - set => Internal.Id9 = (Internal.Id9 & 0xFFF8FFFFFFFFFFFF) | ((ulong)value << 48); + get => (CompareOp)((Internal.Id7 >> 48) & 0x7); + set => Internal.Id7 = (Internal.Id7 & 0xFFF8FFFFFFFFFFFF) | ((ulong)value << 48); } public CullModeFlags CullMode { - get => (CullModeFlags)((Internal.Id9 >> 51) & 0x3); - set => Internal.Id9 = (Internal.Id9 & 0xFFE7FFFFFFFFFFFF) | ((ulong)value << 51); + get => (CullModeFlags)((Internal.Id7 >> 51) & 0x3); + set => Internal.Id7 = (Internal.Id7 & 0xFFE7FFFFFFFFFFFF) | ((ulong)value << 51); } public bool PrimitiveRestartEnable { - get => ((Internal.Id9 >> 53) & 0x1) != 0UL; - set => Internal.Id9 = (Internal.Id9 & 0xFFDFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 53); + get => ((Internal.Id7 >> 53) & 0x1) != 0UL; + set => Internal.Id7 = (Internal.Id7 & 0xFFDFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 53); } public bool DepthClampEnable { - get => ((Internal.Id9 >> 54) & 0x1) != 0UL; - set => Internal.Id9 = (Internal.Id9 & 0xFFBFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 54); + get => ((Internal.Id7 >> 54) & 0x1) != 0UL; + set => Internal.Id7 = (Internal.Id7 & 0xFFBFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 54); } public bool RasterizerDiscardEnable { - get => ((Internal.Id9 >> 55) & 0x1) != 0UL; - set => Internal.Id9 = (Internal.Id9 & 0xFF7FFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 55); + get => ((Internal.Id7 >> 55) & 0x1) != 0UL; + set => Internal.Id7 = (Internal.Id7 & 0xFF7FFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 55); } public FrontFace FrontFace { - get => (FrontFace)((Internal.Id9 >> 56) & 0x1); - set => Internal.Id9 = (Internal.Id9 & 0xFEFFFFFFFFFFFFFF) | ((ulong)value << 56); + get => (FrontFace)((Internal.Id7 >> 56) & 0x1); + set => Internal.Id7 = (Internal.Id7 & 0xFEFFFFFFFFFFFFFF) | ((ulong)value << 56); } public bool DepthBiasEnable { - get => ((Internal.Id9 >> 57) & 0x1) != 0UL; - set => Internal.Id9 = (Internal.Id9 & 0xFDFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 57); + get => ((Internal.Id7 >> 57) & 0x1) != 0UL; + set => Internal.Id7 = (Internal.Id7 & 0xFDFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 57); } public bool DepthTestEnable { - get => ((Internal.Id9 >> 58) & 0x1) != 0UL; - set => Internal.Id9 = (Internal.Id9 & 0xFBFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 58); + get => ((Internal.Id7 >> 58) & 0x1) != 0UL; + set => Internal.Id7 = (Internal.Id7 & 0xFBFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 58); } public bool DepthWriteEnable { - get => ((Internal.Id9 >> 59) & 0x1) != 0UL; - set => Internal.Id9 = (Internal.Id9 & 0xF7FFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 59); + get => ((Internal.Id7 >> 59) & 0x1) != 0UL; + set => Internal.Id7 = (Internal.Id7 & 0xF7FFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 59); } public bool DepthBoundsTestEnable { - get => ((Internal.Id9 >> 60) & 0x1) != 0UL; - set => Internal.Id9 = (Internal.Id9 & 0xEFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 60); + get => ((Internal.Id7 >> 60) & 0x1) != 0UL; + set => Internal.Id7 = (Internal.Id7 & 0xEFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 60); } public bool StencilTestEnable { - get => ((Internal.Id9 >> 61) & 0x1) != 0UL; - set => Internal.Id9 = (Internal.Id9 & 0xDFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 61); + get => ((Internal.Id7 >> 61) & 0x1) != 0UL; + set => Internal.Id7 = (Internal.Id7 & 0xDFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 61); } public bool LogicOpEnable { - get => ((Internal.Id9 >> 62) & 0x1) != 0UL; - set => Internal.Id9 = (Internal.Id9 & 0xBFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 62); + get => ((Internal.Id7 >> 62) & 0x1) != 0UL; + set => Internal.Id7 = (Internal.Id7 & 0xBFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 62); } public bool HasDepthStencil { - get => ((Internal.Id9 >> 63) & 0x1) != 0UL; - set => Internal.Id9 = (Internal.Id9 & 0x7FFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 63); + get => ((Internal.Id7 >> 63) & 0x1) != 0UL; + set => Internal.Id7 = (Internal.Id7 & 0x7FFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 63); } public uint PatchControlPoints { - get => (uint)((Internal.Id10 >> 0) & 0xFFFFFFFF); - set => Internal.Id10 = (Internal.Id10 & 0xFFFFFFFF00000000) | ((ulong)value << 0); + get => (uint)((Internal.Id8 >> 0) & 0xFFFFFFFF); + set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFF00000000) | ((ulong)value << 0); } public uint SamplesCount { - get => (uint)((Internal.Id10 >> 32) & 0xFFFFFFFF); - set => Internal.Id10 = (Internal.Id10 & 0xFFFFFFFF) | ((ulong)value << 32); + get => (uint)((Internal.Id8 >> 32) & 0xFFFFFFFF); + set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFF) | ((ulong)value << 32); } public bool AlphaToCoverageEnable { - get => ((Internal.Id11 >> 0) & 0x1) != 0UL; - set => Internal.Id11 = (Internal.Id11 & 0xFFFFFFFFFFFFFFFE) | ((value ? 1UL : 0UL) << 0); + get => ((Internal.Id9 >> 0) & 0x1) != 0UL; + set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFFE) | ((value ? 1UL : 0UL) << 0); } public bool AlphaToOneEnable { - get => ((Internal.Id11 >> 1) & 0x1) != 0UL; - set => Internal.Id11 = (Internal.Id11 & 0xFFFFFFFFFFFFFFFD) | ((value ? 1UL : 0UL) << 1); + get => ((Internal.Id9 >> 1) & 0x1) != 0UL; + set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFFD) | ((value ? 1UL : 0UL) << 1); } public NativeArray Stages; @@ -356,7 +332,7 @@ namespace Ryujinx.Graphics.Vulkan Pipeline pipelineHandle = default; bool hasSpec = program.SpecDescriptions != null; - + var desc = hasSpec ? program.SpecDescriptions[0] : SpecDescription.Empty; if (hasSpec && SpecializationData.Length < (int)desc.Info.DataSize) @@ -510,11 +486,6 @@ namespace Ryujinx.Graphics.Vulkan PAttachments = pColorBlendAttachmentState }; - colorBlendState.BlendConstants[0] = BlendConstantR; - colorBlendState.BlendConstants[1] = BlendConstantG; - colorBlendState.BlendConstants[2] = BlendConstantB; - colorBlendState.BlendConstants[3] = BlendConstantA; - bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState; int dynamicStatesCount = supportsExtDynamicState ? 9 : 8; diff --git a/Ryujinx.Graphics.Vulkan/PipelineUid.cs b/Ryujinx.Graphics.Vulkan/PipelineUid.cs index 8ea52e20da..78d6e9f71c 100644 --- a/Ryujinx.Graphics.Vulkan/PipelineUid.cs +++ b/Ryujinx.Graphics.Vulkan/PipelineUid.cs @@ -21,15 +21,13 @@ namespace Ryujinx.Graphics.Vulkan public ulong Id8; public ulong Id9; - public ulong Id10; - public ulong Id11; - private uint VertexAttributeDescriptionsCount => (byte)((Id8 >> 38) & 0xFF); - private uint VertexBindingDescriptionsCount => (byte)((Id8 >> 46) & 0xFF); - private uint ViewportsCount => (byte)((Id8 >> 54) & 0xFF); - private uint ScissorsCount => (byte)((Id9 >> 0) & 0xFF); - private uint ColorBlendAttachmentStateCount => (byte)((Id9 >> 8) & 0xFF); - private bool HasDepthStencil => ((Id9 >> 63) & 0x1) != 0UL; + private uint VertexAttributeDescriptionsCount => (byte)((Id6 >> 38) & 0xFF); + private uint VertexBindingDescriptionsCount => (byte)((Id6 >> 46) & 0xFF); + private uint ViewportsCount => (byte)((Id6 >> 54) & 0xFF); + private uint ScissorsCount => (byte)((Id7 >> 0) & 0xFF); + private uint ColorBlendAttachmentStateCount => (byte)((Id7 >> 8) & 0xFF); + private bool HasDepthStencil => ((Id7 >> 63) & 0x1) != 0UL; public Array32 VertexAttributeDescriptions; public Array33 VertexBindingDescriptions; @@ -47,7 +45,7 @@ namespace Ryujinx.Graphics.Vulkan { if (!Unsafe.As>(ref Id0).Equals(Unsafe.As>(ref other.Id0)) || !Unsafe.As>(ref Id4).Equals(Unsafe.As>(ref other.Id4)) || - !Unsafe.As>(ref Id8).Equals(Unsafe.As>(ref other.Id8))) + !Unsafe.As>(ref Id8).Equals(Unsafe.As>(ref other.Id8))) { return false; } @@ -91,9 +89,7 @@ namespace Ryujinx.Graphics.Vulkan Id6 * 23 ^ Id7 * 23 ^ Id8 * 23 ^ - Id9 * 23 ^ - Id10 * 23 ^ - Id11 * 23; + Id9 * 23; for (int i = 0; i < (int)VertexAttributeDescriptionsCount; i++) {