mirror of
				https://github.com/ryujinx-mirror/ryujinx.git
				synced 2025-11-04 08:59:04 -06:00 
			
		
		
		
	Workaround AMD bug on logic op with float framebuffer (#6852)
* Workaround AMD bug on logic op with float framebuffer * Format whitespace * Update comment
This commit is contained in:
		@@ -711,5 +711,36 @@ namespace Ryujinx.Graphics.GAL
 | 
			
		||||
        {
 | 
			
		||||
            return format.IsUint() || format.IsSint();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Checks if the texture format is a float or sRGB color format.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <remarks>
 | 
			
		||||
        /// Does not include normalized, compressed or depth formats.
 | 
			
		||||
        /// Float and sRGB formats do not participate in logical operations.
 | 
			
		||||
        /// </remarks>
 | 
			
		||||
        /// <param name="format">Texture format</param>
 | 
			
		||||
        /// <returns>True if the format is a float or sRGB color format, false otherwise</returns>
 | 
			
		||||
        public static bool IsFloatOrSrgb(this Format format)
 | 
			
		||||
        {
 | 
			
		||||
            switch (format)
 | 
			
		||||
            {
 | 
			
		||||
                case Format.R8G8B8A8Srgb:
 | 
			
		||||
                case Format.B8G8R8A8Srgb:
 | 
			
		||||
                case Format.R16Float:
 | 
			
		||||
                case Format.R16G16Float:
 | 
			
		||||
                case Format.R16G16B16Float:
 | 
			
		||||
                case Format.R16G16B16A16Float:
 | 
			
		||||
                case Format.R32Float:
 | 
			
		||||
                case Format.R32G32Float:
 | 
			
		||||
                case Format.R32G32B32Float:
 | 
			
		||||
                case Format.R32G32B32A32Float:
 | 
			
		||||
                case Format.R11G11B10Float:
 | 
			
		||||
                case Format.R9G9B9E5Float:
 | 
			
		||||
                    return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,7 @@ namespace Ryujinx.Graphics.Vulkan
 | 
			
		||||
        public VkFormat[] AttachmentFormats { get; }
 | 
			
		||||
        public int[] AttachmentIndices { get; }
 | 
			
		||||
        public uint AttachmentIntegerFormatMask { get; }
 | 
			
		||||
        public bool LogicOpsAllowed { get; }
 | 
			
		||||
 | 
			
		||||
        public int AttachmentsCount { get; }
 | 
			
		||||
        public int MaxColorAttachmentIndex => AttachmentIndices.Length > 0 ? AttachmentIndices[^1] : -1;
 | 
			
		||||
@@ -32,7 +33,9 @@ namespace Ryujinx.Graphics.Vulkan
 | 
			
		||||
 | 
			
		||||
        public FramebufferParams(Device device, TextureView view, uint width, uint height)
 | 
			
		||||
        {
 | 
			
		||||
            bool isDepthStencil = view.Info.Format.IsDepthOrStencil();
 | 
			
		||||
            var format = view.Info.Format;
 | 
			
		||||
 | 
			
		||||
            bool isDepthStencil = format.IsDepthOrStencil();
 | 
			
		||||
 | 
			
		||||
            _device = device;
 | 
			
		||||
            _attachments = new[] { view.GetImageViewForAttachment() };
 | 
			
		||||
@@ -56,6 +59,8 @@ namespace Ryujinx.Graphics.Vulkan
 | 
			
		||||
            AttachmentSamples = new[] { (uint)view.Info.Samples };
 | 
			
		||||
            AttachmentFormats = new[] { view.VkFormat };
 | 
			
		||||
            AttachmentIndices = isDepthStencil ? Array.Empty<int>() : new[] { 0 };
 | 
			
		||||
            AttachmentIntegerFormatMask = format.IsInteger() ? 1u : 0u;
 | 
			
		||||
            LogicOpsAllowed = !format.IsFloatOrSrgb();
 | 
			
		||||
 | 
			
		||||
            AttachmentsCount = 1;
 | 
			
		||||
 | 
			
		||||
@@ -85,6 +90,7 @@ namespace Ryujinx.Graphics.Vulkan
 | 
			
		||||
            int index = 0;
 | 
			
		||||
            int bindIndex = 0;
 | 
			
		||||
            uint attachmentIntegerFormatMask = 0;
 | 
			
		||||
            bool allFormatsFloatOrSrgb = colorsCount != 0;
 | 
			
		||||
 | 
			
		||||
            foreach (ITexture color in colors)
 | 
			
		||||
            {
 | 
			
		||||
@@ -101,11 +107,15 @@ namespace Ryujinx.Graphics.Vulkan
 | 
			
		||||
                    AttachmentFormats[index] = texture.VkFormat;
 | 
			
		||||
                    AttachmentIndices[index] = bindIndex;
 | 
			
		||||
 | 
			
		||||
                    if (texture.Info.Format.IsInteger())
 | 
			
		||||
                    var format = texture.Info.Format;
 | 
			
		||||
 | 
			
		||||
                    if (format.IsInteger())
 | 
			
		||||
                    {
 | 
			
		||||
                        attachmentIntegerFormatMask |= 1u << bindIndex;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    allFormatsFloatOrSrgb &= format.IsFloatOrSrgb();
 | 
			
		||||
 | 
			
		||||
                    width = Math.Min(width, (uint)texture.Width);
 | 
			
		||||
                    height = Math.Min(height, (uint)texture.Height);
 | 
			
		||||
                    layers = Math.Min(layers, (uint)texture.Layers);
 | 
			
		||||
@@ -120,6 +130,7 @@ namespace Ryujinx.Graphics.Vulkan
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            AttachmentIntegerFormatMask = attachmentIntegerFormatMask;
 | 
			
		||||
            LogicOpsAllowed = !allFormatsFloatOrSrgb;
 | 
			
		||||
 | 
			
		||||
            if (depthStencil is TextureView dsTexture && dsTexture.Valid)
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -1498,6 +1498,7 @@ namespace Ryujinx.Graphics.Vulkan
 | 
			
		||||
            var dstAttachmentFormats = _newState.Internal.AttachmentFormats.AsSpan();
 | 
			
		||||
            FramebufferParams.AttachmentFormats.CopyTo(dstAttachmentFormats);
 | 
			
		||||
            _newState.Internal.AttachmentIntegerFormatMask = FramebufferParams.AttachmentIntegerFormatMask;
 | 
			
		||||
            _newState.Internal.LogicOpsAllowed = FramebufferParams.LogicOpsAllowed;
 | 
			
		||||
 | 
			
		||||
            for (int i = FramebufferParams.AttachmentFormats.Length; i < dstAttachmentFormats.Length; i++)
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -302,6 +302,7 @@ namespace Ryujinx.Graphics.Vulkan
 | 
			
		||||
            int attachmentCount = 0;
 | 
			
		||||
            int maxColorAttachmentIndex = -1;
 | 
			
		||||
            uint attachmentIntegerFormatMask = 0;
 | 
			
		||||
            bool allFormatsFloatOrSrgb = true;
 | 
			
		||||
 | 
			
		||||
            for (int i = 0; i < Constants.MaxRenderTargets; i++)
 | 
			
		||||
            {
 | 
			
		||||
@@ -314,6 +315,8 @@ namespace Ryujinx.Graphics.Vulkan
 | 
			
		||||
                    {
 | 
			
		||||
                        attachmentIntegerFormatMask |= 1u << i;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    allFormatsFloatOrSrgb &= state.AttachmentFormats[i].IsFloatOrSrgb();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -325,6 +328,7 @@ namespace Ryujinx.Graphics.Vulkan
 | 
			
		||||
            pipeline.ColorBlendAttachmentStateCount = (uint)(maxColorAttachmentIndex + 1);
 | 
			
		||||
            pipeline.VertexAttributeDescriptionsCount = (uint)Math.Min(Constants.MaxVertexAttributes, state.VertexAttribCount);
 | 
			
		||||
            pipeline.Internal.AttachmentIntegerFormatMask = attachmentIntegerFormatMask;
 | 
			
		||||
            pipeline.Internal.LogicOpsAllowed = attachmentCount == 0 || !allFormatsFloatOrSrgb;
 | 
			
		||||
 | 
			
		||||
            return pipeline;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -560,10 +560,14 @@ namespace Ryujinx.Graphics.Vulkan
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // AMD has a bug where it enables logical operations even for float formats,
 | 
			
		||||
                // so we need to force disable them here.
 | 
			
		||||
                bool logicOpEnable = LogicOpEnable && (gd.Vendor != Vendor.Amd || Internal.LogicOpsAllowed);
 | 
			
		||||
 | 
			
		||||
                var colorBlendState = new PipelineColorBlendStateCreateInfo
 | 
			
		||||
                {
 | 
			
		||||
                    SType = StructureType.PipelineColorBlendStateCreateInfo,
 | 
			
		||||
                    LogicOpEnable = LogicOpEnable,
 | 
			
		||||
                    LogicOpEnable = logicOpEnable,
 | 
			
		||||
                    LogicOp = LogicOp,
 | 
			
		||||
                    AttachmentCount = ColorBlendAttachmentStateCount,
 | 
			
		||||
                    PAttachments = pColorBlendAttachmentState,
 | 
			
		||||
 
 | 
			
		||||
@@ -34,6 +34,7 @@ namespace Ryujinx.Graphics.Vulkan
 | 
			
		||||
        public Array8<PipelineColorBlendAttachmentState> ColorBlendAttachmentState;
 | 
			
		||||
        public Array9<Format> AttachmentFormats;
 | 
			
		||||
        public uint AttachmentIntegerFormatMask;
 | 
			
		||||
        public bool LogicOpsAllowed;
 | 
			
		||||
 | 
			
		||||
        public readonly override bool Equals(object obj)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user