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); }
protected override void PlatformSwapBuffers() { // First, ensure all pending draws are submitted to the proper render passes, and are completed. FlushFrameDrawCommands(); // Then, present the swapchain. VkPresentInfoKHR presentInfo = VkPresentInfoKHR.New(); presentInfo.waitSemaphoreCount = 1; // Wait on the last render pass to complete before presenting. VkSemaphore signalSemaphore = _renderPassSemaphores[_renderPassStates.Count - 1]; presentInfo.pWaitSemaphores = &signalSemaphore; VkSwapchainKHR swapchain = _scInfo.Swapchain; presentInfo.swapchainCount = 1; presentInfo.pSwapchains = &swapchain; uint imageIndex = _scInfo.ImageIndex; presentInfo.pImageIndices = &imageIndex; vkQueuePresentKHR(_presentQueue, ref presentInfo); ClearFrameObjects(); _framebufferChanged = true; }
public static VkResult vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapChain, ref int imageCount, VkImage[] swapChainImages) { VkPreconditions.CheckNull(device, nameof(device)); VkPreconditions.CheckNull(swapChain, nameof(swapChain)); return(GetDevice(device).GetSwapchainImages(swapChain, ref imageCount, swapChainImages)); }
internal void SetNewSwapchain( VkSwapchainKHR deviceSwapchain, uint width, uint height, VkSurfaceFormatKHR surfaceFormat, VkExtent2D swapchainExtent) { _desiredWidth = width; _desiredHeight = height; // Get the images uint scImageCount = 0; VkResult result = vkGetSwapchainImagesKHR(_gd.Device, deviceSwapchain, ref scImageCount, null); CheckResult(result); if (_scImages == null) { _scImages = new VkImage[(int)scImageCount]; } result = vkGetSwapchainImagesKHR(_gd.Device, deviceSwapchain, ref scImageCount, out _scImages[0]); CheckResult(result); _scImageFormat = surfaceFormat.format; _scExtent = swapchainExtent; CreateDepthTexture(); CreateFramebuffers(); _outputDescription = OutputDescription.CreateFromFramebuffer(this); }
private unsafe void DestroySwapchain() { if (swapChain == VkSwapchainKHR.Null) { return; } // stop our presenter thread if (presenterThread != null) { runPresenter = false; presentWaiter.Set(); presenterThread.Join(); } vkQueueWaitIdle(GraphicsDevice.NativeCommandQueue); backbuffer.OnDestroyed(); foreach (var swapchainImage in swapchainImages) { vkDestroyImageView(GraphicsDevice.NativeDevice, swapchainImage.NativeColorAttachmentView, null); } swapchainImages = null; vkDestroySwapchainKHR(GraphicsDevice.NativeDevice, swapChain, null); swapChain = VkSwapchainKHR.Null; }
private unsafe void PresenterThread() { VkSwapchainKHR swapChainCopy = swapChain; uint currentBufferIndexCopy = 0; VkPresentInfoKHR presentInfo = new VkPresentInfoKHR { sType = VkStructureType.PresentInfoKHR, swapchainCount = 1, pSwapchains = &swapChainCopy, pImageIndices = ¤tBufferIndexCopy, }; while (runPresenter) { // wait until we have a frame to present presentWaiter.Wait(); // set the frame currentBufferIndexCopy = presentFrame; // prepare for next frame presentWaiter.Reset(); // are we still OK to present? if (runPresenter == false) { return; } using (GraphicsDevice.QueueLock.WriteLock()) { vkQueuePresentKHR(GraphicsDevice.NativeCommandQueue, &presentInfo); } } }
public void Render() { if (!isInitialized) { return; } if (this.submitInfos == null) { InitRenderParams(); } VkDevice device = this.device; VkSwapchainKHR swapchain = this.swapchain; VkSemaphore semaphore = this.vkSemaphore; VkFence fence = this.vkFence; VkQueue queue = this.vkQueue; //uint nextIndex = device.AcquireNextImageKHR(swapchain, ulong.MaxValue, semaphore); UInt32 nextIndex; vkAPI.vkAcquireNextImageKHR(device, swapchain, ulong.MaxValue, semaphore, new VkFence(), &nextIndex).Check(); //device.ResetFence(fence); vkAPI.vkResetFences(device, 1, &fence).Check(); //queue.Submit(ref this.submitInfos[nextIndex], fence); //VkSubmitInfo submitInfo = this.submitInfos[nextIndex]; //vkAPI.vkQueueSubmit(queue, 1, &submitInfo, fence).Check(); vkAPI.vkQueueSubmit(queue, 1, &this.submitInfos[nextIndex], fence).Check(); //device.WaitForFence(fence, true, 100000000); vkAPI.vkWaitForFences(device, 1, &fence, true, 100000000).Check(); //queue.PresentKHR(ref this.presentInfos[nextIndex]); //VkPresentInfoKHR presentInfo = this.presentInfos[nextIndex]; //vkAPI.vkQueuePresentKHR(queue, &presentInfo).Check(); vkAPI.vkQueuePresentKHR(queue, &this.presentInfos[nextIndex]).Check(); }
public static extern VkResult AcquireNextImageKHR( VkDevice device, VkSwapchainKHR swapchain, ulong timeout, VkSemaphore semaphore, VkFence fence, out uint pImageIndex );
public static VkResult vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, long timeout, VkSemaphore semaphore, VkFence fence, out int pImageIndex) { VkPreconditions.CheckNull(device, nameof(device)); VkPreconditions.CheckNull(swapchain, nameof(swapchain)); VkPreconditions.CheckRange(timeout, 1, long.MaxValue, nameof(timeout)); return(GetDevice(device).AcquireNextImage(swapchain, timeout, semaphore, fence, out pImageIndex)); }
public VkResult AcquireNextImage(VkSwapchainKHR swapchain, long timeout, VkSemaphore semaphore, VkFence fence, out int pImageIndex) { pImageIndex = m_NextImageIndex; m_NextImageIndex = (m_NextImageIndex + 1) % m_Images.Count; // semaphore?.Signal(); // fence?.Signal(); return(VkResult.VK_SUCCESS); }
public void Create() { if (state != ActivableState.Activated) { Activate(); } Dev.WaitIdle(); VkSurfaceCapabilitiesKHR capabilities = Dev.phy.GetSurfaceCapabilities(presentQueue.Surface); createInfos.minImageCount = capabilities.minImageCount; createInfos.preTransform = capabilities.currentTransform; createInfos.oldSwapchain = handle; if (capabilities.currentExtent.width == 0xFFFFFFFF) { if (createInfos.imageExtent.width < capabilities.minImageExtent.width) { createInfos.imageExtent.width = capabilities.minImageExtent.width; } else if (createInfos.imageExtent.width > capabilities.maxImageExtent.width) { createInfos.imageExtent.width = capabilities.maxImageExtent.width; } if (createInfos.imageExtent.height < capabilities.minImageExtent.height) { createInfos.imageExtent.height = capabilities.minImageExtent.height; } else if (createInfos.imageExtent.height > capabilities.maxImageExtent.height) { createInfos.imageExtent.height = capabilities.maxImageExtent.height; } } else { createInfos.imageExtent = capabilities.currentExtent; } VkSwapchainKHR newSwapChain = Dev.CreateSwapChain(createInfos); if (handle.Handle != 0) { _destroy(); } handle = newSwapChain; VkImage[] tmp = Dev.GetSwapChainImages(handle); images = new Image[tmp.Length]; for (int i = 0; i < tmp.Length; i++) { images[i] = new Image(Dev, tmp[i], ColorFormat, ImageUsage, Width, Height); images[i].CreateView(); images[i].SetName("SwapChain Img" + i); images[i].Descriptor.imageView.SetDebugMarkerName(Dev, "SwapChain Img" + i + " view"); } }
public static void vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapChain, VkAllocationCallbacks pAllocator) { VkPreconditions.CheckNull(device, nameof(device)); if (swapChain != null) { GetDevice(device).DestroySwapchainKHR(swapChain); } }
protected virtual void Draw(Timer timer) { // Acquire an index of drawing image for this frame. uint nextImageIndex; VkResult result = vkAcquireNextImageKHR(Context.Device, Swapchain, ulong.MaxValue, ImageAvailableSemaphore, VkFence.Null, out nextImageIndex); result.CheckResult(); // Use a fence to wait until the command buffer has finished execution before using it again VkFence fence = SubmitFences[nextImageIndex]; result = vkWaitForFences(Context.Device, 1, &fence, false, ulong.MaxValue); result.CheckResult(); result = vkResetFences(Context.Device, 1, &fence); result.CheckResult(); VkSemaphore signalSemaphore = RenderingFinishedSemaphore; VkSemaphore waitSemaphore = ImageAvailableSemaphore; VkPipelineStageFlags waitStages = VkPipelineStageFlags.ColorAttachmentOutput; VkCommandBuffer commandBuffer = CommandBuffers[nextImageIndex]; VkSubmitInfo submitInfo = new VkSubmitInfo() { sType = VkStructureType.SubmitInfo, waitSemaphoreCount = 1, pWaitSemaphores = &waitSemaphore, pWaitDstStageMask = &waitStages, commandBufferCount = 1, pCommandBuffers = &commandBuffer, signalSemaphoreCount = 1, pSignalSemaphores = &signalSemaphore, }; result = vkQueueSubmit(Context.GraphicsQueue, 1, &submitInfo, SubmitFences[nextImageIndex]); result.CheckResult(); // Present the color output to screen. VkSemaphore waitSemaphoreHandle = RenderingFinishedSemaphore; VkSwapchainKHR swapchainHandle = Swapchain; var nativePresentInfo = new VkPresentInfoKHR { sType = VkStructureType.PresentInfoKHR, pNext = null, waitSemaphoreCount = 1, pWaitSemaphores = &waitSemaphoreHandle, swapchainCount = 1, pSwapchains = &swapchainHandle, pImageIndices = &nextImageIndex }; result = vkQueuePresentKHR(Context.PresentQueue, &nativePresentInfo); result.CheckResult(); }
void drawFrame() { int imageIndex; Vulkan.vkAcquireNextImageKHR(device, swapChain, long.MaxValue, imageAvailableSemaphore, null, out imageIndex); VkSubmitInfo submitInfo = new VkSubmitInfo(); submitInfo.sType = VkStructureType.VK_STRUCTURE_TYPE_SUBMIT_INFO; VkSemaphore[] waitSemaphores = new VkSemaphore[] { imageAvailableSemaphore }; VkPipelineStageFlagBits[] waitStages = new VkPipelineStageFlagBits[] { VkPipelineStageFlagBits.VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; submitInfo.waitSemaphoreCount = 1; submitInfo.pWaitSemaphores = waitSemaphores; submitInfo.pWaitDstStageMask = waitStages; submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = new VkCommandBuffer[] { commandBuffers[imageIndex] }; VkSemaphore[] signalSemaphores = new VkSemaphore[] { renderFinishedSemaphore }; submitInfo.signalSemaphoreCount = 1; submitInfo.pSignalSemaphores = signalSemaphores; fpsSubmitQueue.Begin(); VkResult result = Vulkan.vkQueueSubmit(graphicsQueue, 1, new VkSubmitInfo[] { submitInfo }, null); fpsSubmitQueue.End(); fpsSubmitQueue.DebugPeriodicReport(); if (result != VkResult.VK_SUCCESS) { throw Program.Throw("failed to submit draw command buffer!"); } VkPresentInfoKHR presentInfo = new VkPresentInfoKHR(); presentInfo.sType = VkStructureType.VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; presentInfo.waitSemaphoreCount = 1; presentInfo.pWaitSemaphores = signalSemaphores; VkSwapchainKHR[] swapChains = new VkSwapchainKHR[] { swapChain }; presentInfo.swapchainCount = 1; presentInfo.pSwapchains = swapChains; presentInfo.pImageIndices = new int[] { imageIndex }; fpsPresentQueue.Begin(); Vulkan.vkQueuePresentKHR(presentQueue, presentInfo); fpsPresentQueue.End(); fpsPresentQueue.DebugPeriodicReport(); Vulkan.vkQueueWaitIdle(presentQueue); }
public static ReadOnlySpan <VkImage> vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain) { int swapchainImageCount = 0; vkGetSwapchainImagesKHR(device, swapchain, &swapchainImageCount, null).CheckResult(); ReadOnlySpan <VkImage> swapchainImages = new VkImage[swapchainImageCount]; fixed(VkImage *swapchainImagesPtr = swapchainImages) { vkGetSwapchainImagesKHR(device, swapchain, &swapchainImageCount, swapchainImagesPtr).CheckResult(); } return(swapchainImages); }
public VkImage[] GetSwapchainImagesKHR(VkSwapchainKHR swapchain) { unsafe { VkImage[] props; uint count = 0; do { props = new VkImage[count]; fixed(VkImage *pptr = props) VkException.Check(vkGetSwapchainImagesKHR(this, swapchain, &count, pptr)); } while (props.Length != count); return(props); } }
unsafe public VkImage[] GetSwapChainImages(VkSwapchainKHR swapchain) { uint imageCount = 0; Utils.CheckResult(vkGetSwapchainImagesKHR(dev, swapchain, out imageCount, IntPtr.Zero)); if (imageCount == 0) { throw new Exception("Swapchain image count is 0."); } VkImage[] imgs = new VkImage[imageCount]; Utils.CheckResult(vkGetSwapchainImagesKHR(dev, swapchain, out imageCount, imgs.Pin())); imgs.Unpin(); return(imgs); }
public void Present(SwapChain swapChain, VkSemaphore wait) { VkPresentInfoKHR present = VkPresentInfoKHR.New(); uint idx = swapChain.currentImageIndex; VkSwapchainKHR sc = swapChain.handle; present.swapchainCount = 1; present.pSwapchains = sc.Pin(); present.waitSemaphoreCount = 1; present.pWaitSemaphores = wait.Pin(); present.pImageIndices = idx.Pin(); Utils.CheckResult(vkQueuePresentKHR(handle, ref present)); sc.Unpin(); wait.Unpin(); idx.Unpin(); }
public void Present() { VkSemaphore Semaphore = NativeDevice.RenderFinishedSemaphore; VkSwapchainKHR swapchain = SwapChain; CommandList commandList = NativeDevice.NativeCommandList; VkPresentInfoKHR presentInfo = new VkPresentInfoKHR() { sType = VkStructureType.PresentInfoKHR, waitSemaphoreCount = 1, pWaitSemaphores = &Semaphore, swapchainCount = 1, pSwapchains = &swapchain, pImageIndices = Interop.AllocToPointer(ref commandList.imageIndex), }; vkQueuePresentKHR(NativeDevice.NativeCommandQueue, &presentInfo); }
private unsafe void DestroySwapchain() { if (swapChain == VkSwapchainKHR.Null) { return; } vkDeviceWaitIdle(GraphicsDevice.NativeDevice); backbuffer.OnDestroyed(); foreach (var swapchainImage in swapchainImages) { vkDestroyImageView(GraphicsDevice.NativeDevice, swapchainImage.NativeColorAttachmentView, null); } swapchainImages = null; vkDestroySwapchainKHR(GraphicsDevice.NativeDevice, swapChain, null); swapChain = VkSwapchainKHR.Null; }
private VkImage[] GetSwapchainImages(VkSwapchainKHR swapchain) { uint swapchainImageCount; VkResult result = vkGetSwapchainImagesKHR(Context.Device, swapchain, &swapchainImageCount, null); result.CheckResult(); var swapchainImages = stackalloc VkImage[(int)swapchainImageCount]; result = vkGetSwapchainImagesKHR(Context.Device, swapchain, &swapchainImageCount, swapchainImages); result.CheckResult(); var images = new VkImage[swapchainImageCount]; for (int i = 0; i < swapchainImageCount; i++) { images[i] = swapchainImages[i]; } return(images); }
private void InitRenderParams() { VkSwapchainKHR swapchain = this.swapchain; VkSemaphore semaphore = this.vkSemaphore; VkCommandBuffer[] commandBuffers = this.commandBuffers; submitInfos = VkSubmitInfo.Alloc(2); presentInfos = VkPresentInfoKHR.Alloc(2); for (uint index = 0; index < 2; index++) { //submitInfos[index].waitSemaphoresDstStageMasks.Set(semaphore); submitInfos[index].waitSemaphores = semaphore; submitInfos[index].waitSemaphoresDstStageMasks.Set(VkPipelineStageFlagBits.AllGraphics); submitInfos[index].commandBuffers = commandBuffers[index]; presentInfos[index].swapchains = swapchain; //presentInfo->swapchainsImages.Set(swapchain); presentInfos[index].swapchainsImages.Set(index); } }
public override void SwapBuffers() { vkQueueWaitIdle(_graphicsQueue); // Meh FlushQueuedDisposables(); // Then, present the swapchain. VkPresentInfoKHR presentInfo = VkPresentInfoKHR.New(); VkSwapchainKHR swapchain = _scFB.Swapchain; presentInfo.swapchainCount = 1; presentInfo.pSwapchains = &swapchain; uint imageIndex = _scFB.ImageIndex; presentInfo.pImageIndices = &imageIndex; vkQueuePresentKHR(_presentQueue, ref presentInfo); _scFB.AcquireNextImage(_device, VkSemaphore.Null, _imageAvailableFence); vkWaitForFences(_device, 1, ref _imageAvailableFence, true, ulong.MaxValue); vkResetFences(_device, 1, ref _imageAvailableFence); }
public override unsafe void Present() { // remember which frame we need to present (for presenting thread) VkSwapchainKHR swapChainCopy = swapChain; uint currentBufferIndexCopy = currentBufferIndex; VkPresentInfoKHR presentInfo = new VkPresentInfoKHR { sType = VkStructureType.PresentInfoKHR, swapchainCount = 1, pSwapchains = &swapChainCopy, pImageIndices = ¤tBufferIndexCopy, }; VkResult result = VkResult.Success; try { result = vkAcquireNextImageKHR(GraphicsDevice.NativeDevice, swapChain, (ulong)0, VkSemaphore.Null, VkFence.Null, out currentBufferIndex); vkQueuePresentKHR(GraphicsDevice.NativeCommandQueue, &presentInfo); } catch (AccessViolationException ave) { Xenko.Graphics.SDL.Window.GeneratePresentError(); } if ((int)result < 0) { Xenko.Graphics.SDL.Window.GenerateSwapchainError("vkAcquireNextImageKHR result: " + (int)result); } // did we get another image? while ((int)result > 0) { result = vkAcquireNextImageKHR(GraphicsDevice.NativeDevice, swapChain, (ulong)0, VkSemaphore.Null, VkFence.Null, out currentBufferIndex); Thread.Sleep(1); } // Flip render targets backbuffer.SetNativeHandles(swapchainImages[currentBufferIndex].NativeImage, swapchainImages[currentBufferIndex].NativeColorAttachmentView); }
public void Init(IntPtr hwnd, IntPtr processHandle) { if (this.isInitialized) { return; } this.instance = InitInstance(); InitDebugCallback(this.instance); this.surface = InitSurface(this.instance, hwnd, processHandle); this.vkPhysicalDevice = InitPhysicalDevice(this.instance); VkSurfaceFormatKHR surfaceFormat = SelectFormat(this.vkPhysicalDevice, this.surface); this.device = CreateDevice(this.vkPhysicalDevice, this.surface); this.vkQueue = this.device.GetQueue(0, 0); VkSurfaceCapabilitiesKHR surfaceCapabilities; //this.vkPhysicalDevice.GetSurfaceCapabilitiesKhr(this.vkSurface, out surfaceCapabilities); vkAPI.vkGetPhysicalDeviceSurfaceCapabilitiesKHR(this.vkPhysicalDevice, this.surface, &surfaceCapabilities).Check(); this.swapchain = CreateSwapchain(this.device, this.surface, surfaceFormat, surfaceCapabilities); this.vkImages = this.device.GetSwapchainImages(this.swapchain); this.renderPass = CreateRenderPass(this.device, surfaceFormat); this.framebuffers = CreateFramebuffers(this.device, this.vkImages, surfaceFormat, this.renderPass, surfaceCapabilities); this.vkFence = this.device.CreateFence(); this.vkSemaphore = this.device.CreateSemaphore(); // buffers for vertex data. VkBuffer vertexBuffer = CreateBuffer(this.vkPhysicalDevice, this.device, Vertices, VkBufferUsageFlagBits.VertexBuffer, typeof(float)); VkBuffer indexBuffer = CreateBuffer(this.vkPhysicalDevice, this.device, Indexes, VkBufferUsageFlagBits.IndexBuffer, typeof(short)); var uniformBufferData = new AreaUniformBuffer(1, 1); this.originalWidth = 1; this.width = this.originalWidth; this.originalHeight = 1; this.height = this.originalHeight; this.uniformBuffer = CreateBuffer(this.vkPhysicalDevice, this.device, uniformBufferData, VkBufferUsageFlagBits.UniformBuffer, typeof(AreaUniformBuffer)); this.descriptorSetLayout = CreateDescriptorSetLayout(this.device); this.vkPipelineLayout = CreatePipelineLayout(this.device, this.descriptorSetLayout); VkPipeline pipeline = CreatePipeline(this.device, surfaceCapabilities, this.renderPass, this.vkPipelineLayout); this.descriptorSet = CreateDescriptorSet(this.device, this.descriptorSetLayout); UpdateDescriptorSets(this.device, this.uniformBuffer, this.descriptorSet); this.commandBuffers = CreateCommandBuffers( this.device, this.renderPass, surfaceCapabilities, this.vkImages, this.framebuffers, pipeline, vertexBuffer, indexBuffer, (uint)Indexes.Length, this.vkPipelineLayout, this.descriptorSet); this.isInitialized = true; }
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; }
public static extern VkResult GetSwapchainImagesKHR( VkDevice device, VkSwapchainKHR swapchain, ref uint pSwapchainImageCount, IntPtr pSwapchainImages );
public static VkResult vkCreateSwapchainKHR(VkDevice device, VkSwapchainCreateInfoKHR pCreateInfo, VkAllocationCallbacks pAllocator, out VkSwapchainKHR pSwapchain) { VkPreconditions.CheckNull(device, nameof(device)); return(GetDevice(device).CreateSwapchain(pCreateInfo, out pSwapchain)); }
/// <summary> /// Create/recreate swapchain and populate images array /// </summary> public void Create() { Dev.WaitIdle(); VkSurfaceCapabilitiesKHR capabilities = Dev.phy.GetSurfaceCapabilities(presentQueue.Surface); createInfos.minImageCount = capabilities.minImageCount; createInfos.preTransform = capabilities.currentTransform; createInfos.oldSwapchain = Handle; if (capabilities.currentExtent.width == 0xFFFFFFFF) { if (createInfos.imageExtent.width < capabilities.minImageExtent.width) { createInfos.imageExtent.width = capabilities.minImageExtent.width; } else if (createInfos.imageExtent.width > capabilities.maxImageExtent.width) { createInfos.imageExtent.width = capabilities.maxImageExtent.width; } if (createInfos.imageExtent.height < capabilities.minImageExtent.height) { createInfos.imageExtent.height = capabilities.minImageExtent.height; } else if (createInfos.imageExtent.height > capabilities.maxImageExtent.height) { createInfos.imageExtent.height = capabilities.maxImageExtent.height; } } else { createInfos.imageExtent = capabilities.currentExtent; } Utils.CheckResult(vkCreateSwapchainKHR(Dev.VkDev, ref createInfos, IntPtr.Zero, out VkSwapchainKHR newSwapChain)); if (Handle.Handle != 0) { _destroy(); } presentComplete = Dev.CreateSemaphore(); presentComplete.SetDebugMarkerName(Dev, "Semaphore PresentComplete"); Handle = newSwapChain; Utils.CheckResult(vkGetSwapchainImagesKHR(Dev.VkDev, Handle, out uint imageCount, IntPtr.Zero)); if (imageCount == 0) { throw new Exception("Swapchain image count is 0."); } VkImage[] imgs = new VkImage[imageCount]; Utils.CheckResult(vkGetSwapchainImagesKHR(Dev.VkDev, Handle, out imageCount, imgs.Pin())); imgs.Unpin(); images = new Image[imgs.Length]; for (int i = 0; i < imgs.Length; i++) { images[i] = new Image(Dev, imgs[i], ColorFormat, ImageUsage, Width, Height); images[i].CreateView(); images[i].SetName("SwapChain Img" + i); images[i].Descriptor.imageView.SetDebugMarkerName(Dev, "SwapChain Img" + i + " view"); } }
/** * 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); } } }