Example #1
0
        protected SwapchainData CreateSwapchain(PhysicalDevice physicalDevice, SurfaceKHR surface, uint windowWidth, uint windowHeight)
        {
            var data = new SwapchainData();

            var surfaceFormats = physicalDevice.GetSurfaceFormatsKHR(surface);
            var surfaceFormat  = surfaceFormats[0].Format;

            var surfaceCapabilities = physicalDevice.GetSurfaceCapabilitiesKHR(surface);

            var desiredImageCount = Math.Min(surfaceCapabilities.MinImageCount + 1, surfaceCapabilities.MaxImageCount);

            SurfaceTransformFlagsKHR preTransform;

            if ((surfaceCapabilities.SupportedTransforms & SurfaceTransformFlagsKHR.Identity) != 0)
            {
                preTransform = SurfaceTransformFlagsKHR.Identity;
            }
            else
            {
                preTransform = surfaceCapabilities.CurrentTransform;
            }

            var presentModes = physicalDevice.GetSurfacePresentModesKHR(surface);

            var swapChainPresentMode = PresentModeKHR.Fifo;

            if (presentModes.Contains(PresentModeKHR.Mailbox))
            {
                swapChainPresentMode = PresentModeKHR.Mailbox;
            }
            else if (presentModes.Contains(PresentModeKHR.Immediate))
            {
                swapChainPresentMode = PresentModeKHR.Immediate;
            }

            var imageExtent         = new Extent2D(windowWidth, windowHeight);
            var swapchainCreateInfo = new SwapchainCreateInfoKHR
            {
                Surface       = surface,
                MinImageCount = desiredImageCount,

                ImageFormat      = surfaceFormat,
                ImageExtent      = imageExtent,
                ImageArrayLayers = 1,
                ImageUsage       = ImageUsageFlags.ColorAttachment,
                ImageSharingMode = SharingMode.Exclusive,
                //ImageColorSpace    = ColorSpaceKHR.SrgbNonlinear,

                QueueFamilyIndices = null,
                PreTransform       = preTransform,
                CompositeAlpha     = CompositeAlphaFlagsKHR.Opaque,
                PresentMode        = swapChainPresentMode,
                Clipped            = true,
            };

            data.Swapchain   = device.CreateSwapchainKHR(swapchainCreateInfo);
            data.ImageFormat = surfaceFormat;

            return(data);
        }
Example #2
0
        public static Result CreateSwapchainKHR(Device device, ref SwapchainCreateInfoKHR pCreateInfo, ref SwapchainKHR pSwapchain, AllocationCallbacks pAllocator = null)
        {
            _SwapchainCreateInfoKHR info = new _SwapchainCreateInfoKHR(pCreateInfo);
            Result res = _CreateSwapchainKHR(device, ref info, pAllocator, out pSwapchain);

            info.destroy();

            return(res);
        }
        public SwapchainManager(Device LogicalDevice, SurfaceFormatKHR SelectedSurfaceFormat)
        {
            var compositeAlpha = VulkanRenderer.Surface.SurfaceCapabilities.SupportedCompositeAlpha.HasFlag(CompositeAlphaFlagsKHR.Inherit)
               ? CompositeAlphaFlagsKHR.Inherit
               : CompositeAlphaFlagsKHR.Opaque;
            SemaphoreCreateInfo semaphoreInfo = new SemaphoreCreateInfo();

            SwapchainDrawCompleteSemaphore = LogicalDevice.CreateSemaphore(semaphoreInfo);
            CreateDefaultSwapchainRenderPass(LogicalDevice);
            renderPassBeginInfo = new RenderPassBeginInfo {
                ClearValueCount = 1, ClearValues = new ClearValue[] { new ClearValue {
                                                                          Color = new ClearColorValue(Color.AliceBlue)
                                                                      } }, RenderPass = myBaseRenderPass
            };
            renderPassBeginInfo.RenderArea = new Rect2D {
                Extent = new Extent2D {
                    Width = VulkanRenderer.Surface.SurfaceCapabilities.CurrentExtent.Width, Height = VulkanRenderer.Surface.SurfaceCapabilities.CurrentExtent.Height
                }, Offset = new Offset2D {
                    X = 0, Y = 0
                }
            };
            var swapchainInfo = new SwapchainCreateInfoKHR
            {
                Surface            = VulkanRenderer.Surface,
                MinImageCount      = VulkanRenderer.Surface.SurfaceCapabilities.MinImageCount + 1,
                ImageFormat        = VulkanRenderer.Surface.SelectedSurfaceFormat.Format,
                ImageColorSpace    = VulkanRenderer.Surface.SelectedSurfaceFormat.ColorSpace,
                ImageExtent        = VulkanRenderer.Surface.SurfaceCapabilities.CurrentExtent,
                ImageUsage         = ImageUsageFlags.ColorAttachment,
                PreTransform       = SurfaceTransformFlagsKHR.Identity,
                ImageArrayLayers   = 1,
                ImageSharingMode   = SharingMode.Exclusive,
                QueueFamilyIndices = new uint[] { VulkanRenderer.ActiveGraphicsFamilyQueueIndex },
                PresentMode        = PresentModeKHR.Fifo,
                CompositeAlpha     = compositeAlpha
            };

            Swapchain            = VulkanRenderer.SelectedLogicalDevice.CreateSwapchainKHR(swapchainInfo);
            Images               = VulkanRenderer.SelectedLogicalDevice.GetSwapchainImagesKHR(Swapchain);
            SwapChainPresentInfo = new PresentInfoKHR
            {
                Swapchains   = new SwapchainKHR[] { Swapchain },
                ImageIndices = new uint[] { VulkanRenderer.SelectedLogicalDevice.AcquireNextImageKHR(Swapchain, ulong.MaxValue, SwapchainDrawCompleteSemaphore) }
            };


            Framebuffers = new SwapChainFrameBuffer[Images.Length]; //Move this to swap chains

            for (int i = 0; i < Images.Length; i++)
            {
                Framebuffers[i] = new SwapChainFrameBuffer(myBaseRenderPass, Images[i], i, VulkanRenderer.Surface.SurfaceCapabilities.CurrentExtent.Width, VulkanRenderer.Surface.SurfaceCapabilities.CurrentExtent.Height, 1);
                Framebuffers[i].Initialize();
            }
        }
Example #4
0
        public unsafe SwapChain(Api api, Window window, Surface surface, PresentModeKHR presentMode)
        {
            _api = api;

            QuerySwapChainSupport(_api.Device.PhysicalDevice, surface.VkServiceKHR, out var details);
            if (details.Formats.Count == 0 || details.PresentModes.Count == 0)
            {
                throw new Exception($"{nameof(SwapChain)}: Empty swap chain support");
            }

            ChooseSwapSurfaceFormat(details.Formats, out var surfaceFormat);
            var actualPresentMode = ChooseSwapPresentMode(details.PresentModes, presentMode);

            ChooseSwapExtent(window, details.Capabilities, out var extent);
            var imageCount = ChooseImageCount(details.Capabilities);

            var createInfo = new SwapchainCreateInfoKHR();

            createInfo.SType            = StructureType.SwapchainCreateInfoKhr;
            createInfo.Surface          = surface.VkServiceKHR;
            createInfo.MinImageCount    = imageCount;
            createInfo.ImageFormat      = surfaceFormat.Format;
            createInfo.ImageColorSpace  = surfaceFormat.ColorSpace;
            createInfo.ImageExtent      = extent;
            createInfo.ImageArrayLayers = 1;
            createInfo.ImageUsage       = ImageUsageFlags.ImageUsageColorAttachmentBit | ImageUsageFlags.ImageUsageTransferDstBit;
            createInfo.PreTransform     = details.Capabilities.CurrentTransform;
            createInfo.CompositeAlpha   = CompositeAlphaFlagsKHR.CompositeAlphaOpaqueBitKhr;
            createInfo.PresentMode      = actualPresentMode;
            createInfo.Clipped          = true;
            createInfo.OldSwapchain     = default;

            Span <uint> queueFamilyIndices = stackalloc uint[]
            {
                api.Device.GraphicsFamilyIndex,
                api.Device.PresentationFamilyIndex,
            };

            if (api.Device.GraphicsFamilyIndex != api.Device.PresentationFamilyIndex)
            {
                createInfo.ImageSharingMode      = SharingMode.Concurrent;
                createInfo.QueueFamilyIndexCount = 2;
                createInfo.PQueueFamilyIndices   = (uint *)Unsafe.AsPointer(ref queueFamilyIndices[0]);
            }
            else
            {
                createInfo.ImageSharingMode      = SharingMode.Exclusive;
                createInfo.QueueFamilyIndexCount = 0;                 // Optional
                createInfo.PQueueFamilyIndices   = null;              // Optional
            }

            Util.Verify(_api.KhrSwapchain.CreateSwapchain(_api.Device.VkDevice, createInfo, default, out _swapChainKhr), $"{nameof(SwapChain)}: Could not create a swap chain");
Example #5
0
            public _SwapchainCreateInfoKHR(SwapchainCreateInfoKHR info)
            {
                SType                 = info.type;
                Next                  = info.next;
                Flags                 = info.flags;
                Surface               = info.surface;
                MinImageCount         = info.minImageCount;
                ImageFormat           = info.imageFormat;
                ImageColorSpace       = info.imageColorSpace;
                ImageExtent           = info.imageExtent;
                ImageArrayLayers      = info.imageArrayLayers;
                ImageUsage            = info.imageUsage;
                ImageSharingMode      = info.imageSharingMode;
                QueueFamilyIndexCount = (UInt32)(info.queueFamilyIndices?.Count ?? 0);
                QueueFamilyIndices    = info.queueFamilyIndices != null?Alloc.alloc(info.queueFamilyIndices) : IntPtr.Zero;

                PreTransform   = info.preTransform;
                CompositeAlpha = info.compositeAlpha;
                PresentMode    = info.presentMode;
                Clipped        = info.clipped;
                OldSwapchain   = info.oldSwapchain;
            }
Example #6
0
 public abstract Result CreateSwapchain([Count(Count = 0)] Device device, [Count(Count = 0), Flow(FlowDirection.In)] ref SwapchainCreateInfoKHR pCreateInfo, [Count(Count = 0), Flow(FlowDirection.In)] ref AllocationCallbacks pAllocator, [Count(Count = 0), Flow(FlowDirection.Out)] out SwapchainKHR pSwapchain);
Example #7
0
        private SwapchainKHR CreateSwapchain(out Extent2D extent, out Format swapImageFormat, out SwapchainImage[] swapImages)
        {
            QuerySwapchainSupport(this.PhysicalDevice, out var details);

            var surfaceFormat = ChooseSwapSurfaceFormat(details.Formats);
            var presentMode   = ChooseSwapPresentMode(details.PresentModes);

            extent = ChooseSwapExtent(details.Capabilities);

            var imageCount = details.Capabilities.MinImageCount + 1;

            if (details.Capabilities.MaxImageCount > 0 && imageCount > details.Capabilities.MaxImageCount)
            {
                imageCount = details.Capabilities.MaxImageCount;
            }

            var createInfo = new SwapchainCreateInfoKHR
            {
                SType            = StructureType.SwapchainCreateInfoKhr,
                Surface          = this.WindowSurface,
                MinImageCount    = imageCount,
                ImageFormat      = surfaceFormat.Format,
                ImageColorSpace  = surfaceFormat.ColorSpace,
                ImageExtent      = extent,
                ImageArrayLayers = 1,
                ImageUsage       = ImageUsageFlags.ImageUsageColorAttachmentBit
            };

            if (this.QueueIndices.GraphicsFamily != this.QueueIndices.PresentFamily)
            {
                createInfo.ImageSharingMode      = SharingMode.Concurrent;
                createInfo.QueueFamilyIndexCount = 2;

                var indices = stackalloc uint[2] {
                    this.QueueIndices.GraphicsFamily.Value, this.QueueIndices.PresentFamily.Value
                };

                createInfo.PQueueFamilyIndices = indices;
            }
            else
            {
                createInfo.ImageSharingMode = SharingMode.Exclusive;
            }

            createInfo.PreTransform   = details.Capabilities.CurrentTransform;
            createInfo.CompositeAlpha = CompositeAlphaFlagsKHR.CompositeAlphaOpaqueBitKhr;
            createInfo.PresentMode    = presentMode;
            createInfo.Clipped        = true;

            createInfo.OldSwapchain = default;

            SwapchainKHR swapchain;

            var res = this.VkSwapchain.CreateSwapchain(Device, &createInfo, null, &swapchain);

            if (res != Result.Success)
            {
                throw new VMASharp.VulkanResultException("Failed to create swapchain!", res);
            }

            uint count = 0;

            res = VkSwapchain.GetSwapchainImages(this.Device, swapchain, &count, null);

            if (res != Result.Success)
            {
                throw new VMASharp.VulkanResultException("Failed to retrieve swapchain images!", res);
            }

            var images = stackalloc Image[(int)count];

            res = VkSwapchain.GetSwapchainImages(this.Device, swapchain, &count, images);

            if (res != Result.Success)
            {
                throw new VMASharp.VulkanResultException("Failed to retrieve swapchain images!", res);
            }

            var viewCreateInfo = new ImageViewCreateInfo
            {
                SType      = StructureType.ImageViewCreateInfo,
                ViewType   = ImageViewType.ImageViewType2D,
                Format     = surfaceFormat.Format,
                Components =
                {
                    R = ComponentSwizzle.Identity,
                    G = ComponentSwizzle.Identity,
                    B = ComponentSwizzle.Identity,
                    A = ComponentSwizzle.Identity
                },
                SubresourceRange =
                {
                    AspectMask     = ImageAspectFlags.ImageAspectColorBit,
                    BaseMipLevel   =                                    0,
                    LevelCount     =                                    1,
                    BaseArrayLayer =                                    0,
                    LayerCount     = 1
                }
            };

            var arr = new SwapchainImage[count];

            for (int i = 0; i < arr.Length; ++i)
            {
                viewCreateInfo.Image = images[i];

                ImageView view = default;
                res = VkApi.CreateImageView(this.Device, &viewCreateInfo, null, &view);

                if (res != Result.Success)
                {
                    throw new VMASharp.VulkanResultException("Swapchain image view creation failed!", res);
                }

                arr[i] = new SwapchainImage {
                    Image = images[i], View = view
                };
            }

            swapImageFormat = surfaceFormat.Format;
            swapImages      = arr;

            return(swapchain);
        }
Example #8
0
        void CreateSwapChain()
        {
            CanRender = false;

            if (!vulkan.Device.IsZero)
            {
                vk.DeviceWaitIdle(vulkan.Device);
            }

            if (vulkan.SwapChain.Images != null)
            {
                for (int i = 0; i < vulkan.SwapChain.Images.Length; ++i)
                {
                    if (vulkan.SwapChain.Images[i].View != ImageView.Zero)
                    {
                        vk.DestroyImageView(vulkan.Device, vulkan.SwapChain.Images[i].View);
                    }
                }
            }

            SurfaceCapabilitiesKHR surface_capabilities;

            khrSurface.GetPhysicalDeviceSurfaceCapabilitiesKHR(vulkan.PhysicalDevice, vulkan.PresentationSurface, out surface_capabilities).CheckError();

            var surface_formats = DelegateUtility.EnumerateToArray <SurfaceFormatKHR> (khrSurface.GetPhysicalDeviceSurfaceFormatsKHR,
                                                                                       (IntPtr)vulkan.PhysicalDevice, (ulong)vulkan.PresentationSurface);

            var present_modes = DelegateUtility.EnumerateToArray <int> (khrSurface.GetPhysicalDeviceSurfacePresentModesKHR,
                                                                        (IntPtr)vulkan.PhysicalDevice, (ulong)vulkan.PresentationSurface);


            uint                        desired_number_of_images = GetSwapChainNumImages(ref surface_capabilities);
            SurfaceFormatKHR            desired_format           = GetSwapChainFormat(surface_formats);
            Extent2D                    desired_extent           = GetSwapChainExtent(ref surface_capabilities);
            ImageUsageFlagBits          desired_usage            = GetSwapChainUsageFlagBits(ref surface_capabilities);
            SurfaceTransformFlagBitsKHR desired_transform        = GetSwapChainTransform(ref surface_capabilities);
            PresentModeKHR              desired_present_mode     = GetSwapChainPresentMode(present_modes);
            SwapchainKHR                old_swap_chain           = vulkan.SwapChain.Handle;

            if (desired_usage == (ImageUsageFlagBits)(-1))
            {
                return;
            }
            if (desired_present_mode == (PresentModeKHR)(-1))
            {
                return;
            }

            if ((desired_extent.width == 0) || (desired_extent.height == 0))
            {
                // Current surface size is (0, 0) so we can't create a swap chain and render anything (CanRender == false)
                // But we don't wont to kill the application as this situation may occur i.e. when window gets minimized
                return;
            }

            SwapchainCreateInfoKHR swap_chain_create_info = new SwapchainCreateInfoKHR
            {
                sType                 = StructureType.SwapchainCreateInfoKhr,         // VkStructureType                sType
                pNext                 = IntPtr.Zero,                                  // const void                    *pNext
                flags                 = 0,                                            // VkSwapchainCreateFlagBitsKHR      flags
                surface               = vulkan.PresentationSurface,                   // VkSurfaceKHR                   surface
                minImageCount         = desired_number_of_images,                     // uint32_t                       minImageCount
                imageFormat           = desired_format.format,                        // VkFormat                       imageFormat
                imageColorSpace       = desired_format.colorSpace,                    // VkColorSpaceKHR                imageColorSpace
                imageExtent           = desired_extent,                               // VkExtent2D                     imageExtent
                imageArrayLayers      = 1,                                            // uint32_t                       imageArrayLayers
                imageUsage            = desired_usage,                                // VkImageUsageFlagBits              imageUsage
                imageSharingMode      = SharingMode.Exclusive,                        // VkSharingMode                  imageSharingMode
                queueFamilyIndexCount = 0,                                            // uint32_t                       queueFamilyIndexCount
                pQueueFamilyIndices   = (uint *)0,                                    // const uint32_t                *pQueueFamilyIndices
                preTransform          = desired_transform,                            // VkSurfaceTransformFlagBitsKHR  preTransform
                compositeAlpha        = CompositeAlphaFlagBitsKHR.OpaqueBitKhr,       // VkCompositeAlphaFlagBitsKHR    compositeAlpha
                presentMode           = desired_present_mode,                         // VkPresentModeKHR               presentMode
                clipped               = Boolean32.True,                               // VkBool32                       clipped
                oldSwapchain          = old_swap_chain                                // VkSwapchainKHR                 oldSwapchain
            };

            khrSwapChain.CreateSwapchainKHR(vulkan.Device, ref swap_chain_create_info, (AllocationCallbacks *)0, out vulkan.SwapChain.Handle).CheckError();

            if (!old_swap_chain.IsZero)
            {
                khrSwapChain.DestroySwapchainKHR(vulkan.Device, old_swap_chain);
            }

            vulkan.SwapChain.Format = desired_format.format;

            var images = DelegateUtility.EnumerateToArray <Image> (khrSwapChain.GetSwapchainImagesKHR,
                                                                   (IntPtr)vulkan.Device, (ulong)vulkan.SwapChain.Handle);

            if (vulkan.SwapChain.Images == null || vulkan.SwapChain.Images.Length != images.Length)
            {
                vulkan.SwapChain.Images = new ImageParameters[images.Length];
            }

            for (int i = 0; i < images.Length; ++i)
            {
                vulkan.SwapChain.Images[i].Handle = images[i];
            }

            vulkan.SwapChain.Extent = desired_extent;

            CreateSwapChainImageViews();
        }
Example #9
0
        private static unsafe SwapchainKHR CreateSwapchain(VulkanInstance instance, VulkanDevice device,
                                                           VulkanPhysicalDevice physicalDevice, VulkanSurface surface, out Extent2D swapchainExtent,
                                                           SwapchainKHR?oldswapchain = null, bool vsyncEnabled = true)
        {
            if (_swapchainExtension == null)
            {
                instance.Api.TryGetDeviceExtension(instance.InternalHandle, device.InternalHandle, out _swapchainExtension);
            }

            while (!surface.CanSurfacePresent(physicalDevice))
            {
                Thread.Sleep(16);
            }

            VulkanSurface.SurfaceExtension.GetPhysicalDeviceSurfaceCapabilities(physicalDevice.InternalHandle,
                                                                                surface.ApiHandle, out var capabilities);

            var imageCount = capabilities.MinImageCount + 1;

            if (capabilities.MaxImageCount > 0 && imageCount > capabilities.MaxImageCount)
            {
                imageCount = capabilities.MaxImageCount;
            }

            var surfaceFormat = surface.GetSurfaceFormat(physicalDevice);

            bool supportsIdentityTransform = capabilities.SupportedTransforms.HasFlag(SurfaceTransformFlagsKHR.SurfaceTransformIdentityBitKhr);
            bool isRotated = capabilities.CurrentTransform.HasFlag(SurfaceTransformFlagsKHR.SurfaceTransformRotate90BitKhr) ||
                             capabilities.CurrentTransform.HasFlag(SurfaceTransformFlagsKHR.SurfaceTransformRotate270BitKhr);

            swapchainExtent = GetSwapchainExtent(surface, capabilities);

            CompositeAlphaFlagsKHR compositeAlphaFlags = GetSuitableCompositeAlphaFlags(capabilities);

            PresentModeKHR presentMode = GetSuitablePresentMode(physicalDevice, surface, vsyncEnabled);

            var swapchainCreateInfo = new SwapchainCreateInfoKHR
            {
                SType           = StructureType.SwapchainCreateInfoKhr,
                Surface         = surface.ApiHandle,
                MinImageCount   = imageCount,
                ImageFormat     = surfaceFormat.Format,
                ImageColorSpace = surfaceFormat.ColorSpace,
                ImageExtent     = swapchainExtent,
                ImageUsage      =
                    ImageUsageFlags.ImageUsageColorAttachmentBit | ImageUsageFlags.ImageUsageTransferDstBit,
                ImageSharingMode = SharingMode.Exclusive,
                ImageArrayLayers = 1,
                PreTransform     = supportsIdentityTransform && isRotated ?
                                   SurfaceTransformFlagsKHR.SurfaceTransformIdentityBitKhr :
                                   capabilities.CurrentTransform,
                CompositeAlpha = compositeAlphaFlags,
                PresentMode    = presentMode,
                Clipped        = true,
                OldSwapchain   = oldswapchain ?? new SwapchainKHR()
            };

            _swapchainExtension.CreateSwapchain(device.InternalHandle, swapchainCreateInfo, null, out var swapchain)
            .ThrowOnError();

            if (oldswapchain != null)
            {
                _swapchainExtension.DestroySwapchain(device.InternalHandle, oldswapchain.Value, null);
            }

            return(swapchain);
        }
Example #10
0
        private unsafe void CreateSwapchain()
        {
            _gd.SurfaceApi.GetPhysicalDeviceSurfaceCapabilities(_physicalDevice, _surface, out var capabilities);

            uint surfaceFormatsCount;

            _gd.SurfaceApi.GetPhysicalDeviceSurfaceFormats(_physicalDevice, _surface, &surfaceFormatsCount, null);

            var surfaceFormats = new SurfaceFormatKHR[surfaceFormatsCount];

            fixed(SurfaceFormatKHR *pSurfaceFormats = surfaceFormats)
            {
                _gd.SurfaceApi.GetPhysicalDeviceSurfaceFormats(_physicalDevice, _surface, &surfaceFormatsCount, pSurfaceFormats);
            }

            uint presentModesCount;

            _gd.SurfaceApi.GetPhysicalDeviceSurfacePresentModes(_physicalDevice, _surface, &presentModesCount, null);

            var presentModes = new PresentModeKHR[presentModesCount];

            fixed(PresentModeKHR *pPresentModes = presentModes)
            {
                _gd.SurfaceApi.GetPhysicalDeviceSurfacePresentModes(_physicalDevice, _surface, &presentModesCount, pPresentModes);
            }

            uint imageCount = capabilities.MinImageCount + 1;

            if (capabilities.MaxImageCount > 0 && imageCount > capabilities.MaxImageCount)
            {
                imageCount = capabilities.MaxImageCount;
            }

            var surfaceFormat = ChooseSwapSurfaceFormat(surfaceFormats);

            var extent = ChooseSwapExtent(capabilities);

            _width  = (int)extent.Width;
            _height = (int)extent.Height;
            _format = surfaceFormat.Format;

            var oldSwapchain = _swapchain;

            var swapchainCreateInfo = new SwapchainCreateInfoKHR()
            {
                SType            = StructureType.SwapchainCreateInfoKhr,
                Surface          = _surface,
                MinImageCount    = imageCount,
                ImageFormat      = surfaceFormat.Format,
                ImageColorSpace  = surfaceFormat.ColorSpace,
                ImageExtent      = extent,
                ImageUsage       = ImageUsageFlags.ImageUsageColorAttachmentBit | ImageUsageFlags.ImageUsageTransferDstBit,
                ImageSharingMode = SharingMode.Exclusive,
                ImageArrayLayers = 1,
                PreTransform     = capabilities.CurrentTransform,
                CompositeAlpha   = CompositeAlphaFlagsKHR.CompositeAlphaOpaqueBitKhr,
                PresentMode      = ChooseSwapPresentMode(presentModes),
                Clipped          = true,
                OldSwapchain     = oldSwapchain
            };

            _gd.SwapchainApi.CreateSwapchain(_device, swapchainCreateInfo, null, out _swapchain).ThrowOnError();

            _gd.SwapchainApi.GetSwapchainImages(_device, _swapchain, &imageCount, null);

            _swapchainImages = new Image[imageCount];

            fixed(Image *pSwapchainImages = _swapchainImages)
            {
                _gd.SwapchainApi.GetSwapchainImages(_device, _swapchain, &imageCount, pSwapchainImages);
            }

            _swapchainImageViews = new Auto <DisposableImageView> [imageCount];

            for (int i = 0; i < imageCount; i++)
            {
                _swapchainImageViews[i] = CreateSwapchainImageView(_swapchainImages[i], surfaceFormat.Format);
            }
        }
 public abstract Result CreateSharedSwapchain([Count(Count = 0)] Device device, [Count(Count = 0)] uint swapchainCount, [Count(Computed = "swapchainCount"), Flow(FlowDirection.In)] ref SwapchainCreateInfoKHR pCreateInfos, [Count(Count = 0), Flow(FlowDirection.In)] ref AllocationCallbacks pAllocator, [Count(Computed = "swapchainCount"), Flow(FlowDirection.Out)] out SwapchainKHR pSwapchains);