Compare commits

...

4 Commits

Author SHA1 Message Date
Mary
b5032b3c91 vulkan: Fix access level of extensions fields and make them readonly (#4608) 2023-03-27 08:40:27 +02:00
Mary
f0a3dff136 vulkan: Remove CreateCommandBufferPool from VulkanInitialization (#4606)
It was only called in one place, that can be simplified.
2023-03-27 02:16:31 +00:00
Mary
f659dcb9d8 vulkan: fix broken "VK_EXT_subgroup_size_control" support check (#4607)
Not sure since when it was broken...
2023-03-26 19:01:30 +02:00
riperiperi
a34fb0e939 Vulkan: Insert barriers before clears (#4596)
* Vulkan: Insert barriers before clears

Newer NVIDIA GPUs seem to be able to start clearing render targets before the last rasterization task is completed, which can cause it to clear a texture while it is being sampled.

This change adds a barrier from read to write when doing a clear, assuming it has been sampled in the past. It could be possible for this to be needed for sample into draw by some GPU, but it's not right now afaik.

This should fix visual artifacts on newer NVIDIA GPUs and driver combos. Contrary to popular belief, Tetris® Effect: Connected is not affected. Testing welcome, hopefully should fix most cases of this and not cost too much performance.

* Visual Studio Moment

* Address feedback

* Address Feedback 2
2023-03-26 12:51:02 +02:00
7 changed files with 66 additions and 37 deletions

View File

@@ -236,7 +236,7 @@ namespace Ryujinx.Graphics.Vulkan
}
else if (texture is TextureView view)
{
view.Storage.InsertBarrier(cbs, AccessFlags.ShaderReadBit, stage.ConvertToPipelineStageFlags());
view.Storage.InsertWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, stage.ConvertToPipelineStageFlags());
_textureRefs[binding] = view.GetImageView();
_samplerRefs[binding] = ((SamplerHolder)sampler)?.GetSampler();

View File

@@ -322,7 +322,7 @@ namespace Ryujinx.Graphics.Vulkan
GAL.Format.S8Uint => ImageAspectFlags.StencilBit,
GAL.Format.D24UnormS8Uint or
GAL.Format.D32FloatS8Uint or
GAL.Format.S8UintD24Unorm => ImageAspectFlags.DepthBit | ImageAspectFlags.StencilBit,
GAL.Format.S8UintD24Unorm => ImageAspectFlags.DepthBit | ImageAspectFlags.StencilBit,
_ => ImageAspectFlags.ColorBit
};
}

View File

@@ -218,5 +218,23 @@ namespace Ryujinx.Graphics.Vulkan
AccessFlags.DepthStencilAttachmentWriteBit,
PipelineStageFlags.ColorAttachmentOutputBit);
}
public void InsertClearBarrier(CommandBufferScoped cbs, int index)
{
if (_colors != null)
{
int realIndex = Array.IndexOf(AttachmentIndices, index);
if (realIndex != -1)
{
_colors[realIndex].Storage?.InsertReadToWriteBarrier(cbs, AccessFlags.ColorAttachmentWriteBit, PipelineStageFlags.ColorAttachmentOutputBit);
}
}
}
public void InsertClearBarrierDS(CommandBufferScoped cbs)
{
_depthStencil?.Storage?.InsertReadToWriteBarrier(cbs, AccessFlags.DepthStencilAttachmentWriteBit, PipelineStageFlags.EarlyFragmentTestsBit);
}
}
}

View File

@@ -226,6 +226,8 @@ namespace Ryujinx.Graphics.Vulkan
var attachment = new ClearAttachment(ImageAspectFlags.ColorBit, (uint)index, clearValue);
var clearRect = FramebufferParams.GetClearRect(ClearScissor, layer, layerCount);
FramebufferParams.InsertClearBarrier(Cbs, index);
Gd.Api.CmdClearAttachments(CommandBuffer, 1, &attachment, 1, &clearRect);
}
@@ -256,6 +258,8 @@ namespace Ryujinx.Graphics.Vulkan
var attachment = new ClearAttachment(flags, 0, clearValue);
var clearRect = FramebufferParams.GetClearRect(ClearScissor, layer, layerCount);
FramebufferParams.InsertClearBarrierDS(Cbs);
Gd.Api.CmdClearAttachments(CommandBuffer, 1, &attachment, 1, &clearRect);
}

View File

@@ -46,6 +46,8 @@ namespace Ryujinx.Graphics.Vulkan
private AccessFlags _lastModificationAccess;
private PipelineStageFlags _lastModificationStage;
private AccessFlags _lastReadAccess;
private PipelineStageFlags _lastReadStage;
private int _viewsCount;
private ulong _size;
@@ -440,31 +442,39 @@ namespace Ryujinx.Graphics.Vulkan
_lastModificationStage = stage;
}
public void InsertBarrier(CommandBufferScoped cbs, AccessFlags dstAccessFlags, PipelineStageFlags dstStageFlags)
public void InsertReadToWriteBarrier(CommandBufferScoped cbs, AccessFlags dstAccessFlags, PipelineStageFlags dstStageFlags)
{
if (_lastReadAccess != AccessFlags.NoneKhr)
{
ImageAspectFlags aspectFlags = Info.Format.ConvertAspectFlags();
TextureView.InsertImageBarrier(
_gd.Api,
cbs.CommandBuffer,
_imageAuto.Get(cbs).Value,
_lastReadAccess,
dstAccessFlags,
_lastReadStage,
dstStageFlags,
aspectFlags,
0,
0,
_info.GetLayers(),
_info.Levels);
_lastReadAccess = AccessFlags.NoneKhr;
_lastReadStage = PipelineStageFlags.None;
}
}
public void InsertWriteToReadBarrier(CommandBufferScoped cbs, AccessFlags dstAccessFlags, PipelineStageFlags dstStageFlags)
{
_lastReadAccess |= dstAccessFlags;
_lastReadStage |= dstStageFlags;
if (_lastModificationAccess != AccessFlags.NoneKhr)
{
ImageAspectFlags aspectFlags;
if (_info.Format.IsDepthOrStencil())
{
if (_info.Format == GAL.Format.S8Uint)
{
aspectFlags = ImageAspectFlags.StencilBit;
}
else if (_info.Format == GAL.Format.D16Unorm || _info.Format == GAL.Format.D32Float)
{
aspectFlags = ImageAspectFlags.DepthBit;
}
else
{
aspectFlags = ImageAspectFlags.DepthBit | ImageAspectFlags.StencilBit;
}
}
else
{
aspectFlags = ImageAspectFlags.ColorBit;
}
ImageAspectFlags aspectFlags = Info.Format.ConvertAspectFlags();
TextureView.InsertImageBarrier(
_gd.Api,

View File

@@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.Vulkan
private const string AppName = "Ryujinx.Graphics.Vulkan";
private const int QueuesCount = 2;
public static string[] DesirableExtensions { get; } = new string[]
private static readonly string[] _desirableExtensions = new string[]
{
ExtConditionalRendering.ExtensionName,
ExtExtendedDynamicState.ExtensionName,
@@ -42,7 +42,7 @@ namespace Ryujinx.Graphics.Vulkan
"VK_KHR_portability_subset", // By spec, we should enable this if present.
};
public static string[] RequiredExtensions { get; } = new string[]
private static readonly string[] _requiredExtensions = new string[]
{
KhrSwapchain.ExtensionName
};
@@ -337,14 +337,14 @@ namespace Ryujinx.Graphics.Vulkan
{
string extensionName = Marshal.PtrToStringAnsi((IntPtr)pExtensionProperties[i].ExtensionName);
if (RequiredExtensions.Contains(extensionName))
if (_requiredExtensions.Contains(extensionName))
{
extensionMatches++;
}
}
}
return extensionMatches == RequiredExtensions.Length && FindSuitableQueueFamily(api, physicalDevice, surface, out _) != InvalidIndex;
return extensionMatches == _requiredExtensions.Length && FindSuitableQueueFamily(api, physicalDevice, surface, out _) != InvalidIndex;
}
internal static uint FindSuitableQueueFamily(Vk api, PhysicalDevice physicalDevice, SurfaceKHR surface, out uint queueCount)
@@ -626,7 +626,7 @@ namespace Ryujinx.Graphics.Vulkan
pExtendedFeatures = &featuresCustomBorderColor;
}
var enabledExtensions = RequiredExtensions.Union(DesirableExtensions.Intersect(supportedExtensions)).ToArray();
var enabledExtensions = _requiredExtensions.Union(_desirableExtensions.Intersect(supportedExtensions)).ToArray();
IntPtr* ppEnabledExtensions = stackalloc IntPtr[enabledExtensions.Length];
@@ -672,11 +672,6 @@ namespace Ryujinx.Graphics.Vulkan
return extensionProperties.Select(x => Marshal.PtrToStringAnsi((IntPtr)x.ExtensionName)).ToArray();
}
internal static CommandBufferPool CreateCommandBufferPool(Vk api, Device device, Queue queue, object queueLock, uint queueFamilyIndex)
{
return new CommandBufferPool(api, device, queue, queueLock, queueFamilyIndex);
}
internal unsafe static void CreateDebugMessenger(
Vk api,
GraphicsDebugLevel logLevel,

View File

@@ -168,7 +168,9 @@ namespace Ryujinx.Graphics.Vulkan
SType = StructureType.PhysicalDeviceSubgroupSizeControlPropertiesExt
};
if (Capabilities.SupportsSubgroupSizeControl)
bool supportsSubgroupSizeControl = supportedExtensions.Contains("VK_EXT_subgroup_size_control");
if (supportsSubgroupSizeControl)
{
properties2.PNext = &propertiesSubgroupSizeControl;
}
@@ -292,7 +294,7 @@ namespace Ryujinx.Graphics.Vulkan
supportedExtensions.Contains(KhrDrawIndirectCount.ExtensionName),
supportedExtensions.Contains("VK_EXT_fragment_shader_interlock"),
supportedExtensions.Contains("VK_NV_geometry_shader_passthrough"),
supportedExtensions.Contains("VK_EXT_subgroup_size_control"),
supportsSubgroupSizeControl,
featuresShaderInt8.ShaderInt8,
supportedExtensions.Contains("VK_EXT_shader_stencil_export"),
supportedExtensions.Contains(ExtConditionalRendering.ExtensionName),
@@ -318,7 +320,7 @@ namespace Ryujinx.Graphics.Vulkan
MemoryAllocator = new MemoryAllocator(Api, _physicalDevice, _device, properties.Limits.MaxMemoryAllocationCount);
CommandBufferPool = VulkanInitialization.CreateCommandBufferPool(Api, _device, Queue, QueueLock, queueFamilyIndex);
CommandBufferPool = new CommandBufferPool(Api, _device, Queue, QueueLock, queueFamilyIndex);
DescriptorSetManager = new DescriptorSetManager(_device);