Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
44862dce3e | |||
e601419bd4 | |||
d6bc0de785 | |||
9f26fd3600 | |||
88df636c87 | |||
7ccff037e8 |
@ -1,6 +1,7 @@
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Data.Core;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Markup.Xaml.MarkupExtensions;
|
||||
using Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Ava.Common.Locale
|
||||
@ -18,11 +19,20 @@ namespace Ryujinx.Ava.Common.Locale
|
||||
{
|
||||
LocaleKeys keyToUse = Key;
|
||||
|
||||
ReflectionBindingExtension binding = new($"[{keyToUse}]")
|
||||
{
|
||||
Mode = BindingMode.OneWay,
|
||||
Source = LocaleManager.Instance,
|
||||
};
|
||||
var builder = new CompiledBindingPathBuilder();
|
||||
|
||||
builder.SetRawSource(LocaleManager.Instance)
|
||||
.Property(new ClrPropertyInfo("Item",
|
||||
obj => (LocaleManager.Instance[keyToUse]),
|
||||
null,
|
||||
typeof(string)), (weakRef, iPropInfo) =>
|
||||
{
|
||||
return PropertyInfoAccessorFactory.CreateInpcPropertyAccessor(weakRef, iPropInfo);
|
||||
});
|
||||
|
||||
var path = builder.Build();
|
||||
|
||||
var binding = new CompiledBindingExtension(path);
|
||||
|
||||
return binding.ProvideValue(serviceProvider);
|
||||
}
|
||||
|
@ -6,9 +6,11 @@
|
||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
Title="{locale:Locale ErrorWindowTitle}"
|
||||
xmlns:views="using:Ryujinx.Ava.UI.Applet"
|
||||
Width="450"
|
||||
Height="340"
|
||||
CanResize="False"
|
||||
x:DataType="views:ErrorAppletWindow"
|
||||
SizeToContent="Height"
|
||||
mc:Ignorable="d"
|
||||
Focusable="True">
|
||||
@ -38,7 +40,7 @@
|
||||
Grid.Column="1"
|
||||
Margin="10"
|
||||
VerticalAlignment="Stretch"
|
||||
Text="{ReflectionBinding Message}"
|
||||
Text="{Binding Message}"
|
||||
TextWrapping="Wrap" />
|
||||
<StackPanel
|
||||
Name="ButtonStack"
|
||||
@ -49,4 +51,4 @@
|
||||
Orientation="Horizontal"
|
||||
Spacing="10" />
|
||||
</Grid>
|
||||
</Window>
|
||||
</Window>
|
||||
|
@ -4,7 +4,9 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:views="using:Ryujinx.Ava.UI.Controls"
|
||||
Width="400"
|
||||
x:DataType="views:SwkbdAppletDialog"
|
||||
mc:Ignorable="d"
|
||||
Focusable="True">
|
||||
<Grid
|
||||
@ -34,13 +36,13 @@
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Margin="5"
|
||||
Text="{ReflectionBinding MainText}"
|
||||
Text="{Binding MainText}"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Margin="5"
|
||||
Text="{ReflectionBinding SecondaryText}"
|
||||
Text="{Binding SecondaryText}"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBox
|
||||
Name="Input"
|
||||
@ -50,7 +52,7 @@
|
||||
VerticalAlignment="Center"
|
||||
Focusable="True"
|
||||
KeyUp="Message_KeyUp"
|
||||
Text="{ReflectionBinding Message}"
|
||||
Text="{Binding Message}"
|
||||
TextInput="Message_TextInput"
|
||||
TextWrapping="Wrap"
|
||||
UseFloatingWatermark="True" />
|
||||
|
@ -46,7 +46,7 @@
|
||||
<Setter Property="CornerRadius" Value="4" />
|
||||
</Style>
|
||||
<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>
|
||||
</ListBox.Styles>
|
||||
<ListBox.ItemTemplate>
|
||||
@ -56,10 +56,10 @@
|
||||
Margin="10"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Classes.huge="{ReflectionBinding $parent[UserControl].DataContext.IsGridHuge}"
|
||||
Classes.large="{ReflectionBinding $parent[UserControl].DataContext.IsGridLarge}"
|
||||
Classes.normal="{ReflectionBinding $parent[UserControl].DataContext.IsGridMedium}"
|
||||
Classes.small="{ReflectionBinding $parent[UserControl].DataContext.IsGridSmall}"
|
||||
Classes.huge="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridHuge}"
|
||||
Classes.large="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridLarge}"
|
||||
Classes.normal="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridMedium}"
|
||||
Classes.small="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridSmall}"
|
||||
ClipToBounds="True"
|
||||
CornerRadius="4">
|
||||
<Grid>
|
||||
@ -78,7 +78,7 @@
|
||||
Margin="0,10,0,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
IsVisible="{ReflectionBinding $parent[UserControl].DataContext.ShowNames}">
|
||||
IsVisible="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).ShowNames}">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
@ -101,4 +101,4 @@
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
</UserControl>
|
||||
|
@ -42,7 +42,7 @@
|
||||
</ListBox.ItemsPanel>
|
||||
<ListBox.Styles>
|
||||
<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>
|
||||
</ListBox.Styles>
|
||||
<ListBox.ItemTemplate>
|
||||
@ -67,10 +67,10 @@
|
||||
Grid.RowSpan="3"
|
||||
Grid.Column="0"
|
||||
Margin="0"
|
||||
Classes.huge="{ReflectionBinding $parent[UserControl].DataContext.IsGridHuge}"
|
||||
Classes.large="{ReflectionBinding $parent[UserControl].DataContext.IsGridLarge}"
|
||||
Classes.normal="{ReflectionBinding $parent[UserControl].DataContext.IsGridMedium}"
|
||||
Classes.small="{ReflectionBinding $parent[UserControl].DataContext.IsGridSmall}"
|
||||
Classes.huge="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridHuge}"
|
||||
Classes.large="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridLarge}"
|
||||
Classes.normal="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridMedium}"
|
||||
Classes.small="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridSmall}"
|
||||
Source="{Binding Icon, Converter={StaticResource ByteImage}}" />
|
||||
<Border
|
||||
Grid.Column="2"
|
||||
@ -157,4 +157,4 @@
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
</UserControl>
|
||||
|
@ -11,6 +11,7 @@
|
||||
Height="500"
|
||||
MinWidth="500"
|
||||
MinHeight="500"
|
||||
x:DataType="window:CheatWindow"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
mc:Ignorable="d"
|
||||
Focusable="True">
|
||||
@ -40,7 +41,7 @@
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
LineHeight="18"
|
||||
Text="{ReflectionBinding Heading}"
|
||||
Text="{Binding Heading}"
|
||||
TextAlignment="Center"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
@ -61,7 +62,7 @@
|
||||
MinWidth="160"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{ReflectionBinding BuildId}"
|
||||
Text="{Binding BuildId}"
|
||||
IsReadOnly="True" />
|
||||
<Border
|
||||
Grid.Row="3"
|
||||
@ -77,7 +78,7 @@
|
||||
MinHeight="300"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
ItemsSource="{ReflectionBinding LoadedCheats}">
|
||||
ItemsSource="{Binding LoadedCheats}">
|
||||
<TreeView.Styles>
|
||||
<Styles>
|
||||
<Style Selector="TreeViewItem:empty /template/ ItemsPresenter">
|
||||
@ -120,18 +121,18 @@
|
||||
Name="SaveButton"
|
||||
MinWidth="90"
|
||||
Margin="5"
|
||||
Command="{ReflectionBinding Save}"
|
||||
IsVisible="{ReflectionBinding !NoCheatsFound}">
|
||||
Command="{Binding Save}"
|
||||
IsVisible="{Binding !NoCheatsFound}">
|
||||
<TextBlock Text="{locale:Locale SettingsButtonSave}" />
|
||||
</Button>
|
||||
<Button
|
||||
Name="CancelButton"
|
||||
MinWidth="90"
|
||||
Margin="5"
|
||||
Command="{ReflectionBinding Close}">
|
||||
Command="{Binding Close}">
|
||||
<TextBlock Text="{locale:Locale InputDialogCancel}" />
|
||||
</Button>
|
||||
</DockPanel>
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
</window:StyleableWindow>
|
||||
</window:StyleableWindow>
|
||||
|
@ -17,7 +17,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
private readonly string _enabledCheatsPath;
|
||||
public bool NoCheatsFound { get; }
|
||||
|
||||
private AvaloniaList<CheatsList> LoadedCheats { get; }
|
||||
public AvaloniaList<CheatsList> LoadedCheats { get; }
|
||||
|
||||
public string Heading { get; }
|
||||
public string BuildId { get; }
|
||||
|
@ -39,14 +39,14 @@
|
||||
Name="EnableAllButton"
|
||||
MinWidth="90"
|
||||
Margin="5"
|
||||
Command="{ReflectionBinding EnableAll}">
|
||||
Command="{Binding EnableAll}">
|
||||
<TextBlock Text="{locale:Locale DlcManagerEnableAllButton}" />
|
||||
</Button>
|
||||
<Button
|
||||
Name="DisableAllButton"
|
||||
MinWidth="90"
|
||||
Margin="5"
|
||||
Command="{ReflectionBinding DisableAll}">
|
||||
Command="{Binding DisableAll}">
|
||||
<TextBlock Text="{locale:Locale DlcManagerDisableAllButton}" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
@ -157,14 +157,14 @@
|
||||
Name="AddButton"
|
||||
MinWidth="90"
|
||||
Margin="5"
|
||||
Command="{ReflectionBinding Add}">
|
||||
Command="{Binding Add}">
|
||||
<TextBlock Text="{locale:Locale SettingsTabGeneralAdd}" />
|
||||
</Button>
|
||||
<Button
|
||||
Name="RemoveAllButton"
|
||||
MinWidth="90"
|
||||
Margin="5"
|
||||
Command="{ReflectionBinding RemoveAll}">
|
||||
Command="{Binding RemoveAll}">
|
||||
<TextBlock Text="{locale:Locale DlcManagerRemoveAllButton}" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
@ -189,4 +189,4 @@
|
||||
</StackPanel>
|
||||
</Panel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
</UserControl>
|
||||
|
@ -89,6 +89,16 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
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)))
|
||||
{
|
||||
context.AddExtension("SPV_NV_viewport_array2");
|
||||
@ -277,14 +287,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
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)
|
||||
{
|
||||
context.AddExecutionMode(spvFunc, ExecutionMode.Xfb);
|
||||
|
@ -257,14 +257,22 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
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)
|
||||
{
|
||||
_depthStencil?.Storage?.InsertReadToWriteBarrier(cbs, AccessFlags.DepthStencilAttachmentWriteBit, PipelineStageFlags.LateFragmentTestsBit);
|
||||
_depthStencil?.Storage?.InsertReadToWriteBarrier(
|
||||
cbs,
|
||||
AccessFlags.DepthStencilAttachmentWriteBit,
|
||||
PipelineStageFlags.LateFragmentTestsBit,
|
||||
insideRenderPass: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
public readonly bool SupportsPreciseOcclusionQueries;
|
||||
public readonly bool SupportsPipelineStatisticsQuery;
|
||||
public readonly bool SupportsGeometryShader;
|
||||
public readonly bool SupportsTessellationShader;
|
||||
public readonly bool SupportsViewportArray2;
|
||||
public readonly bool SupportsHostImportedMemory;
|
||||
public readonly bool SupportsDepthClipControl;
|
||||
@ -77,6 +78,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
bool supportsPreciseOcclusionQueries,
|
||||
bool supportsPipelineStatisticsQuery,
|
||||
bool supportsGeometryShader,
|
||||
bool supportsTessellationShader,
|
||||
bool supportsViewportArray2,
|
||||
bool supportsHostImportedMemory,
|
||||
bool supportsDepthClipControl,
|
||||
@ -112,6 +114,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
SupportsPreciseOcclusionQueries = supportsPreciseOcclusionQueries;
|
||||
SupportsPipelineStatisticsQuery = supportsPipelineStatisticsQuery;
|
||||
SupportsGeometryShader = supportsGeometryShader;
|
||||
SupportsTessellationShader = supportsTessellationShader;
|
||||
SupportsViewportArray2 = supportsViewportArray2;
|
||||
SupportsHostImportedMemory = supportsHostImportedMemory;
|
||||
SupportsDepthClipControl = supportsDepthClipControl;
|
||||
|
@ -149,10 +149,22 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
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(
|
||||
CommandBuffer,
|
||||
PipelineStageFlags.FragmentShaderBit,
|
||||
PipelineStageFlags.FragmentShaderBit,
|
||||
pipelineStageFlags,
|
||||
pipelineStageFlags,
|
||||
0,
|
||||
1,
|
||||
memoryBarrier,
|
||||
|
@ -9,8 +9,12 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
static class PipelineConverter
|
||||
{
|
||||
private const AccessFlags SubpassSrcAccessMask = AccessFlags.MemoryReadBit | AccessFlags.MemoryWriteBit | AccessFlags.ColorAttachmentWriteBit;
|
||||
private const AccessFlags SubpassDstAccessMask = AccessFlags.MemoryReadBit | AccessFlags.MemoryWriteBit | AccessFlags.ShaderReadBit;
|
||||
private const AccessFlags SubpassAccessMask =
|
||||
AccessFlags.MemoryReadBit |
|
||||
AccessFlags.MemoryWriteBit |
|
||||
AccessFlags.ShaderReadBit |
|
||||
AccessFlags.ColorAttachmentWriteBit |
|
||||
AccessFlags.DepthStencilAttachmentWriteBit;
|
||||
|
||||
public static unsafe DisposableRenderPass ToRenderPass(this ProgramPipelineState state, VulkanRenderer gd, Device device)
|
||||
{
|
||||
@ -132,8 +136,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
0,
|
||||
PipelineStageFlags.AllGraphicsBit,
|
||||
PipelineStageFlags.AllGraphicsBit,
|
||||
SubpassSrcAccessMask,
|
||||
SubpassDstAccessMask,
|
||||
SubpassAccessMask,
|
||||
SubpassAccessMask,
|
||||
0);
|
||||
}
|
||||
|
||||
@ -146,8 +150,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
0,
|
||||
PipelineStageFlags.AllGraphicsBit,
|
||||
PipelineStageFlags.AllGraphicsBit,
|
||||
SubpassSrcAccessMask,
|
||||
SubpassDstAccessMask,
|
||||
SubpassAccessMask,
|
||||
SubpassAccessMask,
|
||||
0);
|
||||
}
|
||||
|
||||
|
@ -146,7 +146,10 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
private void RecordScissor(Vk api, CommandBuffer commandBuffer)
|
||||
{
|
||||
api.CmdSetScissor(commandBuffer, 0, (uint)ScissorsCount, _scissors.AsSpan());
|
||||
if (ScissorsCount != 0)
|
||||
{
|
||||
api.CmdSetScissor(commandBuffer, 0, (uint)ScissorsCount, _scissors.AsSpan());
|
||||
}
|
||||
}
|
||||
|
||||
private readonly void RecordStencilMasks(Vk api, CommandBuffer commandBuffer)
|
||||
|
@ -78,7 +78,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -304,7 +304,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
usage |= ImageUsageFlags.ColorAttachmentBit;
|
||||
}
|
||||
|
||||
if (((forceStorage && !format.IsDepthOrStencil()) || format.IsImageCompatible()) && (supportsMsStorage || !target.IsMultisample()))
|
||||
if (format.IsImageCompatible() && (supportsMsStorage || !target.IsMultisample()))
|
||||
{
|
||||
usage |= ImageUsageFlags.StorageBit;
|
||||
}
|
||||
@ -440,25 +440,27 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
_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)
|
||||
{
|
||||
ImageAspectFlags aspectFlags = Info.Format.ConvertAspectFlags();
|
||||
var lastReadStage = _lastReadStage;
|
||||
|
||||
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,
|
||||
cbs.CommandBuffer,
|
||||
_imageAuto.Get(cbs).Value,
|
||||
_lastReadAccess,
|
||||
dstAccessFlags,
|
||||
_lastReadStage,
|
||||
dstStageFlags,
|
||||
aspectFlags,
|
||||
0,
|
||||
0,
|
||||
_info.GetLayers(),
|
||||
_info.Levels);
|
||||
lastReadStage,
|
||||
dstStageFlags);
|
||||
|
||||
_lastReadAccess = AccessFlags.None;
|
||||
_lastReadStage = PipelineStageFlags.None;
|
||||
@ -472,21 +474,13 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
if (_lastModificationAccess != AccessFlags.None)
|
||||
{
|
||||
ImageAspectFlags aspectFlags = Info.Format.ConvertAspectFlags();
|
||||
|
||||
TextureView.InsertImageBarrier(
|
||||
TextureView.InsertMemoryBarrier(
|
||||
_gd.Api,
|
||||
cbs.CommandBuffer,
|
||||
_imageAuto.Get(cbs).Value,
|
||||
_lastModificationAccess,
|
||||
dstAccessFlags,
|
||||
_lastModificationStage,
|
||||
dstStageFlags,
|
||||
aspectFlags,
|
||||
0,
|
||||
0,
|
||||
_info.GetLayers(),
|
||||
_info.Levels);
|
||||
dstStageFlags);
|
||||
|
||||
_lastModificationAccess = AccessFlags.None;
|
||||
}
|
||||
|
@ -435,6 +435,34 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
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(
|
||||
Vk api,
|
||||
CommandBuffer commandBuffer,
|
||||
|
@ -327,6 +327,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
features2.Features.OcclusionQueryPrecise,
|
||||
_physicalDevice.PhysicalDeviceFeatures.PipelineStatisticsQuery,
|
||||
_physicalDevice.PhysicalDeviceFeatures.GeometryShader,
|
||||
_physicalDevice.PhysicalDeviceFeatures.TessellationShader,
|
||||
_physicalDevice.IsDeviceExtensionPresent("VK_NV_viewport_array2"),
|
||||
_physicalDevice.IsDeviceExtensionPresent(ExtExternalMemoryHost.ExtensionName),
|
||||
supportsDepthClipControl && featuresDepthClipControl.DepthClipControl,
|
||||
|
@ -22,8 +22,10 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
private Image[] _swapchainImages;
|
||||
private Auto<DisposableImageView>[] _swapchainImageViews;
|
||||
|
||||
private Semaphore _imageAvailableSemaphore;
|
||||
private Semaphore _renderFinishedSemaphore;
|
||||
private Semaphore[] _imageAvailableSemaphores;
|
||||
private Semaphore[] _renderFinishedSemaphores;
|
||||
|
||||
private int _frameIndex;
|
||||
|
||||
private int _width;
|
||||
private int _height;
|
||||
@ -48,14 +50,6 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
_surface = surface;
|
||||
|
||||
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()
|
||||
@ -69,7 +63,22 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
}
|
||||
|
||||
// Destroy old Swapchain.
|
||||
|
||||
_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);
|
||||
|
||||
CreateSwapchain();
|
||||
@ -151,6 +160,25 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
_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)
|
||||
@ -185,6 +213,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
return new SurfaceFormatKHR(VkFormat.B8G8R8A8Unorm, ColorSpaceKHR.PaceSrgbNonlinearKhr);
|
||||
}
|
||||
|
||||
var formatToReturn = availableFormats[0];
|
||||
if (colorSpacePassthroughEnabled)
|
||||
{
|
||||
@ -212,6 +241,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return formatToReturn;
|
||||
}
|
||||
|
||||
@ -265,6 +295,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
_gd.PipelineInternal.AutoFlush.Present();
|
||||
|
||||
uint nextImage = 0;
|
||||
int semaphoreIndex = _frameIndex++ % _imageAvailableSemaphores.Length;
|
||||
|
||||
while (true)
|
||||
{
|
||||
@ -272,7 +303,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
_device,
|
||||
_swapchain,
|
||||
ulong.MaxValue,
|
||||
_imageAvailableSemaphore,
|
||||
_imageAvailableSemaphores[semaphoreIndex],
|
||||
new Fence(),
|
||||
ref nextImage);
|
||||
|
||||
@ -411,12 +442,12 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
_gd.CommandBufferPool.Return(
|
||||
cbs,
|
||||
stackalloc[] { _imageAvailableSemaphore },
|
||||
stackalloc[] { _imageAvailableSemaphores[semaphoreIndex] },
|
||||
stackalloc[] { PipelineStageFlags.ColorAttachmentOutputBit },
|
||||
stackalloc[] { _renderFinishedSemaphore });
|
||||
stackalloc[] { _renderFinishedSemaphores[semaphoreIndex] });
|
||||
|
||||
// TODO: Present queue.
|
||||
var semaphore = _renderFinishedSemaphore;
|
||||
var semaphore = _renderFinishedSemaphores[semaphoreIndex];
|
||||
var swapchain = _swapchain;
|
||||
|
||||
Result result;
|
||||
@ -593,14 +624,21 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
_gd.Api.DestroySemaphore(_device, _renderFinishedSemaphore, null);
|
||||
_gd.Api.DestroySemaphore(_device, _imageAvailableSemaphore, null);
|
||||
|
||||
for (int i = 0; i < _swapchainImageViews.Length; i++)
|
||||
{
|
||||
_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);
|
||||
}
|
||||
|
||||
|
@ -299,11 +299,21 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
||||
{
|
||||
try
|
||||
{
|
||||
LinuxError result = WinSockHelper.ValidateSocketOption(option, level, write: false);
|
||||
|
||||
if (result != LinuxError.SUCCESS)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.ServiceBsd, $"Invalid GetSockOpt Option: {option} Level: {level}");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!WinSockHelper.TryConvertSocketOption(option, level, out SocketOptionName optionName))
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported GetSockOpt Option: {option} Level: {level}");
|
||||
optionValue.Clear();
|
||||
|
||||
return LinuxError.EOPNOTSUPP;
|
||||
return LinuxError.SUCCESS;
|
||||
}
|
||||
|
||||
byte[] tempOptionValue = new byte[optionValue.Length];
|
||||
@ -324,11 +334,20 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
||||
{
|
||||
try
|
||||
{
|
||||
LinuxError result = WinSockHelper.ValidateSocketOption(option, level, write: true);
|
||||
|
||||
if (result != LinuxError.SUCCESS)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.ServiceBsd, $"Invalid SetSockOpt Option: {option} Level: {level}");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!WinSockHelper.TryConvertSocketOption(option, level, out SocketOptionName optionName))
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported SetSockOpt Option: {option} Level: {level}");
|
||||
|
||||
return LinuxError.EOPNOTSUPP;
|
||||
return LinuxError.SUCCESS;
|
||||
}
|
||||
|
||||
int value = optionValue.Length >= 4 ? MemoryMarshal.Read<int>(optionValue) : MemoryMarshal.Read<byte>(optionValue);
|
||||
|
@ -183,6 +183,104 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
||||
{ BsdSocketOption.TcpKeepCnt, SocketOptionName.TcpKeepAliveRetryCount },
|
||||
};
|
||||
|
||||
[Flags]
|
||||
private enum OptionDir
|
||||
{
|
||||
Get = 1 << 0,
|
||||
Set = 1 << 1,
|
||||
GetSet = Get | Set,
|
||||
}
|
||||
|
||||
private static readonly Dictionary<BsdSocketOption, OptionDir> _validSoSocketOptionMap = new()
|
||||
{
|
||||
{ BsdSocketOption.SoDebug, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoAcceptConn, OptionDir.Get },
|
||||
{ BsdSocketOption.SoReuseAddr, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoKeepAlive, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoDontRoute, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoBroadcast, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoUseLoopBack, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoLinger, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoOobInline, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoReusePort, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoTimestamp, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoNoSigpipe, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoAcceptFilter, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoSndBuf, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoRcvBuf, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoSndLoWat, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoRcvLoWat, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoSndTimeo, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoRcvTimeo, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoError, OptionDir.Get },
|
||||
{ BsdSocketOption.SoType, OptionDir.Get },
|
||||
{ BsdSocketOption.SoLabel, OptionDir.Get },
|
||||
{ BsdSocketOption.SoPeerLabel, OptionDir.Get },
|
||||
{ BsdSocketOption.SoListenQLimit, OptionDir.Get },
|
||||
{ BsdSocketOption.SoListenQLen, OptionDir.Get },
|
||||
{ BsdSocketOption.SoListenIncQLen, OptionDir.Get },
|
||||
{ BsdSocketOption.SoSetFib, OptionDir.Set },
|
||||
{ BsdSocketOption.SoUserCookie, OptionDir.Set },
|
||||
{ BsdSocketOption.SoProtocol, OptionDir.Get },
|
||||
{ BsdSocketOption.SoBinTime, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoNoOffload, OptionDir.Set },
|
||||
{ BsdSocketOption.SoNoDdp, OptionDir.Set },
|
||||
{ BsdSocketOption.SoReusePortLb, OptionDir.GetSet },
|
||||
};
|
||||
|
||||
private static readonly Dictionary<BsdSocketOption, OptionDir> _validIpSocketOptionMap = new()
|
||||
{
|
||||
{ BsdSocketOption.IpOptions, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpHdrIncl, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpTos, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpTtl, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpRecvOpts, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpRecvRetOpts, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpRecvDstAddr, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpRetOpts, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpMulticastIf, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpMulticastTtl, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpMulticastLoop, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpAddMembership, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpDropMembership, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpMulticastVif, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpRsvpOn, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpRsvpOff, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpRsvpVifOn, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpRsvpVifOff, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpPortRange, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpRecvIf, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpIpsecPolicy, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpOnesBcast, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpBindany, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpBindMulti, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpRssListenBucket, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpOrigDstAddr, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpRecvTtl, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpMinTtl, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpDontFrag, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpRecvTos, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpAddSourceMembership, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpDropSourceMembership, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpBlockSource, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpUnblockSource, OptionDir.GetSet },
|
||||
};
|
||||
|
||||
private static readonly Dictionary<BsdSocketOption, OptionDir> _validTcpSocketOptionMap = new()
|
||||
{
|
||||
{ BsdSocketOption.TcpNoDelay, OptionDir.GetSet },
|
||||
{ BsdSocketOption.TcpMaxSeg, OptionDir.GetSet },
|
||||
{ BsdSocketOption.TcpNoPush, OptionDir.GetSet },
|
||||
{ BsdSocketOption.TcpNoOpt, OptionDir.GetSet },
|
||||
{ BsdSocketOption.TcpMd5Sig, OptionDir.GetSet },
|
||||
{ BsdSocketOption.TcpInfo, OptionDir.GetSet },
|
||||
{ BsdSocketOption.TcpCongestion, OptionDir.GetSet },
|
||||
{ BsdSocketOption.TcpKeepInit, OptionDir.GetSet },
|
||||
{ BsdSocketOption.TcpKeepIdle, OptionDir.GetSet },
|
||||
{ BsdSocketOption.TcpKeepIntvl, OptionDir.GetSet },
|
||||
{ BsdSocketOption.TcpKeepCnt, OptionDir.GetSet },
|
||||
};
|
||||
|
||||
public static LinuxError ConvertError(WsaError errorCode)
|
||||
{
|
||||
if (OperatingSystem.IsMacOS())
|
||||
@ -221,5 +319,29 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
||||
|
||||
return table.TryGetValue(option, out name);
|
||||
}
|
||||
|
||||
public static LinuxError ValidateSocketOption(BsdSocketOption option, SocketOptionLevel level, bool write)
|
||||
{
|
||||
var table = level switch
|
||||
{
|
||||
SocketOptionLevel.Socket => _validSoSocketOptionMap,
|
||||
SocketOptionLevel.IP => _validIpSocketOptionMap,
|
||||
SocketOptionLevel.Tcp => _validTcpSocketOptionMap,
|
||||
_ => null,
|
||||
};
|
||||
|
||||
OptionDir dir = write ? OptionDir.Set : OptionDir.Get;
|
||||
|
||||
if (table == null || !table.TryGetValue(option, out OptionDir validDir))
|
||||
{
|
||||
return LinuxError.ENOPROTOOPT;
|
||||
}
|
||||
else if ((validDir & dir) != dir)
|
||||
{
|
||||
return LinuxError.EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return LinuxError.SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user