Пример #1
0
 public unsafe Swapchain[] CreateSharedSwapchains(SwapchainCreateInfo[] createInfos, AllocationCallbacks allocator)
 {
     var swapchains = new Swapchain[createInfos.Length];
     fixed (SwapchainCreateInfo* __createInfos__ = &createInfos[0])
     fixed (Swapchain* __swapchains__ = &swapchains[0])
     {
         vkCreateSharedSwapchainsKHR(this, (uint)createInfos.Length, __createInfos__, &allocator, __swapchains__).CheckError();
     }
     return swapchains;
 }
        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);

                FormatProperties formatProperties;
                GraphicsDevice.NativePhysicalDevice.GetFormatProperties(nativeFromat, out formatProperties);

                if ((formatProperties.OptimalTilingFeatures & FormatFeatureFlags.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 = GraphicsDevice.NativePhysicalDevice.QueueFamilyProperties.
                Where((properties, index) => (properties.QueueFlags & QueueFlags.Graphics) != 0 && GraphicsDevice.NativePhysicalDevice.GetSurfaceSupport((uint)index, surface)).
                Select((properties, index) => index).First();

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

            var surfaceFormats = GraphicsDevice.NativePhysicalDevice.GetSurfaceFormats(surface);
            if ((surfaceFormats.Length != 1 || surfaceFormats[0].Format != Format.Undefined) &&
                !surfaceFormats.Any(x => x.Format == backBufferFormat))
            {
                backBufferFormat = surfaceFormats[0].Format;
            }

            // Create swapchain
            SurfaceCapabilities surfaceCapabilities;
            GraphicsDevice.NativePhysicalDevice.GetSurfaceCapabilities(surface, out surfaceCapabilities);

            // Buffer count
            uint desiredImageCount = Math.Max(surfaceCapabilities.MinImageCount, 2);
            if (surfaceCapabilities.MaxImageCount > 0 && desiredImageCount > surfaceCapabilities.MaxImageCount)
            {
                desiredImageCount = surfaceCapabilities.MaxImageCount;
            }

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

            // Find present mode
            var presentModes = GraphicsDevice.NativePhysicalDevice.GetSurfacePresentModes(surface);
            var swapChainPresentMode = PresentMode.Fifo; // Always supported
            foreach (var presentMode in presentModes)
            {
                // TODO VULKAN: Handle PresentInterval.Two
                if (Description.PresentationInterval == PresentInterval.Immediate)
                {
                    // Prefer mailbox to immediate
                    if (presentMode == PresentMode.Immediate)
                    {
                        swapChainPresentMode = PresentMode.Immediate;
                    }
                    else if (presentMode == PresentMode.Mailbox)
                    {
                        swapChainPresentMode = PresentMode.Mailbox;
                        break;
                    }
                }
            }

            // Create swapchain
            var swapchainCreateInfo = new SwapchainCreateInfo
            {
                StructureType = StructureType.SwapchainCreateInfo,
                Surface = surface,
                ImageArrayLayers = 1,
                ImageSharingMode = SharingMode.Exclusive,
                ImageExtent = new Extent2D((uint)Description.BackBufferWidth, (uint)Description.BackBufferHeight),
                ImageFormat = backBufferFormat,
                ImageColorSpace = Description.ColorSpace == ColorSpace.Gamma ? SharpVulkan.ColorSpace.SRgbNonlinear : 0,
                ImageUsage = ImageUsageFlags.ColorAttachment | (surfaceCapabilities.SupportedUsageFlags & ImageUsageFlags.TransferSource), // TODO VULKAN: Use off-screen buffer to emulate
                PresentMode = swapChainPresentMode,
                CompositeAlpha = CompositeAlphaFlags.Opaque,
                MinImageCount = desiredImageCount,
                PreTransform = preTransform,
                OldSwapchain = swapChain,
                Clipped = true
            };
            var newSwapChain = GraphicsDevice.NativeDevice.CreateSwapchain(ref swapchainCreateInfo);

            DestroySwapchain();

            swapChain = newSwapChain;
            CreateBackBuffers();
        }
        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);

                FormatProperties formatProperties;
                GraphicsDevice.NativePhysicalDevice.GetFormatProperties(nativeFromat, out formatProperties);

                if ((formatProperties.OptimalTilingFeatures & FormatFeatureFlags.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 = GraphicsDevice.NativePhysicalDevice.QueueFamilyProperties.
                                 Where((properties, index) => (properties.QueueFlags & QueueFlags.Graphics) != 0 && GraphicsDevice.NativePhysicalDevice.GetSurfaceSupport((uint)index, surface)).
                                 Select((properties, index) => index).First();

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

            var surfaceFormats = GraphicsDevice.NativePhysicalDevice.GetSurfaceFormats(surface);

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

            // Create swapchain
            SurfaceCapabilities surfaceCapabilities;

            GraphicsDevice.NativePhysicalDevice.GetSurfaceCapabilities(surface, out surfaceCapabilities);

            // Buffer count
            uint desiredImageCount = Math.Max(surfaceCapabilities.MinImageCount, 4);

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

            // Transform
            SurfaceTransformFlags preTransform;

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

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

            if (Description.PresentationInterval == PresentInterval.Immediate)
            {
                var presentModes = GraphicsDevice.NativePhysicalDevice.GetSurfacePresentModes(surface);
                if (presentModes.Contains(PresentMode.Mailbox))
                {
                    swapChainPresentMode = PresentMode.Mailbox;
                }
            }

            // Create swapchain
            var swapchainCreateInfo = new SwapchainCreateInfo
            {
                StructureType    = StructureType.SwapchainCreateInfo,
                Surface          = surface,
                ImageArrayLayers = 1,
                ImageSharingMode = SharingMode.Exclusive,
                ImageExtent      = new Extent2D((uint)Description.BackBufferWidth, (uint)Description.BackBufferHeight),
                ImageFormat      = backBufferFormat,
                ImageColorSpace  = Description.ColorSpace == ColorSpace.Gamma ? SharpVulkan.ColorSpace.SRgbNonlinear : 0,
                ImageUsage       = ImageUsageFlags.ColorAttachment | ImageUsageFlags.TransferDestination | (surfaceCapabilities.SupportedUsageFlags & ImageUsageFlags.TransferSource), // TODO VULKAN: Use off-screen buffer to emulate
                PresentMode      = swapChainPresentMode,
                CompositeAlpha   = CompositeAlphaFlags.Opaque,
                MinImageCount    = desiredImageCount,
                PreTransform     = preTransform,
                OldSwapchain     = Swapchain.Null,
                Clipped          = true
            };

            swapChain = GraphicsDevice.NativeDevice.CreateSwapchain(ref swapchainCreateInfo);

            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);

            // start new presentation thread
            runPresenter    = true;
            presenterThread = new Thread(new ThreadStart(PresenterThread));
            presenterThread.IsBackground = true;
            presenterThread.Name         = "Vulkan Presentation Thread";
            presenterThread.Priority     = ThreadPriority.AboveNormal;
            presenterThread.Start();
        }
Пример #4
0
        protected virtual void CreateSwapchain()
        {
            // surface format
            var surfaceFormats = physicalDevice.GetSurfaceFormats(surface);
            if (surfaceFormats.Length == 1 && surfaceFormats[0].Format == Format.Undefined)
            {
                backBufferFormat = Format.B8G8R8A8UNorm;
            }
            else
            {
                backBufferFormat = surfaceFormats[0].Format;
            }

            SurfaceCapabilities surfaceCapabilities;
            physicalDevice.GetSurfaceCapabilities(surface, out surfaceCapabilities);

            // Buffer count
            uint desiredImageCount = surfaceCapabilities.MinImageCount + 1;
            if (surfaceCapabilities.MaxImageCount > 0 && desiredImageCount > surfaceCapabilities.MaxImageCount)
            {
                desiredImageCount = surfaceCapabilities.MaxImageCount;
            }

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

            // Present mode
            var presentModes = physicalDevice.GetSurfacePresentModes(surface);

            var swapChainPresentMode = PresentMode.Fifo;
            if (presentModes.Contains(PresentMode.Mailbox))
                swapChainPresentMode = PresentMode.Mailbox;
            else if (presentModes.Contains(PresentMode.Immediate))
                swapChainPresentMode = PresentMode.Immediate;

            // Create swapchain
            var swapchainCreateInfo = new SwapchainCreateInfo
            {
                StructureType = StructureType.SwapchainCreateInfo,
                Surface = surface,
                ImageSharingMode = SharingMode.Exclusive,
                ImageExtent = new Extent2D((uint)form.ClientSize.Width, (uint)form.ClientSize.Height),
                ImageArrayLayers = 1,
                ImageFormat = backBufferFormat,
                ImageColorSpace = ColorSpace.SRgbNonlinear,
                ImageUsage = ImageUsageFlags.ColorAttachment,
                PresentMode = swapChainPresentMode,
                CompositeAlpha = CompositeAlphaFlags.Opaque,
                MinImageCount = desiredImageCount,
                PreTransform = preTransform,
                Clipped = true
                // OldSwapchain =
            };
            swapchain = device.CreateSwapchain(ref swapchainCreateInfo);

            // Initialize swapchain image layout
            backBuffers = device.GetSwapchainImages(swapchain);
            foreach (var image in backBuffers)
            {
                SetImageLayout(image, ImageAspectFlags.Color, ImageLayout.Undefined, ImageLayout.PresentSource);
            }
            Flush();
        }
Пример #5
0
        protected virtual void CreateSwapchain()
        {
            // surface format
            var surfaceFormats = physicalDevice.GetSurfaceFormats(surface);

            if (surfaceFormats.Length == 1 && surfaceFormats[0].Format == Format.Undefined)
            {
                backBufferFormat = Format.B8G8R8A8UNorm;
            }
            else
            {
                backBufferFormat = surfaceFormats[0].Format;
            }

            SurfaceCapabilities surfaceCapabilities;

            physicalDevice.GetSurfaceCapabilities(surface, out surfaceCapabilities);

            // Buffer count
            uint desiredImageCount = surfaceCapabilities.MinImageCount + 1;

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

            // Transform
            SurfaceTransformFlags preTransform;

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

            // Present mode
            var presentModes = physicalDevice.GetSurfacePresentModes(surface);

            var swapChainPresentMode = PresentMode.Fifo;

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

            // Create swapchain
            var swapchainCreateInfo = new SwapchainCreateInfo
            {
                StructureType    = StructureType.SwapchainCreateInfo,
                Surface          = surface,
                ImageSharingMode = SharingMode.Exclusive,
                ImageExtent      = new Extent2D((uint)form.ClientSize.Width, (uint)form.ClientSize.Height),
                ImageArrayLayers = 1,
                ImageFormat      = backBufferFormat,
                ImageColorSpace  = ColorSpace.SRgbNonlinear,
                ImageUsage       = ImageUsageFlags.ColorAttachment,
                PresentMode      = swapChainPresentMode,
                CompositeAlpha   = CompositeAlphaFlags.Opaque,
                MinImageCount    = desiredImageCount,
                PreTransform     = preTransform,
                Clipped          = true
                                   // OldSwapchain =
            };

            swapchain = device.CreateSwapchain(ref swapchainCreateInfo);

            // Initialize swapchain image layout
            backBuffers = device.GetSwapchainImages(swapchain);
            foreach (var image in backBuffers)
            {
                SetImageLayout(image, ImageAspectFlags.Color, ImageLayout.Undefined, ImageLayout.PresentSource);
            }
            Flush();
        }
Пример #6
0
        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);

                FormatProperties formatProperties;
                GraphicsDevice.NativePhysicalDevice.GetFormatProperties(nativeFromat, out formatProperties);

                if ((formatProperties.OptimalTilingFeatures & FormatFeatureFlags.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 = GraphicsDevice.NativePhysicalDevice.QueueFamilyProperties.
                                 Where((properties, index) => (properties.QueueFlags & QueueFlags.Graphics) != 0 && GraphicsDevice.NativePhysicalDevice.GetSurfaceSupport((uint)index, surface)).
                                 Select((properties, index) => index).First();

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

            var surfaceFormats = GraphicsDevice.NativePhysicalDevice.GetSurfaceFormats(surface);

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

            // Create swapchain
            SurfaceCapabilities surfaceCapabilities;

            GraphicsDevice.NativePhysicalDevice.GetSurfaceCapabilities(surface, out surfaceCapabilities);

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

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

            // Transform
            SurfaceTransformFlags preTransform;

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

            // Find present mode
            var presentModes         = GraphicsDevice.NativePhysicalDevice.GetSurfacePresentModes(surface);
            var swapChainPresentMode = PresentMode.Fifo; // Always supported

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

            // Create swapchain
            var swapchainCreateInfo = new SwapchainCreateInfo
            {
                StructureType    = StructureType.SwapchainCreateInfo,
                Surface          = surface,
                ImageArrayLayers = 1,
                ImageSharingMode = SharingMode.Exclusive,
                ImageExtent      = new Extent2D((uint)Description.BackBufferWidth, (uint)Description.BackBufferHeight),
                ImageFormat      = backBufferFormat,
                ImageColorSpace  = Description.ColorSpace == ColorSpace.Gamma ? SharpVulkan.ColorSpace.SRgbNonlinear : 0,
                ImageUsage       = ImageUsageFlags.ColorAttachment | ImageUsageFlags.TransferDestination | (surfaceCapabilities.SupportedUsageFlags & ImageUsageFlags.TransferSource), // TODO VULKAN: Use off-screen buffer to emulate
                PresentMode      = swapChainPresentMode,
                CompositeAlpha   = CompositeAlphaFlags.Opaque,
                MinImageCount    = desiredImageCount,
                PreTransform     = preTransform,
                OldSwapchain     = swapChain,
                Clipped          = true
            };
            var newSwapChain = GraphicsDevice.NativeDevice.CreateSwapchain(ref swapchainCreateInfo);

            DestroySwapchain();

            swapChain = newSwapChain;
            CreateBackBuffers();
        }
Пример #7
0
 public unsafe Swapchain CreateSwapchain(ref SwapchainCreateInfo createInfo, AllocationCallbacks* allocator = null)
 {
     Swapchain swapchain;
     fixed (SwapchainCreateInfo* __createInfo__ = &createInfo)
     {
         vkCreateSwapchainKHR(this, __createInfo__, allocator, &swapchain).CheckError();
     }
     return swapchain;
 }
Пример #8
0
 internal static unsafe extern Result vkCreateSwapchainKHR(Device device, SwapchainCreateInfo* createInfo, AllocationCallbacks* allocator, Swapchain* swapchain);
Пример #9
0
 internal static unsafe extern Result vkCreateSharedSwapchainsKHR(Device device, uint swapchainCount, SwapchainCreateInfo* createInfos, AllocationCallbacks* allocator, Swapchain* swapchains);