Skip to content

Commit

Permalink
Make sure blend is disabled if render target has integer format (#5122)
Browse files Browse the repository at this point in the history
* Make sure blend is disabled if render target has integer format

* Change approach to avoid permanently mutating state
  • Loading branch information
gdkchan committed May 28, 2023
1 parent 96d1f0d commit 832a5e8
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 0 deletions.
9 changes: 9 additions & 0 deletions src/Ryujinx.Graphics.Vulkan/FramebufferParams.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class FramebufferParams
public uint[] AttachmentSamples { get; }
public VkFormat[] AttachmentFormats { get; }
public int[] AttachmentIndices { get; }
public uint AttachmentIntegerFormatMask { get; }

public int AttachmentsCount { get; }
public int MaxColorAttachmentIndex => AttachmentIndices.Length > 0 ? AttachmentIndices[AttachmentIndices.Length - 1] : -1;
Expand Down Expand Up @@ -74,6 +75,7 @@ public FramebufferParams(Device device, ITexture[] colors, ITexture depthStencil

int index = 0;
int bindIndex = 0;
uint attachmentIntegerFormatMask = 0;

foreach (ITexture color in colors)
{
Expand All @@ -89,6 +91,11 @@ public FramebufferParams(Device device, ITexture[] colors, ITexture depthStencil
AttachmentFormats[index] = texture.VkFormat;
AttachmentIndices[index] = bindIndex;

if (texture.Info.Format.IsInteger())
{
attachmentIntegerFormatMask |= 1u << bindIndex;
}

width = Math.Min(width, (uint)texture.Width);
height = Math.Min(height, (uint)texture.Height);
layers = Math.Min(layers, (uint)texture.Layers);
Expand All @@ -102,6 +109,8 @@ public FramebufferParams(Device device, ITexture[] colors, ITexture depthStencil
bindIndex++;
}

AttachmentIntegerFormatMask = attachmentIntegerFormatMask;

if (depthStencil is TextureView dsTexture && dsTexture.Valid)
{
_attachments[count - 1] = dsTexture.GetImageViewForAttachment();
Expand Down
1 change: 1 addition & 0 deletions src/Ryujinx.Graphics.Vulkan/PipelineBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1487,6 +1487,7 @@ protected void UpdatePipelineAttachmentFormats()
{
var dstAttachmentFormats = _newState.Internal.AttachmentFormats.AsSpan();
FramebufferParams.AttachmentFormats.CopyTo(dstAttachmentFormats);
_newState.Internal.AttachmentIntegerFormatMask = FramebufferParams.AttachmentIntegerFormatMask;

for (int i = FramebufferParams.AttachmentFormats.Length; i < dstAttachmentFormats.Length; i++)
{
Expand Down
7 changes: 7 additions & 0 deletions src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -294,13 +294,19 @@ public static PipelineState ToVulkanPipelineState(this ProgramPipelineState stat

int attachmentCount = 0;
int maxColorAttachmentIndex = -1;
uint attachmentIntegerFormatMask = 0;

for (int i = 0; i < Constants.MaxRenderTargets; i++)
{
if (state.AttachmentEnable[i])
{
pipeline.Internal.AttachmentFormats[attachmentCount++] = gd.FormatCapabilities.ConvertToVkFormat(state.AttachmentFormats[i]);
maxColorAttachmentIndex = i;

if (state.AttachmentFormats[i].IsInteger())
{
attachmentIntegerFormatMask |= 1u << i;
}
}
}

Expand All @@ -311,6 +317,7 @@ public static PipelineState ToVulkanPipelineState(this ProgramPipelineState stat

pipeline.ColorBlendAttachmentStateCount = (uint)(maxColorAttachmentIndex + 1);
pipeline.VertexAttributeDescriptionsCount = (uint)Math.Min(Constants.MaxVertexAttributes, state.VertexAttribCount);
pipeline.Internal.AttachmentIntegerFormatMask = attachmentIntegerFormatMask;

return pipeline;
}
Expand Down
31 changes: 31 additions & 0 deletions src/Ryujinx.Graphics.Vulkan/PipelineState.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Ryujinx.Common.Memory;
using Silk.NET.Vulkan;
using System;
using System.Numerics;

namespace Ryujinx.Graphics.Vulkan
{
Expand Down Expand Up @@ -542,6 +543,27 @@ public void Initialize()
MaxDepthBounds = MaxDepthBounds
};

uint blendEnables = 0;

if (gd.IsMoltenVk && Internal.AttachmentIntegerFormatMask != 0)
{
// Blend can't be enabled for integer formats, so let's make sure it is disabled.
uint attachmentIntegerFormatMask = Internal.AttachmentIntegerFormatMask;

while (attachmentIntegerFormatMask != 0)
{
int i = BitOperations.TrailingZeroCount(attachmentIntegerFormatMask);

if (Internal.ColorBlendAttachmentState[i].BlendEnable)
{
blendEnables |= 1u << i;
}

Internal.ColorBlendAttachmentState[i].BlendEnable = false;
attachmentIntegerFormatMask &= ~(1u << i);
}
}

var colorBlendState = new PipelineColorBlendStateCreateInfo()
{
SType = StructureType.PipelineColorBlendStateCreateInfo,
Expand Down Expand Up @@ -619,6 +641,15 @@ public void Initialize()
};

gd.Api.CreateGraphicsPipelines(device, cache, 1, &pipelineCreateInfo, null, &pipelineHandle).ThrowOnError();

// Restore previous blend enable values if we changed it.
while (blendEnables != 0)
{
int i = BitOperations.TrailingZeroCount(blendEnables);

Internal.ColorBlendAttachmentState[i].BlendEnable = true;
blendEnables &= ~(1u << i);
}
}

pipeline = new Auto<DisposablePipeline>(new DisposablePipeline(gd.Api, device, pipelineHandle));
Expand Down
1 change: 1 addition & 0 deletions src/Ryujinx.Graphics.Vulkan/PipelineUid.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ struct PipelineUid : IRefEquatable<PipelineUid>
public Array16<Rect2D> Scissors;
public Array8<PipelineColorBlendAttachmentState> ColorBlendAttachmentState;
public Array9<Format> AttachmentFormats;
public uint AttachmentIntegerFormatMask;

public override bool Equals(object obj)
{
Expand Down

0 comments on commit 832a5e8

Please sign in to comment.