public SoftwareSwapchain(SoftwareDevice device, VkSwapchainCreateInfoKHR createInfo)
 {
     this.m_device     = device;
     this.m_surface    = (BaseSoftwareSurface)createInfo.surface;
     this.m_createInfo = createInfo;
     this.m_Images     = new List <SoftwareImage>();
 }
Beispiel #2
0
        internal VkSwapchainKHR CreateSwapChain(VkSwapchainCreateInfoKHR infos)
        {
            VkSwapchainKHR newSwapChain;

            Utils.CheckResult(vkCreateSwapchainKHR(dev, ref infos, IntPtr.Zero, out newSwapChain));
            return(newSwapChain);
        }
Beispiel #3
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]);
            }
        }
Beispiel #4
0
        static VkSwapchainKHR CreateSwapchain(VkSwapchainKHR oldSwapchain, VkInstance instance, VkDevice device, VkPhysicalDevice physicalDevice,
                                              VkSurfaceKHR surface, uint queueFamilyIndex)
        {
            vkDestroySwapchainKHR(device, oldSwapchain, null);//Does nothing if oldswapchain is null

            VkSurfaceCapabilitiesKHR capabilities = new VkSurfaceCapabilitiesKHR();

            Assert(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &capabilities));

            GetSwapchainFormat(physicalDevice, surface);
            VkSwapchainKHR           swapchain   = VkSwapchainKHR.Null;
            VkSwapchainCreateInfoKHR pCreateInfo = VkSwapchainCreateInfoKHR.New();

            pCreateInfo.surface               = surface;
            pCreateInfo.minImageCount         = capabilities.minImageCount;
            pCreateInfo.imageFormat           = surfaceFormat.format;//SHORTCUT: Some devices might not support
            pCreateInfo.imageColorSpace       = surfaceFormat.colorSpace;
            pCreateInfo.imageExtent           = capabilities.currentExtent;
            pCreateInfo.imageArrayLayers      = 1;
            pCreateInfo.imageUsage            = VkImageUsageFlags.ColorAttachment;
            pCreateInfo.queueFamilyIndexCount = 1;
            pCreateInfo.pQueueFamilyIndices   = &queueFamilyIndex;
            pCreateInfo.preTransform          = VkSurfaceTransformFlagsKHR.IdentityKHR;
            pCreateInfo.compositeAlpha        = VkCompositeAlphaFlagsKHR.OpaqueKHR;
            pCreateInfo.presentMode           = VkPresentModeKHR.MailboxKHR;

            Assert(vkCreateSwapchainKHR(device, &pCreateInfo, null, &swapchain));

            return(swapchain);
        }
Beispiel #5
0
        protected VkSwapchainKHR CreateSwapchain(VkDevice device, VkSurfaceKHR surface,
                                                 VkSurfaceFormatKHR surfaceFormat, VkSurfaceCapabilitiesKHR surfaceCapabilities)
        {
            var compositeAlpha = surfaceCapabilities.supportedCompositeAlpha.HasFlag(
                VkCompositeAlphaFlagBitsKHR.InheritKHR)
                ? VkCompositeAlphaFlagBitsKHR.InheritKHR
                : VkCompositeAlphaFlagBitsKHR.OpaqueKHR;
            UInt32 index = 0;
            var    info  = new VkSwapchainCreateInfoKHR {
                sType = VkStructureType.SwapchainCreateInfoKHR
            };

            info.surface            = surface;
            info.minImageCount      = surfaceCapabilities.minImageCount;
            info.imageFormat        = surfaceFormat.format;
            info.imageColorSpace    = surfaceFormat.colorSpace;
            info.imageExtent        = surfaceCapabilities.currentExtent;
            info.imageUsage         = VkImageUsageFlagBits.ColorAttachment;
            info.preTransform       = VkSurfaceTransformFlagBitsKHR.IdentityKHR;
            info.imageArrayLayers   = 1;
            info.imageSharingMode   = VkSharingMode.Exclusive;
            info.queueFamilyIndices = index;
            info.presentMode        = VkPresentModeKHR.FifoKHR;
            info.compositeAlpha     = compositeAlpha;
            //return device.CreateSwapchainKHR(ref info, null);
            VkSwapchainKHR swapchain;

            vkAPI.vkCreateSwapchainKHR(device, &info, null, &swapchain).Check();

            return(swapchain);
        }
Beispiel #6
0
        private SoftwareImage(SoftwareDevice device, VkSwapchainCreateInfoKHR createInfo, out VkResult result)
        {
            this.m_device = device;

            this.m_imageFormat     = createInfo.imageFormat;
            this.m_imageExtent     = VkExtent3D.Create(createInfo.imageExtent.width, createInfo.imageExtent.height, 1);
            this.m_imageColorSpace = createInfo.imageColorSpace;

            Initialize(out result);
        }
Beispiel #7
0
        public DummySwapchain(DummyDevice m_device, VkSwapchainCreateInfoKHR createInfo)
        {
            this.m_device     = m_device;
            this.m_CreateInfo = createInfo;
            this.m_Images     = new List <VkImage>();

            while (m_Images.Count < Math.Max(1, createInfo.minImageCount))
            {
                m_Images.Add(new DummyImage(m_device, createInfo));
            }
        }
Beispiel #8
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();
                }
            }
Beispiel #9
0
        public static SoftwareImage CreateSwapchainImage(SoftwareDevice device, VkSwapchainCreateInfoKHR swapchainInfo, out VkResult result)
        {
            VkImageCreateInfo createInfo = new VkImageCreateInfo();

            createInfo.extent        = VkExtent3D.Create(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height, 1);
            createInfo.format        = swapchainInfo.imageFormat;
            createInfo.imageType     = VkImageType.VK_IMAGE_TYPE_2D;
            createInfo.arrayLayers   = swapchainInfo.imageArrayLayers;
            createInfo.sharingMode   = swapchainInfo.imageSharingMode;
            createInfo.usage         = VkImageUsageFlags.VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VkImageUsageFlags.VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
            createInfo.samples       = VkSampleCountFlagBits.VK_SAMPLE_COUNT_1_BIT;
            createInfo.mipLevels     = 1;
            createInfo.initialLayout = VkImageLayout.VK_IMAGE_LAYOUT_UNDEFINED;

            return(new SoftwareImage(device, createInfo, out result));
        }
Beispiel #10
0
        void CreateSwapchain(SwapchainCreateInfo mInfo)
        {
            var info = new VkSwapchainCreateInfoKHR();

            info.sType            = VkStructureType.SwapchainCreateInfoKhr;
            info.surface          = mInfo.surface.Native;
            info.minImageCount    = mInfo.minImageCount;
            info.imageFormat      = mInfo.imageFormat;
            info.imageColorSpace  = mInfo.imageColorSpace;
            info.imageExtent      = mInfo.imageExtent;
            info.imageArrayLayers = mInfo.imageArrayLayers;
            info.imageUsage       = mInfo.imageUsage;
            info.imageSharingMode = mInfo.imageSharingMode;

            var indicesMarshalled = new NativeArray <uint>(mInfo.queueFamilyIndices);

            info.queueFamilyIndexCount = (uint)indicesMarshalled.Count;
            info.pQueueFamilyIndices   = indicesMarshalled.Address;

            info.preTransform   = mInfo.preTransform;
            info.compositeAlpha = mInfo.compositeAlpha;
            info.presentMode    = mInfo.presentMode;
            info.clipped        = mInfo.clipped ? 1u : 0u;

            if (mInfo.oldSwapchain != null)
            {
                info.oldSwapchain = mInfo.oldSwapchain.Native;
            }

            using (indicesMarshalled) {
                var result = Device.Commands.createSwapchain(Device.Native, ref info, Device.Instance.AllocationCallbacks, out swapchain);
                if (result != VkResult.Success)
                {
                    throw new SwapchainException(string.Format("Error creating swapchain: {0}", result));
                }
            }

            Format      = info.imageFormat;
            ColorSpace  = info.imageColorSpace;
            Extent      = info.imageExtent;
            ArrayLayers = info.imageArrayLayers;
            PresentMode = info.presentMode;
            Usage       = info.imageUsage;
            SharingMode = info.imageSharingMode;
        }
Beispiel #11
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;
        }
        public static VkResult Create(SoftwareDevice device, VkSwapchainCreateInfoKHR createInfo, out VkSwapchainKHR swapChain)
        {
            SoftwareSwapchain retVal = new SoftwareSwapchain(device, createInfo);

            retVal.m_Images.Clear();

            while (retVal.m_Images.Count < createInfo.minImageCount)
            {
                VkResult      resultCode;
                SoftwareImage image = SoftwareImage.CreateSwapchainImage(device, createInfo, out resultCode);
                if (resultCode != VkResult.VK_SUCCESS)
                {
                    swapChain = default(VkSwapchainKHR);
                    return(resultCode);
                }
                retVal.m_Images.Add(image);
            }

            swapChain = retVal;
            return(VkResult.VK_SUCCESS);
        }
Beispiel #13
0
        private void CreateSwapChain()
        {
            var swapChainSupport = QuerySwapChainSupport(physicalDevice, surface);
            var surfaceFormat    = ChooseSwapSurfaceFormat(swapChainSupport.Formats);
            var presentMode      = ChooseSwapPresentMode(swapChainSupport.PresentModes);
            var extent           = ChooseSwapExtent(swapChainSupport.Capabilities);
            var minImages        = swapChainSupport.Capabilities.MinImageCount;
            var maxImages        = swapChainSupport.Capabilities.MaxImageCount > 0
                ? swapChainSupport.Capabilities.MaxImageCount
                : int.MaxValue;
            var imageCount     = Math.Max(minImages, Math.Min(maxImages, 2));
            var indices        = FindQueueFamilies(physicalDevice, surface).Value;
            var separateQueues = indices.GraphicsFamily != indices.PresentFamily;
            var createInfo     = new VkSwapchainCreateInfoKHR
            {
                Surface            = surface,
                MinImageCount      = imageCount,
                ImageFormat        = surfaceFormat.Format,
                ImageColorSpace    = surfaceFormat.ColorSpace,
                ImageExtent        = extent,
                ImageArrayLayers   = 1,
                ImageUsage         = VkImageUsageFlags.ColorAttachment,
                ImageSharingMode   = separateQueues ? VkSharingMode.Concurrent : VkSharingMode.Exclusive,
                QueueFamilyIndices = separateQueues ? new[] { indices.GraphicsFamily, indices.PresentFamily } : null,
                PreTransform       = swapChainSupport.Capabilities.CurrentTransform,
                CompositeAlpha     = VkCompositeAlphaFlagsKHR.Opaque,
                PresentMode        = presentMode,
                Clipped            = true,
                OldSwapchain       = null
            };

            swapChain            = device.CreateSwapchainKHR(createInfo, null).Object;
            swapChainImages      = swapChain.GetImagesKHR().Object;
            swapchainImageFormat = surfaceFormat.Format;
            swapChainExtent      = extent;
        }
Beispiel #14
0
 public override VkResult CreateSwapchain(VkSwapchainCreateInfoKHR createInfo, out VkSwapchainKHR swapChain)
 {
     swapChain = new DummySwapchain(this, createInfo);
     return(VkResult.VK_SUCCESS);
 }
Beispiel #15
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));
            }
        }
Beispiel #16
0
        void CreateSwapchain()
        {
            var support = GetSwapchainSupport(physicalDevice);
            var cap     = support.cap.Value;

            var surfaceFormat = ChooseSwapSurfaceFormat(support.formats);
            var mode          = ChooseSwapPresentMode(support.modes);
            var extent        = ChooseSwapExtent(ref cap);

            uint imageCount = cap.minImageCount + 1;

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

            var info = new VkSwapchainCreateInfoKHR();

            info.sType            = CSGL.Vulkan.VkStructureType.SwapchainCreateInfoKhr;
            info.surface          = surface;
            info.minImageCount    = imageCount;
            info.imageFormat      = surfaceFormat.format;
            info.imageColorSpace  = surfaceFormat.colorSpace;
            info.imageExtent      = extent;
            info.imageArrayLayers = 1;
            info.imageUsage       = CSGL.Vulkan.VkImageUsageFlags.ColorAttachmentBit;

            var queueFamilyIndices = new NativeArray <uint>(2);

            queueFamilyIndices[0] = graphicsIndex;
            queueFamilyIndices[1] = presentIndex;

            if (graphicsIndex != presentIndex)
            {
                info.imageSharingMode      = CSGL.Vulkan.VkSharingMode.Concurrent;
                info.queueFamilyIndexCount = 2;
                info.pQueueFamilyIndices   = queueFamilyIndices.Address;
            }
            else
            {
                info.imageSharingMode = CSGL.Vulkan.VkSharingMode.Exclusive;
            }

            info.preTransform   = cap.currentTransform;
            info.compositeAlpha = CSGL.Vulkan.VkCompositeAlphaFlagsKHR.OpaqueBitKhr;
            info.presentMode    = mode;
            info.clipped        = 1;

            var oldSwapchain = swapchain;

            info.oldSwapchain = oldSwapchain;

            VkSwapchainKHR newSwapchain;
            var            result = createSwapchain(device, ref info, alloc, out newSwapchain);

            if (swapchain != VkSwapchainKHR.Null)
            {
                destroySwapchain(device, swapchain, alloc);
            }
            swapchain = newSwapchain;

            getSwapchainImages(device, swapchain, ref imageCount, IntPtr.Zero);
            var swapchainImagesNative = new NativeArray <VkImage>(imageCount);

            getSwapchainImages(device, swapchain, ref imageCount, swapchainImagesNative.Address);

            swapchainImages = new List <VkImage>(swapchainImagesNative.Count);

            for (int i = 0; i < imageCount; i++)
            {
                swapchainImages.Add(swapchainImagesNative[i]);
            }

            swapchainImageFormat = surfaceFormat.format;
            swapchainExtent      = extent;

            support.cap.Dispose();
            queueFamilyIndices.Dispose();
        }
 public abstract VkResult CreateSwapchain(VkSwapchainCreateInfoKHR createInfo, out VkSwapchainKHR swapChain);
Beispiel #18
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;
        }
        private unsafe void CreateSwapChain()
        {
            var formats = new[] { PixelFormat.B8G8R8A8_UNorm_SRgb, PixelFormat.R8G8B8A8_UNorm_SRgb, PixelFormat.B8G8R8A8_UNorm, PixelFormat.R8G8B8A8_UNorm };

            foreach (var format in formats)
            {
                var nativeFromat = VulkanConvertExtensions.ConvertPixelFormat(format);

                vkGetPhysicalDeviceFormatProperties(GraphicsDevice.NativePhysicalDevice, nativeFromat, out var formatProperties);

                if ((formatProperties.optimalTilingFeatures & VkFormatFeatureFlags.ColorAttachment) != 0)
                {
                    Description.BackBufferFormat = format;
                    break;
                }
            }

            // Queue
            // TODO VULKAN: Queue family is needed when creating the Device, so here we can just do a sanity check?
            var queueNodeIndex = vkGetPhysicalDeviceQueueFamilyProperties(GraphicsDevice.NativePhysicalDevice).ToArray().
                                 Where((properties, index) => (properties.queueFlags & VkQueueFlags.Graphics) != 0 && vkGetPhysicalDeviceSurfaceSupportKHR(GraphicsDevice.NativePhysicalDevice, (uint)index, surface, out var supported) == VkResult.Success && supported).
                                 Select((properties, index) => index).First();

            // Surface format
            var backBufferFormat = VulkanConvertExtensions.ConvertPixelFormat(Description.BackBufferFormat);

            var surfaceFormats = vkGetPhysicalDeviceSurfaceFormatsKHR(GraphicsDevice.NativePhysicalDevice, surface).ToArray();

            if ((surfaceFormats.Length != 1 || surfaceFormats[0].format != VkFormat.Undefined) &&
                !surfaceFormats.Any(x => x.format == backBufferFormat))
            {
                backBufferFormat = surfaceFormats[0].format;
            }

            // Create swapchain
            vkGetPhysicalDeviceSurfaceCapabilitiesKHR(GraphicsDevice.NativePhysicalDevice, surface, out var surfaceCapabilities);

            // Buffer count
            uint desiredImageCount = Math.Max(surfaceCapabilities.minImageCount, 2);

            if (surfaceCapabilities.maxImageCount > 0 && desiredImageCount > surfaceCapabilities.maxImageCount)
            {
                desiredImageCount = surfaceCapabilities.maxImageCount;
            }

            // Transform
            VkSurfaceTransformFlagsKHR preTransform;

            if ((surfaceCapabilities.supportedTransforms & VkSurfaceTransformFlagsKHR.Identity) != 0)
            {
                preTransform = VkSurfaceTransformFlagsKHR.Identity;
            }
            else
            {
                preTransform = surfaceCapabilities.currentTransform;
            }

            // Find present mode
            var presentModes         = vkGetPhysicalDeviceSurfacePresentModesKHR(GraphicsDevice.NativePhysicalDevice, surface);
            var swapChainPresentMode = VkPresentModeKHR.Fifo; // Always supported

            foreach (var presentMode in presentModes)
            {
                // TODO VULKAN: Handle PresentInterval.Two
                if (Description.PresentationInterval == PresentInterval.Immediate)
                {
                    // Prefer mailbox to immediate
                    if (presentMode == VkPresentModeKHR.Immediate)
                    {
                        swapChainPresentMode = VkPresentModeKHR.Immediate;
                    }
                    else if (presentMode == VkPresentModeKHR.Mailbox)
                    {
                        swapChainPresentMode = VkPresentModeKHR.Mailbox;
                        break;
                    }
                }
            }

            // Create swapchain
            var swapchainCreateInfo = new VkSwapchainCreateInfoKHR
            {
                sType            = VkStructureType.SwapchainCreateInfoKHR,
                surface          = surface,
                imageArrayLayers = 1,
                imageSharingMode = VkSharingMode.Exclusive,
                imageExtent      = new Vortice.Mathematics.Size(Description.BackBufferWidth, Description.BackBufferHeight),
                imageFormat      = backBufferFormat,
                imageColorSpace  = Description.ColorSpace == ColorSpace.Gamma ? VkColorSpaceKHR.SrgbNonLinear : 0,
                imageUsage       = VkImageUsageFlags.ColorAttachment | VkImageUsageFlags.TransferDst | (surfaceCapabilities.supportedUsageFlags & VkImageUsageFlags.TransferSrc), // TODO VULKAN: Use off-screen buffer to emulate
                presentMode      = swapChainPresentMode,
                compositeAlpha   = VkCompositeAlphaFlagsKHR.Opaque,
                minImageCount    = desiredImageCount,
                preTransform     = preTransform,
                oldSwapchain     = swapChain,
                clipped          = true
            };

            vkCreateSwapchainKHR(GraphicsDevice.NativeDevice, &swapchainCreateInfo, null, out var newSwapChain);

            DestroySwapchain();

            swapChain = newSwapChain;
            CreateBackBuffers();
        }
Beispiel #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]);
            }
        }
Beispiel #21
0
        private unsafe void CreateSwapChain()
        {
            // we are destroying the swap chain now, because it causes lots of other things to be reset too (like all commandbufferpools)
            // normally we pass the old swapchain to the create new swapchain Vulkan call... but I haven't figured out a stable way of
            // preserving the old swap chain to be passed during the new swapchain creation, and then destroying just the old swapchain parts.
            // might have to reset the command buffers and pipeline stuff after swapchain handoff... for another day e.g. TODO
            DestroySwapchain();

            var formats = new[] { PixelFormat.B8G8R8A8_UNorm_SRgb, PixelFormat.R8G8B8A8_UNorm_SRgb, PixelFormat.B8G8R8A8_UNorm, PixelFormat.R8G8B8A8_UNorm };

            foreach (var format in formats)
            {
                var nativeFromat = VulkanConvertExtensions.ConvertPixelFormat(format);

                vkGetPhysicalDeviceFormatProperties(GraphicsDevice.NativePhysicalDevice, nativeFromat, out var formatProperties);

                if ((formatProperties.optimalTilingFeatures & VkFormatFeatureFlags.ColorAttachment) != 0)
                {
                    Description.BackBufferFormat = format;
                    break;
                }
            }

            // Queue
            // TODO VULKAN: Queue family is needed when creating the Device, so here we can just do a sanity check?
            var queueNodeIndex = vkGetPhysicalDeviceQueueFamilyProperties(GraphicsDevice.NativePhysicalDevice).ToArray().
                                 Where((properties, index) => (properties.queueFlags & VkQueueFlags.Graphics) != 0 && vkGetPhysicalDeviceSurfaceSupportKHR(GraphicsDevice.NativePhysicalDevice, (uint)index, surface, out var supported) == VkResult.Success && supported == Vortice.Vulkan.VkBool32.True).
                                 Select((properties, index) => index).First();

            // Surface format
            var backBufferFormat = VulkanConvertExtensions.ConvertPixelFormat(Description.BackBufferFormat);

            var surfaceFormats = vkGetPhysicalDeviceSurfaceFormatsKHR(GraphicsDevice.NativePhysicalDevice, surface).ToArray();

            if ((surfaceFormats.Length != 1 || surfaceFormats[0].format != VkFormat.Undefined) &&
                !surfaceFormats.Any(x => x.format == backBufferFormat))
            {
                backBufferFormat = surfaceFormats[0].format;
            }

            // Create swapchain
            vkGetPhysicalDeviceSurfaceCapabilitiesKHR(GraphicsDevice.NativePhysicalDevice, surface, out var surfaceCapabilities);

            // Buffer count
            uint desiredImageCount = Math.Max(surfaceCapabilities.minImageCount, 6);

            if (surfaceCapabilities.maxImageCount > 0 && desiredImageCount > surfaceCapabilities.maxImageCount)
            {
                desiredImageCount = surfaceCapabilities.maxImageCount;
            }

            // Transform
            VkSurfaceTransformFlagsKHR preTransform;

            if ((surfaceCapabilities.supportedTransforms & VkSurfaceTransformFlagsKHR.Identity) != 0)
            {
                preTransform = VkSurfaceTransformFlagsKHR.Identity;
            }
            else
            {
                preTransform = surfaceCapabilities.currentTransform;
            }

            // Find present mode
            var swapChainPresentMode = VkPresentModeKHR.Fifo; // Always supported, but slow

            if (Description.PresentationInterval == PresentInterval.Immediate)
            {
                var presentModes = vkGetPhysicalDeviceSurfacePresentModesKHR(GraphicsDevice.NativePhysicalDevice, surface);
                foreach (var pm in presentModes)
                {
                    if (pm == VkPresentModeKHR.Mailbox)
                    {
                        swapChainPresentMode = VkPresentModeKHR.Mailbox;
                        break;
                    }
                }
            }

            // Create swapchain
            var swapchainCreateInfo = new VkSwapchainCreateInfoKHR
            {
                sType            = VkStructureType.SwapchainCreateInfoKHR,
                surface          = surface,
                imageArrayLayers = 1,
                imageSharingMode = VkSharingMode.Exclusive,
                imageExtent      = new Vortice.Vulkan.VkExtent2D(Description.BackBufferWidth, Description.BackBufferHeight),
                imageFormat      = backBufferFormat,
                imageColorSpace  = Description.ColorSpace == ColorSpace.Gamma ? VkColorSpaceKHR.SrgbNonLinear : 0,
                imageUsage       = VkImageUsageFlags.ColorAttachment | VkImageUsageFlags.TransferDst | (surfaceCapabilities.supportedUsageFlags & VkImageUsageFlags.TransferSrc), // TODO VULKAN: Use off-screen buffer to emulate
                presentMode      = swapChainPresentMode,
                compositeAlpha   = VkCompositeAlphaFlagsKHR.Opaque,
                minImageCount    = desiredImageCount,
                preTransform     = preTransform,
                oldSwapchain     = swapChain,
                clipped          = Vortice.Vulkan.VkBool32.True
            };

            vkCreateSwapchainKHR(GraphicsDevice.NativeDevice, &swapchainCreateInfo, null, out swapChain);

            CreateBackBuffers();

            // resize/create stencil buffers
            var newTextureDescription = DepthStencilBuffer.Description;

            newTextureDescription.Width  = Description.BackBufferWidth;
            newTextureDescription.Height = Description.BackBufferHeight;

            // Manually update the texture
            DepthStencilBuffer.OnDestroyed();

            // Put it in our back buffer texture
            DepthStencilBuffer.InitializeFrom(newTextureDescription);
        }
Beispiel #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();
        }
Beispiel #23
0
        private ulong CreateSwapChain()
        {
            ulong swapChain;

            VkSurfaceCapabilitiesKHR surfaceCapabilities;
            var result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(_graphicsAdapter.PhysicalDevice, Surface, &surfaceCapabilities);

            if (result != VK_SUCCESS)
            {
                ThrowExternalException(nameof(vkGetPhysicalDeviceSurfaceCapabilitiesKHR), (int)result);
            }

            uint presentModeCount;

            result = vkGetPhysicalDeviceSurfacePresentModesKHR(_graphicsAdapter.PhysicalDevice, Surface, &presentModeCount, pPresentModes: null);

            if (result != VK_SUCCESS)
            {
                ThrowExternalException(nameof(vkGetPhysicalDeviceSurfacePresentModesKHR), (int)result);
            }

            var presentModes = stackalloc VkPresentModeKHR[(int)presentModeCount];

            result = vkGetPhysicalDeviceSurfacePresentModesKHR(_graphicsAdapter.PhysicalDevice, Surface, &presentModeCount, presentModes);

            if (result != VK_SUCCESS)
            {
                ThrowExternalException(nameof(vkGetPhysicalDeviceSurfacePresentModesKHR), (int)result);
            }

            if (((uint)_graphicsSurface.BufferCount < surfaceCapabilities.minImageCount) ||
                ((surfaceCapabilities.maxImageCount != 0) && ((uint)_graphicsSurface.BufferCount > surfaceCapabilities.maxImageCount)))
            {
                ThrowArgumentOutOfRangeException(nameof(_graphicsSurface), _graphicsSurface);
            }

            var swapChainCreateInfo = new VkSwapchainCreateInfoKHR {
                sType           = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
                pNext           = null,
                flags           = 0,
                surface         = Surface,
                minImageCount   = (uint)_graphicsSurface.BufferCount,
                imageFormat     = VK_FORMAT_UNDEFINED,
                imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
                imageExtent     = new VkExtent2D {
                    width  = (uint)_graphicsSurface.Width,
                    height = (uint)_graphicsSurface.Height,
                },
                imageArrayLayers      = 1,
                imageUsage            = (uint)(VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT),
                imageSharingMode      = VK_SHARING_MODE_EXCLUSIVE,
                queueFamilyIndexCount = 0,
                pQueueFamilyIndices   = null,
                preTransform          = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
                compositeAlpha        = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
                presentMode           = VK_PRESENT_MODE_FIFO_KHR,
                clipped      = VK_TRUE,
                oldSwapchain = VK_NULL_HANDLE,
            };

            if ((surfaceCapabilities.supportedTransforms & (uint)VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) == 0)
            {
                swapChainCreateInfo.preTransform = surfaceCapabilities.currentTransform;
            }

            uint surfaceFormatCount;

            result = vkGetPhysicalDeviceSurfaceFormatsKHR(_graphicsAdapter.PhysicalDevice, Surface, &surfaceFormatCount, pSurfaceFormats: null);

            if (result != VK_SUCCESS)
            {
                ThrowExternalException(nameof(vkGetPhysicalDeviceSurfaceFormatsKHR), (int)result);
            }

            var surfaceFormats = stackalloc VkSurfaceFormatKHR[(int)surfaceFormatCount];

            result = vkGetPhysicalDeviceSurfaceFormatsKHR(_graphicsAdapter.PhysicalDevice, Surface, &surfaceFormatCount, surfaceFormats);

            if (result != VK_SUCCESS)
            {
                ThrowExternalException(nameof(vkGetPhysicalDeviceSurfaceFormatsKHR), (int)result);
            }

            for (var i = 0u; i < surfaceFormatCount; i++)
            {
                if (surfaceFormats[i].format == VK_FORMAT_R8G8B8A8_SRGB)
                {
                    swapChainCreateInfo.imageFormat     = surfaceFormats[i].format;
                    swapChainCreateInfo.imageColorSpace = surfaceFormats[i].colorSpace;
                    break;
                }
            }
            result = vkCreateSwapchainKHR(Device, &swapChainCreateInfo, pAllocator: null, &swapChain);

            if (result != VK_SUCCESS)
            {
                ThrowExternalException(nameof(vkCreateSwapchainKHR), (int)result);
            }
            _swapChainFormat = swapChainCreateInfo.imageFormat;

            return(swapChain);
        }
Beispiel #24
0
 public DummyImage(DummyDevice device, VkSwapchainCreateInfoKHR createInfo)
 {
     this.m_device     = device;
     this.m_createInfo = createInfo;
 }
Beispiel #25
0
 public static extern VkResult CreateSwapchainKHR(
     VkDevice device,
     ref VkSwapchainCreateInfoKHR pCreateInfo,
     IntPtr pAllocator,
     out VkSwapchainKHR pSwapchain
     );
Beispiel #26
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;
        }
Beispiel #27
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);
                }
            }
        }
Beispiel #28
0
 public override VkResult CreateSwapchain(VkSwapchainCreateInfoKHR createInfo, out VkSwapchainKHR swapChain)
 {
     return(SoftwareSwapchain.Create(this, createInfo, out swapChain));
 }
        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;
        }
Beispiel #30
0
 public static VkSwapchainKHR CreateSwapchainKHR(ref VkSwapchainCreateInfoKHR pCreateInfo)
 {
     VulkanUtil.CheckResult(vkCreateSwapchainKHR(device, Utilities.AsPtr(ref pCreateInfo), null, out VkSwapchainKHR pSwapchain));
     return(pSwapchain);
 }