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