diff options
| author | Emmanuel Hansen <emmausssss@gmail.com> | 2022-08-16 16:32:37 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-08-16 16:32:37 +0000 |
| commit | c8f9292babd5aa6021ce1bd6a977130baebb7de3 (patch) | |
| tree | e6e62d79d08726129485476078732f9b89f6ab5c /Ryujinx.Ava/Ui/Backend/Vulkan | |
| parent | 0ec933a6152ebb7724da1e3a05a5ae1c2ea07b2f (diff) | |
Avalonia - Couple fixes and improvements to vulkan (#3483)
* drop split devices, rebase
* add fallback to opengl if vulkan is not available
* addressed review
* ensure present image references are incremented and decremented when necessary
* allow changing vsync for vulkan
* fix screenshot on avalonia vulkan
* save favorite when toggled
* improve sync between popups
* use separate devices for each new window
* fix crash when closing window
* addressed review
* don't create the main window with immediate mode
* change skia vk delegate to method
* update vulkan throwonerror
* addressed review
Diffstat (limited to 'Ryujinx.Ava/Ui/Backend/Vulkan')
12 files changed, 236 insertions, 167 deletions
diff --git a/Ryujinx.Ava/Ui/Backend/Vulkan/ResultExtensions.cs b/Ryujinx.Ava/Ui/Backend/Vulkan/ResultExtensions.cs index b1326dbf..2a1cd229 100644 --- a/Ryujinx.Ava/Ui/Backend/Vulkan/ResultExtensions.cs +++ b/Ryujinx.Ava/Ui/Backend/Vulkan/ResultExtensions.cs @@ -7,7 +7,8 @@ namespace Ryujinx.Ava.Ui.Vulkan { public static void ThrowOnError(this Result result) { - if (result != Result.Success) + // Only negative result codes are errors. + if ((int)result < (int)Result.Success) { throw new Exception($"Unexpected API error \"{result}\"."); } diff --git a/Ryujinx.Ava/Ui/Backend/Vulkan/Skia/VulkanRenderTarget.cs b/Ryujinx.Ava/Ui/Backend/Vulkan/Skia/VulkanRenderTarget.cs index ba7ddc7a..70ec39c7 100644 --- a/Ryujinx.Ava/Ui/Backend/Vulkan/Skia/VulkanRenderTarget.cs +++ b/Ryujinx.Ava/Ui/Backend/Vulkan/Skia/VulkanRenderTarget.cs @@ -1,26 +1,90 @@ using System; +using Avalonia; using Avalonia.Skia; using Ryujinx.Ava.Ui.Vulkan; using Ryujinx.Ava.Ui.Vulkan.Surfaces; +using Silk.NET.Vulkan; using SkiaSharp; namespace Ryujinx.Ava.Ui.Backend.Vulkan { internal class VulkanRenderTarget : ISkiaGpuRenderTarget { - public GRContext GrContext { get; set; } + public GRContext GrContext { get; private set; } private readonly VulkanSurfaceRenderTarget _surface; + private readonly VulkanPlatformInterface _vulkanPlatformInterface; private readonly IVulkanPlatformSurface _vulkanPlatformSurface; + private GRVkBackendContext _grVkBackend; public VulkanRenderTarget(VulkanPlatformInterface vulkanPlatformInterface, IVulkanPlatformSurface vulkanPlatformSurface) { _surface = vulkanPlatformInterface.CreateRenderTarget(vulkanPlatformSurface); + _vulkanPlatformInterface = vulkanPlatformInterface; _vulkanPlatformSurface = vulkanPlatformSurface; + + Initialize(); + } + + private void Initialize() + { + GRVkGetProcedureAddressDelegate getProc = GetVulkanProcAddress; + + _grVkBackend = new GRVkBackendContext() + { + VkInstance = _surface.Device.Handle, + VkPhysicalDevice = _vulkanPlatformInterface.PhysicalDevice.Handle, + VkDevice = _surface.Device.Handle, + VkQueue = _surface.Device.Queue.Handle, + GraphicsQueueIndex = _vulkanPlatformInterface.PhysicalDevice.QueueFamilyIndex, + GetProcedureAddress = getProc + }; + + GrContext = GRContext.CreateVulkan(_grVkBackend); + + var gpu = AvaloniaLocator.Current.GetService<VulkanSkiaGpu>(); + + if (gpu.MaxResourceBytes.HasValue) + { + GrContext.SetResourceCacheLimit(gpu.MaxResourceBytes.Value); + } + } + + private IntPtr GetVulkanProcAddress(string name, IntPtr instanceHandle, IntPtr deviceHandle) + { + IntPtr addr; + + if (deviceHandle != IntPtr.Zero) + { + addr = _vulkanPlatformInterface.Api.GetDeviceProcAddr(new Device(deviceHandle), name); + + if (addr != IntPtr.Zero) + { + return addr; + } + + addr = _vulkanPlatformInterface.Api.GetDeviceProcAddr(new Device(_surface.Device.Handle), name); + + if (addr != IntPtr.Zero) + { + return addr; + } + } + + addr = _vulkanPlatformInterface.Api.GetInstanceProcAddr(new Instance(_vulkanPlatformInterface.Instance.Handle), name); + + if (addr == IntPtr.Zero) + { + addr = _vulkanPlatformInterface.Api.GetInstanceProcAddr(new Instance(instanceHandle), name); + } + + return addr; } public void Dispose() { + _grVkBackend.Dispose(); + GrContext.Dispose(); _surface.Dispose(); } @@ -45,20 +109,22 @@ namespace Ryujinx.Ava.Ui.Backend.Vulkan { GrContext.ResetContext(); + var image = _surface.GetImage(); + var imageInfo = new GRVkImageInfo() { CurrentQueueFamily = disp.QueueFamilyIndex, - Format = _surface.ImageFormat, - Image = _surface.Image.Handle, - ImageLayout = (uint)_surface.Image.CurrentLayout, - ImageTiling = (uint)_surface.Image.Tiling, + Format = (uint)image.Format, + Image = image.Handle, + ImageLayout = (uint)image.CurrentLayout, + ImageTiling = (uint)image.Tiling, ImageUsageFlags = _surface.UsageFlags, LevelCount = _surface.MipLevels, SampleCount = 1, Protected = false, Alloc = new GRVkAlloc() { - Memory = _surface.Image.MemoryHandle, + Memory = image.MemoryHandle, Flags = 0, Offset = 0, Size = _surface.MemorySize diff --git a/Ryujinx.Ava/Ui/Backend/Vulkan/Skia/VulkanSkiaGpu.cs b/Ryujinx.Ava/Ui/Backend/Vulkan/Skia/VulkanSkiaGpu.cs index 4fc6b929..a5c27086 100644 --- a/Ryujinx.Ava/Ui/Backend/Vulkan/Skia/VulkanSkiaGpu.cs +++ b/Ryujinx.Ava/Ui/Backend/Vulkan/Skia/VulkanSkiaGpu.cs @@ -13,71 +13,12 @@ namespace Ryujinx.Ava.Ui.Backend.Vulkan public class VulkanSkiaGpu : ISkiaGpu { private readonly VulkanPlatformInterface _vulkan; - private readonly long? _maxResourceBytes; - private GRVkBackendContext _grVkBackend; - private bool _initialized; - - public GRContext GrContext { get; private set; } + public long? MaxResourceBytes { get; } public VulkanSkiaGpu(long? maxResourceBytes) { _vulkan = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>(); - _maxResourceBytes = maxResourceBytes; - } - - private void Initialize() - { - if (_initialized) - { - return; - } - - _initialized = true; - GRVkGetProcedureAddressDelegate getProc = (string name, IntPtr instanceHandle, IntPtr deviceHandle) => - { - IntPtr addr = IntPtr.Zero; - - if (deviceHandle != IntPtr.Zero) - { - addr = _vulkan.Device.Api.GetDeviceProcAddr(new Device(deviceHandle), name); - - if (addr != IntPtr.Zero) - { - return addr; - } - - addr = _vulkan.Device.Api.GetDeviceProcAddr(new Device(_vulkan.Device.Handle), name); - - if (addr != IntPtr.Zero) - { - return addr; - } - } - - addr = _vulkan.Device.Api.GetInstanceProcAddr(new Instance(_vulkan.Instance.Handle), name); - - if (addr == IntPtr.Zero) - { - addr = _vulkan.Device.Api.GetInstanceProcAddr(new Instance(instanceHandle), name); - } - - return addr; - }; - - _grVkBackend = new GRVkBackendContext() - { - VkInstance = _vulkan.Device.Handle, - VkPhysicalDevice = _vulkan.PhysicalDevice.Handle, - VkDevice = _vulkan.Device.Handle, - VkQueue = _vulkan.Device.Queue.Handle, - GraphicsQueueIndex = _vulkan.PhysicalDevice.QueueFamilyIndex, - GetProcedureAddress = getProc - }; - GrContext = GRContext.CreateVulkan(_grVkBackend); - if (_maxResourceBytes.HasValue) - { - GrContext.SetResourceCacheLimit(_maxResourceBytes.Value); - } + MaxResourceBytes = maxResourceBytes; } public ISkiaGpuRenderTarget TryCreateRenderTarget(IEnumerable<object> surfaces) @@ -106,10 +47,6 @@ namespace Ryujinx.Ava.Ui.Backend.Vulkan VulkanRenderTarget vulkanRenderTarget = new VulkanRenderTarget(_vulkan, window); - Initialize(); - - vulkanRenderTarget.GrContext = GrContext; - return vulkanRenderTarget; } diff --git a/Ryujinx.Ava/Ui/Backend/Vulkan/Surfaces/VulkanSurfaceRenderTarget.cs b/Ryujinx.Ava/Ui/Backend/Vulkan/Surfaces/VulkanSurfaceRenderTarget.cs index b2b8843d..510e6724 100644 --- a/Ryujinx.Ava/Ui/Backend/Vulkan/Surfaces/VulkanSurfaceRenderTarget.cs +++ b/Ryujinx.Ava/Ui/Backend/Vulkan/Surfaces/VulkanSurfaceRenderTarget.cs @@ -1,5 +1,6 @@ using System; using Avalonia; +using Ryujinx.Graphics.Vulkan; using Silk.NET.Vulkan; namespace Ryujinx.Ava.Ui.Vulkan.Surfaces @@ -7,24 +8,35 @@ namespace Ryujinx.Ava.Ui.Vulkan.Surfaces internal class VulkanSurfaceRenderTarget : IDisposable { private readonly VulkanPlatformInterface _platformInterface; - private readonly Format _format; - public VulkanImage Image { get; private set; } - public bool IsCorrupted { get; private set; } = true; + private VulkanCommandBufferPool.VulkanCommandBuffer _commandBuffer; + private VulkanImage Image { get; set; } + private object _lock = new object(); public uint MipLevels => Image.MipLevels; + public VulkanDevice Device { get; } public VulkanSurfaceRenderTarget(VulkanPlatformInterface platformInterface, VulkanSurface surface) { _platformInterface = platformInterface; - Display = VulkanDisplay.CreateDisplay(platformInterface.Instance, platformInterface.Device, - platformInterface.PhysicalDevice, surface); + var device = VulkanInitialization.CreateDevice(platformInterface.Api, + platformInterface.PhysicalDevice.InternalHandle, + platformInterface.PhysicalDevice.QueueFamilyIndex, + VulkanInitialization.GetSupportedExtensions(platformInterface.Api, platformInterface.PhysicalDevice.InternalHandle), + platformInterface.PhysicalDevice.QueueCount); + + Device = new VulkanDevice(device, platformInterface.PhysicalDevice, platformInterface.Api); + + Display = VulkanDisplay.CreateDisplay( + platformInterface.Instance, + Device, + platformInterface.PhysicalDevice, + surface); Surface = surface; // Skia seems to only create surfaces from images with unorm format - IsRgba = Display.SurfaceFormat.Format >= Format.R8G8B8A8Unorm && Display.SurfaceFormat.Format <= Format.R8G8B8A8Srgb; @@ -33,13 +45,13 @@ namespace Ryujinx.Ava.Ui.Vulkan.Surfaces public bool IsRgba { get; } - public uint ImageFormat => (uint) _format; + public uint ImageFormat => (uint)_format; public ulong MemorySize => Image.MemorySize; - public VulkanDisplay Display { get; } + public VulkanDisplay Display { get; private set; } - public VulkanSurface Surface { get; } + public VulkanSurface Surface { get; private set; } public uint UsageFlags => Image.UsageFlags; @@ -47,46 +59,76 @@ namespace Ryujinx.Ava.Ui.Vulkan.Surfaces public void Dispose() { - _platformInterface.Device.WaitIdle(); - DestroyImage(); - Display?.Dispose(); - Surface?.Dispose(); + lock (_lock) + { + DestroyImage(); + Display?.Dispose(); + Surface?.Dispose(); + Device?.Dispose(); + + Display = null; + Surface = null; + } } public VulkanSurfaceRenderingSession BeginDraw(float scaling) { - var session = new VulkanSurfaceRenderingSession(Display, _platformInterface.Device, this, scaling); - - if (IsCorrupted) + if (Image == null) { - IsCorrupted = false; - DestroyImage(); - CreateImage(); - } - else - { - Image.TransitionLayout(ImageLayout.ColorAttachmentOptimal, AccessFlags.AccessNoneKhr); + RecreateImage(); } + _commandBuffer?.WaitForFence(); + _commandBuffer = null; + + var session = new VulkanSurfaceRenderingSession(Display, Device, this, scaling); + + Image.TransitionLayout(ImageLayout.ColorAttachmentOptimal, AccessFlags.AccessNoneKhr); + return session; } - public void Invalidate() + public void RecreateImage() { - IsCorrupted = true; + DestroyImage(); + CreateImage(); } private void CreateImage() { Size = Display.Size; - Image = new VulkanImage(_platformInterface.Device, _platformInterface.PhysicalDevice, _platformInterface.Device.CommandBufferPool, ImageFormat, Size); + Image = new VulkanImage(Device, _platformInterface.PhysicalDevice, Display.CommandBufferPool, ImageFormat, Size); } private void DestroyImage() { - _platformInterface.Device.WaitIdle(); + _commandBuffer?.WaitForFence(); + _commandBuffer = null; Image?.Dispose(); + Image = null; + } + + public VulkanImage GetImage() + { + return Image; + } + + public void EndDraw() + { + lock (_lock) + { + if (Display == null) + { + return; + } + + _commandBuffer = Display.StartPresentation(); + + Display.BlitImageToCurrentImage(this, _commandBuffer.InternalHandle); + + Display.EndPresentation(_commandBuffer); + } } } } diff --git a/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanCommandBufferPool.cs b/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanCommandBufferPool.cs index 240035ca..a00ecf2b 100644 --- a/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanCommandBufferPool.cs +++ b/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanCommandBufferPool.cs @@ -10,6 +10,7 @@ namespace Ryujinx.Ava.Ui.Vulkan private readonly CommandPool _commandPool; private readonly List<VulkanCommandBuffer> _usedCommandBuffers = new(); + private readonly object _lock = new object(); public unsafe VulkanCommandBufferPool(VulkanDevice device, VulkanPhysicalDevice physicalDevice) { @@ -36,9 +37,12 @@ namespace Ryujinx.Ava.Ui.Vulkan Level = CommandBufferLevel.Primary }; - _device.Api.AllocateCommandBuffers(_device.InternalHandle, commandBufferAllocateInfo, out var commandBuffer); + lock (_lock) + { + _device.Api.AllocateCommandBuffers(_device.InternalHandle, commandBufferAllocateInfo, out var commandBuffer); - return commandBuffer; + return commandBuffer; + } } public VulkanCommandBuffer CreateCommandBuffer() @@ -48,7 +52,7 @@ namespace Ryujinx.Ava.Ui.Vulkan public void FreeUsedCommandBuffers() { - lock (_usedCommandBuffers) + lock (_lock) { foreach (var usedCommandBuffer in _usedCommandBuffers) { @@ -61,7 +65,7 @@ namespace Ryujinx.Ava.Ui.Vulkan private void DisposeCommandBuffer(VulkanCommandBuffer commandBuffer) { - lock (_usedCommandBuffers) + lock (_lock) { _usedCommandBuffers.Add(commandBuffer); } @@ -69,8 +73,11 @@ namespace Ryujinx.Ava.Ui.Vulkan public void Dispose() { - FreeUsedCommandBuffers(); - _device.Api.DestroyCommandPool(_device.InternalHandle, _commandPool, Span<AllocationCallbacks>.Empty); + lock (_lock) + { + FreeUsedCommandBuffers(); + _device.Api.DestroyCommandPool(_device.InternalHandle, _commandPool, Span<AllocationCallbacks>.Empty); + } } public class VulkanCommandBuffer : IDisposable @@ -80,6 +87,8 @@ namespace Ryujinx.Ava.Ui.Vulkan private readonly Fence _fence; private bool _hasEnded; private bool _hasStarted; + private bool _isDisposed; + private object _lock = new object(); public IntPtr Handle => InternalHandle.Handle; @@ -101,6 +110,22 @@ namespace Ryujinx.Ava.Ui.Vulkan device.Api.CreateFence(device.InternalHandle, fenceCreateInfo, null, out _fence); } + public void WaitForFence() + { + if (_isDisposed) + { + return; + } + + lock (_lock) + { + if (!_isDisposed) + { + _device.Api.WaitForFences(_device.InternalHandle, 1, _fence, true, ulong.MaxValue); + } + } + } + public void BeginRecording() { if (!_hasStarted) @@ -173,9 +198,17 @@ namespace Ryujinx.Ava.Ui.Vulkan public void Dispose() { - _device.Api.WaitForFences(_device.InternalHandle, 1, _fence, true, ulong.MaxValue); - _device.Api.FreeCommandBuffers(_device.InternalHandle, _commandBufferPool._commandPool, 1, InternalHandle); - _device.Api.DestroyFence(_device.InternalHandle, _fence, Span<AllocationCallbacks>.Empty); + lock (_lock) + { + if (!_isDisposed) + { + _isDisposed = true; + + _device.Api.WaitForFences(_device.InternalHandle, 1, _fence, true, ulong.MaxValue); + _device.Api.FreeCommandBuffers(_device.InternalHandle, _commandBufferPool._commandPool, 1, InternalHandle); + _device.Api.DestroyFence(_device.InternalHandle, _fence, Span<AllocationCallbacks>.Empty); + } + } } } } diff --git a/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanDevice.cs b/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanDevice.cs index b03fd720..3d893e19 100644 --- a/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanDevice.cs +++ b/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanDevice.cs @@ -14,12 +14,9 @@ namespace Ryujinx.Ava.Ui.Vulkan api.GetDeviceQueue(apiHandle, physicalDevice.QueueFamilyIndex, 0, out var queue); - var vulkanQueue = new VulkanQueue(this, queue); - Queue = vulkanQueue; + Queue = new VulkanQueue(this, queue); - PresentQueue = vulkanQueue; - - CommandBufferPool = new VulkanCommandBufferPool(this, physicalDevice); + PresentQueue = Queue; } public IntPtr Handle => InternalHandle.Handle; @@ -29,13 +26,12 @@ namespace Ryujinx.Ava.Ui.Vulkan public VulkanQueue Queue { get; private set; } public VulkanQueue PresentQueue { get; } - public VulkanCommandBufferPool CommandBufferPool { get; } public void Dispose() { WaitIdle(); - CommandBufferPool?.Dispose(); Queue = null; + Api.DestroyDevice(InternalHandle, Span<AllocationCallbacks>.Empty); } internal void Submit(SubmitInfo submitInfo, Fence fence = default) diff --git a/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanDisplay.cs b/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanDisplay.cs index bfe5b5a6..f3116fbd 100644 --- a/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanDisplay.cs +++ b/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanDisplay.cs @@ -3,7 +3,6 @@ using System.Linq; using System.Threading; using Avalonia; using Ryujinx.Ava.Ui.Vulkan.Surfaces; -using Ryujinx.Ui.Common.Configuration; using Silk.NET.Vulkan; using Silk.NET.Vulkan.Extensions.KHR; @@ -15,16 +14,19 @@ namespace Ryujinx.Ava.Ui.Vulkan private readonly VulkanInstance _instance; private readonly VulkanPhysicalDevice _physicalDevice; private readonly VulkanSemaphorePair _semaphorePair; + private readonly VulkanDevice _device; private uint _nextImage; private readonly VulkanSurface _surface; private SurfaceFormatKHR _surfaceFormat; private SwapchainKHR _swapchain; private Extent2D _swapchainExtent; private Image[] _swapchainImages; - private VulkanDevice _device { get; } - private ImageView[] _swapchainImageViews = new ImageView[0]; + private ImageView[] _swapchainImageViews = Array.Empty<ImageView>(); private bool _vsyncStateChanged; private bool _vsyncEnabled; + private bool _surfaceChanged; + + public event EventHandler Presented; public VulkanCommandBufferPool CommandBufferPool { get; set; } @@ -73,6 +75,14 @@ namespace Ryujinx.Ava.Ui.Vulkan CommandBufferPool.Dispose(); } + public bool IsSurfaceChanged() + { + var changed = _surfaceChanged; + _surfaceChanged = false; + + return changed; + } + private static unsafe SwapchainKHR CreateSwapchain(VulkanInstance instance, VulkanDevice device, VulkanPhysicalDevice physicalDevice, VulkanSurface surface, out Extent2D swapchainExtent, SwapchainKHR? oldswapchain = null, bool vsyncEnabled = true) @@ -193,22 +203,23 @@ namespace Ryujinx.Ava.Ui.Vulkan } var modes = presentModes.ToList(); - var presentMode = PresentModeKHR.PresentModeFifoKhr; if (!vsyncEnabled && modes.Contains(PresentModeKHR.PresentModeImmediateKhr)) { - presentMode = PresentModeKHR.PresentModeImmediateKhr; + return PresentModeKHR.PresentModeImmediateKhr; } else if (modes.Contains(PresentModeKHR.PresentModeMailboxKhr)) { - presentMode = PresentModeKHR.PresentModeMailboxKhr; + return PresentModeKHR.PresentModeMailboxKhr; } - else if (modes.Contains(PresentModeKHR.PresentModeImmediateKhr)) + else if (modes.Contains(PresentModeKHR.PresentModeFifoKhr)) { - presentMode = PresentModeKHR.PresentModeImmediateKhr; + return PresentModeKHR.PresentModeFifoKhr; + } + else + { + return PresentModeKHR.PresentModeImmediateKhr; } - - return presentMode; } internal static VulkanDisplay CreateDisplay(VulkanInstance instance, VulkanDevice device, @@ -266,6 +277,8 @@ namespace Ryujinx.Ava.Ui.Vulkan _swapchain = CreateSwapchain(_instance, _device, _physicalDevice, _surface, out _swapchainExtent, _swapchain, _vsyncEnabled); CreateSwapchainImages(); + + _surfaceChanged = true; } private unsafe ImageView CreateSwapchainImageView(Image swapchainImage, Format format) @@ -306,7 +319,7 @@ namespace Ryujinx.Ava.Ui.Vulkan return true; } - internal VulkanCommandBufferPool.VulkanCommandBuffer StartPresentation(VulkanSurfaceRenderTarget renderTarget) + internal VulkanCommandBufferPool.VulkanCommandBuffer StartPresentation() { _nextImage = 0; while (true) @@ -346,8 +359,10 @@ namespace Ryujinx.Ava.Ui.Vulkan internal void BlitImageToCurrentImage(VulkanSurfaceRenderTarget renderTarget, CommandBuffer commandBuffer) { + var image = renderTarget.GetImage(); + VulkanMemoryHelper.TransitionLayout(_device, commandBuffer, - renderTarget.Image.InternalHandle.Value, (ImageLayout)renderTarget.Image.CurrentLayout, + image.InternalHandle.Value, (ImageLayout)image.CurrentLayout, AccessFlags.AccessNoneKhr, ImageLayout.TransferSrcOptimal, AccessFlags.AccessTransferReadBit, @@ -381,7 +396,7 @@ namespace Ryujinx.Ava.Ui.Vulkan } }; - _device.Api.CmdBlitImage(commandBuffer, renderTarget.Image.InternalHandle.Value, + _device.Api.CmdBlitImage(commandBuffer, image.InternalHandle.Value, ImageLayout.TransferSrcOptimal, _swapchainImages[_nextImage], ImageLayout.TransferDstOptimal, @@ -390,9 +405,9 @@ namespace Ryujinx.Ava.Ui.Vulkan Filter.Linear); VulkanMemoryHelper.TransitionLayout(_device, commandBuffer, - renderTarget.Image.InternalHandle.Value, ImageLayout.TransferSrcOptimal, + image.InternalHandle.Value, ImageLayout.TransferSrcOptimal, AccessFlags.AccessTransferReadBit, - (ImageLayout)renderTarget.Image.CurrentLayout, + (ImageLayout)image.CurrentLayout, AccessFlags.AccessNoneKhr, renderTarget.MipLevels); } @@ -434,6 +449,8 @@ namespace Ryujinx.Ava.Ui.Vulkan } CommandBufferPool.FreeUsedCommandBuffers(); + + Presented?.Invoke(this, null); } } } diff --git a/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanImage.cs b/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanImage.cs index 343ba760..3fbb8665 100644 --- a/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanImage.cs +++ b/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanImage.cs @@ -148,20 +148,18 @@ namespace Ryujinx.Ava.Ui.Vulkan _currentAccessFlags = destinationAccessFlags; } - public void TransitionLayout(uint destinationLayout, uint destinationAccessFlags) + public void Dispose() { - TransitionLayout((ImageLayout)destinationLayout, (AccessFlags)destinationAccessFlags); - } - - public unsafe void Dispose() - { - _device.Api.DestroyImageView(_device.InternalHandle, _imageView.Value, null); - _device.Api.DestroyImage(_device.InternalHandle, InternalHandle.Value, null); - _device.Api.FreeMemory(_device.InternalHandle, _imageMemory, null); + if (InternalHandle != null) + { + _device.Api.DestroyImageView(_device.InternalHandle, _imageView.Value, Span<AllocationCallbacks>.Empty); + _device.Api.DestroyImage(_device.InternalHandle, InternalHandle.Value, Span<AllocationCallbacks>.Empty); + _device.Api.FreeMemory(_device.InternalHandle, _imageMemory, Span<AllocationCallbacks>.Empty); - _imageView = default; - InternalHandle = default; - _imageMemory = default; + _imageView = default; + InternalHandle = null; + _imageMemory = default; + } } } } diff --git a/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanInstance.cs b/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanInstance.cs index a3a9ea61..b50e9c07 100644 --- a/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanInstance.cs +++ b/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanInstance.cs @@ -57,8 +57,7 @@ namespace Ryujinx.Ava.Ui.Vulkan var applicationInfo = new ApplicationInfo { PApplicationName = (byte*)applicationName, - ApiVersion = new Version32((uint)options.VulkanVersion.Major, (uint)options.VulkanVersion.Minor, - (uint)options.VulkanVersion.Build), + ApiVersion = Vk.Version12.Value, PEngineName = (byte*)engineName, EngineVersion = new Version32(1, 0, 0), ApplicationVersion = new Version32(1, 0, 0) diff --git a/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanOptions.cs b/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanOptions.cs index 8e836398..0027753c 100644 --- a/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanOptions.cs +++ b/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanOptions.cs @@ -12,11 +12,6 @@ namespace Ryujinx.Ava.Ui.Vulkan public string ApplicationName { get; set; } /// <summary> - /// Specifies the Vulkan API version to use - /// </summary> - public Version VulkanVersion { get; set; } = new Version(1, 1, 0); - - /// <summary> /// Specifies additional extensions to enable if available on the instance /// </summary> public IEnumerable<string> InstanceExtensions { get; set; } = Enumerable.Empty<string>(); diff --git a/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanPlatformInterface.cs b/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanPlatformInterface.cs index 47a07949..ff8d9328 100644 --- a/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanPlatformInterface.cs +++ b/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanPlatformInterface.cs @@ -18,13 +18,11 @@ namespace Ryujinx.Ava.Ui.Vulkan public VulkanPhysicalDevice PhysicalDevice { get; private set; } public VulkanInstance Instance { get; } - public VulkanDevice Device { get; set; } public Vk Api { get; private set; } public VulkanSurfaceRenderTarget MainSurface { get; set; } public void Dispose() { - Device?.Dispose(); Instance?.Dispose(); Api?.Dispose(); } @@ -54,16 +52,9 @@ namespace Ryujinx.Ava.Ui.Vulkan { var surface = VulkanSurface.CreateSurface(Instance, platformSurface); - if (Device == null) + if (PhysicalDevice == null) { PhysicalDevice = VulkanPhysicalDevice.FindSuitablePhysicalDevice(Instance, surface, _options.PreferDiscreteGpu, _options.PreferredDevice); - var device = VulkanInitialization.CreateDevice(Instance.Api, - PhysicalDevice.InternalHandle, - PhysicalDevice.QueueFamilyIndex, - VulkanInitialization.GetSupportedExtensions(Instance.Api, PhysicalDevice.InternalHandle), - PhysicalDevice.QueueCount); - - Device = new VulkanDevice(device, PhysicalDevice, Instance.Api); } var renderTarget = new VulkanSurfaceRenderTarget(this, surface); @@ -71,7 +62,6 @@ namespace Ryujinx.Ava.Ui.Vulkan if (MainSurface == null && surface != null) { MainSurface = renderTarget; - MainSurface.Display.ChangeVSyncMode(false); } return renderTarget; diff --git a/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanSurfaceRenderingSession.cs b/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanSurfaceRenderingSession.cs index 8833ede5..71f5f18a 100644 --- a/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanSurfaceRenderingSession.cs +++ b/Ryujinx.Ava/Ui/Backend/Vulkan/VulkanSurfaceRenderingSession.cs @@ -9,7 +9,6 @@ namespace Ryujinx.Ava.Ui.Vulkan { private readonly VulkanDevice _device; private readonly VulkanSurfaceRenderTarget _renderTarget; - private VulkanCommandBufferPool.VulkanCommandBuffer _commandBuffer; public VulkanSurfaceRenderingSession(VulkanDisplay display, VulkanDevice device, VulkanSurfaceRenderTarget renderTarget, float scaling) @@ -32,17 +31,13 @@ namespace Ryujinx.Ava.Ui.Vulkan { if (!Display.EnsureSwapchainAvailable()) { - _renderTarget.Invalidate(); + _renderTarget.RecreateImage(); } } public void Dispose() { - _commandBuffer = Display.StartPresentation(_renderTarget); - - Display.BlitImageToCurrentImage(_renderTarget, _commandBuffer.InternalHandle); - - Display.EndPresentation(_commandBuffer); + _renderTarget.EndDraw(); } } } |
