internal static SwapchainKhr[] CreateSharedKhr(Device parent, SwapchainCreateInfoKhr[] createInfos, ref AllocationCallbacks?allocator) { int count = createInfos?.Length ?? 0; var nativeCreateInfos = stackalloc SwapchainCreateInfoKhr.Native[count]; for (int i = 0; i < count; i++) { createInfos[i].ToNative(out nativeCreateInfos[i]); } AllocationCallbacks.Native nativeAllocator; allocator?.ToNative(&nativeAllocator); long * handles = stackalloc long[count]; Result result = vkCreateSharedSwapchainsKHR(parent, count, nativeCreateInfos, allocator.HasValue ? &nativeAllocator : null, handles); for (int i = 0; i < count; i++) { nativeCreateInfos[i].Free(); } VulkanException.ThrowForInvalidResult(result); var swapchains = new SwapchainKhr[count]; for (int i = 0; i < count; i++) { swapchains[i] = new SwapchainKhr(parent, handles[i], ref allocator); } return(swapchains); }
/// <summary> /// Initializes a new instance of the <see cref="SwapchainCreateInfoKhr"/> structure. /// </summary> /// <param name="surface"> /// The <see cref="SurfaceKhr"/> that the swapchain will present images to. /// </param> /// <param name="imageFormat">A format that is valid for swapchains on the specified surface.</param> /// <param name="imageExtent"> /// The size (in pixels) of the swapchain. /// <para> /// Behavior is platform-dependent when the image extent does not match the surface's <see /// cref="SurfaceCapabilitiesKhr.CurrentExtent"/> as returned by <see cref="PhysicalDeviceExtensions.GetSurfaceCapabilitiesKhr"/>. /// </para> /// </param> /// <param name="minImageCount"> /// The minimum number of presentable images that the application needs. The platform will /// either create the swapchain with at least that many images, or will fail to create the swapchain. /// </param> /// <param name="imageColorSpace">Color space value specifying the way the swapchain interprets image data.</param> /// <param name="imageArrayLayers"> /// The number of views in a multiview/stereo surface. /// <para>For non-stereoscopic-3D applications, this value is 1.</para> /// </param> /// <param name="imageUsage">A bitmask describing the intended usage of the (acquired) swapchain images.</param> /// <param name="imageSharingMode">The sharing mode used for the image(s) of the swapchain.</param> /// <param name="queueFamilyIndices"> /// Queue family indices having access to the image(s) of the swapchain when <see /// cref="ImageSharingMode"/> is <see cref="SharingMode.Concurrent"/>. /// </param> /// <param name="preTransform"> /// A value describing the transform, relative to the presentation engine's natural /// orientation, applied to the image content prior to presentation. /// <para> /// If it does not match the <see cref="SurfaceCapabilitiesKhr.CurrentTransform"/> value /// returned by <see cref="PhysicalDeviceExtensions.GetSurfaceCapabilitiesKhr"/>, the /// presentation engine will transform the image content as part of the presentation operation. /// </para> /// </param> /// <param name="compositeAlpha"> /// A bitmask indicating the alpha compositing mode to use when this surface is composited /// together with other surfaces on certain window systems. /// </param> /// <param name="presentMode"> /// The presentation mode the swapchain will use. /// <para> /// A swapchain's present mode determines how incoming present requests will be processed and /// queued internally. /// </para> /// </param> /// <param name="clipped"> /// Indicates whether the Vulkan implementation is allowed to discard rendering operations /// that affect regions of the surface which are not visible.</param> /// <param name="oldSwapchain">Existing swapchain to replace, if any.</param> public SwapchainCreateInfoKhr( SurfaceKhr surface, Format imageFormat, Extent2D imageExtent, int minImageCount = 2, ColorSpaceKhr imageColorSpace = ColorSpaceKhr.SRgbNonlinear, int imageArrayLayers = 1, ImageUsages imageUsage = ImageUsages.ColorAttachment | ImageUsages.TransferDst, SharingMode imageSharingMode = SharingMode.Exclusive, int[] queueFamilyIndices = null, SurfaceTransformsKhr preTransform = SurfaceTransformsKhr.Identity, CompositeAlphasKhr compositeAlpha = CompositeAlphasKhr.Opaque, PresentModeKhr presentMode = PresentModeKhr.Fifo, bool clipped = true, SwapchainKhr oldSwapchain = null) { Flags = SwapchainCreateFlagsKhr.None; Surface = surface; MinImageCount = minImageCount; ImageFormat = imageFormat; ImageColorSpace = imageColorSpace; ImageExtent = imageExtent; ImageArrayLayers = imageArrayLayers; ImageUsage = imageUsage; ImageSharingMode = imageSharingMode; QueueFamilyIndices = queueFamilyIndices; PreTransform = preTransform; CompositeAlpha = compositeAlpha; PresentMode = presentMode; Clipped = clipped; OldSwapchain = oldSwapchain; }
/// <summary> /// Initializes a new instance of the <see cref="SwapchainCreateInfoKhr"/> structure. /// </summary> /// <param name="surface"> /// The <see cref="SurfaceKhr"/> that the swapchain will present images to. /// </param> /// <param name="imageExtent"> /// The size (in pixels) of the swapchain. /// <para> /// Behavior is platform-dependent when the image extent does not match the surface's <see /// cref="SurfaceCapabilitiesKhr.CurrentExtent"/> as returned by <see cref="PhysicalDeviceExtensions.GetSurfaceCapabilitiesKhr"/>. /// </para> /// </param> /// <param name="preTransform"> /// A bitmask describing the transform, relative to the presentation engine's natural /// orientation, applied to the image content prior to presentation. /// <para> /// If it does not match the <see cref="SurfaceCapabilitiesKhr.CurrentTransform"/> value /// returned by <see cref="PhysicalDeviceExtensions.GetSurfaceCapabilitiesKhr"/>, the /// presentation engine will transform the image content as part of the presentation operation. /// </para> /// </param> /// <param name="imageUsage"> /// A bitmask indicating how the application will use the swapchain's presentable images. /// </param> /// <param name="flags">A bitmask indicating parameters of swapchain creation.</param> /// <param name="minImageCount"> /// The minimum number of presentable images that the application needs. The platform will /// either create the swapchain with at least that many images, or will fail to create the swapchain. /// </param> /// <param name="imageFormat">A format that is valid for swapchains on the specified surface.</param> /// <param name="compositeAlpha"> /// A bitmask indicating the alpha compositing mode to use when this surface is composited /// together with other surfaces on certain window systems. /// </param> /// <param name="imageArrayLayers"> /// The number of views in a multiview/stereo surface. For non-stereoscopic-3D applications, /// this value is 1. /// </param> /// <param name="presentMode"> /// The presentation mode the swapchain will use. /// <para> /// A swapchain's present mode determines how incoming present requests will be processed and /// queued internally. /// </para> /// </param> /// <param name="clipped"> /// Indicates whether the Vulkan implementation is allowed to discard rendering operations /// that affect regions of the surface which are not visible. /// </param> /// <param name="oldSwapchain">Existing swapchain to replace, if any.</param> public SwapchainCreateInfoKhr( SurfaceKhr surface, Format imageFormat, Extent2D imageExtent, SurfaceTransformsKhr preTransform, PresentModeKhr presentMode, SwapchainCreateFlagsKhr flags = 0, int minImageCount = 2, ImageUsages imageUsage = ImageUsages.ColorAttachment | ImageUsages.TransferDst, CompositeAlphasKhr compositeAlpha = CompositeAlphasKhr.Opaque, int imageArrayLayers = 1, bool clipped = true, SwapchainKhr oldSwapchain = null) { Flags = flags; Surface = surface; ImageUsage = imageUsage; MinImageCount = minImageCount; ImageFormat = imageFormat; ImageColorSpace = 0; ImageExtent = imageExtent; ImageArrayLayers = imageArrayLayers; ImageSharingMode = 0; QueueFamilyIndices = null; PreTransform = preTransform; CompositeAlpha = compositeAlpha; PresentMode = presentMode; Clipped = clipped; OldSwapchain = oldSwapchain; }
/// <summary> /// Queue an image for presentation. /// </summary> /// <param name="queue"> /// The queue that is capable of presentation to the target surface's platform on the same /// device as the image's swapchain. /// </param> /// <param name="waitSemaphore">Semaphore to wait for before presenting.</param> /// <param name="swapchain">Valid swapchain handle.</param> /// <param name="imageIndex">Index into the array of swapchain's presentable images.</param> /// <exception cref="VulkanException">Vulkan returns an error code.</exception> public static void PresentKhr(this Queue queue, Semaphore waitSemaphore, SwapchainKhr swapchain, int imageIndex) { long waitSemaphoreHandle = waitSemaphore; long swapchainHandle = swapchain; var nativePresentInfo = new PresentInfoKhr.Native { Type = StructureType.PresentInfoKhr, WaitSemaphoreCount = waitSemaphoreHandle == 0 ? 0 : 1, WaitSemaphores = &waitSemaphoreHandle, SwapchainCount = swapchainHandle == 0 ? 0 : 1, Swapchains = &swapchainHandle, ImageIndices = &imageIndex }; Result result = vkQueuePresentKHR(queue, &nativePresentInfo); VulkanException.ThrowForInvalidResult(result); }
private static vkGetSwapchainStatusKHRDelegate vkGetSwapchainStatusKHR(SwapchainKhr swapchain) => swapchain.Parent.GetProc <vkGetSwapchainStatusKHRDelegate>(nameof(vkGetSwapchainStatusKHR));
private void rebuildSwapchain() { var sCaps = VkKhr.PhysicalDeviceExtensions.GetSurfaceCapabilitiesKhr(_vkPhysicalDevice, Surface); // Calculate the size of the images if (sCaps.CurrentExtent.Width != Int32.MaxValue) // We have to use the given size { Extent = sCaps.CurrentExtent; } else // We can choose an extent, but we will just make it the size of the window { Extent = Point.Max(sCaps.MinImageExtent, Point.Min(sCaps.MaxImageExtent, _window.Size)); } // Calculate the number of images int imCount = sCaps.MinImageCount + 1; if (sCaps.MaxImageCount != 0) { imCount = Math.Min(imCount, sCaps.MaxImageCount); } _syncObjects.MaxInflightFrames = (uint)Math.Min(imCount, MAX_INFLIGHT_FRAMES); // Create the swapchain var oldSwapChain = _swapChain; VkKhr.SwapchainCreateInfoKhr cInfo = new VkKhr.SwapchainCreateInfoKhr( Surface, _surfaceFormat.Format, Extent, minImageCount: imCount, imageColorSpace: _surfaceFormat.ColorSpace, imageUsage: Vk.ImageUsages.ColorAttachment | Vk.ImageUsages.TransferDst, presentMode: _presentMode, oldSwapchain: oldSwapChain ); _swapChain = VkKhr.DeviceExtensions.CreateSwapchainKhr(_vkDevice, cInfo); // Destroy the old swapchain oldSwapChain?.Dispose(); // Get the new swapchain images var imgs = _swapChain.GetImages(); _swapChainImages = new SwapchainImage[imgs.Length]; imgs.ForEach((img, idx) => { Vk.ImageViewCreateInfo vInfo = new Vk.ImageViewCreateInfo( _surfaceFormat.Format, DEFAULT_SUBRESOURCE_RANGE, viewType: Vk.ImageViewType.Image2D, components: default ); var view = img.CreateView(vInfo); _swapChainImages[idx] = new SwapchainImage { Image = img, View = view, TransferBarrier = new Vk.ImageMemoryBarrier( img, new Vk.ImageSubresourceRange(Vk.ImageAspects.Color, 0, 1, 0, 1), Vk.Accesses.ColorAttachmentRead, Vk.Accesses.TransferWrite, Vk.ImageLayout.PresentSrcKhr, Vk.ImageLayout.TransferDstOptimal ), PresentBarrier = new Vk.ImageMemoryBarrier( img, new Vk.ImageSubresourceRange(Vk.ImageAspects.Color, 0, 1, 0, 1), Vk.Accesses.TransferWrite, Vk.Accesses.ColorAttachmentRead, Vk.ImageLayout.TransferDstOptimal, Vk.ImageLayout.PresentSrcKhr ) }; }); // Perform the initial layout transitions to present mode _commandBuffer.Begin(ONE_TIME_SUBMIT); var imb = new Vk.ImageMemoryBarrier(null, new Vk.ImageSubresourceRange(Vk.ImageAspects.Color, 0, 1, 0, 1), Vk.Accesses.TransferWrite, Vk.Accesses.ColorAttachmentRead, Vk.ImageLayout.Undefined, Vk.ImageLayout.PresentSrcKhr); _commandBuffer.CmdPipelineBarrier(Vk.PipelineStages.AllCommands, Vk.PipelineStages.AllCommands, imageMemoryBarriers: _swapChainImages.Select(sci => { imb.Image = sci.Image; return(imb); }).ToArray()); _commandBuffer.End(); _presentQueue.Submit(new Vk.SubmitInfo(commandBuffers: new[] { _commandBuffer }), _blitFence); _blitFence.Wait(); // Do not reset // Report LDEBUG($"Presentation swapchain rebuilt @ {Extent} " + $"(F:{_surfaceFormat.Format}:{_surfaceFormat.ColorSpace==VkKhr.ColorSpaceKhr.SRgbNonlinear} I:{_swapChainImages.Length}:{_syncObjects.MaxInflightFrames})."); Dirty = false; }
/// <summary> /// Create multiple swapchains that share presentable images. /// <para> /// Is similar to <see cref="CreateSwapchainKhr"/>, except that it takes an array of <see /// cref="SwapchainCreateInfoKhr"/> structures, and returns an array of swapchain objects. /// </para> /// <para> /// The swapchain creation parameters that affect the properties and number of presentable /// images must match between all the swapchains.If the displays used by any of the /// swapchains do not use the same presentable image layout or are incompatible in a way that /// prevents sharing images, swapchain creation will fail with the result code <see /// cref="Result.ErrorIncompatibleDisplayKhr"/>. If any error occurs, no swapchains will be /// created. Images presented to multiple swapchains must be re-acquired from all of them /// before transitioning away from <see cref="ImageLayout.PresentSrcKhr"/>. After destroying /// one or more of the swapchains, the remaining swapchains and the presentable images can /// continue to be used. /// </para> /// </summary> /// <param name="device">The device to create the swapchains for.</param> /// <param name="createInfos">Structures specifying the parameters of the created swapchains.</param> /// <param name="allocator"> /// The allocator used for host memory allocated for the swapchain objects when there is no /// more specific allocator available. /// </param> /// <returns>The created swapchain objects.</returns> /// <exception cref="VulkanException">Vulkan returns an error code.</exception> public static SwapchainKhr[] CreateSharedSwapchainsKhr(this Device device, SwapchainCreateInfoKhr[] createInfos, AllocationCallbacks?allocator = null) { return(SwapchainKhr.CreateSharedKhr(device, createInfos, ref allocator)); }