Exemplo n.º 1
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);
        }
Exemplo n.º 2
0
        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;
        }