protected SwapchainData CreateSwapchain(PhysicalDevice physicalDevice, SurfaceKHR surface, uint windowWidth, uint windowHeight) { var data = new SwapchainData(); var surfaceFormats = physicalDevice.GetSurfaceFormatsKHR(surface); var surfaceFormat = surfaceFormats[0].Format; var surfaceCapabilities = physicalDevice.GetSurfaceCapabilitiesKHR(surface); var desiredImageCount = Math.Min(surfaceCapabilities.MinImageCount + 1, surfaceCapabilities.MaxImageCount); SurfaceTransformFlagsKHR preTransform; if ((surfaceCapabilities.SupportedTransforms & SurfaceTransformFlagsKHR.Identity) != 0) { preTransform = SurfaceTransformFlagsKHR.Identity; } else { preTransform = surfaceCapabilities.CurrentTransform; } var presentModes = physicalDevice.GetSurfacePresentModesKHR(surface); var swapChainPresentMode = PresentModeKHR.Fifo; if (presentModes.Contains(PresentModeKHR.Mailbox)) { swapChainPresentMode = PresentModeKHR.Mailbox; } else if (presentModes.Contains(PresentModeKHR.Immediate)) { swapChainPresentMode = PresentModeKHR.Immediate; } var imageExtent = new Extent2D(windowWidth, windowHeight); var swapchainCreateInfo = new SwapchainCreateInfoKHR { Surface = surface, MinImageCount = desiredImageCount, ImageFormat = surfaceFormat, ImageExtent = imageExtent, ImageArrayLayers = 1, ImageUsage = ImageUsageFlags.ColorAttachment, ImageSharingMode = SharingMode.Exclusive, //ImageColorSpace = ColorSpaceKHR.SrgbNonlinear, QueueFamilyIndices = null, PreTransform = preTransform, CompositeAlpha = CompositeAlphaFlagsKHR.Opaque, PresentMode = swapChainPresentMode, Clipped = true, }; data.Swapchain = device.CreateSwapchainKHR(swapchainCreateInfo); data.ImageFormat = surfaceFormat; return(data); }
public static Result CreateSwapchainKHR(Device device, ref SwapchainCreateInfoKHR pCreateInfo, ref SwapchainKHR pSwapchain, AllocationCallbacks pAllocator = null) { _SwapchainCreateInfoKHR info = new _SwapchainCreateInfoKHR(pCreateInfo); Result res = _CreateSwapchainKHR(device, ref info, pAllocator, out pSwapchain); info.destroy(); return(res); }
public SwapchainManager(Device LogicalDevice, SurfaceFormatKHR SelectedSurfaceFormat) { var compositeAlpha = VulkanRenderer.Surface.SurfaceCapabilities.SupportedCompositeAlpha.HasFlag(CompositeAlphaFlagsKHR.Inherit) ? CompositeAlphaFlagsKHR.Inherit : CompositeAlphaFlagsKHR.Opaque; SemaphoreCreateInfo semaphoreInfo = new SemaphoreCreateInfo(); SwapchainDrawCompleteSemaphore = LogicalDevice.CreateSemaphore(semaphoreInfo); CreateDefaultSwapchainRenderPass(LogicalDevice); renderPassBeginInfo = new RenderPassBeginInfo { ClearValueCount = 1, ClearValues = new ClearValue[] { new ClearValue { Color = new ClearColorValue(Color.AliceBlue) } }, RenderPass = myBaseRenderPass }; renderPassBeginInfo.RenderArea = new Rect2D { Extent = new Extent2D { Width = VulkanRenderer.Surface.SurfaceCapabilities.CurrentExtent.Width, Height = VulkanRenderer.Surface.SurfaceCapabilities.CurrentExtent.Height }, Offset = new Offset2D { X = 0, Y = 0 } }; var swapchainInfo = new SwapchainCreateInfoKHR { Surface = VulkanRenderer.Surface, MinImageCount = VulkanRenderer.Surface.SurfaceCapabilities.MinImageCount + 1, ImageFormat = VulkanRenderer.Surface.SelectedSurfaceFormat.Format, ImageColorSpace = VulkanRenderer.Surface.SelectedSurfaceFormat.ColorSpace, ImageExtent = VulkanRenderer.Surface.SurfaceCapabilities.CurrentExtent, ImageUsage = ImageUsageFlags.ColorAttachment, PreTransform = SurfaceTransformFlagsKHR.Identity, ImageArrayLayers = 1, ImageSharingMode = SharingMode.Exclusive, QueueFamilyIndices = new uint[] { VulkanRenderer.ActiveGraphicsFamilyQueueIndex }, PresentMode = PresentModeKHR.Fifo, CompositeAlpha = compositeAlpha }; Swapchain = VulkanRenderer.SelectedLogicalDevice.CreateSwapchainKHR(swapchainInfo); Images = VulkanRenderer.SelectedLogicalDevice.GetSwapchainImagesKHR(Swapchain); SwapChainPresentInfo = new PresentInfoKHR { Swapchains = new SwapchainKHR[] { Swapchain }, ImageIndices = new uint[] { VulkanRenderer.SelectedLogicalDevice.AcquireNextImageKHR(Swapchain, ulong.MaxValue, SwapchainDrawCompleteSemaphore) } }; Framebuffers = new SwapChainFrameBuffer[Images.Length]; //Move this to swap chains for (int i = 0; i < Images.Length; i++) { Framebuffers[i] = new SwapChainFrameBuffer(myBaseRenderPass, Images[i], i, VulkanRenderer.Surface.SurfaceCapabilities.CurrentExtent.Width, VulkanRenderer.Surface.SurfaceCapabilities.CurrentExtent.Height, 1); Framebuffers[i].Initialize(); } }
public unsafe SwapChain(Api api, Window window, Surface surface, PresentModeKHR presentMode) { _api = api; QuerySwapChainSupport(_api.Device.PhysicalDevice, surface.VkServiceKHR, out var details); if (details.Formats.Count == 0 || details.PresentModes.Count == 0) { throw new Exception($"{nameof(SwapChain)}: Empty swap chain support"); } ChooseSwapSurfaceFormat(details.Formats, out var surfaceFormat); var actualPresentMode = ChooseSwapPresentMode(details.PresentModes, presentMode); ChooseSwapExtent(window, details.Capabilities, out var extent); var imageCount = ChooseImageCount(details.Capabilities); var createInfo = new SwapchainCreateInfoKHR(); createInfo.SType = StructureType.SwapchainCreateInfoKhr; createInfo.Surface = surface.VkServiceKHR; createInfo.MinImageCount = imageCount; createInfo.ImageFormat = surfaceFormat.Format; createInfo.ImageColorSpace = surfaceFormat.ColorSpace; createInfo.ImageExtent = extent; createInfo.ImageArrayLayers = 1; createInfo.ImageUsage = ImageUsageFlags.ImageUsageColorAttachmentBit | ImageUsageFlags.ImageUsageTransferDstBit; createInfo.PreTransform = details.Capabilities.CurrentTransform; createInfo.CompositeAlpha = CompositeAlphaFlagsKHR.CompositeAlphaOpaqueBitKhr; createInfo.PresentMode = actualPresentMode; createInfo.Clipped = true; createInfo.OldSwapchain = default; Span <uint> queueFamilyIndices = stackalloc uint[] { api.Device.GraphicsFamilyIndex, api.Device.PresentationFamilyIndex, }; if (api.Device.GraphicsFamilyIndex != api.Device.PresentationFamilyIndex) { createInfo.ImageSharingMode = SharingMode.Concurrent; createInfo.QueueFamilyIndexCount = 2; createInfo.PQueueFamilyIndices = (uint *)Unsafe.AsPointer(ref queueFamilyIndices[0]); } else { createInfo.ImageSharingMode = SharingMode.Exclusive; createInfo.QueueFamilyIndexCount = 0; // Optional createInfo.PQueueFamilyIndices = null; // Optional } Util.Verify(_api.KhrSwapchain.CreateSwapchain(_api.Device.VkDevice, createInfo, default, out _swapChainKhr), $"{nameof(SwapChain)}: Could not create a swap chain");
public _SwapchainCreateInfoKHR(SwapchainCreateInfoKHR info) { SType = info.type; Next = info.next; Flags = info.flags; Surface = info.surface; MinImageCount = info.minImageCount; ImageFormat = info.imageFormat; ImageColorSpace = info.imageColorSpace; ImageExtent = info.imageExtent; ImageArrayLayers = info.imageArrayLayers; ImageUsage = info.imageUsage; ImageSharingMode = info.imageSharingMode; QueueFamilyIndexCount = (UInt32)(info.queueFamilyIndices?.Count ?? 0); QueueFamilyIndices = info.queueFamilyIndices != null?Alloc.alloc(info.queueFamilyIndices) : IntPtr.Zero; PreTransform = info.preTransform; CompositeAlpha = info.compositeAlpha; PresentMode = info.presentMode; Clipped = info.clipped; OldSwapchain = info.oldSwapchain; }
public abstract Result CreateSwapchain([Count(Count = 0)] Device device, [Count(Count = 0), Flow(FlowDirection.In)] ref SwapchainCreateInfoKHR pCreateInfo, [Count(Count = 0), Flow(FlowDirection.In)] ref AllocationCallbacks pAllocator, [Count(Count = 0), Flow(FlowDirection.Out)] out SwapchainKHR pSwapchain);
private SwapchainKHR CreateSwapchain(out Extent2D extent, out Format swapImageFormat, out SwapchainImage[] swapImages) { QuerySwapchainSupport(this.PhysicalDevice, out var details); var surfaceFormat = ChooseSwapSurfaceFormat(details.Formats); var presentMode = ChooseSwapPresentMode(details.PresentModes); extent = ChooseSwapExtent(details.Capabilities); var imageCount = details.Capabilities.MinImageCount + 1; if (details.Capabilities.MaxImageCount > 0 && imageCount > details.Capabilities.MaxImageCount) { imageCount = details.Capabilities.MaxImageCount; } var createInfo = new SwapchainCreateInfoKHR { SType = StructureType.SwapchainCreateInfoKhr, Surface = this.WindowSurface, MinImageCount = imageCount, ImageFormat = surfaceFormat.Format, ImageColorSpace = surfaceFormat.ColorSpace, ImageExtent = extent, ImageArrayLayers = 1, ImageUsage = ImageUsageFlags.ImageUsageColorAttachmentBit }; if (this.QueueIndices.GraphicsFamily != this.QueueIndices.PresentFamily) { createInfo.ImageSharingMode = SharingMode.Concurrent; createInfo.QueueFamilyIndexCount = 2; var indices = stackalloc uint[2] { this.QueueIndices.GraphicsFamily.Value, this.QueueIndices.PresentFamily.Value }; createInfo.PQueueFamilyIndices = indices; } else { createInfo.ImageSharingMode = SharingMode.Exclusive; } createInfo.PreTransform = details.Capabilities.CurrentTransform; createInfo.CompositeAlpha = CompositeAlphaFlagsKHR.CompositeAlphaOpaqueBitKhr; createInfo.PresentMode = presentMode; createInfo.Clipped = true; createInfo.OldSwapchain = default; SwapchainKHR swapchain; var res = this.VkSwapchain.CreateSwapchain(Device, &createInfo, null, &swapchain); if (res != Result.Success) { throw new VMASharp.VulkanResultException("Failed to create swapchain!", res); } uint count = 0; res = VkSwapchain.GetSwapchainImages(this.Device, swapchain, &count, null); if (res != Result.Success) { throw new VMASharp.VulkanResultException("Failed to retrieve swapchain images!", res); } var images = stackalloc Image[(int)count]; res = VkSwapchain.GetSwapchainImages(this.Device, swapchain, &count, images); if (res != Result.Success) { throw new VMASharp.VulkanResultException("Failed to retrieve swapchain images!", res); } var viewCreateInfo = new ImageViewCreateInfo { SType = StructureType.ImageViewCreateInfo, ViewType = ImageViewType.ImageViewType2D, Format = surfaceFormat.Format, Components = { R = ComponentSwizzle.Identity, G = ComponentSwizzle.Identity, B = ComponentSwizzle.Identity, A = ComponentSwizzle.Identity }, SubresourceRange = { AspectMask = ImageAspectFlags.ImageAspectColorBit, BaseMipLevel = 0, LevelCount = 1, BaseArrayLayer = 0, LayerCount = 1 } }; var arr = new SwapchainImage[count]; for (int i = 0; i < arr.Length; ++i) { viewCreateInfo.Image = images[i]; ImageView view = default; res = VkApi.CreateImageView(this.Device, &viewCreateInfo, null, &view); if (res != Result.Success) { throw new VMASharp.VulkanResultException("Swapchain image view creation failed!", res); } arr[i] = new SwapchainImage { Image = images[i], View = view }; } swapImageFormat = surfaceFormat.Format; swapImages = arr; return(swapchain); }
void CreateSwapChain() { CanRender = false; if (!vulkan.Device.IsZero) { vk.DeviceWaitIdle(vulkan.Device); } if (vulkan.SwapChain.Images != null) { for (int i = 0; i < vulkan.SwapChain.Images.Length; ++i) { if (vulkan.SwapChain.Images[i].View != ImageView.Zero) { vk.DestroyImageView(vulkan.Device, vulkan.SwapChain.Images[i].View); } } } SurfaceCapabilitiesKHR surface_capabilities; khrSurface.GetPhysicalDeviceSurfaceCapabilitiesKHR(vulkan.PhysicalDevice, vulkan.PresentationSurface, out surface_capabilities).CheckError(); var surface_formats = DelegateUtility.EnumerateToArray <SurfaceFormatKHR> (khrSurface.GetPhysicalDeviceSurfaceFormatsKHR, (IntPtr)vulkan.PhysicalDevice, (ulong)vulkan.PresentationSurface); var present_modes = DelegateUtility.EnumerateToArray <int> (khrSurface.GetPhysicalDeviceSurfacePresentModesKHR, (IntPtr)vulkan.PhysicalDevice, (ulong)vulkan.PresentationSurface); uint desired_number_of_images = GetSwapChainNumImages(ref surface_capabilities); SurfaceFormatKHR desired_format = GetSwapChainFormat(surface_formats); Extent2D desired_extent = GetSwapChainExtent(ref surface_capabilities); ImageUsageFlagBits desired_usage = GetSwapChainUsageFlagBits(ref surface_capabilities); SurfaceTransformFlagBitsKHR desired_transform = GetSwapChainTransform(ref surface_capabilities); PresentModeKHR desired_present_mode = GetSwapChainPresentMode(present_modes); SwapchainKHR old_swap_chain = vulkan.SwapChain.Handle; if (desired_usage == (ImageUsageFlagBits)(-1)) { return; } if (desired_present_mode == (PresentModeKHR)(-1)) { return; } if ((desired_extent.width == 0) || (desired_extent.height == 0)) { // Current surface size is (0, 0) so we can't create a swap chain and render anything (CanRender == false) // But we don't wont to kill the application as this situation may occur i.e. when window gets minimized return; } SwapchainCreateInfoKHR swap_chain_create_info = new SwapchainCreateInfoKHR { sType = StructureType.SwapchainCreateInfoKhr, // VkStructureType sType pNext = IntPtr.Zero, // const void *pNext flags = 0, // VkSwapchainCreateFlagBitsKHR flags surface = vulkan.PresentationSurface, // VkSurfaceKHR surface minImageCount = desired_number_of_images, // uint32_t minImageCount imageFormat = desired_format.format, // VkFormat imageFormat imageColorSpace = desired_format.colorSpace, // VkColorSpaceKHR imageColorSpace imageExtent = desired_extent, // VkExtent2D imageExtent imageArrayLayers = 1, // uint32_t imageArrayLayers imageUsage = desired_usage, // VkImageUsageFlagBits imageUsage imageSharingMode = SharingMode.Exclusive, // VkSharingMode imageSharingMode queueFamilyIndexCount = 0, // uint32_t queueFamilyIndexCount pQueueFamilyIndices = (uint *)0, // const uint32_t *pQueueFamilyIndices preTransform = desired_transform, // VkSurfaceTransformFlagBitsKHR preTransform compositeAlpha = CompositeAlphaFlagBitsKHR.OpaqueBitKhr, // VkCompositeAlphaFlagBitsKHR compositeAlpha presentMode = desired_present_mode, // VkPresentModeKHR presentMode clipped = Boolean32.True, // VkBool32 clipped oldSwapchain = old_swap_chain // VkSwapchainKHR oldSwapchain }; khrSwapChain.CreateSwapchainKHR(vulkan.Device, ref swap_chain_create_info, (AllocationCallbacks *)0, out vulkan.SwapChain.Handle).CheckError(); if (!old_swap_chain.IsZero) { khrSwapChain.DestroySwapchainKHR(vulkan.Device, old_swap_chain); } vulkan.SwapChain.Format = desired_format.format; var images = DelegateUtility.EnumerateToArray <Image> (khrSwapChain.GetSwapchainImagesKHR, (IntPtr)vulkan.Device, (ulong)vulkan.SwapChain.Handle); if (vulkan.SwapChain.Images == null || vulkan.SwapChain.Images.Length != images.Length) { vulkan.SwapChain.Images = new ImageParameters[images.Length]; } for (int i = 0; i < images.Length; ++i) { vulkan.SwapChain.Images[i].Handle = images[i]; } vulkan.SwapChain.Extent = desired_extent; CreateSwapChainImageViews(); }
private static unsafe SwapchainKHR CreateSwapchain(VulkanInstance instance, VulkanDevice device, VulkanPhysicalDevice physicalDevice, VulkanSurface surface, out Extent2D swapchainExtent, SwapchainKHR?oldswapchain = null, bool vsyncEnabled = true) { if (_swapchainExtension == null) { instance.Api.TryGetDeviceExtension(instance.InternalHandle, device.InternalHandle, out _swapchainExtension); } while (!surface.CanSurfacePresent(physicalDevice)) { Thread.Sleep(16); } VulkanSurface.SurfaceExtension.GetPhysicalDeviceSurfaceCapabilities(physicalDevice.InternalHandle, surface.ApiHandle, out var capabilities); var imageCount = capabilities.MinImageCount + 1; if (capabilities.MaxImageCount > 0 && imageCount > capabilities.MaxImageCount) { imageCount = capabilities.MaxImageCount; } var surfaceFormat = surface.GetSurfaceFormat(physicalDevice); bool supportsIdentityTransform = capabilities.SupportedTransforms.HasFlag(SurfaceTransformFlagsKHR.SurfaceTransformIdentityBitKhr); bool isRotated = capabilities.CurrentTransform.HasFlag(SurfaceTransformFlagsKHR.SurfaceTransformRotate90BitKhr) || capabilities.CurrentTransform.HasFlag(SurfaceTransformFlagsKHR.SurfaceTransformRotate270BitKhr); swapchainExtent = GetSwapchainExtent(surface, capabilities); CompositeAlphaFlagsKHR compositeAlphaFlags = GetSuitableCompositeAlphaFlags(capabilities); PresentModeKHR presentMode = GetSuitablePresentMode(physicalDevice, surface, vsyncEnabled); var swapchainCreateInfo = new SwapchainCreateInfoKHR { SType = StructureType.SwapchainCreateInfoKhr, Surface = surface.ApiHandle, MinImageCount = imageCount, ImageFormat = surfaceFormat.Format, ImageColorSpace = surfaceFormat.ColorSpace, ImageExtent = swapchainExtent, ImageUsage = ImageUsageFlags.ImageUsageColorAttachmentBit | ImageUsageFlags.ImageUsageTransferDstBit, ImageSharingMode = SharingMode.Exclusive, ImageArrayLayers = 1, PreTransform = supportsIdentityTransform && isRotated ? SurfaceTransformFlagsKHR.SurfaceTransformIdentityBitKhr : capabilities.CurrentTransform, CompositeAlpha = compositeAlphaFlags, PresentMode = presentMode, Clipped = true, OldSwapchain = oldswapchain ?? new SwapchainKHR() }; _swapchainExtension.CreateSwapchain(device.InternalHandle, swapchainCreateInfo, null, out var swapchain) .ThrowOnError(); if (oldswapchain != null) { _swapchainExtension.DestroySwapchain(device.InternalHandle, oldswapchain.Value, null); } return(swapchain); }
private unsafe void CreateSwapchain() { _gd.SurfaceApi.GetPhysicalDeviceSurfaceCapabilities(_physicalDevice, _surface, out var capabilities); uint surfaceFormatsCount; _gd.SurfaceApi.GetPhysicalDeviceSurfaceFormats(_physicalDevice, _surface, &surfaceFormatsCount, null); var surfaceFormats = new SurfaceFormatKHR[surfaceFormatsCount]; fixed(SurfaceFormatKHR *pSurfaceFormats = surfaceFormats) { _gd.SurfaceApi.GetPhysicalDeviceSurfaceFormats(_physicalDevice, _surface, &surfaceFormatsCount, pSurfaceFormats); } uint presentModesCount; _gd.SurfaceApi.GetPhysicalDeviceSurfacePresentModes(_physicalDevice, _surface, &presentModesCount, null); var presentModes = new PresentModeKHR[presentModesCount]; fixed(PresentModeKHR *pPresentModes = presentModes) { _gd.SurfaceApi.GetPhysicalDeviceSurfacePresentModes(_physicalDevice, _surface, &presentModesCount, pPresentModes); } uint imageCount = capabilities.MinImageCount + 1; if (capabilities.MaxImageCount > 0 && imageCount > capabilities.MaxImageCount) { imageCount = capabilities.MaxImageCount; } var surfaceFormat = ChooseSwapSurfaceFormat(surfaceFormats); var extent = ChooseSwapExtent(capabilities); _width = (int)extent.Width; _height = (int)extent.Height; _format = surfaceFormat.Format; var oldSwapchain = _swapchain; var swapchainCreateInfo = new SwapchainCreateInfoKHR() { SType = StructureType.SwapchainCreateInfoKhr, Surface = _surface, MinImageCount = imageCount, ImageFormat = surfaceFormat.Format, ImageColorSpace = surfaceFormat.ColorSpace, ImageExtent = extent, ImageUsage = ImageUsageFlags.ImageUsageColorAttachmentBit | ImageUsageFlags.ImageUsageTransferDstBit, ImageSharingMode = SharingMode.Exclusive, ImageArrayLayers = 1, PreTransform = capabilities.CurrentTransform, CompositeAlpha = CompositeAlphaFlagsKHR.CompositeAlphaOpaqueBitKhr, PresentMode = ChooseSwapPresentMode(presentModes), Clipped = true, OldSwapchain = oldSwapchain }; _gd.SwapchainApi.CreateSwapchain(_device, swapchainCreateInfo, null, out _swapchain).ThrowOnError(); _gd.SwapchainApi.GetSwapchainImages(_device, _swapchain, &imageCount, null); _swapchainImages = new Image[imageCount]; fixed(Image *pSwapchainImages = _swapchainImages) { _gd.SwapchainApi.GetSwapchainImages(_device, _swapchain, &imageCount, pSwapchainImages); } _swapchainImageViews = new Auto <DisposableImageView> [imageCount]; for (int i = 0; i < imageCount; i++) { _swapchainImageViews[i] = CreateSwapchainImageView(_swapchainImages[i], surfaceFormat.Format); } }
public abstract Result CreateSharedSwapchain([Count(Count = 0)] Device device, [Count(Count = 0)] uint swapchainCount, [Count(Computed = "swapchainCount"), Flow(FlowDirection.In)] ref SwapchainCreateInfoKHR pCreateInfos, [Count(Count = 0), Flow(FlowDirection.In)] ref AllocationCallbacks pAllocator, [Count(Computed = "swapchainCount"), Flow(FlowDirection.Out)] out SwapchainKHR pSwapchains);