private unsafe void CreateBackBuffers() { // Create the texture object var backBufferDescription = new TextureDescription { ArraySize = 1, Dimension = TextureDimension.Texture2D, Height = Description.BackBufferHeight, Width = Description.BackBufferWidth, Depth = 1, Flags = TextureFlags.RenderTarget, Format = Description.BackBufferFormat, MipLevels = 1, MultisampleCount = MultisampleCount.None, Usage = GraphicsResourceUsage.Default }; backbuffer.InitializeWithoutResources(backBufferDescription); var createInfo = new VkImageViewCreateInfo { sType = VkStructureType.ImageViewCreateInfo, subresourceRange = new VkImageSubresourceRange(VkImageAspectFlags.Color, 0, 1, 0, 1), format = backbuffer.NativeFormat, viewType = VkImageViewType.Image2D, }; // We initialize swapchain images to PresentSource, since we swap them out while in this layout. backbuffer.NativeAccessMask = VkAccessFlags.MemoryRead; backbuffer.NativeLayout = VkImageLayout.PresentSrcKHR; var imageMemoryBarrier = new VkImageMemoryBarrier { sType = VkStructureType.ImageMemoryBarrier, subresourceRange = new VkImageSubresourceRange(VkImageAspectFlags.Color, 0, 1, 0, 1), oldLayout = VkImageLayout.Undefined, newLayout = VkImageLayout.PresentSrcKHR, srcAccessMask = VkAccessFlags.None, dstAccessMask = VkAccessFlags.MemoryRead }; var commandBufferAllocationInfo = new VkCommandBufferAllocateInfo { sType = VkStructureType.CommandBufferAllocateInfo, level = VkCommandBufferLevel.Primary, commandPool = GraphicsDevice.NativeCopyCommandPools.Value, commandBufferCount = 1 }; VkCommandBuffer commandBuffer; vkAllocateCommandBuffers(GraphicsDevice.NativeDevice, &commandBufferAllocationInfo, &commandBuffer); var beginInfo = new VkCommandBufferBeginInfo { sType = VkStructureType.CommandBufferBeginInfo }; vkBeginCommandBuffer(commandBuffer, &beginInfo); var buffers = vkGetSwapchainImagesKHR(GraphicsDevice.NativeDevice, swapChain); swapchainImages = new SwapChainImageInfo[buffers.Length]; for (int i = 0; i < buffers.Length; i++) { // Create image views swapchainImages[i].NativeImage = createInfo.image = buffers[i]; vkCreateImageView(GraphicsDevice.NativeDevice, &createInfo, null, out swapchainImages[i].NativeColorAttachmentView); // Transition to default layout imageMemoryBarrier.image = buffers[i]; vkCmdPipelineBarrier(commandBuffer, VkPipelineStageFlags.AllCommands, VkPipelineStageFlags.AllCommands, VkDependencyFlags.None, 0, null, 0, null, 1, &imageMemoryBarrier); } // Close and submit vkEndCommandBuffer(commandBuffer); var submitInfo = new VkSubmitInfo { sType = VkStructureType.SubmitInfo, commandBufferCount = 1, pCommandBuffers = &commandBuffer, }; lock (GraphicsDevice.QueueLock) { vkQueueSubmit(GraphicsDevice.NativeCommandQueue, 1, &submitInfo, VkFence.Null); vkQueueWaitIdle(GraphicsDevice.NativeCommandQueue); } vkFreeCommandBuffers(GraphicsDevice.NativeDevice, GraphicsDevice.NativeCopyCommandPools.Value, 1, &commandBuffer); // Get next image vkAcquireNextImageKHR(GraphicsDevice.NativeDevice, swapChain, ulong.MaxValue, GraphicsDevice.GetNextPresentSemaphore(), VkFence.Null, out currentBufferIndex); // Apply the first swap chain image to the texture backbuffer.SetNativeHandles(swapchainImages[currentBufferIndex].NativeImage, swapchainImages[currentBufferIndex].NativeColorAttachmentView); }
private unsafe void CreateBackBuffers() { // Create the texture object var backBufferDescription = new TextureDescription { ArraySize = 1, Dimension = TextureDimension.Texture2D, Height = Description.BackBufferHeight, Width = Description.BackBufferWidth, Depth = 1, Flags = TextureFlags.RenderTarget, Format = Description.BackBufferFormat, MipLevels = 1, MultisampleCount = MultisampleCount.None, Usage = GraphicsResourceUsage.Default }; backbuffer.InitializeWithoutResources(backBufferDescription); var createInfo = new ImageViewCreateInfo { StructureType = StructureType.ImageViewCreateInfo, SubresourceRange = new ImageSubresourceRange(ImageAspectFlags.Color, 0, 1, 0, 1), Format = backbuffer.NativeFormat, ViewType = ImageViewType.Image2D, }; // We initialize swapchain images to PresentSource, since we swap them out while in this layout. backbuffer.NativeAccessMask = AccessFlags.MemoryRead; backbuffer.NativeLayout = ImageLayout.PresentSource; var imageMemoryBarrier = new ImageMemoryBarrier { StructureType = StructureType.ImageMemoryBarrier, SubresourceRange = new ImageSubresourceRange(ImageAspectFlags.Color, 0, 1, 0, 1), OldLayout = ImageLayout.Undefined, NewLayout = ImageLayout.PresentSource, SourceAccessMask = AccessFlags.None, DestinationAccessMask = AccessFlags.MemoryRead }; var commandBuffer = GraphicsDevice.NativeCopyCommandBuffer; var beginInfo = new CommandBufferBeginInfo { StructureType = StructureType.CommandBufferBeginInfo }; commandBuffer.Begin(ref beginInfo); var buffers = GraphicsDevice.NativeDevice.GetSwapchainImages(swapChain); swapchainImages = new SwapChainImageInfo[buffers.Length]; for (int i = 0; i < buffers.Length; i++) { // Create image views swapchainImages[i].NativeImage = createInfo.Image = buffers[i]; swapchainImages[i].NativeColorAttachmentView = GraphicsDevice.NativeDevice.CreateImageView(ref createInfo); // Transition to default layout imageMemoryBarrier.Image = buffers[i]; commandBuffer.PipelineBarrier(PipelineStageFlags.AllCommands, PipelineStageFlags.AllCommands, DependencyFlags.None, 0, null, 0, null, 1, &imageMemoryBarrier); } // Close and submit commandBuffer.End(); var submitInfo = new SubmitInfo { StructureType = StructureType.SubmitInfo, CommandBufferCount = 1, CommandBuffers = new IntPtr(&commandBuffer), }; GraphicsDevice.NativeCommandQueue.Submit(1, &submitInfo, Fence.Null); GraphicsDevice.NativeCommandQueue.WaitIdle(); commandBuffer.Reset(CommandBufferResetFlags.None); // Get next image currentBufferIndex = GraphicsDevice.NativeDevice.AcquireNextImage(swapChain, ulong.MaxValue, GraphicsDevice.GetNextPresentSemaphore(), Fence.Null); // Apply the first swap chain image to the texture backbuffer.SetNativeHandles(swapchainImages[currentBufferIndex].NativeImage, swapchainImages[currentBufferIndex].NativeColorAttachmentView); }