Exemplo n.º 1
0
        public Swapchain(GraphicsDevice device, Window window)
        {
            Device = device;
            Window = window;

            SwapChainSupportDetails swapChainSupport = QuerySwapChainSupport(device.PhysicalDevice, device._surface);

            VkSurfaceFormatKHR surfaceFormat = ChooseSwapSurfaceFormat(swapChainSupport.Formats);
            VkPresentModeKHR   presentMode   = ChooseSwapPresentMode(swapChainSupport.PresentModes);

            _extent = ChooseSwapExtent(swapChainSupport.Capabilities);

            CreateRenderPass(surfaceFormat.format);

            uint imageCount = swapChainSupport.Capabilities.minImageCount + 1;

            if (swapChainSupport.Capabilities.maxImageCount > 0 &&
                imageCount > swapChainSupport.Capabilities.maxImageCount)
            {
                imageCount = swapChainSupport.Capabilities.maxImageCount;
            }

            var createInfo = new VkSwapchainCreateInfoKHR
            {
                sType            = VkStructureType.SwapchainCreateInfoKHR,
                surface          = device._surface,
                minImageCount    = imageCount,
                imageFormat      = surfaceFormat.format,
                imageColorSpace  = surfaceFormat.colorSpace,
                imageExtent      = _extent,
                imageArrayLayers = 1,
                imageUsage       = VkImageUsageFlags.ColorAttachment,
                imageSharingMode = VkSharingMode.Exclusive,
                preTransform     = swapChainSupport.Capabilities.currentTransform,
                compositeAlpha   = VkCompositeAlphaFlagsKHR.Opaque,
                presentMode      = presentMode,
                clipped          = true,
                oldSwapchain     = VkSwapchainKHR.Null
            };

            vkCreateSwapchainKHR(device.VkDevice, &createInfo, null, out Handle).CheckResult();
            var swapChainImages = vkGetSwapchainImagesKHR(device.VkDevice, Handle);

            _swapChainImageViews = new VkImageView[swapChainImages.Length];
            _framebuffers        = new VkFramebuffer[swapChainImages.Length];

            for (var i = 0; i < swapChainImages.Length; i++)
            {
                var viewCreateInfo = new VkImageViewCreateInfo(
                    swapChainImages[i],
                    VkImageViewType.Image2D,
                    surfaceFormat.format,
                    VkComponentMapping.Identity,
                    new VkImageSubresourceRange(VkImageAspectFlags.Color, 0, 1, 0, 1)
                    );

                vkCreateImageView(Device.VkDevice, &viewCreateInfo, null, out _swapChainImageViews[i]).CheckResult();
                vkCreateFramebuffer(Device.VkDevice, RenderPass, new[] { _swapChainImageViews[i] }, (uint)_extent.Width, (uint)_extent.Height, 1u, out _framebuffers[i]);
            }
        }
Exemplo n.º 2
0
 public static VkPresentModeKHR[] GetSurfacePresentModes(this VkPhysicalDevice phy, VkSurfaceKHR surf)
 {
     vkGetPhysicalDeviceSurfacePresentModesKHR(phy, surf, out uint count, IntPtr.Zero);
     VkPresentModeKHR[] modes = new VkPresentModeKHR[count];
     vkGetPhysicalDeviceSurfacePresentModesKHR(phy, surf, out count, modes.Pin());
     modes.Unpin();
     return(modes);
 }
Exemplo n.º 3
0
            private void CreateSwapchain()
            {
                SwapChainSupportDetails swapChainSupport = QuerySwapChainSupport(physicalDevice, surface);

                VkSurfaceFormatKHR surfaceFormat = ChooseSwapSurfaceFormat(swapChainSupport.Formats);
                VkPresentModeKHR   presentMode   = ChooseSwapPresentMode(swapChainSupport.PresentModes);
                var extent = ChooseSwapExtent(swapChainSupport.Capabilities);

                uint imageCount = swapChainSupport.Capabilities.minImageCount + 1;

                if (swapChainSupport.Capabilities.maxImageCount > 0 &&
                    imageCount > swapChainSupport.Capabilities.maxImageCount)
                {
                    imageCount = swapChainSupport.Capabilities.maxImageCount;
                }

                var createInfo = new VkSwapchainCreateInfoKHR
                {
                    sType            = VkStructureType.SwapchainCreateInfoKHR,
                    surface          = surface,
                    minImageCount    = imageCount,
                    imageFormat      = surfaceFormat.format,
                    imageColorSpace  = surfaceFormat.colorSpace,
                    imageExtent      = extent,
                    imageArrayLayers = 1,
                    imageUsage       = VkImageUsageFlags.ColorAttachment,
                    imageSharingMode = VkSharingMode.Exclusive,
                    preTransform     = swapChainSupport.Capabilities.currentTransform,
                    compositeAlpha   = VkCompositeAlphaFlagsKHR.OpaqueKHR,
                    presentMode      = presentMode,
                    clipped          = true,
                    oldSwapchain     = VkSwapchainKHR.Null
                };

                vkCreateSwapchainKHR(device, &createInfo, null, out swapchain).CheckResult();
                var swapChainImages = vkGetSwapchainImagesKHR(device, swapchain);

                swapChainImageViews = new VkImageView[swapChainImages.Length];

                for (var i = 0; i < swapChainImages.Length; i++)
                {
                    var viewCreateInfo = new VkImageViewCreateInfo(
                        swapChainImages[i],
                        VkImageViewType.Image2D,
                        surfaceFormat.format,
                        VkComponentMapping.Identity,
                        new VkImageSubresourceRange(VkImageAspectFlags.Color, 0, 1, 0, 1)
                        );

                    vkCreateImageView(device, &viewCreateInfo, null, out swapChainImageViews[i]).CheckResult();
                }
            }
Exemplo n.º 4
0
        public VkObjectResult <IReadOnlyList <VkPresentModeKHR> > GetSurfacePresentModesKHR(IVkSurfaceKHR surface)
        {
            int count;

            Direct.GetPhysicalDeviceSurfacePresentModesKHR(Handle, surface.Handle, &count, null).CheckSuccess();
            var resultArray = new VkPresentModeKHR[count];

            fixed(VkPresentModeKHR *pResults = resultArray)
            {
                var result = Direct.GetPhysicalDeviceSurfacePresentModesKHR(Handle, surface.Handle, &count, pResults);

                return(new VkObjectResult <IReadOnlyList <VkPresentModeKHR> >(result, resultArray));
            }
        }
Exemplo n.º 5
0
        public static ReadOnlySpan <VkPresentModeKHR> vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface)
        {
            uint presentModeCount = 0;

            vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, null).CheckResult();

            ReadOnlySpan <VkPresentModeKHR> presentModes = new VkPresentModeKHR[presentModeCount];

            fixed(VkPresentModeKHR *presentModesPtr = presentModes)
            {
                vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, presentModesPtr).CheckResult();
            }

            return(presentModes);
        }
Exemplo n.º 6
0
        public VkPresentModeKHR[] GetPhysicalDeviceSurfacePresentModesKHR(VkSurfaceKHR surface)
        {
            unsafe
            {
                VkPresentModeKHR[] props;
                uint count = 0;
                do
                {
                    props = new VkPresentModeKHR[count];

                    fixed(VkPresentModeKHR *pptr = props)
                    VkException.Check(vkGetPhysicalDeviceSurfacePresentModesKHR(this, surface, &count, pptr));
                } while (props.Length != count);

                return(props);
            }
        }
Exemplo n.º 7
0
        /// <summary>
        /// Returns global layer properties.
        /// </summary>
        /// <returns></returns>
        public static VkPresentModeKHR[] PresentModesKHR(VkPhysicalDevice device, VkSurfaceKHR surface)
        {
            VkPresentModeKHR[] result;
            UInt32             count;

            vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &count, null);
            result = new VkPresentModeKHR[count];
            if (count > 0)
            {
                fixed(VkPresentModeKHR *pointer = result)
                {
                    vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &count, pointer);
                }
            }

            return(result);
        }
Exemplo n.º 8
0
        /// <summary>
        /// Create a new managed `SwapChain` object. Native object will only be created with a call to the 'Create` method.
        /// </summary>
        /// <param name="_presentableQueue">Presentable queue.</param>
        /// <param name="width">Swapchain x dimension.</param>
        /// <param name="height">Swapchain y dimension.</param>
        /// <param name="format">Swapchain's images format.</param>
        /// <param name="presentMode">a present mode supported by the engine as returned by the `GetSurfacePresentModes` method of the `PhysicalDevice`</param>
        public SwapChain(PresentQueue _presentableQueue, uint width = 800, uint height = 600, VkFormat format = VkFormat.B8g8r8a8Unorm,
                         VkPresentModeKHR presentMode = VkPresentModeKHR.FifoKHR)
            : base(_presentableQueue.dev)
        {
            presentQueue = _presentableQueue;
            createInfos  = VkSwapchainCreateInfoKHR.New();

            VkSurfaceFormatKHR[] formats = Dev.phy.GetSurfaceFormats(presentQueue.Surface);
            for (int i = 0; i < formats.Length; i++)
            {
                if (formats[i].format == format)
                {
                    createInfos.imageFormat     = format;
                    createInfos.imageColorSpace = formats[i].colorSpace;
                    break;
                }
            }
            if (createInfos.imageFormat == VkFormat.Undefined)
            {
                throw new Exception("Invalid format for swapchain: " + format);
            }

            VkPresentModeKHR[] presentModes = Dev.phy.GetSurfacePresentModes(presentQueue.Surface);
            for (int i = 0; i < presentModes.Length; i++)
            {
                if (presentModes[i] == presentMode)
                {
                    createInfos.presentMode = presentMode;
                    break;
                }
            }
            if (createInfos.presentMode != presentMode)
            {
                throw new Exception("Invalid presentMode for swapchain: " + presentMode);
            }

            createInfos.surface          = presentQueue.Surface;
            createInfos.imageExtent      = new VkExtent2D(width, height);
            createInfos.imageArrayLayers = 1;
            createInfos.imageUsage       = IMAGES_USAGE;
            createInfos.imageSharingMode = VkSharingMode.Exclusive;
            createInfos.compositeAlpha   = VkCompositeAlphaFlagsKHR.OpaqueKHR;
            createInfos.presentMode      = presentMode;
            createInfos.clipped          = 1;
        }
Exemplo n.º 9
0
        private VkPresentModeKHR ChooseSwapPresentMode(VkPresentModeKHR[] presentModes)
        {
            VkPresentModeKHR bestMode = VkPresentModeKHR.VK_PRESENT_MODE_FIFO_KHR;

            foreach (var availablePresentMode in presentModes)
            {
                if (availablePresentMode == VkPresentModeKHR.VK_PRESENT_MODE_MAILBOX_KHR)
                {
                    return(availablePresentMode);
                }
                else if (availablePresentMode == VkPresentModeKHR.VK_PRESENT_MODE_IMMEDIATE_KHR)
                {
                    bestMode = VkPresentModeKHR.VK_PRESENT_MODE_IMMEDIATE_KHR;
                }
            }

            return(bestMode);
        }
Exemplo n.º 10
0
 public VkPresentModeKHR[] GetSurfacePresentModes(VkSurfaceKHR surf)
 {
     vkGetPhysicalDeviceSurfacePresentModesKHR(phy, surf, out uint count, IntPtr.Zero);
     if (Type.GetType("Mono.Runtime") == null)
     {
         uint[] modes = new uint[count];                //this cause an error on mono
         vkGetPhysicalDeviceSurfacePresentModesKHR(phy, surf, out count, modes.Pin());
         modes.Unpin();
         VkPresentModeKHR[] mds = new VkPresentModeKHR[count];
         for (int i = 0; i < count; i++)
         {
             mds[i] = (VkPresentModeKHR)modes[i];
         }
         return(mds);
     }
     else
     {
         VkPresentModeKHR[] modes = new VkPresentModeKHR[count];                //enums not blittable on ms.Net
         vkGetPhysicalDeviceSurfacePresentModesKHR(phy, surf, out count, modes.Pin());
         modes.Unpin();
         return(modes);
     }
 }
Exemplo n.º 11
0
        private VkSwapchainKHR CreateSwapchain()
        {
            VkSurfaceCapabilitiesKHR capabilities;

            vkGetPhysicalDeviceSurfaceCapabilitiesKHR(Context.PhysicalDevice, Surface, out capabilities).CheckResult();

            uint count;

            vkGetPhysicalDeviceSurfaceFormatsKHR(Context.PhysicalDevice, Surface, &count, null);

            VkSurfaceFormatKHR[] formats = new VkSurfaceFormatKHR[(int)count];

            fixed(VkSurfaceFormatKHR *formatsPtr = formats)
            vkGetPhysicalDeviceSurfaceFormatsKHR(Context.PhysicalDevice, Surface, &count, formatsPtr).CheckResult();

            vkGetPhysicalDeviceSurfacePresentModesKHR(Context.PhysicalDevice, Surface, &count, null).CheckResult();

            VkPresentModeKHR[] presentModes = new VkPresentModeKHR[count];

            fixed(VkPresentModeKHR *presentModesPtr = presentModes)
            vkGetPhysicalDeviceSurfacePresentModesKHR(Context.PhysicalDevice, Surface, &count, presentModesPtr).CheckResult();

            VkFormat format = formats.Length == 1 && formats[0].format == VkFormat.Undefined
                ? VkFormat.B8G8R8A8UNorm
                : formats[0].format;
            VkPresentModeKHR presentMode =
                presentModes.Contains(VkPresentModeKHR.Mailbox) ? VkPresentModeKHR.Mailbox :
                presentModes.Contains(VkPresentModeKHR.FifoRelaxed) ? VkPresentModeKHR.FifoRelaxed :
                presentModes.Contains(VkPresentModeKHR.Fifo) ? VkPresentModeKHR.Fifo :
                VkPresentModeKHR.Immediate;

            SwapChainSupportDetails swapChainSupport = QuerySwapChainSupport(Context.PhysicalDevice, Surface);
            VkSurfaceFormatKHR      surfaceFormat    = ChooseSwapSurfaceFormat(swapChainSupport.Formats);

            uint imageCount = swapChainSupport.Capabilities.minImageCount + 1;

            if (swapChainSupport.Capabilities.maxImageCount > 0 &&
                imageCount > swapChainSupport.Capabilities.maxImageCount)
            {
                imageCount = swapChainSupport.Capabilities.maxImageCount;
            }

            SwapchainFormat = format;

            VkSwapchainCreateInfoKHR swapchainCI = new VkSwapchainCreateInfoKHR()
            {
                sType                 = VkStructureType.SwapchainCreateInfoKHR,
                pNext                 = null,
                surface               = Surface,
                minImageCount         = imageCount,
                imageFormat           = format,
                imageColorSpace       = surfaceFormat.colorSpace,
                imageExtent           = capabilities.currentExtent,
                imageUsage            = VkImageUsageFlags.ColorAttachment,
                preTransform          = capabilities.currentTransform,
                imageArrayLayers      = 1,
                imageSharingMode      = VkSharingMode.Exclusive,
                queueFamilyIndexCount = 0,
                pQueueFamilyIndices   = null,
                presentMode           = presentMode,

                //oldSwapchain = SwapChain,

                // Setting clipped to VK_TRUE allows the implementation to discard rendering outside of the Surface area
                clipped        = true,
                compositeAlpha = VkCompositeAlphaFlagsKHR.Opaque,
            };
            VkSwapchainKHR SwapChain;

            vkCreateSwapchainKHR(Context.Device, &swapchainCI, null, out SwapChain).CheckResult();

            return(SwapChain);
        }
Exemplo n.º 12
0
        /**
         * Create the swapchain and get it's Images with given width and height
         *
         * @param width Pointer to the width of the swapchain (may be adjusted to fit the requirements of the swapchain)
         * @param height Pointer to the height of the swapchain (may be adjusted to fit the requirements of the swapchain)
         * @param vsync (Optional) Can be used to force vsync'd rendering (by using VK_PRESENT_MODE_FIFO_KHR as presentation mode)
         */
        public void Create(uint *width, uint *height, bool vsync = false)
        {
            VkResult       err;
            VkSwapchainKHR oldSwapchain = Swapchain;

            // Get physical Device Surface properties and formats
            VkSurfaceCapabilitiesKHR surfCaps;

            err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(PhysicalDevice, Surface, &surfCaps);
            Debug.Assert(err == VkResult.Success);

            // Get available present modes
            uint presentModeCount;

            err = vkGetPhysicalDeviceSurfacePresentModesKHR(PhysicalDevice, Surface, &presentModeCount, null);
            Debug.Assert(err == VkResult.Success);
            Debug.Assert(presentModeCount > 0);

            using (NativeList <VkPresentModeKHR> presentModes = new NativeList <VkPresentModeKHR>(presentModeCount))
            {
                err = vkGetPhysicalDeviceSurfacePresentModesKHR(PhysicalDevice, Surface, &presentModeCount, (VkPresentModeKHR *)presentModes.Data);
                Debug.Assert(err == VkResult.Success);
                presentModes.Count = presentModeCount;

                VkExtent2D swapchainExtent;
                // If width (and height) equals the special value 0xFFFFFFFF, the size of the Surface will be set by the swapchain
                if (surfCaps.currentExtent.width == unchecked ((uint)-1))
                {
                    // If the Surface size is undefined, the size is set to
                    // the size of the Images requested.
                    swapchainExtent.width  = *width;
                    swapchainExtent.height = *height;
                }
                else
                {
                    // If the Surface size is defined, the swap chain size must match
                    swapchainExtent = surfCaps.currentExtent;
                    *width  = surfCaps.currentExtent.width;
                    *height = surfCaps.currentExtent.height;
                }


                // Select a present mode for the swapchain

                // The VK_PRESENT_MODE_FIFO_KHR mode must always be present as per spec
                // This mode waits for the vertical blank ("v-sync")
                VkPresentModeKHR swapchainPresentMode = VkPresentModeKHR.FifoKHR;

                // If v-sync is not requested, try to find a mailbox mode
                // It's the lowest latency non-tearing present mode available
                if (!vsync)
                {
                    for (uint i = 0; i < presentModeCount; i++)
                    {
                        if (presentModes[i] == VkPresentModeKHR.MailboxKHR)
                        {
                            swapchainPresentMode = VkPresentModeKHR.MailboxKHR;
                            break;
                        }
                        if ((swapchainPresentMode != VkPresentModeKHR.MailboxKHR) && (presentModes[i] == VkPresentModeKHR.ImmediateKHR))
                        {
                            swapchainPresentMode = VkPresentModeKHR.ImmediateKHR;
                        }
                    }
                }

                // Determine the number of Images
                uint desiredNumberOfSwapchainImages = surfCaps.minImageCount + 1;
                if ((surfCaps.maxImageCount > 0) && (desiredNumberOfSwapchainImages > surfCaps.maxImageCount))
                {
                    desiredNumberOfSwapchainImages = surfCaps.maxImageCount;
                }

                // Find the transformation of the Surface
                VkSurfaceTransformFlagsKHR preTransform;
                if ((surfCaps.supportedTransforms & VkSurfaceTransformFlagsKHR.IdentityKHR) != 0)
                {
                    // We prefer a non-rotated transform
                    preTransform = VkSurfaceTransformFlagsKHR.IdentityKHR;
                }
                else
                {
                    preTransform = surfCaps.currentTransform;
                }

                VkSwapchainCreateInfoKHR swapchainCI = VkSwapchainCreateInfoKHR.New();
                swapchainCI.pNext           = null;
                swapchainCI.surface         = Surface;
                swapchainCI.minImageCount   = desiredNumberOfSwapchainImages;
                swapchainCI.imageFormat     = ColorFormat;
                swapchainCI.imageColorSpace = ColorSpace;
                swapchainCI.imageExtent     = new VkExtent2D()
                {
                    width = swapchainExtent.width, height = swapchainExtent.height
                };
                swapchainCI.imageUsage            = VkImageUsageFlags.ColorAttachment;
                swapchainCI.preTransform          = preTransform;
                swapchainCI.imageArrayLayers      = 1;
                swapchainCI.imageSharingMode      = VkSharingMode.Exclusive;
                swapchainCI.queueFamilyIndexCount = 0;
                swapchainCI.pQueueFamilyIndices   = null;
                swapchainCI.presentMode           = swapchainPresentMode;
                swapchainCI.oldSwapchain          = oldSwapchain;
                // Setting clipped to VK_TRUE allows the implementation to discard rendering outside of the Surface area
                swapchainCI.clipped        = True;
                swapchainCI.compositeAlpha = VkCompositeAlphaFlagsKHR.OpaqueKHR;

                // Set additional usage flag for blitting from the swapchain Images if supported
                VkFormatProperties formatProps;
                vkGetPhysicalDeviceFormatProperties(PhysicalDevice, ColorFormat, out formatProps);
                if ((formatProps.optimalTilingFeatures & VkFormatFeatureFlags.BlitDst) != 0)
                {
                    swapchainCI.imageUsage |= VkImageUsageFlags.TransferSrc;
                }

                VkSwapchainKHR swapChain;
                err = vkCreateSwapchainKHR(Device, &swapchainCI, null, out swapChain);
                Debug.Assert(err == VkResult.Success);
                Swapchain = swapChain;

                // If an existing swap chain is re-created, destroy the old swap chain
                // This also cleans up all the presentable Images
                if (oldSwapchain.Handle != 0)
                {
                    for (uint i = 0; i < ImageCount; i++)
                    {
                        vkDestroyImageView(Device, Buffers[i].View, null);
                    }
                    vkDestroySwapchainKHR(Device, oldSwapchain, null);
                }

                uint imageCount;
                err = vkGetSwapchainImagesKHR(Device, swapChain, &imageCount, null);
                Debug.Assert(err == VkResult.Success);
                ImageCount = imageCount;

                // Get the swap chain Images
                Images.Resize(imageCount);
                err          = vkGetSwapchainImagesKHR(Device, swapChain, &imageCount, (VkImage *)Images.Data.ToPointer());
                Images.Count = imageCount;
                Debug.Assert(err == VkResult.Success);

                // Get the swap chain Buffers containing the image and imageview
                Buffers.Resize(imageCount);
                Buffers.Count = imageCount;
                for (uint i = 0; i < imageCount; i++)
                {
                    VkImageViewCreateInfo colorAttachmentView = new VkImageViewCreateInfo();
                    colorAttachmentView.sType      = VkStructureType.ImageViewCreateInfo;
                    colorAttachmentView.pNext      = null;
                    colorAttachmentView.format     = ColorFormat;
                    colorAttachmentView.components = new VkComponentMapping()
                    {
                        r = VkComponentSwizzle.R,
                        g = VkComponentSwizzle.G,
                        b = VkComponentSwizzle.B,
                        a = VkComponentSwizzle.A
                    };

                    colorAttachmentView.subresourceRange.aspectMask     = VkImageAspectFlags.Color;
                    colorAttachmentView.subresourceRange.baseMipLevel   = 0;
                    colorAttachmentView.subresourceRange.levelCount     = 1;
                    colorAttachmentView.subresourceRange.baseArrayLayer = 0;
                    colorAttachmentView.subresourceRange.layerCount     = 1;
                    colorAttachmentView.viewType = VkImageViewType.Image2D;
                    colorAttachmentView.flags    = 0;

                    Buffers[i].Image = Images[i];

                    colorAttachmentView.image = Buffers[i].Image;

                    VkImageView view;
                    err             = vkCreateImageView(Device, &colorAttachmentView, null, &view);
                    Buffers[i].View = view;
                    Debug.Assert(err == VkResult.Success);
                }
            }
        }
Exemplo n.º 13
0
        private void CreateSwapChain()
        {
            var swapChainSupport = new SwapChainSupportDetails(vkPhysicalDevice, vkSurface);

            VkSurfaceFormatKHR surfaceFormat = ChooseSwapSurfaceFormat(swapChainSupport.formats);
            VkPresentModeKHR   presentMode   = ChooseSwapPresentMode(swapChainSupport.presentModes);
            VkExtent2D         extent        = ChooseSwapExtent(swapChainSupport.capabilities);

            uint imageCount = swapChainSupport.capabilities.minImageCount + 1;

            if (swapChainSupport.capabilities.maxImageCount > 0 && imageCount > swapChainSupport.capabilities.maxImageCount)
            {
                imageCount = Math.Min(imageCount, swapChainSupport.capabilities.maxImageCount);
            }

            var createInfo = new VkSwapchainCreateInfoKHR()
            {
                sType            = VkStructureType.VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
                surface          = vkSurface,
                minImageCount    = imageCount,
                imageFormat      = surfaceFormat.format,
                imageColorSpace  = surfaceFormat.colorSpace,
                imageExtent      = extent,
                imageArrayLayers = 1,
                imageUsage       = VkImageUsageFlagBits.VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
                preTransform     = swapChainSupport.capabilities.currentTransform,
                compositeAlpha   = VkCompositeAlphaFlagBitsKHR.VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
                presentMode      = presentMode,
                clipped          = true,
            };

            var indices = new QueueFamilyIndices(vkPhysicalDevice, vkSurface);

            uint *QueueFamilyIndicesPtr = stackalloc uint[]
            {
                (uint)indices.GraphicsFamily,
                (uint)indices.PresentFamily,
            };

            if (indices.GraphicsFamily != indices.PresentFamily)
            {
                createInfo.imageSharingMode    = VkSharingMode.VK_SHARING_MODE_CONCURRENT;
                createInfo.pQueueFamilyIndices = QueueFamilyIndicesPtr;
            }
            else
            {
                createInfo.imageSharingMode = VkSharingMode.VK_SHARING_MODE_EXCLUSIVE;
            }

            VkSwapchainKHR newSwapChain;
            var            result = VulkanNative.vkCreateSwapchainKHR(vkDevice, &createInfo, null, &newSwapChain);

            vkSwapChain = newSwapChain;
            Helpers.CheckErrors(result);

            VulkanNative.vkGetSwapchainImagesKHR(vkDevice, vkSwapChain, &imageCount, null);
            VkImage *images = stackalloc VkImage[(int)imageCount];

            result = VulkanNative.vkGetSwapchainImagesKHR(vkDevice, vkSwapChain, &imageCount, images);
            Helpers.CheckErrors(result);

            vkSwapChainImages = new VkImage[imageCount];
            for (int i = 0; i < imageCount; i++)
            {
                vkSwapChainImages[i] = images[i];
            }

            vkSwapChainImageFormat = surfaceFormat.format;
            vkSwapChainExtent      = extent;
        }
Exemplo n.º 14
0
		public static extern VkResult vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes);
Exemplo n.º 15
0
        /**
         * Create the swapchain and get it's Images with given width and height
         *
         * @param width Pointer to the width of the swapchain (may be adjusted to fit the requirements of the swapchain)
         * @param height Pointer to the height of the swapchain (may be adjusted to fit the requirements of the swapchain)
         * @param vsync (Optional) Can be used to force vsync'd rendering (by using VK_PRESENT_MODE_FIFO_KHR as presentation mode)
         */
        public unsafe void Create(ref uint width, ref uint height, bool vsync = false)
        {
            VkResult       err;
            VkSwapchainKHR oldSwapchain = swapchain;

            // Get physical Device Surface properties and formats
            VkSurfaceCapabilitiesKHR surfCaps;

            err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(Device.PhysicalDevice, Surface, out surfCaps);
            Debug.Assert(err == VkResult.Success);

            // Get available present modes
            uint presentModeCount;

            err = vkGetPhysicalDeviceSurfacePresentModesKHR(Device.PhysicalDevice, Surface, &presentModeCount, null);
            Debug.Assert(err == VkResult.Success);
            Debug.Assert(presentModeCount > 0);

            using (Vector <VkPresentModeKHR> presentModes = new Vector <VkPresentModeKHR>(presentModeCount))
            {
                err = vkGetPhysicalDeviceSurfacePresentModesKHR(Device.PhysicalDevice, Surface, &presentModeCount, (VkPresentModeKHR *)presentModes.Data);
                Debug.Assert(err == VkResult.Success);
                presentModes.Count = presentModeCount;

                // If width (and height) equals the special value 0xFFFFFFFF, the size of the Surface will be set by the swapchain
                if (surfCaps.currentExtent.width != unchecked ((uint)-1))
                {
                    width  = surfCaps.currentExtent.width;
                    height = surfCaps.currentExtent.height;
                }

                extent = new VkExtent3D(width, height, 1);

                // Select a present mode for the swapchain

                // The VK_PRESENT_MODE_FIFO_KHR mode must always be present as per spec
                // This mode waits for the vertical blank ("v-sync")
                VkPresentModeKHR swapchainPresentMode = VkPresentModeKHR.Fifo;

                // If v-sync is not requested, try to find a mailbox mode
                // It's the lowest latency non-tearing present mode available
                if (!vsync)
                {
                    for (uint i = 0; i < presentModeCount; i++)
                    {
                        if (presentModes[i] == VkPresentModeKHR.Mailbox)
                        {
                            swapchainPresentMode = VkPresentModeKHR.Mailbox;
                            break;
                        }
                        if ((swapchainPresentMode != VkPresentModeKHR.Mailbox) && (presentModes[i] == VkPresentModeKHR.Immediate))
                        {
                            swapchainPresentMode = VkPresentModeKHR.Immediate;
                        }
                    }
                }

                // Determine the number of Images
                uint desiredNumberOfSwapchainImages = IMAGE_COUNT;// surfCaps.minImageCount + 1;
                if ((surfCaps.maxImageCount > 0) && (desiredNumberOfSwapchainImages > surfCaps.maxImageCount))
                {
                    Debug.Assert(false);
                    desiredNumberOfSwapchainImages = surfCaps.maxImageCount;
                }

                // Find the transformation of the Surface
                VkSurfaceTransformFlagsKHR preTransform;
                if ((surfCaps.supportedTransforms & VkSurfaceTransformFlagsKHR.Identity) != 0)
                {
                    // We prefer a non-rotated transform
                    preTransform = VkSurfaceTransformFlagsKHR.Identity;
                }
                else
                {
                    preTransform = surfCaps.currentTransform;
                }

                VkSwapchainCreateInfoKHR swapchainCI = new VkSwapchainCreateInfoKHR
                {
                    sType                 = VkStructureType.SwapchainCreateInfoKHR,
                    pNext                 = null,
                    surface               = Surface,
                    minImageCount         = desiredNumberOfSwapchainImages,
                    imageFormat           = ColorFormat,
                    imageColorSpace       = ColorSpace,
                    imageExtent           = new VkExtent2D(extent.width, extent.height),
                    imageUsage            = VkImageUsageFlags.ColorAttachment,
                    preTransform          = preTransform,
                    imageArrayLayers      = 1,
                    imageSharingMode      = VkSharingMode.Exclusive,
                    queueFamilyIndexCount = 0,
                    pQueueFamilyIndices   = null,
                    presentMode           = swapchainPresentMode,
                    oldSwapchain          = oldSwapchain,
                    // Setting clipped to VK_TRUE allows the implementation to discard rendering outside of the Surface area
                    clipped        = true,
                    compositeAlpha = VkCompositeAlphaFlagsKHR.Opaque
                };

                // Set additional usage flag for blitting from the swapchain Images if supported
                Device.GetPhysicalDeviceFormatProperties(ColorFormat, out VkFormatProperties formatProps);

                if ((formatProps.optimalTilingFeatures & VkFormatFeatureFlags.BlitDst) != 0)
                {
                    swapchainCI.imageUsage |= VkImageUsageFlags.TransferSrc;
                }

                swapchain = Device.CreateSwapchainKHR(ref swapchainCI);

                // If an existing swap chain is re-created, destroy the old swap chain
                // This also cleans up all the presentable Images
                if (oldSwapchain.Handle != 0)
                {
                    for (uint i = 0; i < ImageCount; i++)
                    {
                        ImageViews[i].Dispose();
                    }

                    Device.DestroySwapchainKHR(oldSwapchain);
                }

                var vkImages = Vulkan.vkGetSwapchainImagesKHR(Device.Handle, swapchain);
                VkImages.Clear();
                Images     = new Image[vkImages.Length];
                ImageViews = new ImageView[vkImages.Length];
                for (int i = 0; i < vkImages.Length; i++)
                {
                    Images[i] = new Image(vkImages[i])
                    {
                        imageType = VkImageType.Image2D,
                        extent    = extent
                    };
                    ImageViews[i] = ImageView.Create(Images[i], VkImageViewType.Image2D, ColorFormat, VkImageAspectFlags.Color, 0, 1);
                }

                // Get the swap chain Images
                VkImages.Add(vkImages);
            }
        }
Exemplo n.º 16
0
        private void CreateSwapchain(uint width, uint height)
        {
            _currentImageIndex = 0;
            uint surfaceFormatCount = 0;

            vkGetPhysicalDeviceSurfaceFormatsKHR(_gd.PhysicalDevice, _surface, ref surfaceFormatCount, null);
            VkSurfaceFormatKHR[] formats = new VkSurfaceFormatKHR[surfaceFormatCount];
            vkGetPhysicalDeviceSurfaceFormatsKHR(_gd.PhysicalDevice, _surface, ref surfaceFormatCount, out formats[0]);

            VkSurfaceFormatKHR surfaceFormat = new VkSurfaceFormatKHR();

            if (formats.Length == 1 && formats[0].format == VkFormat.Undefined)
            {
                surfaceFormat = new VkSurfaceFormatKHR {
                    colorSpace = VkColorSpaceKHR.SrgbNonlinearKHR, format = VkFormat.B8g8r8a8Unorm
                };
            }
            else
            {
                foreach (VkSurfaceFormatKHR format in formats)
                {
                    if (format.colorSpace == VkColorSpaceKHR.SrgbNonlinearKHR && format.format == VkFormat.B8g8r8a8Unorm)
                    {
                        surfaceFormat = format;
                        break;
                    }
                }
                if (surfaceFormat.format == VkFormat.Undefined)
                {
                    surfaceFormat = formats[0];
                }
            }

            uint presentModeCount = 0;

            vkGetPhysicalDeviceSurfacePresentModesKHR(_gd.PhysicalDevice, _surface, ref presentModeCount, null);
            VkPresentModeKHR[] presentModes = new VkPresentModeKHR[presentModeCount];
            vkGetPhysicalDeviceSurfacePresentModesKHR(_gd.PhysicalDevice, _surface, ref presentModeCount, out presentModes[0]);

            VkPresentModeKHR presentMode = VkPresentModeKHR.FifoKHR;

            if (presentModes.Contains(VkPresentModeKHR.MailboxKHR))
            {
                presentMode = VkPresentModeKHR.MailboxKHR;
            }
            else if (presentModes.Contains(VkPresentModeKHR.ImmediateKHR))
            {
                presentMode = VkPresentModeKHR.ImmediateKHR;
            }

            vkGetPhysicalDeviceSurfaceCapabilitiesKHR(_gd.PhysicalDevice, _surface, out VkSurfaceCapabilitiesKHR surfaceCapabilities);
            uint imageCount = surfaceCapabilities.minImageCount + 1;

            VkSwapchainCreateInfoKHR swapchainCI = VkSwapchainCreateInfoKHR.New();

            swapchainCI.surface         = _surface;
            swapchainCI.presentMode     = presentMode;
            swapchainCI.imageFormat     = surfaceFormat.format;
            swapchainCI.imageColorSpace = surfaceFormat.colorSpace;
            swapchainCI.imageExtent     = new VkExtent2D {
                width = (uint)width, height = (uint)height
            };
            swapchainCI.minImageCount    = imageCount;
            swapchainCI.imageArrayLayers = 1;
            swapchainCI.imageUsage       = VkImageUsageFlags.ColorAttachment;

            FixedArray2 <uint> queueFamilyIndices = new FixedArray2 <uint>(_gd.GraphicsQueueIndex, _gd.PresentQueueIndex);

            if (_gd.GraphicsQueueIndex != _gd.PresentQueueIndex)
            {
                swapchainCI.imageSharingMode      = VkSharingMode.Concurrent;
                swapchainCI.queueFamilyIndexCount = 2;
                swapchainCI.pQueueFamilyIndices   = &queueFamilyIndices.First;
            }
            else
            {
                swapchainCI.imageSharingMode      = VkSharingMode.Exclusive;
                swapchainCI.queueFamilyIndexCount = 0;
            }

            swapchainCI.preTransform   = surfaceCapabilities.currentTransform;
            swapchainCI.compositeAlpha = VkCompositeAlphaFlagsKHR.OpaqueKHR;
            swapchainCI.clipped        = true;

            VkSwapchainKHR oldSwapchain = _swapchain;

            swapchainCI.oldSwapchain = oldSwapchain;

            VkResult result = vkCreateSwapchainKHR(_gd.Device, ref swapchainCI, null, out _swapchain);

            CheckResult(result);
            if (oldSwapchain != VkSwapchainKHR.Null)
            {
                vkDestroySwapchainKHR(_gd.Device, oldSwapchain, null);
            }

            // Get the images
            uint scImageCount = 0;

            result = vkGetSwapchainImagesKHR(_gd.Device, _swapchain, ref scImageCount, null);
            CheckResult(result);
            if (_scImages == null)
            {
                _scImages = new VkImage[(int)scImageCount];
            }
            result = vkGetSwapchainImagesKHR(_gd.Device, _swapchain, ref scImageCount, out _scImages[0]);
            CheckResult(result);

            _scImageFormat = surfaceFormat.format;
            _scExtent      = swapchainCI.imageExtent;

            CreateDepthTexture();
            CreateFramebuffers();
        }
Exemplo n.º 17
0
        public SwapchainKHR(SurfaceKHR surface, Device device, uint minImageCount,
                            uint layerCount, VkImageUsageFlag usageFlag,
                            VkFormat imageFormat, VkColorSpaceKHR colorSpace,
                            VkExtent2D dimensions,
                            VkCompositeAlphaFlagBitsKHR compositeAlpha,
                            VkPresentModeKHR presentMode,
                            bool clipped = true,
                            VkSurfaceTransformFlagBitsKHR transform = VkSurfaceTransformFlagBitsKHR.IdentityBitKhr,
                            VkSharingMode sharing     = VkSharingMode.Exclusive, uint[] sharedQueueFamily = null,
                            SwapchainKHR oldSwapchain = null)
        {
            SurfaceKHR = surface;
            Device     = device;

            {
                var surfSupported = false;
                foreach (var family in Device.Queues.Select(x => x.FamilyIndex).Distinct())
                {
                    if (PhysicalDevice.Handle.GetPhysicalDeviceSurfaceSupportKHR(family, SurfaceKHR.Handle))
                    {
                        surfSupported = true;
                        break;
                    }
                }
                if (!surfSupported)
                {
                    throw new NotSupportedException($"No queues on device support the surface");
                }
            }

            _sharingQueueInfo = sharedQueueFamily;

            unsafe
            {
                if (sharing == VkSharingMode.Concurrent)
                {
                    Debug.Assert(sharedQueueFamily != null);
                }
                var hasPinnedSharedQueue    = sharedQueueFamily != null && sharedQueueFamily.Length > 0;
                var pinnedSharedQueueFamily = hasPinnedSharedQueue
                    ? GCHandle.Alloc(sharedQueueFamily, GCHandleType.Pinned)
                    : default(GCHandle);
                try
                {
                    var info = new VkSwapchainCreateInfoKHR()
                    {
                        SType                 = VkStructureType.SwapchainCreateInfoKhr,
                        PNext                 = IntPtr.Zero,
                        Flags                 = 0, // reserved VkSwapchainCreateFlagBitsKHR
                        Surface               = surface.Handle,
                        MinImageCount         = minImageCount,
                        ImageFormat           = imageFormat,
                        ImageColorSpace       = colorSpace,
                        ImageExtent           = dimensions,
                        ImageArrayLayers      = layerCount,
                        ImageUsage            = usageFlag,
                        ImageSharingMode      = sharing,
                        QueueFamilyIndexCount = (uint)(sharedQueueFamily?.Length ?? 0),
                        PQueueFamilyIndices   = hasPinnedSharedQueue
                            ? (uint *)Marshal.UnsafeAddrOfPinnedArrayElement(sharedQueueFamily, 0).ToPointer()
                            : (uint *)0,
                        PreTransform   = transform,
                        CompositeAlpha = compositeAlpha,
                        PresentMode    = presentMode,
                        Clipped        = clipped,
                        OldSwapchain   = oldSwapchain?.Handle ?? VkSwapchainKHR.Null
                    };
                    _info  = info;
                    Handle = Device.Handle.CreateSwapchainKHR(&info, Instance.AllocationCallbacks);
                    if (oldSwapchain != null)
                    {
                        foreach (var img in oldSwapchain._swapchainImages)
                        {
                            img.Dispose();
                        }
                        oldSwapchain.Dispose();
                    }
                }
                finally
                {
                    if (hasPinnedSharedQueue)
                    {
                        pinnedSharedQueueFamily.Free();
                    }
                }
            }

            var images = Device.Handle.GetSwapchainImagesKHR(Handle);

            _swapchainImages.Clear();
            _swapchainImages.Capacity = images.Length;
            foreach (var img in images)
            {
                _swapchainImages.Add(new SwapchainImage(this, img));
            }
        }
Exemplo n.º 18
0
        private void createSwapChain()
        {
            SwapChainSupportDetails swapChainSupport = querySwapChainSupport(physicalDevice);

            VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats);
            VkPresentModeKHR   presentMode   = chooseSwapPresentMode(swapChainSupport.presentModes);
            VkExtent2D         extent        = chooseSwapExtent(swapChainSupport.capabilities);

            int imageCount = swapChainSupport.capabilities.minImageCount + 1;

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

            VkSwapchainCreateInfoKHR createInfo = new VkSwapchainCreateInfoKHR();

            createInfo.sType   = VkStructureType.VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
            createInfo.surface = surface;

            createInfo.minImageCount    = imageCount;
            createInfo.imageFormat      = surfaceFormat.format;
            createInfo.imageColorSpace  = surfaceFormat.colorSpace;
            createInfo.imageExtent      = extent;
            createInfo.imageArrayLayers = 1;
            createInfo.imageUsage       = VkImageUsageFlags.VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;

            QueueFamilyIndices indices = findQueueFamilies(physicalDevice);
            var queueFamilyIndices     = new List <int>()
            {
                indices.graphicsFamily, indices.presentFamily
            };

            if (indices.graphicsFamily != indices.presentFamily)
            {
                createInfo.imageSharingMode      = VkSharingMode.VK_SHARING_MODE_CONCURRENT;
                createInfo.queueFamilyIndexCount = queueFamilyIndices.Count;
                createInfo.pQueueFamilyIndices   = queueFamilyIndices.ToArray();
            }
            else
            {
                createInfo.imageSharingMode = VkSharingMode.VK_SHARING_MODE_EXCLUSIVE;
            }

            createInfo.preTransform   = (VkSurfaceTransformFlagBitsKHR)swapChainSupport.capabilities.currentTransform;
            createInfo.compositeAlpha = VkCompositeAlphaFlagBitsKHR.VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
            createInfo.presentMode    = presentMode;
            createInfo.clipped        = VkBool32.VK_TRUE;

            createInfo.oldSwapchain = null;

            VkResult result = Vulkan.vkCreateSwapchainKHR(device, createInfo, null, out swapChain);

            if (result != VkResult.VK_SUCCESS)
            {
                throw Program.Throw("failed to create swap chain!", result);
            }

            swapChainImages = new VkImage[imageCount];
            Vulkan.vkGetSwapchainImagesKHR(device, swapChain, ref imageCount, swapChainImages);

            swapChainImageFormat = surfaceFormat.format;
            swapChainExtent      = extent;
        }
Exemplo n.º 19
0
        private void CreateSwapChain()
        {
            // Create SwapChain
            SwapChainSupportDetails swapChainSupport = this.QuerySwapChainSupport(this.physicalDevice);

            VkSurfaceFormatKHR surfaceFormat = this.ChooseSwapSurfaceFormat(swapChainSupport.formats);
            VkPresentModeKHR   presentMode   = this.ChooseSwapPresentMode(swapChainSupport.presentModes);
            VkExtent2D         extent        = this.ChooseSwapExtent(swapChainSupport.capabilities);

            uint imageCount = swapChainSupport.capabilities.minImageCount + 1;

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

            VkSwapchainCreateInfoKHR createInfo = new VkSwapchainCreateInfoKHR();

            createInfo.sType            = VkStructureType.VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
            createInfo.surface          = surface;
            createInfo.minImageCount    = imageCount;
            createInfo.imageFormat      = surfaceFormat.format;
            createInfo.imageColorSpace  = surfaceFormat.colorSpace;
            createInfo.imageExtent      = extent;
            createInfo.imageArrayLayers = 1;
            createInfo.imageUsage       = VkImageUsageFlags.VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;

            QueueFamilyIndices indices = this.FindQueueFamilies(this.physicalDevice);
            uint *queueFamilyIndices   = stackalloc uint[] { indices.graphicsFamily.Value, indices.presentFamily.Value };

            if (indices.graphicsFamily != indices.presentFamily)
            {
                createInfo.imageSharingMode      = VkSharingMode.VK_SHARING_MODE_CONCURRENT;
                createInfo.queueFamilyIndexCount = 2;
                createInfo.pQueueFamilyIndices   = queueFamilyIndices;
            }
            else
            {
                createInfo.imageSharingMode      = VkSharingMode.VK_SHARING_MODE_EXCLUSIVE;
                createInfo.queueFamilyIndexCount = 0;    //Optional
                createInfo.pQueueFamilyIndices   = null; //Optional
            }
            createInfo.preTransform   = swapChainSupport.capabilities.currentTransform;
            createInfo.compositeAlpha = VkCompositeAlphaFlagsKHR.VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
            createInfo.presentMode    = presentMode;
            createInfo.clipped        = true;
            createInfo.oldSwapchain   = 0;

            fixed(VkSwapchainKHR *swapChainPtr = &swapChain)
            {
                Helpers.CheckErrors(VulkanNative.vkCreateSwapchainKHR(device, &createInfo, null, swapChainPtr));
            }

            // SwapChain Images
            VulkanNative.vkGetSwapchainImagesKHR(device, swapChain, &imageCount, null);
            this.swapChainImages = new VkImage[imageCount];
            fixed(VkImage *swapChainImagesPtr = &this.swapChainImages[0])
            {
                VulkanNative.vkGetSwapchainImagesKHR(device, swapChain, &imageCount, swapChainImagesPtr);
            }

            this.swapChainImageFormat = surfaceFormat.format;
            this.swapChainExtent      = extent;
        }
Exemplo n.º 20
0
        public void CreateSwapChain()
        {
            var PhysicalDevice = NativeDevice.NativeAdapter.NativePhysicalDevice;

            var width = Parameters.BackBufferWidth;

            var height = Parameters.BackBufferHeight;

            var vsync = Parameters.Settings.VSync;


            // Get available queue family properties
            uint queueCount;

            vkGetPhysicalDeviceQueueFamilyProperties(PhysicalDevice, &queueCount, null);
            VkQueueFamilyProperties *queueProps = stackalloc VkQueueFamilyProperties[(int)queueCount];

            vkGetPhysicalDeviceQueueFamilyProperties(PhysicalDevice, &queueCount, queueProps);



            // Iterate over each queue to learn whether it supports presenting:
            // Find a queue with present support
            // Will be used to present the swap chain Images to the windowing system
            VkBool32 *supportsPresent = stackalloc VkBool32[(int)queueCount];

            for (uint i = 0; i < queueCount; i++)
            {
                vkGetPhysicalDeviceSurfaceSupportKHR(PhysicalDevice, i, Surface, &supportsPresent[i]);
            }



            // Search for a graphics and a present queue in the array of queue
            // families, try to find one that supports both
            uint graphicsQueueNodeIndex = uint.MaxValue;
            uint presentQueueNodeIndex  = uint.MaxValue;

            for (uint i = 0; i < queueCount; i++)
            {
                if ((queueProps[i].queueFlags & VkQueueFlags.Graphics) != 0)
                {
                    if (graphicsQueueNodeIndex == uint.MaxValue)
                    {
                        graphicsQueueNodeIndex = i;
                    }


                    if (supportsPresent[i] == 1)
                    {
                        graphicsQueueNodeIndex = i;
                        presentQueueNodeIndex  = i;
                        break;
                    }
                }
            }

            if (presentQueueNodeIndex == uint.MaxValue)
            {
                // If there's no queue that supports both present and graphics
                // try to find a separate present queue
                for (uint i = 0; i < queueCount; ++i)
                {
                    if (supportsPresent[i] == 1)
                    {
                        presentQueueNodeIndex = i;
                        break;
                    }
                }
            }

            // Exit if either a graphics or a presenting queue hasn't been found
            if (graphicsQueueNodeIndex == uint.MaxValue || presentQueueNodeIndex == uint.MaxValue)
            {
                throw new InvalidOperationException("Could not find a graphics and/or presenting queue!");
            }


            // todo : Add support for separate graphics and presenting queue
            if (graphicsQueueNodeIndex != presentQueueNodeIndex)
            {
                throw new InvalidOperationException("Separate graphics and presenting queues are not supported yet!");
            }



            // Get list of supported Surface formats
            uint formatCount;

            vkGetPhysicalDeviceSurfaceFormatsKHR(PhysicalDevice, Surface, &formatCount, null);
            VkSurfaceFormatKHR *surfaceFormats = stackalloc VkSurfaceFormatKHR[(int)formatCount];

            vkGetPhysicalDeviceSurfaceFormatsKHR(PhysicalDevice, Surface, &formatCount, surfaceFormats);



            // If the Surface format list only includes one entry with VK_FORMAT_UNDEFINED,
            // there is no preferered format, so we assume VK_FORMAT_B8G8R8A8_UNORM
            if ((formatCount == 1) && (surfaceFormats[0].format == VkFormat.Undefined))
            {
                VkColorFormat = VkFormat.B8g8r8a8Unorm;
                ColorSpace    = surfaceFormats[0].colorSpace;
            }
            else
            {
                // iterate over the list of available Surface format and
                // check for the presence of VK_FORMAT_B8G8R8A8_UNORM
                bool found_B8G8R8A8_UNORM = false;

                List <VkSurfaceFormatKHR> Formats = new List <VkSurfaceFormatKHR>();

                for (int i = 0; i < formatCount; i++)
                {
                    Formats.Add(surfaceFormats[i]);
                }



                foreach (var surfaceFormat in Formats)
                {
                    if (surfaceFormat.format == VkFormat.B8g8r8a8Unorm)
                    {
                        VkColorFormat        = surfaceFormat.format;
                        ColorSpace           = surfaceFormat.colorSpace;
                        found_B8G8R8A8_UNORM = true;
                        break;
                    }
                }

                // in case VK_FORMAT_B8G8R8A8_UNORM is not available
                // select the first available color format
                if (!found_B8G8R8A8_UNORM)
                {
                    VkColorFormat = surfaceFormats[0].format;
                    ColorSpace    = surfaceFormats[0].colorSpace;
                }
            }


            // Get physical Device Surface properties and formats
            VkSurfaceCapabilitiesKHR surfCaps;

            vkGetPhysicalDeviceSurfaceCapabilitiesKHR(PhysicalDevice, Surface, &surfCaps);



            // Get available present modes
            uint presentModeCount;

            vkGetPhysicalDeviceSurfacePresentModesKHR(PhysicalDevice, Surface, &presentModeCount, null);
            VkPresentModeKHR *presentModes = stackalloc VkPresentModeKHR[(int)presentModeCount];

            vkGetPhysicalDeviceSurfacePresentModesKHR(PhysicalDevice, Surface, &presentModeCount, (VkPresentModeKHR *)presentModes);



            VkExtent2D swapchainExtent;

            // If width (and height) equals the special value 0xFFFFFFFF, the size of the Surface will be set by the swapchain
            if (surfCaps.currentExtent.width == unchecked ((uint)-1))
            {
                // If the Surface size is undefined, the size is set to
                // the size of the Images requested.
                swapchainExtent.width  = (uint)width;
                swapchainExtent.height = (uint)height;
            }
            else
            {
                // If the Surface size is defined, the swap chain size must match
                swapchainExtent = surfCaps.currentExtent;
                width           = (int)surfCaps.currentExtent.width;
                height          = (int)surfCaps.currentExtent.height;
            }


            // Select a present mode for the swapchain

            // The VK_PRESENT_MODE_FIFO_KHR mode must always be present as per spec
            // This mode waits for the vertical blank ("v-sync")
            VkPresentModeKHR swapchainPresentMode = VkPresentModeKHR.FifoKHR;

            // If v-sync is not requested, try to find a mailbox mode
            // It's the lowest latency non-tearing present mode available
            if (!vsync)
            {
                for (uint i = 0; i < presentModeCount; i++)
                {
                    if (presentModes[i] == VkPresentModeKHR.MailboxKHR)
                    {
                        swapchainPresentMode = VkPresentModeKHR.MailboxKHR;
                        break;
                    }
                    if ((swapchainPresentMode != VkPresentModeKHR.MailboxKHR) && (presentModes[i] == VkPresentModeKHR.ImmediateKHR))
                    {
                        swapchainPresentMode = VkPresentModeKHR.ImmediateKHR;
                    }
                }
            }

            // Determine the number of Images
            uint desiredNumberOfSwapchainImages = surfCaps.minImageCount + 1;

            if ((surfCaps.maxImageCount > 0) && (desiredNumberOfSwapchainImages > surfCaps.maxImageCount))
            {
                desiredNumberOfSwapchainImages = surfCaps.maxImageCount;
            }


            // Find the transformation of the Surface
            VkSurfaceTransformFlagsKHR preTransform;

            if ((surfCaps.supportedTransforms & VkSurfaceTransformFlagsKHR.IdentityKHR) != 0)
            {
                // We prefer a non-rotated transform
                preTransform = VkSurfaceTransformFlagsKHR.IdentityKHR;
            }

            else
            {
                preTransform = surfCaps.currentTransform;
            }


            VkSwapchainCreateInfoKHR swapchainCI = new VkSwapchainCreateInfoKHR()
            {
                sType           = VkStructureType.SwapchainCreateInfoKHR,
                pNext           = null,
                surface         = Surface,
                minImageCount   = desiredNumberOfSwapchainImages,
                imageFormat     = VkColorFormat,
                imageColorSpace = ColorSpace,
                imageExtent     = new VkExtent2D()
                {
                    width  = swapchainExtent.width,
                    height = swapchainExtent.height
                },
                imageUsage            = VkImageUsageFlags.ColorAttachment,
                preTransform          = preTransform,
                imageArrayLayers      = 1,
                imageSharingMode      = VkSharingMode.Exclusive,
                queueFamilyIndexCount = 0,
                pQueueFamilyIndices   = null,
                presentMode           = swapchainPresentMode,
                oldSwapchain          = SwapChain,

                // Setting clipped to VK_TRUE allows the implementation to discard rendering outside of the Surface area
                clipped        = True,
                compositeAlpha = VkCompositeAlphaFlagsKHR.OpaqueKHR,
            };


            // Set additional usage flag for blitting from the swapchain Images if supported
            VkFormatProperties formatProps;

            vkGetPhysicalDeviceFormatProperties(PhysicalDevice, VkColorFormat, out formatProps);
            if ((formatProps.optimalTilingFeatures & VkFormatFeatureFlags.BlitDst) != 0)
            {
                swapchainCI.imageUsage |= VkImageUsageFlags.TransferSrc;
            }


            VkSwapchainKHR swapChain;

            vkCreateSwapchainKHR(NativeDevice.Device, &swapchainCI, null, &swapChain);
            SwapChain = swapChain;


            //vkDestroySwapchainKHR(NativeDevice.Device, SwapChain, null);



            uint imageCount;

            vkGetSwapchainImagesKHR(NativeDevice.Device, SwapChain, &imageCount, null);
            VkImage *VkImages = stackalloc VkImage[(int)imageCount];

            vkGetSwapchainImagesKHR(NativeDevice.Device, swapChain, &imageCount, VkImages);



            Images = new List <VkImage>();

            for (int i = 0; i < imageCount; i++)
            {
                Images.Add(VkImages[i]);
            }
        }
Exemplo n.º 21
0
        private static uint RateDevice(IntPtr physDevice)
        {
            var devProps = new ManagedPtr <VkPhysicalDeviceProperties>();
            var devFeats = new ManagedPtr <VkPhysicalDeviceFeatures>();

            vkGetPhysicalDeviceProperties(physDevice, devProps);
            vkGetPhysicalDeviceFeatures(physDevice, devFeats);

            var devProps_ = devProps.Value;
            var devFeats_ = devFeats.Value;

            uint score = 0;

            if (devProps_.deviceType == VkPhysicalDeviceType.PhysicalDeviceTypeDiscreteGpu)
            {
                score += 100;
            }

            score += devProps_.limits.maxImageDimension2D;

            if (!devFeats_.multiDrawIndirect)
            {
                return(0);
            }

            if (!devFeats_.tessellationShader)
            {
                return(0);
            }

            if (!ExtensionsSupported(physDevice))
            {
                return(0);
            }

            var caps_ptr = new ManagedPtr <VkSurfaceCapabilitiesKHR>();

            vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physDevice, surfaceHndl, caps_ptr);
            var caps = caps_ptr.Value;

            uint fmt_cnt = 0;

            vkGetPhysicalDeviceSurfaceFormatsKHR(physDevice, surfaceHndl, &fmt_cnt, null);
            var fmts_ptr = new ManagedPtrArray <VkSurfaceFormatKHR>(fmt_cnt);

            vkGetPhysicalDeviceSurfaceFormatsKHR(physDevice, surfaceHndl, &fmt_cnt, fmts_ptr);
            var fmts = fmts_ptr.Value;

            bool fmt_valid = false;
            VkSurfaceFormatKHR chosen_fmt = new VkSurfaceFormatKHR();

            foreach (var avail_fmt in fmts)
            {
                if (avail_fmt.format == VkFormat.FormatB8g8r8a8Unorm && avail_fmt.colorSpace == VkColorSpaceKHR.ColorSpaceSrgbNonlinearKhr)
                {
                    chosen_fmt = avail_fmt;
                    fmt_valid  = true;
                    break;
                }
            }
            if (!fmt_valid && fmts.Length > 0)
            {
                chosen_fmt = fmts[0];
                fmt_valid  = true;
            }

            uint present_mode_cnt = 0;

            vkGetPhysicalDeviceSurfacePresentModesKHR(physDevice, surfaceHndl, &present_mode_cnt, null);
            var present_modes = stackalloc VkPresentModeKHR[(int)present_mode_cnt];

            vkGetPhysicalDeviceSurfacePresentModesKHR(physDevice, surfaceHndl, &present_mode_cnt, present_modes);

            bool             present_valid  = false;
            VkPresentModeKHR chosen_present = VkPresentModeKHR.PresentModeBeginRangeKhr;

            for (int i = 0; i < present_mode_cnt; i++)
            {
                var avail_present = present_modes[i];
                if (avail_present == VkPresentModeKHR.PresentModeMailboxKhr)
                {
                    present_valid  = true;
                    chosen_present = VkPresentModeKHR.PresentModeMailboxKhr;
                }
                else if (avail_present == VkPresentModeKHR.PresentModeFifoRelaxedKhr)
                {
                    present_valid  = true;
                    chosen_present = VkPresentModeKHR.PresentModeFifoRelaxedKhr;
                }
            }
            if (!present_valid)
            {
                present_valid  = true;
                chosen_present = VkPresentModeKHR.PresentModeFifoKhr;
            }
            chosen_present = VkPresentModeKHR.PresentModeImmediateKhr;

            if (!fmt_valid)
            {
                return(0);
            }
            if (!present_valid)
            {
                return(0);
            }

            present_mode = chosen_present;
            surface_fmt  = chosen_fmt;

            return(score);
        }
Exemplo n.º 22
0
        public unsafe Swapchain(Device device, NativeWindow window)
        {
            _device = device;
            _window = window;

            //get present queue
            _presentQueueFamily = GetQueueFamilyWithPresentationSupport(
                device,
                window
                );

            //get surface capabilities
            _surfaceCapabilities = GetSurfaceCapabilities(
                device,
                window
                );

            //get surface format support
            _supportedSurfaceFormats = GetSupportedSurfaceFormats(
                device,
                window
                );

            //get present mode support
            _supportedPresentModes = GetSupportedPresentModes(
                device,
                window
                );

            //choose best surface format
            #region Surface Format

            if (
                _supportedSurfaceFormats.Count == 1 &&
                _supportedSurfaceFormats[0].format == VkFormat.Undefined
                )
            {
                _surfaceFormat = new VkSurfaceFormatKHR
                {
                    colorSpace = VkColorSpaceKHR.SrgbNonlinearKHR,
                    format     = VkFormat.R8g8b8Unorm
                };
            }
            else
            {
                bool choosenFormat = false;
                foreach (var format in _supportedSurfaceFormats)
                {
                    if (
                        format.format == VkFormat.R8g8b8Unorm &&
                        format.colorSpace == VkColorSpaceKHR.SrgbNonlinearKHR
                        )
                    {
                        _surfaceFormat = format;
                        choosenFormat  = true;
                        break;
                    }
                }
                if (choosenFormat == false)
                {
                    _surfaceFormat = _supportedSurfaceFormats[0];
                }
            }

            #endregion

            #region Surface Present Mode

            _surfacePresentMode = VkPresentModeKHR.FifoKHR;
            foreach (var presentMode in _supportedPresentModes)
            {
                if (presentMode == VkPresentModeKHR.MailboxKHR)
                {
                    _surfacePresentMode = presentMode;
                    break;
                }
                else if (presentMode == VkPresentModeKHR.ImmediateKHR)
                {
                    _surfacePresentMode = presentMode;
                }
            }

            #endregion

            #region Surface Extent

            if (_surfaceCapabilities.currentExtent.width != uint.MaxValue)
            {
                _surfaceExtent = _surfaceCapabilities.currentExtent;
            }
            else
            {
                _surfaceExtent = new VkExtent2D
                {
                    width = Math.Clamp(
                        Convert.ToUInt32(window.Width),
                        _surfaceCapabilities.minImageExtent.width,
                        _surfaceCapabilities.maxImageExtent.width
                        ),
                    height = Math.Clamp(
                        Convert.ToUInt32(window.Height),
                        _surfaceCapabilities.minImageExtent.height,
                        _surfaceCapabilities.maxImageExtent.height
                        )
                };
            }

            #endregion

            #region Images Count

            var imagesCount = _surfaceCapabilities.minImageCount + 1;
            if (_surfaceCapabilities.maxImageCount > 0)
            {
                if (imagesCount > _surfaceCapabilities.maxImageCount)
                {
                    imagesCount = Math.Min(_surfaceCapabilities.maxImageCount, 2);
                }
            }

            #endregion

            var queueFamilyIndices = new NativeList <uint>();
            foreach (var queueFamily in device.QueueFamilies)
            {
                queueFamilyIndices.Add(queueFamily.Index);
            }

            var swapchainInfo = new VkSwapchainCreateInfoKHR
            {
                sType            = VkStructureType.SwapchainCreateInfoKHR,
                compositeAlpha   = VkCompositeAlphaFlagsKHR.OpaqueKHR,
                minImageCount    = imagesCount,
                imageFormat      = _surfaceFormat.format,
                imageColorSpace  = _surfaceFormat.colorSpace,
                imageExtent      = _surfaceExtent,
                imageArrayLayers = 1,
                imageUsage       = (
                    VkImageUsageFlags.ColorAttachment |
                    VkImageUsageFlags.TransferDst
                    ),
                imageSharingMode      = VkSharingMode.Concurrent,
                preTransform          = _surfaceCapabilities.currentTransform,
                presentMode           = _surfacePresentMode,
                surface               = window.Surface,
                clipped               = true,
                queueFamilyIndexCount = queueFamilyIndices.Count,
                pQueueFamilyIndices   = (uint *)queueFamilyIndices.Data.ToPointer()
            };

            VkSwapchainKHR swapchain;
            if (VulkanNative.vkCreateSwapchainKHR(
                    device.Handle,
                    &swapchainInfo,
                    null,
                    &swapchain
                    ) != VkResult.Success)
            {
                throw new Exception("failed to create swapchain");
            }
            _handle = swapchain;

            SetupSwapchainImages();
        }