Compare commits

..

3 Commits

Author SHA1 Message Date
Emmanuel Hansen
9f26fd3600 remove some usages of reflection binding (#5686) 2023-09-18 22:09:22 +02:00
gdkchan
88df636c87 Replace ShaderOutputLayer with equivalent ShaderViewportIndexLayerEXT capability (#5683) 2023-09-16 18:49:13 +02:00
gdkchan
7ccff037e8 Fix some Vulkan validation errors (mostly related to barriers) (#5603)
* Replace image barriers inside render pass with more generic memory barrier

* Remove forceStorage since it was creating images with storage bit for formats that are not StorageImage compatible

* Add missing flags on subpass dependency

* Don't call vkCmdSetScissor with a scissor count of 0

* One semaphore per swapchain image

* Remove compute stage from read to write barriers

* Try to improve Pipeline.Barrier nonsense

* Set PipelineStateFlags based on supported stages
2023-09-14 19:58:11 +02:00
16 changed files with 190 additions and 92 deletions

View File

@@ -6,9 +6,11 @@
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale" xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="{locale:Locale ErrorWindowTitle}" Title="{locale:Locale ErrorWindowTitle}"
xmlns:views="using:Ryujinx.Ava.UI.Applet"
Width="450" Width="450"
Height="340" Height="340"
CanResize="False" CanResize="False"
x:DataType="views:ErrorAppletWindow"
SizeToContent="Height" SizeToContent="Height"
mc:Ignorable="d" mc:Ignorable="d"
Focusable="True"> Focusable="True">
@@ -38,7 +40,7 @@
Grid.Column="1" Grid.Column="1"
Margin="10" Margin="10"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
Text="{ReflectionBinding Message}" Text="{Binding Message}"
TextWrapping="Wrap" /> TextWrapping="Wrap" />
<StackPanel <StackPanel
Name="ButtonStack" Name="ButtonStack"

View File

@@ -4,7 +4,9 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:views="using:Ryujinx.Ava.UI.Controls"
Width="400" Width="400"
x:DataType="views:SwkbdAppletDialog"
mc:Ignorable="d" mc:Ignorable="d"
Focusable="True"> Focusable="True">
<Grid <Grid
@@ -34,13 +36,13 @@
Grid.Row="1" Grid.Row="1"
Grid.Column="1" Grid.Column="1"
Margin="5" Margin="5"
Text="{ReflectionBinding MainText}" Text="{Binding MainText}"
TextWrapping="Wrap" /> TextWrapping="Wrap" />
<TextBlock <TextBlock
Grid.Row="2" Grid.Row="2"
Grid.Column="1" Grid.Column="1"
Margin="5" Margin="5"
Text="{ReflectionBinding SecondaryText}" Text="{Binding SecondaryText}"
TextWrapping="Wrap" /> TextWrapping="Wrap" />
<TextBox <TextBox
Name="Input" Name="Input"
@@ -50,7 +52,7 @@
VerticalAlignment="Center" VerticalAlignment="Center"
Focusable="True" Focusable="True"
KeyUp="Message_KeyUp" KeyUp="Message_KeyUp"
Text="{ReflectionBinding Message}" Text="{Binding Message}"
TextInput="Message_TextInput" TextInput="Message_TextInput"
TextWrapping="Wrap" TextWrapping="Wrap"
UseFloatingWatermark="True" /> UseFloatingWatermark="True" />

View File

@@ -46,7 +46,7 @@
<Setter Property="CornerRadius" Value="4" /> <Setter Property="CornerRadius" Value="4" />
</Style> </Style>
<Style Selector="ListBoxItem:selected /template/ Rectangle#SelectionIndicator"> <Style Selector="ListBoxItem:selected /template/ Rectangle#SelectionIndicator">
<Setter Property="MinHeight" Value="{ReflectionBinding $parent[UserControl].DataContext.GridItemSelectorSize}" /> <Setter Property="MinHeight" Value="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).GridItemSelectorSize}" />
</Style> </Style>
</ListBox.Styles> </ListBox.Styles>
<ListBox.ItemTemplate> <ListBox.ItemTemplate>
@@ -56,10 +56,10 @@
Margin="10" Margin="10"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
Classes.huge="{ReflectionBinding $parent[UserControl].DataContext.IsGridHuge}" Classes.huge="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridHuge}"
Classes.large="{ReflectionBinding $parent[UserControl].DataContext.IsGridLarge}" Classes.large="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridLarge}"
Classes.normal="{ReflectionBinding $parent[UserControl].DataContext.IsGridMedium}" Classes.normal="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridMedium}"
Classes.small="{ReflectionBinding $parent[UserControl].DataContext.IsGridSmall}" Classes.small="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridSmall}"
ClipToBounds="True" ClipToBounds="True"
CornerRadius="4"> CornerRadius="4">
<Grid> <Grid>
@@ -78,7 +78,7 @@
Margin="0,10,0,0" Margin="0,10,0,0"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
IsVisible="{ReflectionBinding $parent[UserControl].DataContext.ShowNames}"> IsVisible="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).ShowNames}">
<TextBlock <TextBlock
HorizontalAlignment="Center" HorizontalAlignment="Center"
VerticalAlignment="Center" VerticalAlignment="Center"

View File

@@ -42,7 +42,7 @@
</ListBox.ItemsPanel> </ListBox.ItemsPanel>
<ListBox.Styles> <ListBox.Styles>
<Style Selector="ListBoxItem:selected /template/ Rectangle#SelectionIndicator"> <Style Selector="ListBoxItem:selected /template/ Rectangle#SelectionIndicator">
<Setter Property="MinHeight" Value="{ReflectionBinding $parent[UserControl].DataContext.ListItemSelectorSize}" /> <Setter Property="MinHeight" Value="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).ListItemSelectorSize}" />
</Style> </Style>
</ListBox.Styles> </ListBox.Styles>
<ListBox.ItemTemplate> <ListBox.ItemTemplate>
@@ -67,10 +67,10 @@
Grid.RowSpan="3" Grid.RowSpan="3"
Grid.Column="0" Grid.Column="0"
Margin="0" Margin="0"
Classes.huge="{ReflectionBinding $parent[UserControl].DataContext.IsGridHuge}" Classes.huge="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridHuge}"
Classes.large="{ReflectionBinding $parent[UserControl].DataContext.IsGridLarge}" Classes.large="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridLarge}"
Classes.normal="{ReflectionBinding $parent[UserControl].DataContext.IsGridMedium}" Classes.normal="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridMedium}"
Classes.small="{ReflectionBinding $parent[UserControl].DataContext.IsGridSmall}" Classes.small="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridSmall}"
Source="{Binding Icon, Converter={StaticResource ByteImage}}" /> Source="{Binding Icon, Converter={StaticResource ByteImage}}" />
<Border <Border
Grid.Column="2" Grid.Column="2"

View File

@@ -11,6 +11,7 @@
Height="500" Height="500"
MinWidth="500" MinWidth="500"
MinHeight="500" MinHeight="500"
x:DataType="window:CheatWindow"
WindowStartupLocation="CenterOwner" WindowStartupLocation="CenterOwner"
mc:Ignorable="d" mc:Ignorable="d"
Focusable="True"> Focusable="True">
@@ -40,7 +41,7 @@
HorizontalAlignment="Center" HorizontalAlignment="Center"
VerticalAlignment="Center" VerticalAlignment="Center"
LineHeight="18" LineHeight="18"
Text="{ReflectionBinding Heading}" Text="{Binding Heading}"
TextAlignment="Center" TextAlignment="Center"
TextWrapping="Wrap" /> TextWrapping="Wrap" />
<TextBlock <TextBlock
@@ -61,7 +62,7 @@
MinWidth="160" MinWidth="160"
HorizontalAlignment="Center" HorizontalAlignment="Center"
VerticalAlignment="Center" VerticalAlignment="Center"
Text="{ReflectionBinding BuildId}" Text="{Binding BuildId}"
IsReadOnly="True" /> IsReadOnly="True" />
<Border <Border
Grid.Row="3" Grid.Row="3"
@@ -77,7 +78,7 @@
MinHeight="300" MinHeight="300"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
ItemsSource="{ReflectionBinding LoadedCheats}"> ItemsSource="{Binding LoadedCheats}">
<TreeView.Styles> <TreeView.Styles>
<Styles> <Styles>
<Style Selector="TreeViewItem:empty /template/ ItemsPresenter"> <Style Selector="TreeViewItem:empty /template/ ItemsPresenter">
@@ -120,15 +121,15 @@
Name="SaveButton" Name="SaveButton"
MinWidth="90" MinWidth="90"
Margin="5" Margin="5"
Command="{ReflectionBinding Save}" Command="{Binding Save}"
IsVisible="{ReflectionBinding !NoCheatsFound}"> IsVisible="{Binding !NoCheatsFound}">
<TextBlock Text="{locale:Locale SettingsButtonSave}" /> <TextBlock Text="{locale:Locale SettingsButtonSave}" />
</Button> </Button>
<Button <Button
Name="CancelButton" Name="CancelButton"
MinWidth="90" MinWidth="90"
Margin="5" Margin="5"
Command="{ReflectionBinding Close}"> Command="{Binding Close}">
<TextBlock Text="{locale:Locale InputDialogCancel}" /> <TextBlock Text="{locale:Locale InputDialogCancel}" />
</Button> </Button>
</DockPanel> </DockPanel>

View File

@@ -39,14 +39,14 @@
Name="EnableAllButton" Name="EnableAllButton"
MinWidth="90" MinWidth="90"
Margin="5" Margin="5"
Command="{ReflectionBinding EnableAll}"> Command="{Binding EnableAll}">
<TextBlock Text="{locale:Locale DlcManagerEnableAllButton}" /> <TextBlock Text="{locale:Locale DlcManagerEnableAllButton}" />
</Button> </Button>
<Button <Button
Name="DisableAllButton" Name="DisableAllButton"
MinWidth="90" MinWidth="90"
Margin="5" Margin="5"
Command="{ReflectionBinding DisableAll}"> Command="{Binding DisableAll}">
<TextBlock Text="{locale:Locale DlcManagerDisableAllButton}" /> <TextBlock Text="{locale:Locale DlcManagerDisableAllButton}" />
</Button> </Button>
</StackPanel> </StackPanel>
@@ -157,14 +157,14 @@
Name="AddButton" Name="AddButton"
MinWidth="90" MinWidth="90"
Margin="5" Margin="5"
Command="{ReflectionBinding Add}"> Command="{Binding Add}">
<TextBlock Text="{locale:Locale SettingsTabGeneralAdd}" /> <TextBlock Text="{locale:Locale SettingsTabGeneralAdd}" />
</Button> </Button>
<Button <Button
Name="RemoveAllButton" Name="RemoveAllButton"
MinWidth="90" MinWidth="90"
Margin="5" Margin="5"
Command="{ReflectionBinding RemoveAll}"> Command="{Binding RemoveAll}">
<TextBlock Text="{locale:Locale DlcManagerRemoveAllButton}" /> <TextBlock Text="{locale:Locale DlcManagerRemoveAllButton}" />
</Button> </Button>
</StackPanel> </StackPanel>

View File

@@ -89,6 +89,16 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
context.AddCapability(Capability.DrawParameters); context.AddCapability(Capability.DrawParameters);
} }
if (context.Definitions.Stage != ShaderStage.Fragment &&
context.Definitions.Stage != ShaderStage.Geometry &&
context.Definitions.Stage != ShaderStage.Compute &&
(context.Info.IoDefinitions.Contains(new IoDefinition(StorageKind.Output, IoVariable.Layer)) ||
context.Info.IoDefinitions.Contains(new IoDefinition(StorageKind.Output, IoVariable.ViewportIndex))))
{
context.AddExtension("SPV_EXT_shader_viewport_index_layer");
context.AddCapability(Capability.ShaderViewportIndexLayerEXT);
}
if (context.Info.IoDefinitions.Contains(new IoDefinition(StorageKind.Output, IoVariable.ViewportMask))) if (context.Info.IoDefinitions.Contains(new IoDefinition(StorageKind.Output, IoVariable.ViewportMask)))
{ {
context.AddExtension("SPV_NV_viewport_array2"); context.AddExtension("SPV_NV_viewport_array2");
@@ -277,14 +287,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
localSizeZ); localSizeZ);
} }
if (context.Definitions.Stage != ShaderStage.Fragment &&
context.Definitions.Stage != ShaderStage.Geometry &&
context.Definitions.Stage != ShaderStage.Compute &&
context.Info.IoDefinitions.Contains(new IoDefinition(StorageKind.Output, IoVariable.Layer)))
{
context.AddCapability(Capability.ShaderLayer);
}
if (context.Definitions.TransformFeedbackEnabled && context.Definitions.LastInVertexPipeline) if (context.Definitions.TransformFeedbackEnabled && context.Definitions.LastInVertexPipeline)
{ {
context.AddExecutionMode(spvFunc, ExecutionMode.Xfb); context.AddExecutionMode(spvFunc, ExecutionMode.Xfb);

View File

@@ -257,14 +257,22 @@ namespace Ryujinx.Graphics.Vulkan
if (realIndex != -1) if (realIndex != -1)
{ {
_colors[realIndex].Storage?.InsertReadToWriteBarrier(cbs, AccessFlags.ColorAttachmentWriteBit, PipelineStageFlags.ColorAttachmentOutputBit); _colors[realIndex].Storage?.InsertReadToWriteBarrier(
cbs,
AccessFlags.ColorAttachmentWriteBit,
PipelineStageFlags.ColorAttachmentOutputBit,
insideRenderPass: true);
} }
} }
} }
public void InsertClearBarrierDS(CommandBufferScoped cbs) public void InsertClearBarrierDS(CommandBufferScoped cbs)
{ {
_depthStencil?.Storage?.InsertReadToWriteBarrier(cbs, AccessFlags.DepthStencilAttachmentWriteBit, PipelineStageFlags.LateFragmentTestsBit); _depthStencil?.Storage?.InsertReadToWriteBarrier(
cbs,
AccessFlags.DepthStencilAttachmentWriteBit,
PipelineStageFlags.LateFragmentTestsBit,
insideRenderPass: true);
} }
} }
} }

View File

@@ -41,6 +41,7 @@ namespace Ryujinx.Graphics.Vulkan
public readonly bool SupportsPreciseOcclusionQueries; public readonly bool SupportsPreciseOcclusionQueries;
public readonly bool SupportsPipelineStatisticsQuery; public readonly bool SupportsPipelineStatisticsQuery;
public readonly bool SupportsGeometryShader; public readonly bool SupportsGeometryShader;
public readonly bool SupportsTessellationShader;
public readonly bool SupportsViewportArray2; public readonly bool SupportsViewportArray2;
public readonly bool SupportsHostImportedMemory; public readonly bool SupportsHostImportedMemory;
public readonly bool SupportsDepthClipControl; public readonly bool SupportsDepthClipControl;
@@ -77,6 +78,7 @@ namespace Ryujinx.Graphics.Vulkan
bool supportsPreciseOcclusionQueries, bool supportsPreciseOcclusionQueries,
bool supportsPipelineStatisticsQuery, bool supportsPipelineStatisticsQuery,
bool supportsGeometryShader, bool supportsGeometryShader,
bool supportsTessellationShader,
bool supportsViewportArray2, bool supportsViewportArray2,
bool supportsHostImportedMemory, bool supportsHostImportedMemory,
bool supportsDepthClipControl, bool supportsDepthClipControl,
@@ -112,6 +114,7 @@ namespace Ryujinx.Graphics.Vulkan
SupportsPreciseOcclusionQueries = supportsPreciseOcclusionQueries; SupportsPreciseOcclusionQueries = supportsPreciseOcclusionQueries;
SupportsPipelineStatisticsQuery = supportsPipelineStatisticsQuery; SupportsPipelineStatisticsQuery = supportsPipelineStatisticsQuery;
SupportsGeometryShader = supportsGeometryShader; SupportsGeometryShader = supportsGeometryShader;
SupportsTessellationShader = supportsTessellationShader;
SupportsViewportArray2 = supportsViewportArray2; SupportsViewportArray2 = supportsViewportArray2;
SupportsHostImportedMemory = supportsHostImportedMemory; SupportsHostImportedMemory = supportsHostImportedMemory;
SupportsDepthClipControl = supportsDepthClipControl; SupportsDepthClipControl = supportsDepthClipControl;

View File

@@ -149,10 +149,22 @@ namespace Ryujinx.Graphics.Vulkan
DstAccessMask = AccessFlags.MemoryReadBit | AccessFlags.MemoryWriteBit, DstAccessMask = AccessFlags.MemoryReadBit | AccessFlags.MemoryWriteBit,
}; };
PipelineStageFlags pipelineStageFlags = PipelineStageFlags.VertexShaderBit | PipelineStageFlags.FragmentShaderBit;
if (Gd.Capabilities.SupportsGeometryShader)
{
pipelineStageFlags |= PipelineStageFlags.GeometryShaderBit;
}
if (Gd.Capabilities.SupportsTessellationShader)
{
pipelineStageFlags |= PipelineStageFlags.TessellationControlShaderBit | PipelineStageFlags.TessellationEvaluationShaderBit;
}
Gd.Api.CmdPipelineBarrier( Gd.Api.CmdPipelineBarrier(
CommandBuffer, CommandBuffer,
PipelineStageFlags.FragmentShaderBit, pipelineStageFlags,
PipelineStageFlags.FragmentShaderBit, pipelineStageFlags,
0, 0,
1, 1,
memoryBarrier, memoryBarrier,

View File

@@ -9,8 +9,12 @@ namespace Ryujinx.Graphics.Vulkan
{ {
static class PipelineConverter static class PipelineConverter
{ {
private const AccessFlags SubpassSrcAccessMask = AccessFlags.MemoryReadBit | AccessFlags.MemoryWriteBit | AccessFlags.ColorAttachmentWriteBit; private const AccessFlags SubpassAccessMask =
private const AccessFlags SubpassDstAccessMask = AccessFlags.MemoryReadBit | AccessFlags.MemoryWriteBit | AccessFlags.ShaderReadBit; AccessFlags.MemoryReadBit |
AccessFlags.MemoryWriteBit |
AccessFlags.ShaderReadBit |
AccessFlags.ColorAttachmentWriteBit |
AccessFlags.DepthStencilAttachmentWriteBit;
public static unsafe DisposableRenderPass ToRenderPass(this ProgramPipelineState state, VulkanRenderer gd, Device device) public static unsafe DisposableRenderPass ToRenderPass(this ProgramPipelineState state, VulkanRenderer gd, Device device)
{ {
@@ -132,8 +136,8 @@ namespace Ryujinx.Graphics.Vulkan
0, 0,
PipelineStageFlags.AllGraphicsBit, PipelineStageFlags.AllGraphicsBit,
PipelineStageFlags.AllGraphicsBit, PipelineStageFlags.AllGraphicsBit,
SubpassSrcAccessMask, SubpassAccessMask,
SubpassDstAccessMask, SubpassAccessMask,
0); 0);
} }
@@ -146,8 +150,8 @@ namespace Ryujinx.Graphics.Vulkan
0, 0,
PipelineStageFlags.AllGraphicsBit, PipelineStageFlags.AllGraphicsBit,
PipelineStageFlags.AllGraphicsBit, PipelineStageFlags.AllGraphicsBit,
SubpassSrcAccessMask, SubpassAccessMask,
SubpassDstAccessMask, SubpassAccessMask,
0); 0);
} }

View File

@@ -145,9 +145,12 @@ namespace Ryujinx.Graphics.Vulkan
} }
private void RecordScissor(Vk api, CommandBuffer commandBuffer) private void RecordScissor(Vk api, CommandBuffer commandBuffer)
{
if (ScissorsCount != 0)
{ {
api.CmdSetScissor(commandBuffer, 0, (uint)ScissorsCount, _scissors.AsSpan()); api.CmdSetScissor(commandBuffer, 0, (uint)ScissorsCount, _scissors.AsSpan());
} }
}
private readonly void RecordStencilMasks(Vk api, CommandBuffer commandBuffer) private readonly void RecordStencilMasks(Vk api, CommandBuffer commandBuffer)
{ {

View File

@@ -78,7 +78,7 @@ namespace Ryujinx.Graphics.Vulkan
var sampleCountFlags = ConvertToSampleCountFlags(gd.Capabilities.SupportedSampleCounts, (uint)info.Samples); var sampleCountFlags = ConvertToSampleCountFlags(gd.Capabilities.SupportedSampleCounts, (uint)info.Samples);
var usage = GetImageUsage(info.Format, info.Target, gd.Capabilities.SupportsShaderStorageImageMultisample, forceStorage: true); var usage = GetImageUsage(info.Format, info.Target, gd.Capabilities.SupportsShaderStorageImageMultisample);
var flags = ImageCreateFlags.CreateMutableFormatBit; var flags = ImageCreateFlags.CreateMutableFormatBit;
@@ -291,7 +291,7 @@ namespace Ryujinx.Graphics.Vulkan
} }
} }
public static ImageUsageFlags GetImageUsage(Format format, Target target, bool supportsMsStorage, bool forceStorage = false) public static ImageUsageFlags GetImageUsage(Format format, Target target, bool supportsMsStorage)
{ {
var usage = DefaultUsageFlags; var usage = DefaultUsageFlags;
@@ -304,7 +304,7 @@ namespace Ryujinx.Graphics.Vulkan
usage |= ImageUsageFlags.ColorAttachmentBit; usage |= ImageUsageFlags.ColorAttachmentBit;
} }
if (((forceStorage && !format.IsDepthOrStencil()) || format.IsImageCompatible()) && (supportsMsStorage || !target.IsMultisample())) if (format.IsImageCompatible() && (supportsMsStorage || !target.IsMultisample()))
{ {
usage |= ImageUsageFlags.StorageBit; usage |= ImageUsageFlags.StorageBit;
} }
@@ -440,25 +440,27 @@ namespace Ryujinx.Graphics.Vulkan
_lastModificationStage = stage; _lastModificationStage = stage;
} }
public void InsertReadToWriteBarrier(CommandBufferScoped cbs, AccessFlags dstAccessFlags, PipelineStageFlags dstStageFlags) public void InsertReadToWriteBarrier(CommandBufferScoped cbs, AccessFlags dstAccessFlags, PipelineStageFlags dstStageFlags, bool insideRenderPass)
{ {
if (_lastReadAccess != AccessFlags.None) var lastReadStage = _lastReadStage;
{
ImageAspectFlags aspectFlags = Info.Format.ConvertAspectFlags();
TextureView.InsertImageBarrier( if (insideRenderPass)
{
// We can't have barrier from compute inside a render pass,
// as it is invalid to specify compute in the subpass dependency stage mask.
lastReadStage &= ~PipelineStageFlags.ComputeShaderBit;
}
if (lastReadStage != PipelineStageFlags.None)
{
TextureView.InsertMemoryBarrier(
_gd.Api, _gd.Api,
cbs.CommandBuffer, cbs.CommandBuffer,
_imageAuto.Get(cbs).Value,
_lastReadAccess, _lastReadAccess,
dstAccessFlags, dstAccessFlags,
_lastReadStage, lastReadStage,
dstStageFlags, dstStageFlags);
aspectFlags,
0,
0,
_info.GetLayers(),
_info.Levels);
_lastReadAccess = AccessFlags.None; _lastReadAccess = AccessFlags.None;
_lastReadStage = PipelineStageFlags.None; _lastReadStage = PipelineStageFlags.None;
@@ -472,21 +474,13 @@ namespace Ryujinx.Graphics.Vulkan
if (_lastModificationAccess != AccessFlags.None) if (_lastModificationAccess != AccessFlags.None)
{ {
ImageAspectFlags aspectFlags = Info.Format.ConvertAspectFlags(); TextureView.InsertMemoryBarrier(
TextureView.InsertImageBarrier(
_gd.Api, _gd.Api,
cbs.CommandBuffer, cbs.CommandBuffer,
_imageAuto.Get(cbs).Value,
_lastModificationAccess, _lastModificationAccess,
dstAccessFlags, dstAccessFlags,
_lastModificationStage, _lastModificationStage,
dstStageFlags, dstStageFlags);
aspectFlags,
0,
0,
_info.GetLayers(),
_info.Levels);
_lastModificationAccess = AccessFlags.None; _lastModificationAccess = AccessFlags.None;
} }

View File

@@ -435,6 +435,34 @@ namespace Ryujinx.Graphics.Vulkan
ImageAspectFlags.ColorBit); ImageAspectFlags.ColorBit);
} }
public static unsafe void InsertMemoryBarrier(
Vk api,
CommandBuffer commandBuffer,
AccessFlags srcAccessMask,
AccessFlags dstAccessMask,
PipelineStageFlags srcStageMask,
PipelineStageFlags dstStageMask)
{
MemoryBarrier memoryBarrier = new()
{
SType = StructureType.MemoryBarrier,
SrcAccessMask = srcAccessMask,
DstAccessMask = dstAccessMask,
};
api.CmdPipelineBarrier(
commandBuffer,
srcStageMask,
dstStageMask,
DependencyFlags.None,
1,
memoryBarrier,
0,
null,
0,
null);
}
public static unsafe void InsertImageBarrier( public static unsafe void InsertImageBarrier(
Vk api, Vk api,
CommandBuffer commandBuffer, CommandBuffer commandBuffer,

View File

@@ -327,6 +327,7 @@ namespace Ryujinx.Graphics.Vulkan
features2.Features.OcclusionQueryPrecise, features2.Features.OcclusionQueryPrecise,
_physicalDevice.PhysicalDeviceFeatures.PipelineStatisticsQuery, _physicalDevice.PhysicalDeviceFeatures.PipelineStatisticsQuery,
_physicalDevice.PhysicalDeviceFeatures.GeometryShader, _physicalDevice.PhysicalDeviceFeatures.GeometryShader,
_physicalDevice.PhysicalDeviceFeatures.TessellationShader,
_physicalDevice.IsDeviceExtensionPresent("VK_NV_viewport_array2"), _physicalDevice.IsDeviceExtensionPresent("VK_NV_viewport_array2"),
_physicalDevice.IsDeviceExtensionPresent(ExtExternalMemoryHost.ExtensionName), _physicalDevice.IsDeviceExtensionPresent(ExtExternalMemoryHost.ExtensionName),
supportsDepthClipControl && featuresDepthClipControl.DepthClipControl, supportsDepthClipControl && featuresDepthClipControl.DepthClipControl,

View File

@@ -22,8 +22,10 @@ namespace Ryujinx.Graphics.Vulkan
private Image[] _swapchainImages; private Image[] _swapchainImages;
private Auto<DisposableImageView>[] _swapchainImageViews; private Auto<DisposableImageView>[] _swapchainImageViews;
private Semaphore _imageAvailableSemaphore; private Semaphore[] _imageAvailableSemaphores;
private Semaphore _renderFinishedSemaphore; private Semaphore[] _renderFinishedSemaphores;
private int _frameIndex;
private int _width; private int _width;
private int _height; private int _height;
@@ -48,14 +50,6 @@ namespace Ryujinx.Graphics.Vulkan
_surface = surface; _surface = surface;
CreateSwapchain(); CreateSwapchain();
var semaphoreCreateInfo = new SemaphoreCreateInfo
{
SType = StructureType.SemaphoreCreateInfo,
};
gd.Api.CreateSemaphore(device, semaphoreCreateInfo, null, out _imageAvailableSemaphore).ThrowOnError();
gd.Api.CreateSemaphore(device, semaphoreCreateInfo, null, out _renderFinishedSemaphore).ThrowOnError();
} }
private void RecreateSwapchain() private void RecreateSwapchain()
@@ -69,7 +63,22 @@ namespace Ryujinx.Graphics.Vulkan
} }
// Destroy old Swapchain. // Destroy old Swapchain.
_gd.Api.DeviceWaitIdle(_device); _gd.Api.DeviceWaitIdle(_device);
unsafe
{
for (int i = 0; i < _imageAvailableSemaphores.Length; i++)
{
_gd.Api.DestroySemaphore(_device, _imageAvailableSemaphores[i], null);
}
for (int i = 0; i < _renderFinishedSemaphores.Length; i++)
{
_gd.Api.DestroySemaphore(_device, _renderFinishedSemaphores[i], null);
}
}
_gd.SwapchainApi.DestroySwapchain(_device, oldSwapchain, Span<AllocationCallbacks>.Empty); _gd.SwapchainApi.DestroySwapchain(_device, oldSwapchain, Span<AllocationCallbacks>.Empty);
CreateSwapchain(); CreateSwapchain();
@@ -151,6 +160,25 @@ namespace Ryujinx.Graphics.Vulkan
{ {
_swapchainImageViews[i] = CreateSwapchainImageView(_swapchainImages[i], surfaceFormat.Format); _swapchainImageViews[i] = CreateSwapchainImageView(_swapchainImages[i], surfaceFormat.Format);
} }
var semaphoreCreateInfo = new SemaphoreCreateInfo
{
SType = StructureType.SemaphoreCreateInfo,
};
_imageAvailableSemaphores = new Semaphore[imageCount];
for (int i = 0; i < _imageAvailableSemaphores.Length; i++)
{
_gd.Api.CreateSemaphore(_device, semaphoreCreateInfo, null, out _imageAvailableSemaphores[i]).ThrowOnError();
}
_renderFinishedSemaphores = new Semaphore[imageCount];
for (int i = 0; i < _renderFinishedSemaphores.Length; i++)
{
_gd.Api.CreateSemaphore(_device, semaphoreCreateInfo, null, out _renderFinishedSemaphores[i]).ThrowOnError();
}
} }
private unsafe Auto<DisposableImageView> CreateSwapchainImageView(Image swapchainImage, VkFormat format) private unsafe Auto<DisposableImageView> CreateSwapchainImageView(Image swapchainImage, VkFormat format)
@@ -185,6 +213,7 @@ namespace Ryujinx.Graphics.Vulkan
{ {
return new SurfaceFormatKHR(VkFormat.B8G8R8A8Unorm, ColorSpaceKHR.PaceSrgbNonlinearKhr); return new SurfaceFormatKHR(VkFormat.B8G8R8A8Unorm, ColorSpaceKHR.PaceSrgbNonlinearKhr);
} }
var formatToReturn = availableFormats[0]; var formatToReturn = availableFormats[0];
if (colorSpacePassthroughEnabled) if (colorSpacePassthroughEnabled)
{ {
@@ -212,6 +241,7 @@ namespace Ryujinx.Graphics.Vulkan
} }
} }
} }
return formatToReturn; return formatToReturn;
} }
@@ -265,6 +295,7 @@ namespace Ryujinx.Graphics.Vulkan
_gd.PipelineInternal.AutoFlush.Present(); _gd.PipelineInternal.AutoFlush.Present();
uint nextImage = 0; uint nextImage = 0;
int semaphoreIndex = _frameIndex++ % _imageAvailableSemaphores.Length;
while (true) while (true)
{ {
@@ -272,7 +303,7 @@ namespace Ryujinx.Graphics.Vulkan
_device, _device,
_swapchain, _swapchain,
ulong.MaxValue, ulong.MaxValue,
_imageAvailableSemaphore, _imageAvailableSemaphores[semaphoreIndex],
new Fence(), new Fence(),
ref nextImage); ref nextImage);
@@ -411,12 +442,12 @@ namespace Ryujinx.Graphics.Vulkan
_gd.CommandBufferPool.Return( _gd.CommandBufferPool.Return(
cbs, cbs,
stackalloc[] { _imageAvailableSemaphore }, stackalloc[] { _imageAvailableSemaphores[semaphoreIndex] },
stackalloc[] { PipelineStageFlags.ColorAttachmentOutputBit }, stackalloc[] { PipelineStageFlags.ColorAttachmentOutputBit },
stackalloc[] { _renderFinishedSemaphore }); stackalloc[] { _renderFinishedSemaphores[semaphoreIndex] });
// TODO: Present queue. // TODO: Present queue.
var semaphore = _renderFinishedSemaphore; var semaphore = _renderFinishedSemaphores[semaphoreIndex];
var swapchain = _swapchain; var swapchain = _swapchain;
Result result; Result result;
@@ -593,14 +624,21 @@ namespace Ryujinx.Graphics.Vulkan
{ {
unsafe unsafe
{ {
_gd.Api.DestroySemaphore(_device, _renderFinishedSemaphore, null);
_gd.Api.DestroySemaphore(_device, _imageAvailableSemaphore, null);
for (int i = 0; i < _swapchainImageViews.Length; i++) for (int i = 0; i < _swapchainImageViews.Length; i++)
{ {
_swapchainImageViews[i].Dispose(); _swapchainImageViews[i].Dispose();
} }
for (int i = 0; i < _imageAvailableSemaphores.Length; i++)
{
_gd.Api.DestroySemaphore(_device, _imageAvailableSemaphores[i], null);
}
for (int i = 0; i < _renderFinishedSemaphores.Length; i++)
{
_gd.Api.DestroySemaphore(_device, _renderFinishedSemaphores[i], null);
}
_gd.SwapchainApi.DestroySwapchain(_device, _swapchain, null); _gd.SwapchainApi.DestroySwapchain(_device, _swapchain, null);
} }