Compare commits
6 Commits
1.2.81
...
57b7dedfec
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57b7dedfec | ||
|
|
c140e9b23c | ||
|
|
9c8055440e | ||
|
|
c03cd50fa3 | ||
|
|
069f630776 | ||
|
|
f3e1d9cd50 |
@@ -1070,6 +1070,7 @@
|
|||||||
010017B0102A8000,"Emma: Lost in Memories",nvdec,playable,2021-01-28 16:19:10
|
010017B0102A8000,"Emma: Lost in Memories",nvdec,playable,2021-01-28 16:19:10
|
||||||
010068300E08E000,"Enchanted in the Moonlight - Kiryu, Chikage & Yukinojo -",gpu;nvdec,ingame,2022-11-20 16:18:45
|
010068300E08E000,"Enchanted in the Moonlight - Kiryu, Chikage & Yukinojo -",gpu;nvdec,ingame,2022-11-20 16:18:45
|
||||||
01007A4008486000,"Enchanting Mahjong Match",gpu,ingame,2020-04-17 22:01:31
|
01007A4008486000,"Enchanting Mahjong Match",gpu,ingame,2020-04-17 22:01:31
|
||||||
|
0100EF901E552000,"ENDER MAGNOLIA: Bloom in the Mist",deadlock,boots,2025-01-22 17:59:00
|
||||||
01004F3011F92000,"Endless Fables: Dark Moor",gpu;nvdec,ingame,2021-03-07 15:31:03
|
01004F3011F92000,"Endless Fables: Dark Moor",gpu;nvdec,ingame,2021-03-07 15:31:03
|
||||||
010067B017588000,"Endless Ocean™ Luminous",services-horizon;crash,ingame,2024-05-30 02:05:57
|
010067B017588000,"Endless Ocean™ Luminous",services-horizon;crash,ingame,2024-05-30 02:05:57
|
||||||
0100B8700BD14000,"Energy Cycle Edge",services,ingame,2021-11-30 05:02:31
|
0100B8700BD14000,"Energy Cycle Edge",services,ingame,2021-11-30 05:02:31
|
||||||
|
|||||||
|
@@ -78,5 +78,10 @@ namespace Ryujinx.Common.Configuration.Hid.Controller
|
|||||||
/// Controller Rumble Settings
|
/// Controller Rumble Settings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public RumbleConfigController Rumble { get; set; }
|
public RumbleConfigController Rumble { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Controller LED Settings
|
||||||
|
/// </summary>
|
||||||
|
public LedConfigController Led { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
namespace Ryujinx.Common.Configuration.Hid.Controller
|
||||||
|
{
|
||||||
|
public class LedConfigController
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Packed RGB int of the color
|
||||||
|
/// </summary>
|
||||||
|
public uint LedColor { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enable LED color changing by the emulator
|
||||||
|
/// </summary>
|
||||||
|
public bool EnableLed { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,33 +1,13 @@
|
|||||||
using Ryujinx.Common.Utilities;
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Common.GraphicsDriver
|
namespace Ryujinx.Common.GraphicsDriver
|
||||||
{
|
{
|
||||||
public static class DriverUtilities
|
public static class DriverUtilities
|
||||||
{
|
{
|
||||||
private static void AddMesaFlags(string envVar, string newFlags)
|
|
||||||
{
|
|
||||||
string existingFlags = Environment.GetEnvironmentVariable(envVar);
|
|
||||||
|
|
||||||
string flags = existingFlags == null ? newFlags : $"{existingFlags},{newFlags}";
|
|
||||||
|
|
||||||
OsUtils.SetEnvironmentVariableNoCaching(envVar, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void InitDriverConfig(bool oglThreading)
|
|
||||||
{
|
|
||||||
if (OperatingSystem.IsLinux())
|
|
||||||
{
|
|
||||||
AddMesaFlags("RADV_DEBUG", "nodcc");
|
|
||||||
}
|
|
||||||
|
|
||||||
ToggleOGLThreading(oglThreading);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ToggleOGLThreading(bool enabled)
|
public static void ToggleOGLThreading(bool enabled)
|
||||||
{
|
{
|
||||||
OsUtils.SetEnvironmentVariableNoCaching("mesa_glthread", enabled.ToString().ToLower());
|
Environment.SetEnvironmentVariable("mesa_glthread", enabled.ToString().ToLower());
|
||||||
OsUtils.SetEnvironmentVariableNoCaching("__GL_THREADED_OPTIMIZATIONS", enabled ? "1" : "0");
|
Environment.SetEnvironmentVariable("__GL_THREADED_OPTIMIZATIONS", enabled ? "1" : "0");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace Ryujinx.Common.Utilities
|
|
||||||
{
|
|
||||||
public partial class OsUtils
|
|
||||||
{
|
|
||||||
[LibraryImport("libc", SetLastError = true)]
|
|
||||||
private static partial int setenv([MarshalAs(UnmanagedType.LPStr)] string name, [MarshalAs(UnmanagedType.LPStr)] string value, int overwrite);
|
|
||||||
|
|
||||||
public static void SetEnvironmentVariableNoCaching(string key, string value)
|
|
||||||
{
|
|
||||||
// Set the value in the cached environment variables, too.
|
|
||||||
Environment.SetEnvironmentVariable(key, value);
|
|
||||||
|
|
||||||
if (!OperatingSystem.IsWindows())
|
|
||||||
{
|
|
||||||
int res = setenv(key, value, 1);
|
|
||||||
Debug.Assert(res != -1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -32,12 +32,10 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
CommandBuffer
|
CommandBuffer
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool _feedbackLoopActive;
|
|
||||||
private PipelineStageFlags _incoherentBufferWriteStages;
|
private PipelineStageFlags _incoherentBufferWriteStages;
|
||||||
private PipelineStageFlags _incoherentTextureWriteStages;
|
private PipelineStageFlags _incoherentTextureWriteStages;
|
||||||
private PipelineStageFlags _extraStages;
|
private PipelineStageFlags _extraStages;
|
||||||
private IncoherentBarrierType _queuedIncoherentBarrier;
|
private IncoherentBarrierType _queuedIncoherentBarrier;
|
||||||
private bool _queuedFeedbackLoopBarrier;
|
|
||||||
|
|
||||||
public BarrierBatch(VulkanRenderer gd)
|
public BarrierBatch(VulkanRenderer gd)
|
||||||
{
|
{
|
||||||
@@ -55,6 +53,17 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
stages |= PipelineStageFlags.TransformFeedbackBitExt;
|
stages |= PipelineStageFlags.TransformFeedbackBitExt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!gd.IsTBDR)
|
||||||
|
{
|
||||||
|
// Desktop GPUs can transform image barriers into memory barriers.
|
||||||
|
|
||||||
|
access |= AccessFlags.DepthStencilAttachmentWriteBit | AccessFlags.ColorAttachmentWriteBit;
|
||||||
|
access |= AccessFlags.DepthStencilAttachmentReadBit | AccessFlags.ColorAttachmentReadBit;
|
||||||
|
|
||||||
|
stages |= PipelineStageFlags.EarlyFragmentTestsBit | PipelineStageFlags.LateFragmentTestsBit;
|
||||||
|
stages |= PipelineStageFlags.ColorAttachmentOutputBit;
|
||||||
|
}
|
||||||
|
|
||||||
return (access, stages);
|
return (access, stages);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,34 +178,16 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
|
|
||||||
_queuedIncoherentBarrier = IncoherentBarrierType.None;
|
_queuedIncoherentBarrier = IncoherentBarrierType.None;
|
||||||
_queuedFeedbackLoopBarrier = false;
|
|
||||||
}
|
}
|
||||||
else if (_feedbackLoopActive && _queuedFeedbackLoopBarrier)
|
|
||||||
{
|
|
||||||
// Feedback loop barrier.
|
|
||||||
|
|
||||||
MemoryBarrier barrier = new MemoryBarrier()
|
|
||||||
{
|
|
||||||
SType = StructureType.MemoryBarrier,
|
|
||||||
SrcAccessMask = AccessFlags.ShaderWriteBit,
|
|
||||||
DstAccessMask = AccessFlags.ShaderReadBit
|
|
||||||
};
|
|
||||||
|
|
||||||
QueueBarrier(barrier, PipelineStageFlags.FragmentShaderBit, PipelineStageFlags.AllGraphicsBit);
|
|
||||||
|
|
||||||
_queuedFeedbackLoopBarrier = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_feedbackLoopActive = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe void Flush(CommandBufferScoped cbs, bool inRenderPass, RenderPassHolder rpHolder, Action endRenderPass)
|
public unsafe void Flush(CommandBufferScoped cbs, bool inRenderPass, RenderPassHolder rpHolder, Action endRenderPass)
|
||||||
{
|
{
|
||||||
Flush(cbs, null, false, inRenderPass, rpHolder, endRenderPass);
|
Flush(cbs, null, inRenderPass, rpHolder, endRenderPass);
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe void Flush(CommandBufferScoped cbs, ShaderCollection program, bool feedbackLoopActive, bool inRenderPass, RenderPassHolder rpHolder, Action endRenderPass)
|
public unsafe void Flush(CommandBufferScoped cbs, ShaderCollection program, bool inRenderPass, RenderPassHolder rpHolder, Action endRenderPass)
|
||||||
{
|
{
|
||||||
if (program != null)
|
if (program != null)
|
||||||
{
|
{
|
||||||
@@ -204,8 +195,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_incoherentTextureWriteStages |= program.IncoherentTextureWriteStages;
|
_incoherentTextureWriteStages |= program.IncoherentTextureWriteStages;
|
||||||
}
|
}
|
||||||
|
|
||||||
_feedbackLoopActive |= feedbackLoopActive;
|
|
||||||
|
|
||||||
FlushMemoryBarrier(program, inRenderPass);
|
FlushMemoryBarrier(program, inRenderPass);
|
||||||
|
|
||||||
if (!inRenderPass && rpHolder != null)
|
if (!inRenderPass && rpHolder != null)
|
||||||
@@ -417,8 +406,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
_queuedIncoherentBarrier = type;
|
_queuedIncoherentBarrier = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
_queuedFeedbackLoopBarrier = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void QueueTextureBarrier()
|
public void QueueTextureBarrier()
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using Ryujinx.Graphics.Shader;
|
|||||||
using Silk.NET.Vulkan;
|
using Silk.NET.Vulkan;
|
||||||
using System;
|
using System;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using CompareOp = Ryujinx.Graphics.GAL.CompareOp;
|
using CompareOp = Ryujinx.Graphics.GAL.CompareOp;
|
||||||
@@ -43,15 +42,15 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
private record struct TextureRef
|
private record struct TextureRef
|
||||||
{
|
{
|
||||||
public ShaderStage Stage;
|
public ShaderStage Stage;
|
||||||
public TextureView View;
|
public TextureStorage Storage;
|
||||||
public Auto<DisposableImageView> ImageView;
|
public Auto<DisposableImageView> View;
|
||||||
public Auto<DisposableSampler> Sampler;
|
public Auto<DisposableSampler> Sampler;
|
||||||
|
|
||||||
public TextureRef(ShaderStage stage, TextureView view, Auto<DisposableImageView> imageView, Auto<DisposableSampler> sampler)
|
public TextureRef(ShaderStage stage, TextureStorage storage, Auto<DisposableImageView> view, Auto<DisposableSampler> sampler)
|
||||||
{
|
{
|
||||||
Stage = stage;
|
Stage = stage;
|
||||||
|
Storage = storage;
|
||||||
View = view;
|
View = view;
|
||||||
ImageView = imageView;
|
|
||||||
Sampler = sampler;
|
Sampler = sampler;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -59,14 +58,14 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
private record struct ImageRef
|
private record struct ImageRef
|
||||||
{
|
{
|
||||||
public ShaderStage Stage;
|
public ShaderStage Stage;
|
||||||
public TextureView View;
|
public TextureStorage Storage;
|
||||||
public Auto<DisposableImageView> ImageView;
|
public Auto<DisposableImageView> View;
|
||||||
|
|
||||||
public ImageRef(ShaderStage stage, TextureView view, Auto<DisposableImageView> imageView)
|
public ImageRef(ShaderStage stage, TextureStorage storage, Auto<DisposableImageView> view)
|
||||||
{
|
{
|
||||||
Stage = stage;
|
Stage = stage;
|
||||||
|
Storage = storage;
|
||||||
View = view;
|
View = view;
|
||||||
ImageView = imageView;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,8 +123,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
private readonly TextureView _dummyTexture;
|
private readonly TextureView _dummyTexture;
|
||||||
private readonly SamplerHolder _dummySampler;
|
private readonly SamplerHolder _dummySampler;
|
||||||
|
|
||||||
public List<TextureView> FeedbackLoopHazards { get; private set; }
|
|
||||||
|
|
||||||
public DescriptorSetUpdater(VulkanRenderer gd, Device device)
|
public DescriptorSetUpdater(VulkanRenderer gd, Device device)
|
||||||
{
|
{
|
||||||
_gd = gd;
|
_gd = gd;
|
||||||
@@ -210,15 +207,10 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_templateUpdater = new();
|
_templateUpdater = new();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialize(bool isMainPipeline)
|
public void Initialize()
|
||||||
{
|
{
|
||||||
MemoryOwner<byte> dummyTextureData = MemoryOwner<byte>.RentCleared(4);
|
MemoryOwner<byte> dummyTextureData = MemoryOwner<byte>.RentCleared(4);
|
||||||
_dummyTexture.SetData(dummyTextureData);
|
_dummyTexture.SetData(dummyTextureData);
|
||||||
|
|
||||||
if (isMainPipeline)
|
|
||||||
{
|
|
||||||
FeedbackLoopHazards = new();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool BindingOverlaps(ref DescriptorBufferInfo info, int bindingOffset, int offset, int size)
|
private static bool BindingOverlaps(ref DescriptorBufferInfo info, int bindingOffset, int offset, int size)
|
||||||
@@ -281,18 +273,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
public void InsertBindingBarriers(CommandBufferScoped cbs)
|
public void InsertBindingBarriers(CommandBufferScoped cbs)
|
||||||
{
|
{
|
||||||
if ((FeedbackLoopHazards?.Count ?? 0) > 0)
|
|
||||||
{
|
|
||||||
// Clear existing hazards - they will be rebuilt.
|
|
||||||
|
|
||||||
foreach (TextureView hazard in FeedbackLoopHazards)
|
|
||||||
{
|
|
||||||
hazard.DecrementHazardUses();
|
|
||||||
}
|
|
||||||
|
|
||||||
FeedbackLoopHazards.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (ResourceBindingSegment segment in _program.BindingSegments[PipelineBase.TextureSetIndex])
|
foreach (ResourceBindingSegment segment in _program.BindingSegments[PipelineBase.TextureSetIndex])
|
||||||
{
|
{
|
||||||
if (segment.Type == ResourceType.TextureAndSampler)
|
if (segment.Type == ResourceType.TextureAndSampler)
|
||||||
@@ -302,7 +282,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
for (int i = 0; i < segment.Count; i++)
|
for (int i = 0; i < segment.Count; i++)
|
||||||
{
|
{
|
||||||
ref var texture = ref _textureRefs[segment.Binding + i];
|
ref var texture = ref _textureRefs[segment.Binding + i];
|
||||||
texture.View?.PrepareForUsage(cbs, texture.Stage.ConvertToPipelineStageFlags(), FeedbackLoopHazards);
|
texture.Storage?.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, texture.Stage.ConvertToPipelineStageFlags());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -323,7 +303,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
for (int i = 0; i < segment.Count; i++)
|
for (int i = 0; i < segment.Count; i++)
|
||||||
{
|
{
|
||||||
ref var image = ref _imageRefs[segment.Binding + i];
|
ref var image = ref _imageRefs[segment.Binding + i];
|
||||||
image.View?.PrepareForUsage(cbs, image.Stage.ConvertToPipelineStageFlags(), FeedbackLoopHazards);
|
image.Storage?.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, image.Stage.ConvertToPipelineStageFlags());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -397,12 +377,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
else if (image is TextureView view)
|
else if (image is TextureView view)
|
||||||
{
|
{
|
||||||
ref ImageRef iRef = ref _imageRefs[binding];
|
view.Storage.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, stage.ConvertToPipelineStageFlags());
|
||||||
|
_imageRefs[binding] = new(stage, view.Storage, view.GetIdentityImageView());
|
||||||
iRef.View?.ClearUsage(FeedbackLoopHazards);
|
|
||||||
view?.PrepareForUsage(cbs, stage.ConvertToPipelineStageFlags(), FeedbackLoopHazards);
|
|
||||||
|
|
||||||
iRef = new(stage, view, view.GetIdentityImageView());
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -500,12 +476,9 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
else if (texture is TextureView view)
|
else if (texture is TextureView view)
|
||||||
{
|
{
|
||||||
ref TextureRef iRef = ref _textureRefs[binding];
|
view.Storage.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, stage.ConvertToPipelineStageFlags());
|
||||||
|
|
||||||
iRef.View?.ClearUsage(FeedbackLoopHazards);
|
_textureRefs[binding] = new(stage, view.Storage, view.GetImageView(), ((SamplerHolder)sampler)?.GetSampler());
|
||||||
view?.PrepareForUsage(cbs, stage.ConvertToPipelineStageFlags(), FeedbackLoopHazards);
|
|
||||||
|
|
||||||
iRef = new(stage, view, view.GetImageView(), ((SamplerHolder)sampler)?.GetSampler());
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -527,7 +500,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
view.Storage.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, stage.ConvertToPipelineStageFlags());
|
view.Storage.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, stage.ConvertToPipelineStageFlags());
|
||||||
|
|
||||||
_textureRefs[binding] = new(stage, view, view.GetIdentityImageView(), ((SamplerHolder)sampler)?.GetSampler());
|
_textureRefs[binding] = new(stage, view.Storage, view.GetIdentityImageView(), ((SamplerHolder)sampler)?.GetSampler());
|
||||||
|
|
||||||
SignalDirty(DirtyFlags.Texture);
|
SignalDirty(DirtyFlags.Texture);
|
||||||
}
|
}
|
||||||
@@ -853,7 +826,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
ref var texture = ref textures[i];
|
ref var texture = ref textures[i];
|
||||||
ref var refs = ref _textureRefs[binding + i];
|
ref var refs = ref _textureRefs[binding + i];
|
||||||
|
|
||||||
texture.ImageView = refs.ImageView?.Get(cbs).Value ?? default;
|
texture.ImageView = refs.View?.Get(cbs).Value ?? default;
|
||||||
texture.Sampler = refs.Sampler?.Get(cbs).Value ?? default;
|
texture.Sampler = refs.Sampler?.Get(cbs).Value ?? default;
|
||||||
|
|
||||||
if (texture.ImageView.Handle == 0)
|
if (texture.ImageView.Handle == 0)
|
||||||
@@ -903,7 +876,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
images[i].ImageView = _imageRefs[binding + i].ImageView?.Get(cbs).Value ?? default;
|
images[i].ImageView = _imageRefs[binding + i].View?.Get(cbs).Value ?? default;
|
||||||
}
|
}
|
||||||
|
|
||||||
tu.Push<DescriptorImageInfo>(images[..count]);
|
tu.Push<DescriptorImageInfo>(images[..count]);
|
||||||
@@ -974,7 +947,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
ref var texture = ref textures[i];
|
ref var texture = ref textures[i];
|
||||||
ref var refs = ref _textureRefs[binding + i];
|
ref var refs = ref _textureRefs[binding + i];
|
||||||
|
|
||||||
texture.ImageView = refs.ImageView?.Get(cbs).Value ?? default;
|
texture.ImageView = refs.View?.Get(cbs).Value ?? default;
|
||||||
texture.Sampler = refs.Sampler?.Get(cbs).Value ?? default;
|
texture.Sampler = refs.Sampler?.Get(cbs).Value ?? default;
|
||||||
|
|
||||||
if (texture.ImageView.Handle == 0)
|
if (texture.ImageView.Handle == 0)
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Vulkan
|
|
||||||
{
|
|
||||||
[Flags]
|
|
||||||
internal enum FeedbackLoopAspects
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
Color = 1 << 0,
|
|
||||||
Depth = 1 << 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -302,27 +302,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_depthStencil?.Storage?.AddStoreOpUsage(true);
|
_depthStencil?.Storage?.AddStoreOpUsage(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearBindings()
|
|
||||||
{
|
|
||||||
_depthStencil?.Storage.ClearBindings();
|
|
||||||
|
|
||||||
for (int i = 0; i < _colorsCanonical.Length; i++)
|
|
||||||
{
|
|
||||||
_colorsCanonical[i]?.Storage.ClearBindings();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddBindings()
|
|
||||||
{
|
|
||||||
_depthStencil?.Storage.AddBinding(_depthStencil);
|
|
||||||
|
|
||||||
for (int i = 0; i < _colorsCanonical.Length; i++)
|
|
||||||
{
|
|
||||||
TextureView color = _colorsCanonical[i];
|
|
||||||
color?.Storage.AddBinding(color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public (RenderPassHolder rpHolder, Auto<DisposableFramebuffer> framebuffer) GetPassAndFramebuffer(
|
public (RenderPassHolder rpHolder, Auto<DisposableFramebuffer> framebuffer) GetPassAndFramebuffer(
|
||||||
VulkanRenderer gd,
|
VulkanRenderer gd,
|
||||||
Device device,
|
Device device,
|
||||||
|
|||||||
@@ -46,8 +46,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
public readonly bool SupportsViewportArray2;
|
public readonly bool SupportsViewportArray2;
|
||||||
public readonly bool SupportsHostImportedMemory;
|
public readonly bool SupportsHostImportedMemory;
|
||||||
public readonly bool SupportsDepthClipControl;
|
public readonly bool SupportsDepthClipControl;
|
||||||
public readonly bool SupportsAttachmentFeedbackLoop;
|
|
||||||
public readonly bool SupportsDynamicAttachmentFeedbackLoop;
|
|
||||||
public readonly uint SubgroupSize;
|
public readonly uint SubgroupSize;
|
||||||
public readonly SampleCountFlags SupportedSampleCounts;
|
public readonly SampleCountFlags SupportedSampleCounts;
|
||||||
public readonly PortabilitySubsetFlags PortabilitySubset;
|
public readonly PortabilitySubsetFlags PortabilitySubset;
|
||||||
@@ -86,8 +84,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
bool supportsViewportArray2,
|
bool supportsViewportArray2,
|
||||||
bool supportsHostImportedMemory,
|
bool supportsHostImportedMemory,
|
||||||
bool supportsDepthClipControl,
|
bool supportsDepthClipControl,
|
||||||
bool supportsAttachmentFeedbackLoop,
|
|
||||||
bool supportsDynamicAttachmentFeedbackLoop,
|
|
||||||
uint subgroupSize,
|
uint subgroupSize,
|
||||||
SampleCountFlags supportedSampleCounts,
|
SampleCountFlags supportedSampleCounts,
|
||||||
PortabilitySubsetFlags portabilitySubset,
|
PortabilitySubsetFlags portabilitySubset,
|
||||||
@@ -125,8 +121,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
SupportsViewportArray2 = supportsViewportArray2;
|
SupportsViewportArray2 = supportsViewportArray2;
|
||||||
SupportsHostImportedMemory = supportsHostImportedMemory;
|
SupportsHostImportedMemory = supportsHostImportedMemory;
|
||||||
SupportsDepthClipControl = supportsDepthClipControl;
|
SupportsDepthClipControl = supportsDepthClipControl;
|
||||||
SupportsAttachmentFeedbackLoop = supportsAttachmentFeedbackLoop;
|
|
||||||
SupportsDynamicAttachmentFeedbackLoop = supportsDynamicAttachmentFeedbackLoop;
|
|
||||||
SubgroupSize = subgroupSize;
|
SubgroupSize = subgroupSize;
|
||||||
SupportedSampleCounts = supportedSampleCounts;
|
SupportedSampleCounts = supportedSampleCounts;
|
||||||
PortabilitySubset = portabilitySubset;
|
PortabilitySubset = portabilitySubset;
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ using Ryujinx.Graphics.GAL;
|
|||||||
using Ryujinx.Graphics.Shader;
|
using Ryujinx.Graphics.Shader;
|
||||||
using Silk.NET.Vulkan;
|
using Silk.NET.Vulkan;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
@@ -34,7 +33,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
public readonly Action EndRenderPassDelegate;
|
public readonly Action EndRenderPassDelegate;
|
||||||
|
|
||||||
protected PipelineDynamicState DynamicState;
|
protected PipelineDynamicState DynamicState;
|
||||||
protected bool IsMainPipeline;
|
|
||||||
private PipelineState _newState;
|
private PipelineState _newState;
|
||||||
private bool _graphicsStateDirty;
|
private bool _graphicsStateDirty;
|
||||||
private bool _computeStateDirty;
|
private bool _computeStateDirty;
|
||||||
@@ -87,9 +85,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
private bool _tfEnabled;
|
private bool _tfEnabled;
|
||||||
private bool _tfActive;
|
private bool _tfActive;
|
||||||
|
|
||||||
private FeedbackLoopAspects _feedbackLoop;
|
|
||||||
private bool _passWritesDepthStencil;
|
|
||||||
|
|
||||||
private readonly PipelineColorBlendAttachmentState[] _storedBlend;
|
private readonly PipelineColorBlendAttachmentState[] _storedBlend;
|
||||||
public ulong DrawCount { get; private set; }
|
public ulong DrawCount { get; private set; }
|
||||||
public bool RenderPassActive { get; private set; }
|
public bool RenderPassActive { get; private set; }
|
||||||
@@ -131,7 +126,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
_descriptorSetUpdater.Initialize(IsMainPipeline);
|
_descriptorSetUpdater.Initialize();
|
||||||
|
|
||||||
QuadsToTrisPattern = new IndexBufferPattern(Gd, 4, 6, 0, new[] { 0, 1, 2, 0, 2, 3 }, 4, false);
|
QuadsToTrisPattern = new IndexBufferPattern(Gd, 4, 6, 0, new[] { 0, 1, 2, 0, 2, 3 }, 4, false);
|
||||||
TriFanToTrisPattern = new IndexBufferPattern(Gd, 3, 3, 2, new[] { int.MinValue, -1, 0 }, 1, true);
|
TriFanToTrisPattern = new IndexBufferPattern(Gd, 3, 3, 2, new[] { int.MinValue, -1, 0 }, 1, true);
|
||||||
@@ -819,8 +814,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_newState.DepthTestEnable = depthTest.TestEnable;
|
_newState.DepthTestEnable = depthTest.TestEnable;
|
||||||
_newState.DepthWriteEnable = depthTest.WriteEnable;
|
_newState.DepthWriteEnable = depthTest.WriteEnable;
|
||||||
_newState.DepthCompareOp = depthTest.Func.Convert();
|
_newState.DepthCompareOp = depthTest.Func.Convert();
|
||||||
|
|
||||||
UpdatePassDepthStencil();
|
|
||||||
SignalStateChange();
|
SignalStateChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1086,8 +1079,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_newState.StencilFrontPassOp = stencilTest.FrontDpPass.Convert();
|
_newState.StencilFrontPassOp = stencilTest.FrontDpPass.Convert();
|
||||||
_newState.StencilFrontDepthFailOp = stencilTest.FrontDpFail.Convert();
|
_newState.StencilFrontDepthFailOp = stencilTest.FrontDpFail.Convert();
|
||||||
_newState.StencilFrontCompareOp = stencilTest.FrontFunc.Convert();
|
_newState.StencilFrontCompareOp = stencilTest.FrontFunc.Convert();
|
||||||
|
|
||||||
UpdatePassDepthStencil();
|
|
||||||
SignalStateChange();
|
SignalStateChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1435,23 +1426,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsMainPipeline)
|
|
||||||
{
|
|
||||||
FramebufferParams?.ClearBindings();
|
|
||||||
}
|
|
||||||
|
|
||||||
FramebufferParams = new FramebufferParams(Device, colors, depthStencil);
|
FramebufferParams = new FramebufferParams(Device, colors, depthStencil);
|
||||||
|
|
||||||
if (IsMainPipeline)
|
|
||||||
{
|
|
||||||
FramebufferParams.AddBindings();
|
|
||||||
|
|
||||||
_newState.FeedbackLoopAspects = FeedbackLoopAspects.None;
|
|
||||||
_bindingBarriersDirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
_passWritesDepthStencil = false;
|
|
||||||
UpdatePassDepthStencil();
|
|
||||||
UpdatePipelineAttachmentFormats();
|
UpdatePipelineAttachmentFormats();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1518,82 +1493,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Gd.Barriers.Flush(Cbs, _program, _feedbackLoop != 0, RenderPassActive, _rpHolder, EndRenderPassDelegate);
|
Gd.Barriers.Flush(Cbs, _program, RenderPassActive, _rpHolder, EndRenderPassDelegate);
|
||||||
|
|
||||||
_descriptorSetUpdater.UpdateAndBindDescriptorSets(Cbs, PipelineBindPoint.Compute);
|
_descriptorSetUpdater.UpdateAndBindDescriptorSets(Cbs, PipelineBindPoint.Compute);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ChangeFeedbackLoop(FeedbackLoopAspects aspects)
|
|
||||||
{
|
|
||||||
if (_feedbackLoop != aspects)
|
|
||||||
{
|
|
||||||
if (Gd.Capabilities.SupportsDynamicAttachmentFeedbackLoop)
|
|
||||||
{
|
|
||||||
DynamicState.SetFeedbackLoop(aspects);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_newState.FeedbackLoopAspects = aspects;
|
|
||||||
}
|
|
||||||
|
|
||||||
_feedbackLoop = aspects;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private bool UpdateFeedbackLoop()
|
|
||||||
{
|
|
||||||
List<TextureView> hazards = _descriptorSetUpdater.FeedbackLoopHazards;
|
|
||||||
|
|
||||||
if ((hazards?.Count ?? 0) > 0)
|
|
||||||
{
|
|
||||||
FeedbackLoopAspects aspects = 0;
|
|
||||||
|
|
||||||
foreach (TextureView view in hazards)
|
|
||||||
{
|
|
||||||
// May need to enforce feedback loop layout here in the future.
|
|
||||||
// Though technically, it should always work with the general layout.
|
|
||||||
|
|
||||||
if (view.Info.Format.IsDepthOrStencil())
|
|
||||||
{
|
|
||||||
if (_passWritesDepthStencil)
|
|
||||||
{
|
|
||||||
// If depth/stencil isn't written in the pass, it doesn't count as a feedback loop.
|
|
||||||
|
|
||||||
aspects |= FeedbackLoopAspects.Depth;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
aspects |= FeedbackLoopAspects.Color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ChangeFeedbackLoop(aspects);
|
|
||||||
}
|
|
||||||
else if (_feedbackLoop != 0)
|
|
||||||
{
|
|
||||||
return ChangeFeedbackLoop(FeedbackLoopAspects.None);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdatePassDepthStencil()
|
|
||||||
{
|
|
||||||
if (!RenderPassActive)
|
|
||||||
{
|
|
||||||
_passWritesDepthStencil = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stencil test being enabled doesn't necessarily mean a write, but it's not critical to check.
|
|
||||||
_passWritesDepthStencil |= (_newState.DepthTestEnable && _newState.DepthWriteEnable) || _newState.StencilTestEnable;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool RecreateGraphicsPipelineIfNeeded()
|
private bool RecreateGraphicsPipelineIfNeeded()
|
||||||
{
|
{
|
||||||
if (AutoFlush.ShouldFlushDraw(DrawCount))
|
if (AutoFlush.ShouldFlushDraw(DrawCount))
|
||||||
@@ -1601,7 +1505,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
Gd.FlushAllCommands();
|
Gd.FlushAllCommands();
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicState.ReplayIfDirty(Gd, CommandBuffer);
|
DynamicState.ReplayIfDirty(Gd.Api, CommandBuffer);
|
||||||
|
|
||||||
if (_needsIndexBufferRebind && _indexBufferPattern == null)
|
if (_needsIndexBufferRebind && _indexBufferPattern == null)
|
||||||
{
|
{
|
||||||
@@ -1635,15 +1539,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_vertexBufferUpdater.Commit(Cbs);
|
_vertexBufferUpdater.Commit(Cbs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_bindingBarriersDirty)
|
if (_graphicsStateDirty || Pbp != PipelineBindPoint.Graphics)
|
||||||
{
|
|
||||||
// Stale barriers may have been activated by switching program. Emit any that are relevant.
|
|
||||||
_descriptorSetUpdater.InsertBindingBarriers(Cbs);
|
|
||||||
|
|
||||||
_bindingBarriersDirty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UpdateFeedbackLoop() || _graphicsStateDirty || Pbp != PipelineBindPoint.Graphics)
|
|
||||||
{
|
{
|
||||||
if (!CreatePipeline(PipelineBindPoint.Graphics))
|
if (!CreatePipeline(PipelineBindPoint.Graphics))
|
||||||
{
|
{
|
||||||
@@ -1652,9 +1548,17 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
_graphicsStateDirty = false;
|
_graphicsStateDirty = false;
|
||||||
Pbp = PipelineBindPoint.Graphics;
|
Pbp = PipelineBindPoint.Graphics;
|
||||||
|
|
||||||
|
if (_bindingBarriersDirty)
|
||||||
|
{
|
||||||
|
// Stale barriers may have been activated by switching program. Emit any that are relevant.
|
||||||
|
_descriptorSetUpdater.InsertBindingBarriers(Cbs);
|
||||||
|
|
||||||
|
_bindingBarriersDirty = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Gd.Barriers.Flush(Cbs, _program, _feedbackLoop != 0, RenderPassActive, _rpHolder, EndRenderPassDelegate);
|
Gd.Barriers.Flush(Cbs, _program, RenderPassActive, _rpHolder, EndRenderPassDelegate);
|
||||||
|
|
||||||
_descriptorSetUpdater.UpdateAndBindDescriptorSets(Cbs, PipelineBindPoint.Graphics);
|
_descriptorSetUpdater.UpdateAndBindDescriptorSets(Cbs, PipelineBindPoint.Graphics);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
using Silk.NET.Vulkan;
|
using Silk.NET.Vulkan;
|
||||||
using Silk.NET.Vulkan.Extensions.EXT;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Vulkan
|
namespace Ryujinx.Graphics.Vulkan
|
||||||
{
|
{
|
||||||
@@ -22,8 +21,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
private Array4<float> _blendConstants;
|
private Array4<float> _blendConstants;
|
||||||
|
|
||||||
private FeedbackLoopAspects _feedbackLoopAspects;
|
|
||||||
|
|
||||||
public uint ViewportsCount;
|
public uint ViewportsCount;
|
||||||
public Array16<Viewport> Viewports;
|
public Array16<Viewport> Viewports;
|
||||||
|
|
||||||
@@ -35,8 +32,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
Scissor = 1 << 2,
|
Scissor = 1 << 2,
|
||||||
Stencil = 1 << 3,
|
Stencil = 1 << 3,
|
||||||
Viewport = 1 << 4,
|
Viewport = 1 << 4,
|
||||||
FeedbackLoop = 1 << 5,
|
All = Blend | DepthBias | Scissor | Stencil | Viewport,
|
||||||
All = Blend | DepthBias | Scissor | Stencil | Viewport | FeedbackLoop,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private DirtyFlags _dirty;
|
private DirtyFlags _dirty;
|
||||||
@@ -103,22 +99,13 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetFeedbackLoop(FeedbackLoopAspects aspects)
|
|
||||||
{
|
|
||||||
_feedbackLoopAspects = aspects;
|
|
||||||
|
|
||||||
_dirty |= DirtyFlags.FeedbackLoop;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ForceAllDirty()
|
public void ForceAllDirty()
|
||||||
{
|
{
|
||||||
_dirty = DirtyFlags.All;
|
_dirty = DirtyFlags.All;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReplayIfDirty(VulkanRenderer gd, CommandBuffer commandBuffer)
|
public void ReplayIfDirty(Vk api, CommandBuffer commandBuffer)
|
||||||
{
|
{
|
||||||
Vk api = gd.Api;
|
|
||||||
|
|
||||||
if (_dirty.HasFlag(DirtyFlags.Blend))
|
if (_dirty.HasFlag(DirtyFlags.Blend))
|
||||||
{
|
{
|
||||||
RecordBlend(api, commandBuffer);
|
RecordBlend(api, commandBuffer);
|
||||||
@@ -144,11 +131,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
RecordViewport(api, commandBuffer);
|
RecordViewport(api, commandBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_dirty.HasFlag(DirtyFlags.FeedbackLoop) && gd.Capabilities.SupportsDynamicAttachmentFeedbackLoop)
|
|
||||||
{
|
|
||||||
RecordFeedbackLoop(gd.DynamicFeedbackLoopApi, commandBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
_dirty = DirtyFlags.None;
|
_dirty = DirtyFlags.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,17 +169,5 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
api.CmdSetViewport(commandBuffer, 0, ViewportsCount, Viewports.AsSpan());
|
api.CmdSetViewport(commandBuffer, 0, ViewportsCount, Viewports.AsSpan());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly void RecordFeedbackLoop(ExtAttachmentFeedbackLoopDynamicState api, CommandBuffer commandBuffer)
|
|
||||||
{
|
|
||||||
ImageAspectFlags aspects = (_feedbackLoopAspects & FeedbackLoopAspects.Color) != 0 ? ImageAspectFlags.ColorBit : 0;
|
|
||||||
|
|
||||||
if ((_feedbackLoopAspects & FeedbackLoopAspects.Depth) != 0)
|
|
||||||
{
|
|
||||||
aspects |= ImageAspectFlags.DepthBit | ImageAspectFlags.StencilBit;
|
|
||||||
}
|
|
||||||
|
|
||||||
api.CmdSetAttachmentFeedbackLoopEnable(commandBuffer, aspects);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_activeBufferMirrors = new();
|
_activeBufferMirrors = new();
|
||||||
|
|
||||||
CommandBuffer = (Cbs = gd.CommandBufferPool.Rent()).CommandBuffer;
|
CommandBuffer = (Cbs = gd.CommandBufferPool.Rent()).CommandBuffer;
|
||||||
|
|
||||||
IsMainPipeline = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CopyPendingQuery()
|
private void CopyPendingQuery()
|
||||||
@@ -237,7 +235,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
if (Pipeline != null && Pbp == PipelineBindPoint.Graphics)
|
if (Pipeline != null && Pbp == PipelineBindPoint.Graphics)
|
||||||
{
|
{
|
||||||
DynamicState.ReplayIfDirty(Gd, CommandBuffer);
|
DynamicState.ReplayIfDirty(Gd.Api, CommandBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
struct PipelineState : IDisposable
|
struct PipelineState : IDisposable
|
||||||
{
|
{
|
||||||
private const int RequiredSubgroupSize = 32;
|
private const int RequiredSubgroupSize = 32;
|
||||||
private const int MaxDynamicStatesCount = 9;
|
|
||||||
|
|
||||||
public PipelineUid Internal;
|
public PipelineUid Internal;
|
||||||
|
|
||||||
@@ -300,12 +299,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFBF) | ((value ? 1UL : 0UL) << 6);
|
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFBF) | ((value ? 1UL : 0UL) << 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FeedbackLoopAspects FeedbackLoopAspects
|
|
||||||
{
|
|
||||||
readonly get => (FeedbackLoopAspects)((Internal.Id8 >> 7) & 0x3);
|
|
||||||
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFE7F) | (((ulong)value) << 7);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool HasTessellationControlShader;
|
public bool HasTessellationControlShader;
|
||||||
public NativeArray<PipelineShaderStageCreateInfo> Stages;
|
public NativeArray<PipelineShaderStageCreateInfo> Stages;
|
||||||
public PipelineLayout PipelineLayout;
|
public PipelineLayout PipelineLayout;
|
||||||
@@ -571,11 +564,9 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState;
|
bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState;
|
||||||
bool supportsFeedbackLoopDynamicState = gd.Capabilities.SupportsDynamicAttachmentFeedbackLoop;
|
int dynamicStatesCount = supportsExtDynamicState ? 8 : 7;
|
||||||
|
|
||||||
DynamicState* dynamicStates = stackalloc DynamicState[MaxDynamicStatesCount];
|
DynamicState* dynamicStates = stackalloc DynamicState[dynamicStatesCount];
|
||||||
|
|
||||||
int dynamicStatesCount = 7;
|
|
||||||
|
|
||||||
dynamicStates[0] = DynamicState.Viewport;
|
dynamicStates[0] = DynamicState.Viewport;
|
||||||
dynamicStates[1] = DynamicState.Scissor;
|
dynamicStates[1] = DynamicState.Scissor;
|
||||||
@@ -587,12 +578,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
if (supportsExtDynamicState)
|
if (supportsExtDynamicState)
|
||||||
{
|
{
|
||||||
dynamicStates[dynamicStatesCount++] = DynamicState.VertexInputBindingStrideExt;
|
dynamicStates[7] = DynamicState.VertexInputBindingStrideExt;
|
||||||
}
|
|
||||||
|
|
||||||
if (supportsFeedbackLoopDynamicState)
|
|
||||||
{
|
|
||||||
dynamicStates[dynamicStatesCount++] = DynamicState.AttachmentFeedbackLoopEnableExt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo
|
var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo
|
||||||
@@ -602,27 +588,9 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
PDynamicStates = dynamicStates,
|
PDynamicStates = dynamicStates,
|
||||||
};
|
};
|
||||||
|
|
||||||
PipelineCreateFlags flags = 0;
|
|
||||||
|
|
||||||
if (gd.Capabilities.SupportsAttachmentFeedbackLoop)
|
|
||||||
{
|
|
||||||
FeedbackLoopAspects aspects = FeedbackLoopAspects;
|
|
||||||
|
|
||||||
if ((aspects & FeedbackLoopAspects.Color) != 0)
|
|
||||||
{
|
|
||||||
flags |= PipelineCreateFlags.CreateColorAttachmentFeedbackLoopBitExt;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((aspects & FeedbackLoopAspects.Depth) != 0)
|
|
||||||
{
|
|
||||||
flags |= PipelineCreateFlags.CreateDepthStencilAttachmentFeedbackLoopBitExt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var pipelineCreateInfo = new GraphicsPipelineCreateInfo
|
var pipelineCreateInfo = new GraphicsPipelineCreateInfo
|
||||||
{
|
{
|
||||||
SType = StructureType.GraphicsPipelineCreateInfo,
|
SType = StructureType.GraphicsPipelineCreateInfo,
|
||||||
Flags = flags,
|
|
||||||
StageCount = StagesCount,
|
StageCount = StagesCount,
|
||||||
PStages = Stages.Pointer,
|
PStages = Stages.Pointer,
|
||||||
PVertexInputState = &vertexInputState,
|
PVertexInputState = &vertexInputState,
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using Silk.NET.Vulkan;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using Format = Ryujinx.Graphics.GAL.Format;
|
using Format = Ryujinx.Graphics.GAL.Format;
|
||||||
using VkBuffer = Silk.NET.Vulkan.Buffer;
|
using VkBuffer = Silk.NET.Vulkan.Buffer;
|
||||||
using VkFormat = Silk.NET.Vulkan.Format;
|
using VkFormat = Silk.NET.Vulkan.Format;
|
||||||
@@ -13,11 +12,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
class TextureStorage : IDisposable
|
class TextureStorage : IDisposable
|
||||||
{
|
{
|
||||||
private struct TextureSliceInfo
|
|
||||||
{
|
|
||||||
public int BindCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
private const MemoryPropertyFlags DefaultImageMemoryFlags =
|
private const MemoryPropertyFlags DefaultImageMemoryFlags =
|
||||||
MemoryPropertyFlags.DeviceLocalBit;
|
MemoryPropertyFlags.DeviceLocalBit;
|
||||||
|
|
||||||
@@ -49,7 +43,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
private readonly Image _image;
|
private readonly Image _image;
|
||||||
private readonly Auto<DisposableImage> _imageAuto;
|
private readonly Auto<DisposableImage> _imageAuto;
|
||||||
private readonly Auto<MemoryAllocation> _allocationAuto;
|
private readonly Auto<MemoryAllocation> _allocationAuto;
|
||||||
private readonly int _depthOrLayers;
|
|
||||||
private Auto<MemoryAllocation> _foreignAllocationAuto;
|
private Auto<MemoryAllocation> _foreignAllocationAuto;
|
||||||
|
|
||||||
private Dictionary<Format, TextureStorage> _aliasedStorages;
|
private Dictionary<Format, TextureStorage> _aliasedStorages;
|
||||||
@@ -62,9 +55,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
private int _viewsCount;
|
private int _viewsCount;
|
||||||
private readonly ulong _size;
|
private readonly ulong _size;
|
||||||
|
|
||||||
private int _bindCount;
|
|
||||||
private readonly TextureSliceInfo[] _slices;
|
|
||||||
|
|
||||||
public VkFormat VkFormat { get; }
|
public VkFormat VkFormat { get; }
|
||||||
|
|
||||||
public unsafe TextureStorage(
|
public unsafe TextureStorage(
|
||||||
@@ -85,7 +75,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
var depth = (uint)(info.Target == Target.Texture3D ? info.Depth : 1);
|
var depth = (uint)(info.Target == Target.Texture3D ? info.Depth : 1);
|
||||||
|
|
||||||
VkFormat = format;
|
VkFormat = format;
|
||||||
_depthOrLayers = info.GetDepthOrLayers();
|
|
||||||
|
|
||||||
var type = info.Target.Convert();
|
var type = info.Target.Convert();
|
||||||
|
|
||||||
@@ -161,8 +150,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
InitialTransition(ImageLayout.Preinitialized, ImageLayout.General);
|
InitialTransition(ImageLayout.Preinitialized, ImageLayout.General);
|
||||||
}
|
}
|
||||||
|
|
||||||
_slices = new TextureSliceInfo[levels * _depthOrLayers];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextureStorage CreateAliasedColorForDepthStorageUnsafe(Format format)
|
public TextureStorage CreateAliasedColorForDepthStorageUnsafe(Format format)
|
||||||
@@ -325,12 +312,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
usage |= ImageUsageFlags.StorageBit;
|
usage |= ImageUsageFlags.StorageBit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (capabilities.SupportsAttachmentFeedbackLoop &&
|
|
||||||
(usage & (ImageUsageFlags.DepthStencilAttachmentBit | ImageUsageFlags.ColorAttachmentBit)) != 0)
|
|
||||||
{
|
|
||||||
usage |= ImageUsageFlags.AttachmentFeedbackLoopBitExt;
|
|
||||||
}
|
|
||||||
|
|
||||||
return usage;
|
return usage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -531,55 +512,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddBinding(TextureView view)
|
|
||||||
{
|
|
||||||
// Assumes a view only has a first level.
|
|
||||||
|
|
||||||
int index = view.FirstLevel * _depthOrLayers + view.FirstLayer;
|
|
||||||
int layers = view.Layers;
|
|
||||||
|
|
||||||
for (int i = 0; i < layers; i++)
|
|
||||||
{
|
|
||||||
ref TextureSliceInfo info = ref _slices[index++];
|
|
||||||
|
|
||||||
info.BindCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
_bindCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ClearBindings()
|
|
||||||
{
|
|
||||||
if (_bindCount != 0)
|
|
||||||
{
|
|
||||||
Array.Clear(_slices, 0, _slices.Length);
|
|
||||||
|
|
||||||
_bindCount = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public bool IsBound(TextureView view)
|
|
||||||
{
|
|
||||||
if (_bindCount != 0)
|
|
||||||
{
|
|
||||||
int index = view.FirstLevel * _depthOrLayers + view.FirstLayer;
|
|
||||||
int layers = view.Layers;
|
|
||||||
|
|
||||||
for (int i = 0; i < layers; i++)
|
|
||||||
{
|
|
||||||
ref TextureSliceInfo info = ref _slices[index++];
|
|
||||||
|
|
||||||
if (info.BindCount != 0)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void IncrementViewsCount()
|
public void IncrementViewsCount()
|
||||||
{
|
{
|
||||||
_viewsCount++;
|
_viewsCount++;
|
||||||
|
|||||||
@@ -23,8 +23,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
private readonly Auto<DisposableImageView> _imageView2dArray;
|
private readonly Auto<DisposableImageView> _imageView2dArray;
|
||||||
private Dictionary<Format, TextureView> _selfManagedViews;
|
private Dictionary<Format, TextureView> _selfManagedViews;
|
||||||
|
|
||||||
private int _hazardUses;
|
|
||||||
|
|
||||||
private readonly TextureCreateInfo _info;
|
private readonly TextureCreateInfo _info;
|
||||||
|
|
||||||
private HashTableSlim<RenderPassCacheKey, RenderPassHolder> _renderPasses;
|
private HashTableSlim<RenderPassCacheKey, RenderPassHolder> _renderPasses;
|
||||||
@@ -1039,34 +1037,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PrepareForUsage(CommandBufferScoped cbs, PipelineStageFlags flags, List<TextureView> feedbackLoopHazards)
|
|
||||||
{
|
|
||||||
Storage.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, flags);
|
|
||||||
|
|
||||||
if (feedbackLoopHazards != null && Storage.IsBound(this))
|
|
||||||
{
|
|
||||||
feedbackLoopHazards.Add(this);
|
|
||||||
_hazardUses++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ClearUsage(List<TextureView> feedbackLoopHazards)
|
|
||||||
{
|
|
||||||
if (_hazardUses != 0 && feedbackLoopHazards != null)
|
|
||||||
{
|
|
||||||
feedbackLoopHazards.Remove(this);
|
|
||||||
_hazardUses--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DecrementHazardUses()
|
|
||||||
{
|
|
||||||
if (_hazardUses != 0)
|
|
||||||
{
|
|
||||||
_hazardUses--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public (RenderPassHolder rpHolder, Auto<DisposableFramebuffer> framebuffer) GetPassAndFramebuffer(
|
public (RenderPassHolder rpHolder, Auto<DisposableFramebuffer> framebuffer) GetPassAndFramebuffer(
|
||||||
VulkanRenderer gd,
|
VulkanRenderer gd,
|
||||||
Device device,
|
Device device,
|
||||||
|
|||||||
@@ -44,8 +44,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
"VK_EXT_4444_formats",
|
"VK_EXT_4444_formats",
|
||||||
"VK_KHR_8bit_storage",
|
"VK_KHR_8bit_storage",
|
||||||
"VK_KHR_maintenance2",
|
"VK_KHR_maintenance2",
|
||||||
"VK_EXT_attachment_feedback_loop_layout",
|
|
||||||
"VK_EXT_attachment_feedback_loop_dynamic_state",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly string[] _requiredExtensions = {
|
private static readonly string[] _requiredExtensions = {
|
||||||
@@ -359,28 +357,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
features2.PNext = &supportedFeaturesDepthClipControl;
|
features2.PNext = &supportedFeaturesDepthClipControl;
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT supportedFeaturesAttachmentFeedbackLoopLayout = new()
|
|
||||||
{
|
|
||||||
SType = StructureType.PhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesExt,
|
|
||||||
PNext = features2.PNext,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (physicalDevice.IsDeviceExtensionPresent("VK_EXT_attachment_feedback_loop_layout"))
|
|
||||||
{
|
|
||||||
features2.PNext = &supportedFeaturesAttachmentFeedbackLoopLayout;
|
|
||||||
}
|
|
||||||
|
|
||||||
PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT supportedFeaturesDynamicAttachmentFeedbackLoopLayout = new()
|
|
||||||
{
|
|
||||||
SType = StructureType.PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesExt,
|
|
||||||
PNext = features2.PNext,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (physicalDevice.IsDeviceExtensionPresent("VK_EXT_attachment_feedback_loop_dynamic_state"))
|
|
||||||
{
|
|
||||||
features2.PNext = &supportedFeaturesDynamicAttachmentFeedbackLoopLayout;
|
|
||||||
}
|
|
||||||
|
|
||||||
PhysicalDeviceVulkan12Features supportedPhysicalDeviceVulkan12Features = new()
|
PhysicalDeviceVulkan12Features supportedPhysicalDeviceVulkan12Features = new()
|
||||||
{
|
{
|
||||||
SType = StructureType.PhysicalDeviceVulkan12Features,
|
SType = StructureType.PhysicalDeviceVulkan12Features,
|
||||||
@@ -555,36 +531,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
pExtendedFeatures = &featuresDepthClipControl;
|
pExtendedFeatures = &featuresDepthClipControl;
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT featuresAttachmentFeedbackLoopLayout;
|
|
||||||
|
|
||||||
if (physicalDevice.IsDeviceExtensionPresent("VK_EXT_attachment_feedback_loop_layout") &&
|
|
||||||
supportedFeaturesAttachmentFeedbackLoopLayout.AttachmentFeedbackLoopLayout)
|
|
||||||
{
|
|
||||||
featuresAttachmentFeedbackLoopLayout = new()
|
|
||||||
{
|
|
||||||
SType = StructureType.PhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesExt,
|
|
||||||
PNext = pExtendedFeatures,
|
|
||||||
AttachmentFeedbackLoopLayout = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
pExtendedFeatures = &featuresAttachmentFeedbackLoopLayout;
|
|
||||||
}
|
|
||||||
|
|
||||||
PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT featuresDynamicAttachmentFeedbackLoopLayout;
|
|
||||||
|
|
||||||
if (physicalDevice.IsDeviceExtensionPresent("VK_EXT_attachment_feedback_loop_dynamic_state") &&
|
|
||||||
supportedFeaturesDynamicAttachmentFeedbackLoopLayout.AttachmentFeedbackLoopDynamicState)
|
|
||||||
{
|
|
||||||
featuresDynamicAttachmentFeedbackLoopLayout = new()
|
|
||||||
{
|
|
||||||
SType = StructureType.PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesExt,
|
|
||||||
PNext = pExtendedFeatures,
|
|
||||||
AttachmentFeedbackLoopDynamicState = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
pExtendedFeatures = &featuresDynamicAttachmentFeedbackLoopLayout;
|
|
||||||
}
|
|
||||||
|
|
||||||
var enabledExtensions = _requiredExtensions.Union(_desirableExtensions.Intersect(physicalDevice.DeviceExtensions)).ToArray();
|
var enabledExtensions = _requiredExtensions.Union(_desirableExtensions.Intersect(physicalDevice.DeviceExtensions)).ToArray();
|
||||||
|
|
||||||
nint* ppEnabledExtensions = stackalloc nint[enabledExtensions.Length];
|
nint* ppEnabledExtensions = stackalloc nint[enabledExtensions.Length];
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
internal KhrPushDescriptor PushDescriptorApi { get; private set; }
|
internal KhrPushDescriptor PushDescriptorApi { get; private set; }
|
||||||
internal ExtTransformFeedback TransformFeedbackApi { get; private set; }
|
internal ExtTransformFeedback TransformFeedbackApi { get; private set; }
|
||||||
internal KhrDrawIndirectCount DrawIndirectCountApi { get; private set; }
|
internal KhrDrawIndirectCount DrawIndirectCountApi { get; private set; }
|
||||||
internal ExtAttachmentFeedbackLoopDynamicState DynamicFeedbackLoopApi { get; private set; }
|
|
||||||
|
|
||||||
internal uint QueueFamilyIndex { get; private set; }
|
internal uint QueueFamilyIndex { get; private set; }
|
||||||
internal Queue Queue { get; private set; }
|
internal Queue Queue { get; private set; }
|
||||||
@@ -156,11 +155,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
DrawIndirectCountApi = drawIndirectCountApi;
|
DrawIndirectCountApi = drawIndirectCountApi;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Api.TryGetDeviceExtension(_instance.Instance, _device, out ExtAttachmentFeedbackLoopDynamicState dynamicFeedbackLoopApi))
|
|
||||||
{
|
|
||||||
DynamicFeedbackLoopApi = dynamicFeedbackLoopApi;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (maxQueueCount >= 2)
|
if (maxQueueCount >= 2)
|
||||||
{
|
{
|
||||||
Api.GetDeviceQueue(_device, queueFamilyIndex, 1, out var backgroundQueue);
|
Api.GetDeviceQueue(_device, queueFamilyIndex, 1, out var backgroundQueue);
|
||||||
@@ -255,16 +249,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
SType = StructureType.PhysicalDeviceDepthClipControlFeaturesExt,
|
SType = StructureType.PhysicalDeviceDepthClipControlFeaturesExt,
|
||||||
};
|
};
|
||||||
|
|
||||||
PhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT featuresAttachmentFeedbackLoop = new()
|
|
||||||
{
|
|
||||||
SType = StructureType.PhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesExt,
|
|
||||||
};
|
|
||||||
|
|
||||||
PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT featuresDynamicAttachmentFeedbackLoop = new()
|
|
||||||
{
|
|
||||||
SType = StructureType.PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesExt,
|
|
||||||
};
|
|
||||||
|
|
||||||
PhysicalDevicePortabilitySubsetFeaturesKHR featuresPortabilitySubset = new()
|
PhysicalDevicePortabilitySubsetFeaturesKHR featuresPortabilitySubset = new()
|
||||||
{
|
{
|
||||||
SType = StructureType.PhysicalDevicePortabilitySubsetFeaturesKhr,
|
SType = StructureType.PhysicalDevicePortabilitySubsetFeaturesKhr,
|
||||||
@@ -301,22 +285,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
features2.PNext = &featuresDepthClipControl;
|
features2.PNext = &featuresDepthClipControl;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool supportsAttachmentFeedbackLoop = _physicalDevice.IsDeviceExtensionPresent("VK_EXT_attachment_feedback_loop_layout");
|
|
||||||
|
|
||||||
if (supportsAttachmentFeedbackLoop)
|
|
||||||
{
|
|
||||||
featuresAttachmentFeedbackLoop.PNext = features2.PNext;
|
|
||||||
features2.PNext = &featuresAttachmentFeedbackLoop;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool supportsDynamicAttachmentFeedbackLoop = _physicalDevice.IsDeviceExtensionPresent("VK_EXT_attachment_feedback_loop_dynamic_state");
|
|
||||||
|
|
||||||
if (supportsDynamicAttachmentFeedbackLoop)
|
|
||||||
{
|
|
||||||
featuresDynamicAttachmentFeedbackLoop.PNext = features2.PNext;
|
|
||||||
features2.PNext = &featuresDynamicAttachmentFeedbackLoop;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool usePortability = _physicalDevice.IsDeviceExtensionPresent("VK_KHR_portability_subset");
|
bool usePortability = _physicalDevice.IsDeviceExtensionPresent("VK_KHR_portability_subset");
|
||||||
|
|
||||||
if (usePortability)
|
if (usePortability)
|
||||||
@@ -439,8 +407,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_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,
|
||||||
supportsAttachmentFeedbackLoop && featuresAttachmentFeedbackLoop.AttachmentFeedbackLoopLayout,
|
|
||||||
supportsDynamicAttachmentFeedbackLoop && featuresDynamicAttachmentFeedbackLoop.AttachmentFeedbackLoopDynamicState,
|
|
||||||
propertiesSubgroup.SubgroupSize,
|
propertiesSubgroup.SubgroupSize,
|
||||||
supportedSampleCounts,
|
supportedSampleCounts,
|
||||||
portabilityFlags,
|
portabilityFlags,
|
||||||
|
|||||||
@@ -710,9 +710,8 @@ namespace Ryujinx.HLE.FileSystem
|
|||||||
{
|
{
|
||||||
updateNcasItem.Add((nca.Header.ContentType, entry.FullName));
|
updateNcasItem.Add((nca.Header.ContentType, entry.FullName));
|
||||||
}
|
}
|
||||||
else
|
else if (updateNcas.TryAdd(nca.Header.TitleId, new List<(NcaContentType, string)>()))
|
||||||
{
|
{
|
||||||
updateNcas.Add(nca.Header.TitleId, new List<(NcaContentType, string)>());
|
|
||||||
updateNcas[nca.Header.TitleId].Add((nca.Header.ContentType, entry.FullName));
|
updateNcas[nca.Header.TitleId].Add((nca.Header.ContentType, entry.FullName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -898,9 +897,8 @@ namespace Ryujinx.HLE.FileSystem
|
|||||||
{
|
{
|
||||||
updateNcasItem.Add((nca.Header.ContentType, entry.FullPath));
|
updateNcasItem.Add((nca.Header.ContentType, entry.FullPath));
|
||||||
}
|
}
|
||||||
else
|
else if (updateNcas.TryAdd(nca.Header.TitleId, new List<(NcaContentType, string)>()))
|
||||||
{
|
{
|
||||||
updateNcas.Add(nca.Header.TitleId, new List<(NcaContentType, string)>());
|
|
||||||
updateNcas[nca.Header.TitleId].Add((nca.Header.ContentType, entry.FullPath));
|
updateNcas[nca.Header.TitleId].Add((nca.Header.ContentType, entry.FullPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
|
using SDL2;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
@@ -118,6 +119,11 @@ namespace Ryujinx.Input.SDL2
|
|||||||
result |= GamepadFeaturesFlag.Rumble;
|
result |= GamepadFeaturesFlag.Rumble;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (SDL_GameControllerHasLED(_gamepadHandle) == SDL_bool.SDL_TRUE)
|
||||||
|
{
|
||||||
|
result |= GamepadFeaturesFlag.Led;
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,5 +24,10 @@ namespace Ryujinx.Input
|
|||||||
/// <remarks>Also named sixaxis</remarks>
|
/// <remarks>Also named sixaxis</remarks>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Motion,
|
Motion,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The LED on the back of modern PlayStation controllers (DualSense & DualShock 4).
|
||||||
|
/// </summary>
|
||||||
|
Led,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7622,6 +7622,31 @@
|
|||||||
"zh_TW": "陀螺儀無感帶:"
|
"zh_TW": "陀螺儀無感帶:"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ID": "ControllerSettingsLedColor",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "",
|
||||||
|
"de_DE": "",
|
||||||
|
"el_GR": "",
|
||||||
|
"en_US": "Custom LED",
|
||||||
|
"es_ES": "",
|
||||||
|
"fr_FR": "",
|
||||||
|
"he_IL": "",
|
||||||
|
"it_IT": "",
|
||||||
|
"ja_JP": "",
|
||||||
|
"ko_KR": "",
|
||||||
|
"no_NO": "",
|
||||||
|
"pl_PL": "",
|
||||||
|
"pt_BR": "",
|
||||||
|
"ru_RU": "",
|
||||||
|
"sv_SE": "",
|
||||||
|
"th_TH": "",
|
||||||
|
"tr_TR": "",
|
||||||
|
"uk_UA": "",
|
||||||
|
"zh_CN": "",
|
||||||
|
"zh_TW": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ID": "ControllerSettingsSave",
|
"ID": "ControllerSettingsSave",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
@@ -22973,4 +22998,4 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ using Ryujinx.Ava.Utilities.Configuration;
|
|||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
using Ryujinx.Common.GraphicsDriver;
|
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.Logging.Targets;
|
using Ryujinx.Common.Logging.Targets;
|
||||||
using Ryujinx.Common.SystemInterop;
|
using Ryujinx.Common.SystemInterop;
|
||||||
@@ -285,8 +284,6 @@ namespace Ryujinx.Headless
|
|||||||
GraphicsConfig.ShadersDumpPath = option.GraphicsShadersDumpPath;
|
GraphicsConfig.ShadersDumpPath = option.GraphicsShadersDumpPath;
|
||||||
GraphicsConfig.EnableMacroHLE = !option.DisableMacroHLE;
|
GraphicsConfig.EnableMacroHLE = !option.DisableMacroHLE;
|
||||||
|
|
||||||
DriverUtilities.InitDriverConfig(option.BackendThreading == BackendThreading.Off);
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
LoadApplication(option);
|
LoadApplication(option);
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ namespace Ryujinx.Headless
|
|||||||
IgnoreMissingServices = configurationState.System.IgnoreMissingServices;
|
IgnoreMissingServices = configurationState.System.IgnoreMissingServices;
|
||||||
|
|
||||||
if (NeedsOverride(nameof(IgnoreControllerApplet)))
|
if (NeedsOverride(nameof(IgnoreControllerApplet)))
|
||||||
IgnoreControllerApplet = configurationState.IgnoreApplet;
|
IgnoreControllerApplet = configurationState.System.IgnoreApplet;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -136,8 +136,8 @@ namespace Ryujinx.Ava
|
|||||||
// Logging system information.
|
// Logging system information.
|
||||||
PrintSystemInfo();
|
PrintSystemInfo();
|
||||||
|
|
||||||
// Enable OGL multithreading on the driver, and some other flags.
|
// Enable OGL multithreading on the driver, when available.
|
||||||
DriverUtilities.InitDriverConfig(ConfigurationState.Instance.Graphics.BackendThreading == BackendThreading.Off);
|
DriverUtilities.ToggleOGLThreading(ConfigurationState.Instance.Graphics.BackendThreading == BackendThreading.Off);
|
||||||
|
|
||||||
// Check if keys exists.
|
// Check if keys exists.
|
||||||
if (!File.Exists(Path.Combine(AppDataManager.KeysDirPath, "prod.keys")))
|
if (!File.Exists(Path.Combine(AppDataManager.KeysDirPath, "prod.keys")))
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ using Ryujinx.Ava.Common.Locale;
|
|||||||
using Ryujinx.Ava.UI.Controls;
|
using Ryujinx.Ava.UI.Controls;
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
using Ryujinx.Ava.UI.ViewModels.Input;
|
|
||||||
using Ryujinx.Ava.UI.Windows;
|
using Ryujinx.Ava.UI.Windows;
|
||||||
using Ryujinx.Ava.Utilities.Configuration;
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
@@ -42,7 +41,7 @@ namespace Ryujinx.Ava.UI.Applet
|
|||||||
|
|
||||||
bool okPressed = false;
|
bool okPressed = false;
|
||||||
|
|
||||||
if (ConfigurationState.Instance.IgnoreApplet)
|
if (ConfigurationState.Instance.System.IgnoreApplet)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Dispatcher.UIThread.InvokeAsync(async () =>
|
Dispatcher.UIThread.InvokeAsync(async () =>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Avalonia.Media;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||||
@@ -387,6 +388,30 @@ namespace Ryujinx.Ava.UI.Models.Input
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool _enableLedChanging;
|
||||||
|
|
||||||
|
public bool EnableLedChanging
|
||||||
|
{
|
||||||
|
get => _enableLedChanging;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_enableLedChanging = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color _ledColor;
|
||||||
|
|
||||||
|
public Color LedColor
|
||||||
|
{
|
||||||
|
get => _ledColor;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_ledColor = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private bool _enableMotion;
|
private bool _enableMotion;
|
||||||
public bool EnableMotion
|
public bool EnableMotion
|
||||||
{
|
{
|
||||||
@@ -483,12 +508,23 @@ namespace Ryujinx.Ava.UI.Models.Input
|
|||||||
WeakRumble = controllerInput.Rumble.WeakRumble;
|
WeakRumble = controllerInput.Rumble.WeakRumble;
|
||||||
StrongRumble = controllerInput.Rumble.StrongRumble;
|
StrongRumble = controllerInput.Rumble.StrongRumble;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (controllerInput.Led != null)
|
||||||
|
{
|
||||||
|
EnableLedChanging = controllerInput.Led.EnableLed;
|
||||||
|
uint rawColor = controllerInput.Led.LedColor;
|
||||||
|
byte alpha = (byte)(rawColor >> 24);
|
||||||
|
byte red = (byte)(rawColor >> 16);
|
||||||
|
byte green = (byte)(rawColor >> 8);
|
||||||
|
byte blue = (byte)(rawColor % 256);
|
||||||
|
LedColor = new Color(alpha, red, green, blue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputConfig GetConfig()
|
public InputConfig GetConfig()
|
||||||
{
|
{
|
||||||
var config = new StandardControllerInputConfig
|
StandardControllerInputConfig config = new()
|
||||||
{
|
{
|
||||||
Id = Id,
|
Id = Id,
|
||||||
Backend = InputBackendType.GamepadSDL2,
|
Backend = InputBackendType.GamepadSDL2,
|
||||||
@@ -540,6 +576,11 @@ namespace Ryujinx.Ava.UI.Models.Input
|
|||||||
WeakRumble = WeakRumble,
|
WeakRumble = WeakRumble,
|
||||||
StrongRumble = StrongRumble,
|
StrongRumble = StrongRumble,
|
||||||
},
|
},
|
||||||
|
Led = new LedConfigController
|
||||||
|
{
|
||||||
|
EnableLed = EnableLedChanging,
|
||||||
|
LedColor = LedColor.ToUInt32()
|
||||||
|
},
|
||||||
Version = InputConfig.CurrentVersion,
|
Version = InputConfig.CurrentVersion,
|
||||||
DeadzoneLeft = DeadzoneLeft,
|
DeadzoneLeft = DeadzoneLeft,
|
||||||
DeadzoneRight = DeadzoneRight,
|
DeadzoneRight = DeadzoneRight,
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
|
|
||||||
[ObservableProperty] private SvgImage _image;
|
[ObservableProperty] private SvgImage _image;
|
||||||
|
|
||||||
public readonly InputViewModel ParentModel;
|
public InputViewModel ParentModel { get; }
|
||||||
|
|
||||||
public ControllerInputViewModel(InputViewModel model, GamepadInputConfig config)
|
public ControllerInputViewModel(InputViewModel model, GamepadInputConfig config)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -69,6 +69,9 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
public bool IsRight { get; set; }
|
public bool IsRight { get; set; }
|
||||||
public bool IsLeft { get; set; }
|
public bool IsLeft { get; set; }
|
||||||
|
|
||||||
|
public bool HasLed => false; //temporary
|
||||||
|
//SelectedGamepad.Features.HasFlag(GamepadFeaturesFlag.Led);
|
||||||
|
|
||||||
public bool IsModified { get; set; }
|
public bool IsModified { get; set; }
|
||||||
public event Action NotifyChangesEvent;
|
public event Action NotifyChangesEvent;
|
||||||
|
|
||||||
|
|||||||
@@ -488,7 +488,6 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
EnableDiscordIntegration = config.EnableDiscordIntegration;
|
EnableDiscordIntegration = config.EnableDiscordIntegration;
|
||||||
CheckUpdatesOnStart = config.CheckUpdatesOnStart;
|
CheckUpdatesOnStart = config.CheckUpdatesOnStart;
|
||||||
ShowConfirmExit = config.ShowConfirmExit;
|
ShowConfirmExit = config.ShowConfirmExit;
|
||||||
IgnoreApplet = config.IgnoreApplet;
|
|
||||||
RememberWindowState = config.RememberWindowState;
|
RememberWindowState = config.RememberWindowState;
|
||||||
ShowTitleBar = config.ShowTitleBar;
|
ShowTitleBar = config.ShowTitleBar;
|
||||||
HideCursor = (int)config.HideCursor.Value;
|
HideCursor = (int)config.HideCursor.Value;
|
||||||
@@ -532,6 +531,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
EnableFsIntegrityChecks = config.System.EnableFsIntegrityChecks;
|
EnableFsIntegrityChecks = config.System.EnableFsIntegrityChecks;
|
||||||
DramSize = config.System.DramSize;
|
DramSize = config.System.DramSize;
|
||||||
IgnoreMissingServices = config.System.IgnoreMissingServices;
|
IgnoreMissingServices = config.System.IgnoreMissingServices;
|
||||||
|
IgnoreApplet = config.System.IgnoreApplet;
|
||||||
|
|
||||||
// CPU
|
// CPU
|
||||||
EnablePptc = config.System.EnablePtc;
|
EnablePptc = config.System.EnablePtc;
|
||||||
@@ -591,7 +591,6 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
config.EnableDiscordIntegration.Value = EnableDiscordIntegration;
|
config.EnableDiscordIntegration.Value = EnableDiscordIntegration;
|
||||||
config.CheckUpdatesOnStart.Value = CheckUpdatesOnStart;
|
config.CheckUpdatesOnStart.Value = CheckUpdatesOnStart;
|
||||||
config.ShowConfirmExit.Value = ShowConfirmExit;
|
config.ShowConfirmExit.Value = ShowConfirmExit;
|
||||||
config.IgnoreApplet.Value = IgnoreApplet;
|
|
||||||
config.RememberWindowState.Value = RememberWindowState;
|
config.RememberWindowState.Value = RememberWindowState;
|
||||||
config.ShowTitleBar.Value = ShowTitleBar;
|
config.ShowTitleBar.Value = ShowTitleBar;
|
||||||
config.HideCursor.Value = (HideCursorMode)HideCursor;
|
config.HideCursor.Value = (HideCursorMode)HideCursor;
|
||||||
@@ -632,12 +631,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
}
|
}
|
||||||
|
|
||||||
config.System.SystemTimeOffset.Value = Convert.ToInt64((CurrentDate.ToUnixTimeSeconds() + CurrentTime.TotalSeconds) - DateTimeOffset.Now.ToUnixTimeSeconds());
|
config.System.SystemTimeOffset.Value = Convert.ToInt64((CurrentDate.ToUnixTimeSeconds() + CurrentTime.TotalSeconds) - DateTimeOffset.Now.ToUnixTimeSeconds());
|
||||||
config.Graphics.VSyncMode.Value = VSyncMode;
|
|
||||||
config.Graphics.EnableCustomVSyncInterval.Value = EnableCustomVSyncInterval;
|
|
||||||
config.Graphics.CustomVSyncInterval.Value = CustomVSyncInterval;
|
|
||||||
config.System.EnableFsIntegrityChecks.Value = EnableFsIntegrityChecks;
|
config.System.EnableFsIntegrityChecks.Value = EnableFsIntegrityChecks;
|
||||||
config.System.DramSize.Value = DramSize;
|
config.System.DramSize.Value = DramSize;
|
||||||
config.System.IgnoreMissingServices.Value = IgnoreMissingServices;
|
config.System.IgnoreMissingServices.Value = IgnoreMissingServices;
|
||||||
|
config.System.IgnoreApplet.Value = IgnoreApplet;
|
||||||
|
|
||||||
// CPU
|
// CPU
|
||||||
config.System.EnablePtc.Value = EnablePptc;
|
config.System.EnablePtc.Value = EnablePptc;
|
||||||
@@ -646,6 +643,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
config.System.UseHypervisor.Value = UseHypervisor;
|
config.System.UseHypervisor.Value = UseHypervisor;
|
||||||
|
|
||||||
// Graphics
|
// Graphics
|
||||||
|
config.Graphics.VSyncMode.Value = VSyncMode;
|
||||||
|
config.Graphics.EnableCustomVSyncInterval.Value = EnableCustomVSyncInterval;
|
||||||
|
config.Graphics.CustomVSyncInterval.Value = CustomVSyncInterval;
|
||||||
config.Graphics.GraphicsBackend.Value = (GraphicsBackend)GraphicsBackendIndex;
|
config.Graphics.GraphicsBackend.Value = (GraphicsBackend)GraphicsBackendIndex;
|
||||||
config.Graphics.PreferredGpu.Value = _gpuIds.ElementAtOrDefault(PreferredGpuIndex);
|
config.Graphics.PreferredGpu.Value = _gpuIds.ElementAtOrDefault(PreferredGpuIndex);
|
||||||
config.Graphics.EnableShaderCache.Value = EnableShaderCache;
|
config.Graphics.EnableShaderCache.Value = EnableShaderCache;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
|
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
|
||||||
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:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
|
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
|
||||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Input"
|
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Input"
|
||||||
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
||||||
@@ -486,6 +487,37 @@
|
|||||||
</Button>
|
</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
|
<Border
|
||||||
|
BorderBrush="{DynamicResource ThemeControlBorderColor}"
|
||||||
|
BorderThickness="1"
|
||||||
|
CornerRadius="5"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
Margin="0,-1,0,0">
|
||||||
|
<Grid IsVisible="{Binding ParentModel.HasLed}">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<CheckBox
|
||||||
|
Margin="10"
|
||||||
|
MinWidth="0"
|
||||||
|
Grid.Column="0"
|
||||||
|
IsChecked="{Binding Config.EnableLedChanging, Mode=TwoWay}">
|
||||||
|
<TextBlock Text="{ext:Locale ControllerSettingsLedColor}" />
|
||||||
|
</CheckBox>
|
||||||
|
<ui:ColorPickerButton
|
||||||
|
Grid.Column="1"
|
||||||
|
Margin="10"
|
||||||
|
IsMoreButtonVisible="False"
|
||||||
|
UseColorPalette="False"
|
||||||
|
UseColorTriangle="False"
|
||||||
|
UseColorWheel="False"
|
||||||
|
ShowAcceptDismissButtons="False"
|
||||||
|
IsAlphaEnabled="False"
|
||||||
|
Color="{Binding Config.LedColor, Mode=TwoWay}">
|
||||||
|
</ui:ColorPickerButton>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<!-- Right Controls -->
|
<!-- Right Controls -->
|
||||||
|
|||||||
@@ -4,14 +4,11 @@ using Avalonia.Controls.Primitives;
|
|||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Avalonia.LogicalTree;
|
using Avalonia.LogicalTree;
|
||||||
using DiscordRPC;
|
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.ViewModels.Input;
|
using Ryujinx.Ava.UI.ViewModels.Input;
|
||||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||||
using Ryujinx.Common.Logging;
|
|
||||||
using Ryujinx.Input;
|
using Ryujinx.Input;
|
||||||
using Ryujinx.Input.Assigner;
|
using Ryujinx.Input.Assigner;
|
||||||
using System;
|
|
||||||
using StickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
|
using StickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Views.Input
|
namespace Ryujinx.Ava.UI.Views.Input
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current version of the file format
|
/// The current version of the file format
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const int CurrentVersion = 60;
|
public const int CurrentVersion = 61;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Version of the configuration file format
|
/// Version of the configuration file format
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
EnableDiscordIntegration.Value = cff.EnableDiscordIntegration;
|
EnableDiscordIntegration.Value = cff.EnableDiscordIntegration;
|
||||||
CheckUpdatesOnStart.Value = cff.CheckUpdatesOnStart;
|
CheckUpdatesOnStart.Value = cff.CheckUpdatesOnStart;
|
||||||
ShowConfirmExit.Value = cff.ShowConfirmExit;
|
ShowConfirmExit.Value = cff.ShowConfirmExit;
|
||||||
IgnoreApplet.Value = cff.IgnoreApplet;
|
|
||||||
RememberWindowState.Value = cff.RememberWindowState;
|
RememberWindowState.Value = cff.RememberWindowState;
|
||||||
ShowTitleBar.Value = cff.ShowTitleBar;
|
ShowTitleBar.Value = cff.ShowTitleBar;
|
||||||
EnableHardwareAcceleration.Value = cff.EnableHardwareAcceleration;
|
EnableHardwareAcceleration.Value = cff.EnableHardwareAcceleration;
|
||||||
@@ -97,6 +96,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
System.MemoryManagerMode.Value = cff.MemoryManagerMode;
|
System.MemoryManagerMode.Value = cff.MemoryManagerMode;
|
||||||
System.DramSize.Value = cff.DramSize;
|
System.DramSize.Value = cff.DramSize;
|
||||||
System.IgnoreMissingServices.Value = cff.IgnoreMissingServices;
|
System.IgnoreMissingServices.Value = cff.IgnoreMissingServices;
|
||||||
|
System.IgnoreApplet.Value = cff.IgnoreApplet;
|
||||||
System.UseHypervisor.Value = cff.UseHypervisor;
|
System.UseHypervisor.Value = cff.UseHypervisor;
|
||||||
|
|
||||||
UI.GuiColumns.FavColumn.Value = cff.GuiColumns.FavColumn;
|
UI.GuiColumns.FavColumn.Value = cff.GuiColumns.FavColumn;
|
||||||
@@ -263,15 +263,12 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
}),
|
}),
|
||||||
(30, static cff =>
|
(30, static cff =>
|
||||||
{
|
{
|
||||||
foreach (InputConfig config in cff.InputConfig)
|
foreach (StandardControllerInputConfig config in cff.InputConfig.OfType<StandardControllerInputConfig>())
|
||||||
{
|
{
|
||||||
if (config is StandardControllerInputConfig controllerConfig)
|
config.Rumble = new RumbleConfigController
|
||||||
{
|
{
|
||||||
controllerConfig.Rumble = new RumbleConfigController
|
EnableRumble = false, StrongRumble = 1f, WeakRumble = 1f,
|
||||||
{
|
};
|
||||||
EnableRumble = false, StrongRumble = 1f, WeakRumble = 1f,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
(31, static cff => cff.BackendThreading = BackendThreading.Auto),
|
(31, static cff => cff.BackendThreading = BackendThreading.Auto),
|
||||||
@@ -416,7 +413,18 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
// so as a compromise users who want to use it will simply need to re-enable it once after updating.
|
// so as a compromise users who want to use it will simply need to re-enable it once after updating.
|
||||||
cff.IgnoreApplet = false;
|
cff.IgnoreApplet = false;
|
||||||
}),
|
}),
|
||||||
(60, static cff => cff.StartNoUI = false)
|
(60, static cff => cff.StartNoUI = false),
|
||||||
|
(61, static cff =>
|
||||||
|
{
|
||||||
|
foreach (StandardControllerInputConfig config in cff.InputConfig.OfType<StandardControllerInputConfig>())
|
||||||
|
{
|
||||||
|
config.Led = new LedConfigController
|
||||||
|
{
|
||||||
|
EnableLed = false,
|
||||||
|
LedColor = 328189
|
||||||
|
};
|
||||||
|
}
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -366,6 +366,11 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
/// Enable or disable ignoring missing services
|
/// Enable or disable ignoring missing services
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ReactiveObject<bool> IgnoreMissingServices { get; private set; }
|
public ReactiveObject<bool> IgnoreMissingServices { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ignore Controller Applet
|
||||||
|
/// </summary>
|
||||||
|
public ReactiveObject<bool> IgnoreApplet { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Uses Hypervisor over JIT if available
|
/// Uses Hypervisor over JIT if available
|
||||||
@@ -404,6 +409,8 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
DramSize.LogChangesToValue(nameof(DramSize));
|
DramSize.LogChangesToValue(nameof(DramSize));
|
||||||
IgnoreMissingServices = new ReactiveObject<bool>();
|
IgnoreMissingServices = new ReactiveObject<bool>();
|
||||||
IgnoreMissingServices.LogChangesToValue(nameof(IgnoreMissingServices));
|
IgnoreMissingServices.LogChangesToValue(nameof(IgnoreMissingServices));
|
||||||
|
IgnoreApplet = new ReactiveObject<bool>();
|
||||||
|
IgnoreApplet.LogChangesToValue(nameof(IgnoreApplet));
|
||||||
AudioVolume = new ReactiveObject<float>();
|
AudioVolume = new ReactiveObject<float>();
|
||||||
AudioVolume.LogChangesToValue(nameof(AudioVolume));
|
AudioVolume.LogChangesToValue(nameof(AudioVolume));
|
||||||
UseHypervisor = new ReactiveObject<bool>();
|
UseHypervisor = new ReactiveObject<bool>();
|
||||||
@@ -745,11 +752,6 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ReactiveObject<bool> ShowConfirmExit { get; private set; }
|
public ReactiveObject<bool> ShowConfirmExit { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Ignore Applet
|
|
||||||
/// </summary>
|
|
||||||
public ReactiveObject<bool> IgnoreApplet { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enables or disables save window size, position and state on close.
|
/// Enables or disables save window size, position and state on close.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -782,8 +784,6 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
EnableDiscordIntegration = new ReactiveObject<bool>();
|
EnableDiscordIntegration = new ReactiveObject<bool>();
|
||||||
CheckUpdatesOnStart = new ReactiveObject<bool>();
|
CheckUpdatesOnStart = new ReactiveObject<bool>();
|
||||||
ShowConfirmExit = new ReactiveObject<bool>();
|
ShowConfirmExit = new ReactiveObject<bool>();
|
||||||
IgnoreApplet = new ReactiveObject<bool>();
|
|
||||||
IgnoreApplet.LogChangesToValue(nameof(IgnoreApplet));
|
|
||||||
RememberWindowState = new ReactiveObject<bool>();
|
RememberWindowState = new ReactiveObject<bool>();
|
||||||
ShowTitleBar = new ReactiveObject<bool>();
|
ShowTitleBar = new ReactiveObject<bool>();
|
||||||
EnableHardwareAcceleration = new ReactiveObject<bool>();
|
EnableHardwareAcceleration = new ReactiveObject<bool>();
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
EnableDiscordIntegration = EnableDiscordIntegration,
|
EnableDiscordIntegration = EnableDiscordIntegration,
|
||||||
CheckUpdatesOnStart = CheckUpdatesOnStart,
|
CheckUpdatesOnStart = CheckUpdatesOnStart,
|
||||||
ShowConfirmExit = ShowConfirmExit,
|
ShowConfirmExit = ShowConfirmExit,
|
||||||
IgnoreApplet = IgnoreApplet,
|
|
||||||
RememberWindowState = RememberWindowState,
|
RememberWindowState = RememberWindowState,
|
||||||
ShowTitleBar = ShowTitleBar,
|
ShowTitleBar = ShowTitleBar,
|
||||||
EnableHardwareAcceleration = EnableHardwareAcceleration,
|
EnableHardwareAcceleration = EnableHardwareAcceleration,
|
||||||
@@ -78,6 +77,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
MemoryManagerMode = System.MemoryManagerMode,
|
MemoryManagerMode = System.MemoryManagerMode,
|
||||||
DramSize = System.DramSize,
|
DramSize = System.DramSize,
|
||||||
IgnoreMissingServices = System.IgnoreMissingServices,
|
IgnoreMissingServices = System.IgnoreMissingServices,
|
||||||
|
IgnoreApplet = System.IgnoreApplet,
|
||||||
UseHypervisor = System.UseHypervisor,
|
UseHypervisor = System.UseHypervisor,
|
||||||
GuiColumns = new GuiColumns
|
GuiColumns = new GuiColumns
|
||||||
{
|
{
|
||||||
@@ -176,7 +176,6 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
EnableDiscordIntegration.Value = true;
|
EnableDiscordIntegration.Value = true;
|
||||||
CheckUpdatesOnStart.Value = true;
|
CheckUpdatesOnStart.Value = true;
|
||||||
ShowConfirmExit.Value = true;
|
ShowConfirmExit.Value = true;
|
||||||
IgnoreApplet.Value = false;
|
|
||||||
RememberWindowState.Value = true;
|
RememberWindowState.Value = true;
|
||||||
ShowTitleBar.Value = !OperatingSystem.IsWindows();
|
ShowTitleBar.Value = !OperatingSystem.IsWindows();
|
||||||
EnableHardwareAcceleration.Value = true;
|
EnableHardwareAcceleration.Value = true;
|
||||||
@@ -200,6 +199,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
System.MemoryManagerMode.Value = MemoryManagerMode.HostMappedUnsafe;
|
System.MemoryManagerMode.Value = MemoryManagerMode.HostMappedUnsafe;
|
||||||
System.DramSize.Value = MemoryConfiguration.MemoryConfiguration4GiB;
|
System.DramSize.Value = MemoryConfiguration.MemoryConfiguration4GiB;
|
||||||
System.IgnoreMissingServices.Value = false;
|
System.IgnoreMissingServices.Value = false;
|
||||||
|
System.IgnoreApplet.Value = false;
|
||||||
System.UseHypervisor.Value = true;
|
System.UseHypervisor.Value = true;
|
||||||
Multiplayer.LanInterfaceId.Value = "0";
|
Multiplayer.LanInterfaceId.Value = "0";
|
||||||
Multiplayer.Mode.Value = MultiplayerMode.Disabled;
|
Multiplayer.Mode.Value = MultiplayerMode.Disabled;
|
||||||
|
|||||||
Reference in New Issue
Block a user