private unsafe void Transition( CommandBuffer commandBuffer, Image image, AccessFlags srcAccess, AccessFlags dstAccess, ImageLayout srcLayout, ImageLayout dstLayout) { var subresourceRange = new ImageSubresourceRange(ImageAspectFlags.ImageAspectColorBit, 0, 1, 0, 1); var barrier = new ImageMemoryBarrier() { SType = StructureType.ImageMemoryBarrier, SrcAccessMask = srcAccess, DstAccessMask = dstAccess, OldLayout = srcLayout, NewLayout = dstLayout, SrcQueueFamilyIndex = Vk.QueueFamilyIgnored, DstQueueFamilyIndex = Vk.QueueFamilyIgnored, Image = image, SubresourceRange = subresourceRange }; _gd.Api.CmdPipelineBarrier( commandBuffer, PipelineStageFlags.PipelineStageTopOfPipeBit, PipelineStageFlags.PipelineStageAllCommandsBit, 0, 0, null, 0, null, 1, barrier); }
protected override void RecordCommandBuffer(CommandBuffer cmdBuffer, int imageIndex) { var imageSubresourceRange = new ImageSubresourceRange(ImageAspects.Color, 0, 1, 0, 1); var barrierFromPresentToClear = new ImageMemoryBarrier( SwapchainImages[imageIndex], imageSubresourceRange, Accesses.None, Accesses.TransferWrite, ImageLayout.Undefined, ImageLayout.TransferDstOptimal); var barrierFromClearToPresent = new ImageMemoryBarrier( SwapchainImages[imageIndex], imageSubresourceRange, Accesses.TransferWrite, Accesses.MemoryRead, ImageLayout.TransferDstOptimal, ImageLayout.PresentSrcKhr); cmdBuffer.CmdPipelineBarrier( PipelineStages.Transfer, PipelineStages.Transfer, imageMemoryBarriers: new[] { barrierFromPresentToClear }); cmdBuffer.CmdClearColorImage( SwapchainImages[imageIndex], ImageLayout.TransferDstOptimal, new ClearColorValue(new ColorF4(0.39f, 0.58f, 0.93f, 1.0f)), imageSubresourceRange); cmdBuffer.CmdPipelineBarrier( PipelineStages.Transfer, PipelineStages.Transfer, imageMemoryBarriers: new[] { barrierFromClearToPresent }); }
internal void TransitionImageLayout(Image image, Format format, ImageLayout oldLayout, ImageLayout newLayout) { var commandBuffer = this.BeginSingleTimeCommand(); var barrier = new ImageMemoryBarrier { OldLayout = oldLayout, NewLayout = newLayout, SourceQueueFamilyIndex = Constants.QueueFamilyIgnored, DestinationQueueFamilyIndex = Constants.QueueFamilyIgnored, Image = image, SubresourceRange = new ImageSubresourceRange { AspectMask = newLayout == ImageLayout.DepthStencilAttachmentOptimal ? ImageAspectFlags.Depth : ImageAspectFlags.Color, BaseMipLevel = 0, LevelCount = 1, BaseArrayLayer = 0, LayerCount = 1 } }; if (oldLayout == ImageLayout.Preinitialized && newLayout == ImageLayout.TransferSourceOptimal) { barrier.SourceAccessMask = AccessFlags.HostWrite; barrier.DestinationAccessMask = AccessFlags.TransferRead; } else if (oldLayout == ImageLayout.Preinitialized && newLayout == ImageLayout.TransferDestinationOptimal) { barrier.SourceAccessMask = AccessFlags.HostWrite; barrier.DestinationAccessMask = AccessFlags.TransferWrite; } else if (oldLayout == ImageLayout.TransferDestinationOptimal && newLayout == ImageLayout.ShaderReadOnlyOptimal) { barrier.SourceAccessMask = AccessFlags.TransferWrite; barrier.DestinationAccessMask = AccessFlags.ShaderRead; } else if (oldLayout == ImageLayout.Undefined && newLayout == ImageLayout.DepthStencilAttachmentOptimal) { barrier.SourceAccessMask = AccessFlags.None; barrier.DestinationAccessMask = AccessFlags.DepthStencilAttachmentRead | AccessFlags.DepthStencilAttachmentWrite; } else { throw new System.Exception("Unsupported layout transition"); } commandBuffer[0].PipelineBarrier(PipelineStageFlags.TopOfPipe, PipelineStageFlags.TopOfPipe, DependencyFlags.None, null, null, new[] { barrier }); this.EndSingleTimeCommand(commandBuffer); }
void PipelineBarrierSetLayout(CommandBuffer cmdBuffer, Image image, ImageLayout oldLayout, ImageLayout newLayout, AccessFlags srcMask, AccessFlags dstMask) { var subresourceRange = new ImageSubresourceRange(ImageAspectFlags.Color, 0, 1, 0, 1); var imageMemoryBarrier = new ImageMemoryBarrier(oldLayout, newLayout, 0, 0, image, subresourceRange); imageMemoryBarrier.SrcAccessMask = srcMask; imageMemoryBarrier.DstAccessMask = dstMask; var imageMemoryBarriers = new[] { imageMemoryBarrier }; cmdBuffer.PipelineBarrier(PipelineStageFlags.TopOfPipe, PipelineStageFlags.TopOfPipe, DependencyFlags.None, null, null, imageMemoryBarriers); imageMemoryBarrier.Dispose(); }
private static void SetOptimalAccessMasks(ImageMemoryBarrier imageMemoryBarrier, ImageLayout oldLayout, ImageLayout newLayout) { // Undefined layout: // Note: Only allowed as initial layout! // Note: Make sure any writes to the image have been finished if (oldLayout == ImageLayout.Undefined) imageMemoryBarrier.SrcAccessMask = AccessFlags.HostWrite | AccessFlags.TransferWrite; // Old layout is color attachment: // Note: Make sure any writes to the color buffer have been finished if (oldLayout == ImageLayout.ColorAttachmentOptimal) imageMemoryBarrier.SrcAccessMask = AccessFlags.ColorAttachmentWrite; // Old layout is transfer source: // Note: Make sure any reads from the image have been finished if (oldLayout == ImageLayout.TransferSrcOptimal) imageMemoryBarrier.SrcAccessMask = AccessFlags.TransferRead; // Old layout is shader read (sampler, input attachment): // Note: Make sure any shader reads from the image have been finished if (oldLayout == ImageLayout.ShaderReadOnlyOptimal) imageMemoryBarrier.SrcAccessMask = AccessFlags.ShaderRead; // New layout is transfer destination (copy, blit): // Note: Make sure any copyies to the image have been finished if (newLayout == ImageLayout.TransferDstOptimal) imageMemoryBarrier.DstAccessMask = AccessFlags.TransferWrite; // New layout is transfer source (copy, blit): // Note: Make sure any reads from and writes to the image have been finished if (newLayout == ImageLayout.TransferSrcOptimal) { imageMemoryBarrier.SrcAccessMask = imageMemoryBarrier.SrcAccessMask | AccessFlags.TransferRead; imageMemoryBarrier.DstAccessMask = AccessFlags.TransferRead; } // New layout is color attachment: // Note: Make sure any writes to the color buffer hav been finished if (newLayout == ImageLayout.ColorAttachmentOptimal) { imageMemoryBarrier.DstAccessMask = AccessFlags.ColorAttachmentWrite; imageMemoryBarrier.SrcAccessMask = AccessFlags.TransferRead; } // New layout is depth attachment: // Note: Make sure any writes to depth/stencil buffer have been finished if (newLayout == ImageLayout.DepthStencilAttachmentOptimal) imageMemoryBarrier.DstAccessMask = imageMemoryBarrier.DstAccessMask | AccessFlags.DepthStencilAttachmentWrite; // New layout is shader read (sampler, input attachment): // Note: Make sure any writes to the image have been finished if (newLayout == ImageLayout.ShaderReadOnlyOptimal) { imageMemoryBarrier.SrcAccessMask = AccessFlags.HostWrite | AccessFlags.TransferWrite; imageMemoryBarrier.DstAccessMask = AccessFlags.ShaderRead; } }
void SetImageLayout(Image image, ImageAspectFlags aspectMask, ImageLayout oldImageLayout, ImageLayout newImageLayout, AccessFlags srcAccessMask) { if (cmdSetup == null) { cmdSetup = CreateCommandBuffer(QueueFlags.Graphics); cmdSetup.Begin(new CommandBufferBeginInfo()); } ImageMemoryBarrier imageMemoryBarrier = new ImageMemoryBarrier { SrcAccessMask = (uint)srcAccessMask, DstAccessMask = 0, OldLayout = oldImageLayout, NewLayout = newImageLayout, Image = image, SubresourceRange = new ImageSubresourceRange { AspectMask = (uint)aspectMask, BaseMipLevel = 0, LevelCount = 1, BaseArrayLayer = 0, LayerCount = 1, }, }; if (newImageLayout == ImageLayout.TransferDstOptimal) { imageMemoryBarrier.DstAccessMask = (uint)AccessFlags.TransferRead; } else if (newImageLayout == ImageLayout.ColorAttachmentOptimal) { imageMemoryBarrier.DstAccessMask = (uint)AccessFlags.ColorAttachmentWrite; } else if (newImageLayout == ImageLayout.DepthStencilAttachmentOptimal) { imageMemoryBarrier.DstAccessMask = (uint)AccessFlags.DepthStencilAttachmentWrite; } else if (newImageLayout == ImageLayout.ShaderReadOnlyOptimal) { imageMemoryBarrier.DstAccessMask = (uint)(AccessFlags.ShaderRead | AccessFlags.InputAttachmentRead); } // TODO Vulkan : we cant set null as this null->m will be called //cmdSetup.CmdPipelineBarrier(PipelineStageFlags.TopOfPipe, PipelineStageFlags.TopOfPipe, 0, 0, MemoryBarrier.Null, 0, BufferMemoryBarrier.Null, 1, imageMemoryBarrier); cmdSetup.CmdPipelineBarrier(PipelineStageFlags.TopOfPipe, PipelineStageFlags.TopOfPipe, 0, null, null, new ImageMemoryBarrier[] { imageMemoryBarrier }); }
public void Begin() { CommandBuffer.Begin(new CommandBufferBeginInfo(CommandBufferUsages.SimultaneousUse)); if (Context.PresentQueue != Context.GraphicsQueue) { var barrierFromPresentToDraw = new ImageMemoryBarrier( Image.Image, DefaultSubresourceRangeColor, Accesses.MemoryRead, Accesses.ColorAttachmentWrite, ImageLayout.Undefined, ImageLayout.PresentSrcKhr, Context.PresentQueue.FamilyIndex, Context.GraphicsQueue.FamilyIndex); CommandBuffer.CmdPipelineBarrier( PipelineStages.ColorAttachmentOutput, PipelineStages.ColorAttachmentOutput, imageMemoryBarriers: new[] { barrierFromPresentToDraw }); } }
public void End() { if (Context.PresentQueue != Context.GraphicsQueue) { var barrierFromDrawToPresent = new ImageMemoryBarrier( Image.Image, DefaultSubresourceRangeColor, Accesses.ColorAttachmentWrite, Accesses.MemoryRead, ImageLayout.PresentSrcKhr, ImageLayout.PresentSrcKhr, Context.GraphicsQueue.FamilyIndex, Context.PresentQueue.FamilyIndex); CommandBuffer.CmdPipelineBarrier( PipelineStages.ColorAttachmentOutput, PipelineStages.BottomOfPipe, imageMemoryBarriers: new[] { barrierFromDrawToPresent }); } CommandBuffer.End(); }
private void RecordCommandBuffers() { var subresourceRange = new ImageSubresourceRange(ImageAspects.Color, 0, 1, 0, 1); for (int i = 0; i < CommandBuffers.Length; i++) { CommandBuffer cmdBuffer = CommandBuffers[i]; cmdBuffer.Begin(new CommandBufferBeginInfo(CommandBufferUsages.SimultaneousUse)); if (Context.PresentQueue != Context.GraphicsQueue) { var barrierFromPresentToDraw = new ImageMemoryBarrier( SwapchainImages[i], subresourceRange, Accesses.MemoryRead, Accesses.ColorAttachmentWrite, ImageLayout.Undefined, ImageLayout.PresentSrcKhr, Context.PresentQueue.FamilyIndex, Context.GraphicsQueue.FamilyIndex); cmdBuffer.CmdPipelineBarrier( PipelineStages.ColorAttachmentOutput, PipelineStages.ColorAttachmentOutput, imageMemoryBarriers: new[] { barrierFromPresentToDraw }); } RecordCommandBuffer(cmdBuffer, i); if (Context.PresentQueue != Context.GraphicsQueue) { var barrierFromDrawToPresent = new ImageMemoryBarrier( SwapchainImages[i], subresourceRange, Accesses.ColorAttachmentWrite, Accesses.MemoryRead, ImageLayout.PresentSrcKhr, ImageLayout.PresentSrcKhr, Context.GraphicsQueue.FamilyIndex, Context.PresentQueue.FamilyIndex); cmdBuffer.CmdPipelineBarrier( PipelineStages.ColorAttachmentOutput, PipelineStages.BottomOfPipe, imageMemoryBarriers: new[] { barrierFromDrawToPresent }); } cmdBuffer.End(); } }
protected void SetImageLayout(CommandBuffer commandBuffer, Image image, ImageAspectFlags aspectFlags, ImageLayout oldLayout, ImageLayout newLayout) { var imageMemoryBarrier = new ImageMemoryBarrier { OldLayout = oldLayout, NewLayout = newLayout, Image = image, SubresourceRange = new ImageSubresourceRange { AspectMask = aspectFlags, BaseMipLevel = 0, LevelCount = 1, LayerCount = 1, BaseArrayLayer = 0 } }; SetOptimalAccessMasks(imageMemoryBarrier, oldLayout, newLayout); commandBuffer.CmdPipelineBarrier(PipelineStageFlags.TopOfPipe, PipelineStageFlags.TopOfPipe, 0, 0, null, 0, null, 1, imageMemoryBarrier); }
public static unsafe void InsertImageBarrier( Vk api, CommandBuffer commandBuffer, Image image, AccessFlags srcAccessMask, AccessFlags dstAccessMask, PipelineStageFlags srcStageMask, PipelineStageFlags dstStageMask, ImageAspectFlags aspectFlags, int firstLayer, int firstLevel, int layers, int levels) { ImageMemoryBarrier memoryBarrier = new ImageMemoryBarrier() { SType = StructureType.ImageMemoryBarrier, SrcAccessMask = srcAccessMask, DstAccessMask = dstAccessMask, SrcQueueFamilyIndex = Vk.QueueFamilyIgnored, DstQueueFamilyIndex = Vk.QueueFamilyIgnored, Image = image, OldLayout = ImageLayout.General, NewLayout = ImageLayout.General, SubresourceRange = new ImageSubresourceRange(aspectFlags, (uint)firstLevel, (uint)levels, (uint)firstLayer, (uint)layers) }; api.CmdPipelineBarrier( commandBuffer, srcStageMask, dstStageMask, 0, 0, null, 0, null, 1, memoryBarrier); }
public void Clear(System.Drawing.Color color) { var barrierFromPresentToClear = new ImageMemoryBarrier( Image.Image, DefaultSubresourceRangeColor, Accesses.None, Accesses.TransferWrite, ImageLayout.Undefined, ImageLayout.TransferDstOptimal); var barrierFromClearToPresent = new ImageMemoryBarrier( Image.Image, DefaultSubresourceRangeColor, Accesses.TransferWrite, Accesses.MemoryRead, ImageLayout.TransferDstOptimal, ImageLayout.PresentSrcKhr); CommandBuffer.CmdPipelineBarrier( PipelineStages.Transfer, PipelineStages.Transfer, imageMemoryBarriers: new[] { barrierFromPresentToClear }); CommandBuffer.CmdClearColorImage( Image.Image, ImageLayout.TransferDstOptimal, new ClearColorValue(new ColorF4((float)color.R / 255f, (float)color.G / 255f, (float)color.B / 255f, (float)color.A / 255f)), DefaultSubresourceRangeColor); CommandBuffer.CmdPipelineBarrier( PipelineStages.Transfer, PipelineStages.Transfer, imageMemoryBarriers: new[] { barrierFromClearToPresent }); }
internal static unsafe void TransitionLayout(VulkanDevice device, CommandBuffer commandBuffer, Image image, ImageLayout sourceLayout, AccessFlags sourceAccessMask, ImageLayout destinationLayout, AccessFlags destinationAccessMask, uint mipLevels) { var subresourceRange = new ImageSubresourceRange(ImageAspectFlags.ImageAspectColorBit, 0, mipLevels, 0, 1); var barrier = new ImageMemoryBarrier { SType = StructureType.ImageMemoryBarrier, SrcAccessMask = sourceAccessMask, DstAccessMask = destinationAccessMask, OldLayout = sourceLayout, NewLayout = destinationLayout, SrcQueueFamilyIndex = Vk.QueueFamilyIgnored, DstQueueFamilyIndex = Vk.QueueFamilyIgnored, Image = image, SubresourceRange = subresourceRange }; device.Api.CmdPipelineBarrier( commandBuffer, PipelineStageFlags.PipelineStageAllCommandsBit, PipelineStageFlags.PipelineStageAllCommandsBit, 0, 0, null, 0, null, 1, barrier); }
public static ImageWithMemory CreateImageWithMemory( uint width, uint height, ImageUsageFlags imageUsageFlags, ImageLayout imageLayout, AccessFlags accessMask, SampleCountFlags samples = SampleCountFlags.Count1) { ImageWithMemory imageWithMemory = new ImageWithMemory { Image = VContext.Instance.device.CreateImage ( new ImageCreateInfo() { ImageType = ImageType.Image2D, Format = VContext.ColorFormat, Extent = new Extent3D() { Width = width, Height = height, Depth = 1 }, MipLevels = 1, ArrayLayers = 1, Samples = samples, Tiling = ImageTiling.Optimal, Usage = imageUsageFlags, SharingMode = SharingMode.Exclusive, InitialLayout = ImageLayout.Undefined } ) }; MemoryRequirements textureMemoryRequirements = VContext.Instance.device.GetImageMemoryRequirements(imageWithMemory.Image); uint memoryTypeIndex = Util.GetMemoryTypeIndex(textureMemoryRequirements.MemoryTypeBits, MemoryPropertyFlags.DeviceLocal); imageWithMemory.Memory = VContext.Instance.device.AllocateMemory ( new MemoryAllocateInfo() { AllocationSize = textureMemoryRequirements.Size, MemoryTypeIndex = memoryTypeIndex } ); VContext.Instance.device.BindImageMemory(imageWithMemory.Image, imageWithMemory.Memory, 0); if (imageLayout != ImageLayout.Undefined) { CommandBuffer commandBuffer = _commandBuffer.Value; commandBuffer.Begin(new CommandBufferBeginInfo()); ImageSubresourceRange subresourceRange = new ImageSubresourceRange() { AspectMask = ImageAspectFlags.Color, BaseMipLevel = 0, LevelCount = 1, LayerCount = 1, }; ImageMemoryBarrier undefinedToTranserDstBarrier = new ImageMemoryBarrier() { OldLayout = ImageLayout.Undefined, NewLayout = imageLayout, Image = imageWithMemory.Image, SubresourceRange = subresourceRange, SrcAccessMask = 0, DstAccessMask = accessMask }; commandBuffer.CmdPipelineBarrier( PipelineStageFlags.AllCommands, PipelineStageFlags.AllCommands, 0, null, null, undefinedToTranserDstBarrier); commandBuffer.CmdPipelineBarrier( PipelineStageFlags.AllCommands, PipelineStageFlags.AllCommands, 0, null, null, undefinedToTranserDstBarrier); commandBuffer.End(); Fence fence = VContext.Instance.device.CreateFence(new FenceCreateInfo()); SubmitInfo submitInfo = new SubmitInfo() { CommandBuffers = new CommandBuffer[] { commandBuffer } }; VContext.Instance.deviceQueue.Submit(submitInfo, fence); VContext.Instance.device.WaitForFences(new Fence[] { fence }, true, ulong.MaxValue); commandBuffer.Reset(CommandBufferResetFlags.ReleaseResources); VContext.Instance.device.DestroyFence(fence); } imageWithMemory.ImageView = VContext.Instance.CreateImageView(imageWithMemory.Image, VContext.ColorFormat, ImageAspectFlags.Color); return(imageWithMemory); }
private unsafe void CreateBackBuffers() { backbuffer.OnDestroyed(); // 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); // need to make a fence, but can immediately reset it, as it acts as a dummy var fenceCreateInfo = new FenceCreateInfo { StructureType = StructureType.FenceCreateInfo }; presentFence = GraphicsDevice.NativeDevice.CreateFence(ref fenceCreateInfo); currentBufferIndex = GraphicsDevice.NativeDevice.AcquireNextImage(swapChain, ulong.MaxValue, SharpVulkan.Semaphore.Null, presentFence); fixed(Fence *fences = &presentFence) { GraphicsDevice.NativeDevice.ResetFences(1, fences); } // Apply the first swap chain image to the texture backbuffer.SetNativeHandles(swapchainImages[currentBufferIndex].NativeImage, swapchainImages[currentBufferIndex].NativeColorAttachmentView); }
private static void TransitionImageLayout( Image image, ImageAspects aspectMask, int baseMipLevel, int mipLevels, int baseLayer, int layers, ImageLayout oldLayout, ImageLayout newLayout, TransientExecutor executor) { //Get where this transition has to wait and what has to wait for this transition Accesses sourceAccess, destinationAccess; PipelineStages sourcePipelineStages, destinationPipelineStages; if (oldLayout == ImageLayout.Undefined && newLayout == ImageLayout.TransferDstOptimal) { sourceAccess = Accesses.None; destinationAccess = Accesses.TransferWrite; sourcePipelineStages = PipelineStages.TopOfPipe; destinationPipelineStages = PipelineStages.Transfer; } else if (oldLayout == ImageLayout.Undefined && newLayout == ImageLayout.DepthStencilAttachmentOptimal) { sourceAccess = Accesses.None; destinationAccess = Accesses.DepthStencilAttachmentRead | Accesses.DepthStencilAttachmentWrite; sourcePipelineStages = PipelineStages.TopOfPipe; destinationPipelineStages = PipelineStages.EarlyFragmentTests; } else if (oldLayout == ImageLayout.Undefined && newLayout == ImageLayout.ColorAttachmentOptimal) { sourceAccess = Accesses.None; destinationAccess = Accesses.ColorAttachmentRead | Accesses.ColorAttachmentWrite; sourcePipelineStages = PipelineStages.TopOfPipe; destinationPipelineStages = PipelineStages.ColorAttachmentOutput; } else if (oldLayout == ImageLayout.TransferDstOptimal && newLayout == ImageLayout.TransferSrcOptimal) { sourceAccess = Accesses.TransferWrite; destinationAccess = Accesses.TransferRead; sourcePipelineStages = PipelineStages.Transfer; destinationPipelineStages = PipelineStages.Transfer; } else if (oldLayout == ImageLayout.TransferDstOptimal && newLayout == ImageLayout.ShaderReadOnlyOptimal) { sourceAccess = Accesses.TransferWrite; destinationAccess = Accesses.ShaderRead; sourcePipelineStages = PipelineStages.Transfer; destinationPipelineStages = PipelineStages.FragmentShader; } else if (oldLayout == ImageLayout.TransferSrcOptimal && newLayout == ImageLayout.ShaderReadOnlyOptimal) { sourceAccess = Accesses.TransferRead; destinationAccess = Accesses.ShaderRead; sourcePipelineStages = PipelineStages.Transfer; destinationPipelineStages = PipelineStages.FragmentShader; } else { throw new Exception( $"[{nameof(DeviceTexture)}] Unsupported image transition: from: {oldLayout} to: {newLayout}"); } //Create the transition barrier var imageMemoryBarrier = new ImageMemoryBarrier( image: image, subresourceRange: new ImageSubresourceRange( aspectMask: aspectMask, baseMipLevel: baseMipLevel, levelCount: mipLevels, baseArrayLayer: baseLayer, layerCount: layers), srcAccessMask: sourceAccess, dstAccessMask: destinationAccess, oldLayout: oldLayout, newLayout: newLayout); //Execute the barrier executor.ExecuteBlocking(commandBuffer => { commandBuffer.CmdPipelineBarrier( srcStageMask: sourcePipelineStages, dstStageMask: destinationPipelineStages, dependencyFlags: Dependencies.None, memoryBarriers: null, bufferMemoryBarriers: null, imageMemoryBarriers: new [] { imageMemoryBarrier }); }); }
private unsafe void InitializeImage(DataBox[] dataBoxes) { // Begin copy command buffer var commandBufferAllocateInfo = new CommandBufferAllocateInfo { StructureType = StructureType.CommandBufferAllocateInfo, CommandPool = GraphicsDevice.NativeCopyCommandPool, CommandBufferCount = 1, Level = CommandBufferLevel.Primary }; CommandBuffer commandBuffer; lock (GraphicsDevice.QueueLock) { GraphicsDevice.NativeDevice.AllocateCommandBuffers(ref commandBufferAllocateInfo, &commandBuffer); } var beginInfo = new CommandBufferBeginInfo { StructureType = StructureType.CommandBufferBeginInfo, Flags = CommandBufferUsageFlags.OneTimeSubmit }; commandBuffer.Begin(ref beginInfo); if (dataBoxes != null && dataBoxes.Length > 0) { // Buffer-to-image copies need to be aligned to the pixel size and 4 (always a power of 2) var blockSize = Format.IsCompressed() ? NativeFormat.BlockSizeInBytes() : TexturePixelSize; var alignmentMask = (blockSize < 4 ? 4 : blockSize) - 1; int totalSize = dataBoxes.Length * alignmentMask; for (int i = 0; i < dataBoxes.Length; i++) { totalSize += dataBoxes[i].SlicePitch; } SharpVulkan.Buffer uploadResource; int uploadOffset; var uploadMemory = GraphicsDevice.AllocateUploadBuffer(totalSize, out uploadResource, out uploadOffset); // Upload buffer barrier var bufferMemoryBarrier = new BufferMemoryBarrier(uploadResource, AccessFlags.HostWrite, AccessFlags.TransferRead, (ulong)uploadOffset, (ulong)totalSize); // Image barrier var initialBarrier = new ImageMemoryBarrier(NativeImage, ImageLayout.Undefined, ImageLayout.TransferDestinationOptimal, AccessFlags.None, AccessFlags.TransferWrite, new ImageSubresourceRange(NativeImageAspect)); commandBuffer.PipelineBarrier(PipelineStageFlags.Host, PipelineStageFlags.Transfer, DependencyFlags.None, 0, null, 1, &bufferMemoryBarrier, 1, &initialBarrier); // Copy data boxes to upload buffer var copies = new BufferImageCopy[dataBoxes.Length]; for (int i = 0; i < copies.Length; i++) { var slicePitch = dataBoxes[i].SlicePitch; int arraySlice = i / MipLevels; int mipSlice = i % MipLevels; var mipMapDescription = GetMipMapDescription(mipSlice); var alignment = ((uploadOffset + alignmentMask) & ~alignmentMask) - uploadOffset; uploadMemory += alignment; uploadOffset += alignment; Utilities.CopyMemory(uploadMemory, dataBoxes[i].DataPointer, slicePitch); // TODO VULKAN: Check if pitches are valid copies[i] = new BufferImageCopy { BufferOffset = (ulong)uploadOffset, ImageSubresource = new ImageSubresourceLayers(ImageAspectFlags.Color, (uint)arraySlice, 1, (uint)mipSlice), BufferRowLength = 0, //(uint)(dataBoxes[i].RowPitch / pixelSize), BufferImageHeight = 0, //(uint)(dataBoxes[i].SlicePitch / dataBoxes[i].RowPitch), ImageOffset = new Offset3D(0, 0, 0), ImageExtent = new Extent3D((uint)mipMapDescription.Width, (uint)mipMapDescription.Height, (uint)mipMapDescription.Depth) }; uploadMemory += slicePitch; uploadOffset += slicePitch; } // Copy from upload buffer to image fixed(BufferImageCopy *copiesPointer = &copies[0]) { commandBuffer.CopyBufferToImage(uploadResource, NativeImage, ImageLayout.TransferDestinationOptimal, (uint)copies.Length, copiesPointer); } IsInitialized = true; } // Transition to default layout var imageMemoryBarrier = new ImageMemoryBarrier(NativeImage, dataBoxes == null || dataBoxes.Length == 0 ? ImageLayout.Undefined : ImageLayout.TransferDestinationOptimal, NativeLayout, dataBoxes == null || dataBoxes.Length == 0 ? AccessFlags.None : AccessFlags.TransferWrite, NativeAccessMask, new ImageSubresourceRange(NativeImageAspect)); commandBuffer.PipelineBarrier(PipelineStageFlags.Transfer, 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), }; lock (GraphicsDevice.QueueLock) { GraphicsDevice.NativeCommandQueue.Submit(1, &submitInfo, Fence.Null); GraphicsDevice.NativeCommandQueue.WaitIdle(); GraphicsDevice.NativeDevice.FreeCommandBuffers(GraphicsDevice.NativeCopyCommandPool, 1, &commandBuffer); } }
internal void TransitionImageLayout(Image image, Format format, ImageLayout oldLayout, ImageLayout newLayout) { PipelineStageFlags sourceStage = PipelineStageFlags.TopOfPipe; PipelineStageFlags destinationStage = PipelineStageFlags.TopOfPipe; AccessFlags MapAccessMask(ImageLayout layout, ref PipelineStageFlags stage) { switch (layout) { case ImageLayout.Undefined: return(AccessFlags.None); case ImageLayout.Preinitialized: stage = PipelineStageFlags.Host; return(AccessFlags.HostWrite); case ImageLayout.TransferSourceOptimal: stage = PipelineStageFlags.Transfer; return(AccessFlags.TransferRead); case ImageLayout.TransferDestinationOptimal: stage = PipelineStageFlags.Transfer; return(AccessFlags.TransferWrite); case ImageLayout.ShaderReadOnlyOptimal: stage = PipelineStageFlags.VertexShader | PipelineStageFlags.FragmentShader; return(AccessFlags.ShaderRead); case ImageLayout.DepthStencilAttachmentOptimal: stage = PipelineStageFlags.EarlyFragmentTests | PipelineStageFlags.LateFragmentTests; return(AccessFlags.DepthStencilAttachmentRead | AccessFlags.DepthStencilAttachmentWrite); } throw new System.Exception($"Unsupported layout transition '{layout}'"); } var commandBuffer = this.BeginSingleTimeCommand(this.barrierCommandPool); var barrier = new ImageMemoryBarrier { OldLayout = oldLayout, NewLayout = newLayout, SourceAccessMask = MapAccessMask(oldLayout, ref sourceStage), DestinationAccessMask = MapAccessMask(newLayout, ref destinationStage), SourceQueueFamilyIndex = Constants.QueueFamilyIgnored, DestinationQueueFamilyIndex = Constants.QueueFamilyIgnored, Image = image, SubresourceRange = new ImageSubresourceRange { AspectMask = newLayout == ImageLayout.DepthStencilAttachmentOptimal ? ImageAspectFlags.Depth : ImageAspectFlags.Color, BaseMipLevel = 0, LevelCount = 1, BaseArrayLayer = 0, LayerCount = 1 } }; commandBuffer[0].PipelineBarrier(sourceStage, destinationStage, null, null, barrier); this.EndSingleTimeCommand(commandBuffer, this.barrierCommandPool, this.barrierQueue); }
private void SetImageLayout(Image image, ImageAspectFlags imageAspect, ImageLayout oldLayout, ImageLayout newLayout) { if (setupCommanBuffer == CommandBuffer.Null) { // Create command buffer CommandBuffer setupCommandBuffer; var allocateInfo = new CommandBufferAllocateInfo { StructureType = StructureType.CommandBufferAllocateInfo, CommandPool = commandPool, Level = CommandBufferLevel.Primary, CommandBufferCount = 1, }; device.AllocateCommandBuffers(ref allocateInfo, &setupCommandBuffer); setupCommanBuffer = setupCommandBuffer; // Begin command buffer var inheritanceInfo = new CommandBufferInheritanceInfo { StructureType = StructureType.CommandBufferInheritanceInfo }; var beginInfo = new CommandBufferBeginInfo { StructureType = StructureType.CommandBufferBeginInfo, InheritanceInfo = new IntPtr(&inheritanceInfo) }; setupCommanBuffer.Begin(ref beginInfo); } var imageMemoryBarrier = new ImageMemoryBarrier { StructureType = StructureType.ImageMemoryBarrier, OldLayout = oldLayout, NewLayout = newLayout, Image = image, SubresourceRange = new ImageSubresourceRange(imageAspect, 0, 1, 0, 1) }; switch (newLayout) { case ImageLayout.TransferDestinationOptimal: imageMemoryBarrier.DestinationAccessMask = AccessFlags.TransferRead; break; case ImageLayout.ColorAttachmentOptimal: imageMemoryBarrier.DestinationAccessMask = AccessFlags.ColorAttachmentWrite; break; case ImageLayout.DepthStencilAttachmentOptimal: imageMemoryBarrier.DestinationAccessMask = AccessFlags.DepthStencilAttachmentWrite; break; case ImageLayout.ShaderReadOnlyOptimal: imageMemoryBarrier.DestinationAccessMask = AccessFlags.ShaderRead | AccessFlags.InputAttachmentRead; break; } var sourceStages = PipelineStageFlags.TopOfPipe; var destinationStages = PipelineStageFlags.TopOfPipe; setupCommanBuffer.PipelineBarrier(sourceStages, destinationStages, DependencyFlags.None, 0, null, 0, null, 1, &imageMemoryBarrier); }
private void DrawInternal() { // Update descriptors var descriptorSets = stackalloc DescriptorSet[2]; var setLayouts = stackalloc DescriptorSetLayout[2]; setLayouts[0] = setLayouts[1] = descriptorSetLayout; var allocateInfo = new DescriptorSetAllocateInfo { StructureType = StructureType.DescriptorSetAllocateInfo, DescriptorPool = descriptorPool, DescriptorSetCount = 2, SetLayouts = new IntPtr(setLayouts), }; device.AllocateDescriptorSets(ref allocateInfo, descriptorSets); var bufferInfo = new DescriptorBufferInfo { Buffer = uniformBuffer, Range = Vulkan.WholeSize }; var write = new WriteDescriptorSet { StructureType = StructureType.WriteDescriptorSet, DescriptorCount = 1, DestinationSet = descriptorSets[0], DestinationBinding = 0, DescriptorType = DescriptorType.UniformBuffer, BufferInfo = new IntPtr(&bufferInfo) }; var copy = new CopyDescriptorSet { StructureType = StructureType.CopyDescriptorSet, DescriptorCount = 1, SourceBinding = 0, DestinationBinding = 0, SourceSet = descriptorSets[0], DestinationSet = descriptorSets[1] }; device.UpdateDescriptorSets(1, &write, 0, null); device.UpdateDescriptorSets(0, null, 1, ©); // Post-present transition var memoryBarrier = new ImageMemoryBarrier { StructureType = StructureType.ImageMemoryBarrier, Image = backBuffers[currentBackBufferIndex], SubresourceRange = new ImageSubresourceRange(ImageAspectFlags.Color, 0, 1, 0, 1), OldLayout = ImageLayout.PresentSource, NewLayout = ImageLayout.ColorAttachmentOptimal, SourceAccessMask = AccessFlags.MemoryRead, DestinationAccessMask = AccessFlags.ColorAttachmentWrite }; commandBuffer.PipelineBarrier(PipelineStageFlags.TopOfPipe, PipelineStageFlags.TopOfPipe, DependencyFlags.None, 0, null, 0, null, 1, &memoryBarrier); // Clear render target var clearRange = new ImageSubresourceRange(ImageAspectFlags.Color, 0, 1, 0, 1); commandBuffer.ClearColorImage(backBuffers[currentBackBufferIndex], ImageLayout.TransferDestinationOptimal, new RawColor4(0, 0, 0, 1), 1, &clearRange); // Begin render pass var renderPassBeginInfo = new RenderPassBeginInfo { StructureType = StructureType.RenderPassBeginInfo, RenderPass = renderPass, Framebuffer = framebuffers[currentBackBufferIndex], RenderArea = new Rect2D(0, 0, (uint)form.ClientSize.Width, (uint)form.ClientSize.Height), }; commandBuffer.BeginRenderPass(ref renderPassBeginInfo, SubpassContents.Inline); // Bind pipeline commandBuffer.BindPipeline(PipelineBindPoint.Graphics, pipeline); // Bind descriptor sets commandBuffer.BindDescriptorSets(PipelineBindPoint.Graphics, pipelineLayout, 0, 1, descriptorSets + 1, 0, null); // Set viewport and scissor var viewport = new Viewport(0, 0, form.ClientSize.Width, form.ClientSize.Height); commandBuffer.SetViewport(0, 1, &viewport); var scissor = new Rect2D(0, 0, (uint)form.ClientSize.Width, (uint)form.ClientSize.Height); commandBuffer.SetScissor(0, 1, &scissor); // Bind vertex buffer var vertexBufferCopy = vertexBuffer; ulong offset = 0; commandBuffer.BindVertexBuffers(0, 1, &vertexBufferCopy, &offset); // Draw vertices commandBuffer.Draw(3, 1, 0, 0); // End render pass commandBuffer.EndRenderPass(); // Pre-present transition memoryBarrier = new ImageMemoryBarrier { StructureType = StructureType.ImageMemoryBarrier, Image = backBuffers[currentBackBufferIndex], SubresourceRange = new ImageSubresourceRange(ImageAspectFlags.Color, 0, 1, 0, 1), OldLayout = ImageLayout.ColorAttachmentOptimal, NewLayout = ImageLayout.PresentSource, SourceAccessMask = AccessFlags.ColorAttachmentWrite, DestinationAccessMask = AccessFlags.MemoryRead }; commandBuffer.PipelineBarrier(PipelineStageFlags.AllCommands, PipelineStageFlags.BottomOfPipe, DependencyFlags.None, 0, null, 0, null, 1, &memoryBarrier); }
public static ImageWithMemory CreateImageWithMemory( Bitmap texture, bool forceLinear = false, ImageUsageFlags imageUsageFlags = ImageUsageFlags.Sampled, ImageLayout imageLayout = ImageLayout.ShaderReadOnlyOptimal) { ImageWithMemory imageWithMemory = new ImageWithMemory(); System.Drawing.Imaging.BitmapData data = texture.LockBits(new System.Drawing.Rectangle(0, 0, texture.Width, texture.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); int length = data.Stride * data.Height; DeviceSize imageSize = length; byte[] bytes = new byte[length]; System.Runtime.InteropServices.Marshal.Copy(data.Scan0, bytes, 0, length); texture.UnlockBits(data); BufferWithMemory stagingBuffer; fixed(byte *source = &bytes[0]) { stagingBuffer = VContext.Instance.CreateBuffer(BufferUsageFlags.TransferSrc, imageSize, source); } List <BufferImageCopy> bufferCopyRegions = new List <BufferImageCopy>(); DeviceSize offset = 0; for (uint i = 0; i < 1; i++) { BufferImageCopy bufferCopyRegion = new BufferImageCopy() { ImageSubresource = new ImageSubresourceLayers() { AspectMask = ImageAspectFlags.Color, MipLevel = i, BaseArrayLayer = 0, LayerCount = 1 }, ImageExtent = new Extent3D() { Width = (uint)texture.Width, Height = (uint)texture.Height, Depth = 1, }, BufferOffset = offset }; bufferCopyRegions.Add(bufferCopyRegion); offset += imageSize; } imageWithMemory.Image = VContext.Instance.device.CreateImage ( new ImageCreateInfo() { ImageType = ImageType.Image2D, Format = VContext.ColorFormat, Extent = new Extent3D() { Width = (uint)texture.Width, Height = (uint)texture.Height, Depth = 1 }, MipLevels = 1, ArrayLayers = 1, Samples = SampleCountFlags.Count1, Tiling = ImageTiling.Optimal, Usage = ImageUsageFlags.Sampled | ImageUsageFlags.TransferDst, SharingMode = SharingMode.Exclusive, InitialLayout = ImageLayout.Undefined } ); MemoryRequirements textureMemoryRequirements = VContext.Instance.device.GetImageMemoryRequirements(imageWithMemory.Image); uint memoryTypeIndex = Util.GetMemoryTypeIndex(textureMemoryRequirements.MemoryTypeBits, MemoryPropertyFlags.DeviceLocal); imageWithMemory.Memory = VContext.Instance.device.AllocateMemory ( new MemoryAllocateInfo() { AllocationSize = textureMemoryRequirements.Size, MemoryTypeIndex = memoryTypeIndex } ); VContext.Instance.device.BindImageMemory(imageWithMemory.Image, imageWithMemory.Memory, 0); CommandBuffer commandBuffer = _commandBuffer.Value; commandBuffer.Begin(new CommandBufferBeginInfo()); ImageSubresourceRange subresourceRange = new ImageSubresourceRange() { AspectMask = ImageAspectFlags.Color, BaseMipLevel = 0, LevelCount = 1, LayerCount = 1, }; ImageMemoryBarrier undefinedToTranserDstBarrier = new ImageMemoryBarrier() { OldLayout = ImageLayout.Undefined, NewLayout = ImageLayout.TransferDstOptimal, Image = imageWithMemory.Image, SubresourceRange = subresourceRange, SrcAccessMask = 0, DstAccessMask = AccessFlags.TransferWrite }; commandBuffer.CmdPipelineBarrier( PipelineStageFlags.AllCommands, PipelineStageFlags.AllCommands, 0, null, null, undefinedToTranserDstBarrier); // Copy mip levels from staging buffer commandBuffer.CmdCopyBufferToImage( stagingBuffer.Buffer, imageWithMemory.Image, ImageLayout.TransferDstOptimal, bufferCopyRegions.ToArray()); // Change texture image layout to shader read after all mip levels have been copied ImageMemoryBarrier transferDstToShaderReadBarrier = new ImageMemoryBarrier() { OldLayout = ImageLayout.TransferDstOptimal, NewLayout = ImageLayout.ShaderReadOnlyOptimal, Image = imageWithMemory.Image, SubresourceRange = subresourceRange, SrcAccessMask = AccessFlags.TransferWrite, DstAccessMask = AccessFlags.ShaderRead }; commandBuffer.CmdPipelineBarrier( PipelineStageFlags.AllCommands, PipelineStageFlags.AllCommands, 0, null, null, transferDstToShaderReadBarrier); commandBuffer.End(); // Create a fence to make sure that the copies have finished before continuing Fence copyFence = VContext.Instance.device.CreateFence(new FenceCreateInfo()); SubmitInfo submitInfo = new SubmitInfo() { CommandBuffers = new CommandBuffer[] { commandBuffer } }; VContext.Instance.deviceQueue.Submit(submitInfo, copyFence); VContext.Instance.device.WaitForFences(new Fence[] { copyFence }, true, ulong.MaxValue); commandBuffer.Reset(CommandBufferResetFlags.ReleaseResources); VContext.Instance.device.DestroyFence(copyFence); VContext.Instance.device.FreeMemory(stagingBuffer.Memory); VContext.Instance.device.DestroyBuffer(stagingBuffer.Buffer); imageWithMemory.ImageView = VContext.Instance.CreateImageView(imageWithMemory.Image, VContext.ColorFormat, ImageAspectFlags.Color); return(imageWithMemory); }
public void CmdWaitEvent(Event pEvent, PipelineStageFlags srcStageMask, PipelineStageFlags dstStageMask, MemoryBarrier pMemoryBarrier, BufferMemoryBarrier pBufferMemoryBarrier, ImageMemoryBarrier pImageMemoryBarrier) { unsafe { fixed(UInt64 *ptrpEvent = &pEvent.m) { Interop.NativeMethods.vkCmdWaitEvents(this.m, (UInt32)(pEvent != null ? 1 : 0), ptrpEvent, srcStageMask, dstStageMask, (UInt32)(pMemoryBarrier != null ? 1 : 0), pMemoryBarrier != null ? pMemoryBarrier.m : (Interop.MemoryBarrier *) default(IntPtr), (UInt32)(pBufferMemoryBarrier != null ? 1 : 0), pBufferMemoryBarrier != null ? pBufferMemoryBarrier.m : (Interop.BufferMemoryBarrier *) default(IntPtr), (UInt32)(pImageMemoryBarrier != null ? 1 : 0), pImageMemoryBarrier != null ? pImageMemoryBarrier.m : (Interop.ImageMemoryBarrier *) default(IntPtr)); } } }
public void CmdPipelineBarrier(PipelineStageFlags srcStageMask, PipelineStageFlags dstStageMask, DependencyFlags dependencyFlag, MemoryBarrier pMemoryBarrier, BufferMemoryBarrier pBufferMemoryBarrier, ImageMemoryBarrier pImageMemoryBarrier) { unsafe { Interop.NativeMethods.vkCmdPipelineBarrier(this.m, srcStageMask, dstStageMask, dependencyFlag, (UInt32)(pMemoryBarrier != null ? 1 : 0), pMemoryBarrier != null ? pMemoryBarrier.m : (Interop.MemoryBarrier *) default(IntPtr), (UInt32)(pBufferMemoryBarrier != null ? 1 : 0), pBufferMemoryBarrier != null ? pBufferMemoryBarrier.m : (Interop.BufferMemoryBarrier *) default(IntPtr), (UInt32)(pImageMemoryBarrier != null ? 1 : 0), pImageMemoryBarrier != null ? pImageMemoryBarrier.m : (Interop.ImageMemoryBarrier *) default(IntPtr)); } }
private unsafe void InitializeImage(DataBox[] dataBoxes) { var commandBuffer = GraphicsDevice.NativeCopyCommandBuffer; var beginInfo = new CommandBufferBeginInfo { StructureType = StructureType.CommandBufferBeginInfo }; commandBuffer.Begin(ref beginInfo); if (dataBoxes != null && dataBoxes.Length > 0) { int totalSize = dataBoxes.Length * 4; for (int i = 0; i < dataBoxes.Length; i++) { totalSize += dataBoxes[i].SlicePitch; } SharpVulkan.Buffer uploadResource; int uploadOffset; var uploadMemory = GraphicsDevice.AllocateUploadBuffer(totalSize, out uploadResource, out uploadOffset); // Upload buffer barrier var bufferMemoryBarrier = new BufferMemoryBarrier(uploadResource, AccessFlags.HostWrite, AccessFlags.TransferRead, (ulong)uploadOffset, (ulong)totalSize); // Image barrier var initialBarrier = new ImageMemoryBarrier(NativeImage, ImageLayout.Undefined, ImageLayout.TransferDestinationOptimal, AccessFlags.None, AccessFlags.TransferWrite, new ImageSubresourceRange(NativeImageAspect)); commandBuffer.PipelineBarrier(PipelineStageFlags.TopOfPipe, PipelineStageFlags.Transfer, DependencyFlags.None, 0, null, 1, &bufferMemoryBarrier, 1, &initialBarrier); // Copy data boxes to upload buffer var copies = new BufferImageCopy[dataBoxes.Length]; for (int i = 0; i < copies.Length; i++) { var slicePitch = dataBoxes[i].SlicePitch; int arraySlice = i / MipLevels; int mipSlice = i % MipLevels; var mipMapDescription = GetMipMapDescription(mipSlice); SubresourceLayout layout; GraphicsDevice.NativeDevice.GetImageSubresourceLayout(NativeImage, new ImageSubresource(NativeImageAspect, (uint)arraySlice, (uint)mipSlice), out layout); var alignment = ((uploadOffset + 3) & ~3) - uploadOffset; uploadMemory += alignment; uploadOffset += alignment; Utilities.CopyMemory(uploadMemory, dataBoxes[i].DataPointer, slicePitch); // TODO VULKAN: Check if pitches are valid copies[i] = new BufferImageCopy { BufferOffset = (ulong)uploadOffset, ImageSubresource = new ImageSubresourceLayers(ImageAspectFlags.Color, (uint)arraySlice, 1, (uint)mipSlice), BufferRowLength = 0, //(uint)(dataBoxes[i].RowPitch / pixelSize), BufferImageHeight = 0, //(uint)(dataBoxes[i].SlicePitch / dataBoxes[i].RowPitch), ImageOffset = new Offset3D(0, 0, arraySlice), ImageExtent = new Extent3D((uint)mipMapDescription.Width, (uint)mipMapDescription.Height, 1) }; uploadMemory += slicePitch; uploadOffset += slicePitch; } // Copy from upload buffer to image fixed(BufferImageCopy *copiesPointer = &copies[0]) { commandBuffer.CopyBufferToImage(uploadResource, NativeImage, ImageLayout.TransferDestinationOptimal, (uint)copies.Length, copiesPointer); } IsInitialized = true; } // Transition to default layout var imageMemoryBarrier = new ImageMemoryBarrier(NativeImage, dataBoxes == null || dataBoxes.Length == 0 ? ImageLayout.Undefined : ImageLayout.TransferDestinationOptimal, NativeLayout, dataBoxes == null || dataBoxes.Length == 0 ? AccessFlags.None : AccessFlags.TransferWrite, NativeAccessMask, new ImageSubresourceRange(NativeImageAspect)); commandBuffer.PipelineBarrier(PipelineStageFlags.Transfer, 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); }
void RecordCommandBuffers() { var graphics_commandd_buffer_begin_info = new CommandBufferBeginInfo { sType = StructureType.CommandBufferBeginInfo, // VkStructureType sType pNext = IntPtr.Zero, // const void *pNext flags = CommandBufferUsageFlagBits.SimultaneousUseBit, // VkCommandBufferUsageFlagBits flags pInheritanceInfo = (CommandBufferInheritanceInfo *)0 // const VkCommandBufferInheritanceInfo *pInheritanceInfo }; var image_subresource_range = new ImageSubresourceRange { aspectMask = ImageAspectFlagBits.ColorBit, // VkImageAspectFlagBits aspectMask baseMipLevel = 0, // uint32_t baseMipLevel layerCount = 1, // uint32_t levelCount baseArrayLayer = 0, // uint32_t baseArrayLayer levelCount = 1 // uint32_t layerCount }; var clear_value = new ClearValue { color = new ClearColorValue(1.0f, 0.8f, 0.4f, 0.0f), // VkClearColorValue color }; ImageParameters[] swap_chain_images = GetSwapChain.Images; for (int i = 0; i < Vulkan.GraphicsCommandBuffers.Length; ++i) { vk.BeginCommandBuffer(Vulkan.GraphicsCommandBuffers[i], ref graphics_commandd_buffer_begin_info).CheckError(); if (GetPresentQueue.Handle != GetGraphicsQueue.Handle) { var barrier_from_present_to_draw = new ImageMemoryBarrier { sType = StructureType.ImageMemoryBarrier, // VkStructureType sType pNext = IntPtr.Zero, // const void *pNext sourceAccessMask = AccessFlagBits.MemoryReadBit, // VkAccessFlagBits srcAccessMask destinationAccessMask = AccessFlagBits.ColorAttachmentWriteBit, // VkAccessFlagBits dstAccessMask oldLayout = ImageLayout.Undefined, // VkImageLayout oldLayout newLayout = ImageLayout.PresentSourceKhr, // VkImageLayout newLayout sourceQueueFamilyIndex = GetPresentQueue.FamilyIndex, // uint32_t srcQueueFamilyIndex destinationQueueFamilyIndex = GetGraphicsQueue.FamilyIndex, // uint32_t dstQueueFamilyIndex image = swap_chain_images[i].Handle, // VkImage image subresourceRange = image_subresource_range // VkImageSubresourceRange subresourceRange }; vk.CmdPipelineBarrier( Vulkan.GraphicsCommandBuffers[i], PipelineStageFlagBits.ColorAttachmentOutputBit, PipelineStageFlagBits.ColorAttachmentOutputBit, (DependencyFlagBits)0, 0, (MemoryBarrier *)0, 0, (BufferMemoryBarrier *)0, 1, &barrier_from_present_to_draw); } var render_pass_begin_info = new RenderPassBeginInfo { sType = StructureType.RenderPassBeginInfo, // VkStructureType sType pNext = IntPtr.Zero, // const void *pNext renderPass = Vulkan.RenderPass, // VkRenderPass renderPass framebuffer = Vulkan.Framebuffers[i], // VkFramebuffer framebuffer renderArea = new Rect2D { // VkRect2D renderArea offset = new Offset2D { // VkOffset2D offset x = 0, // int32_t x y = 0 // int32_t y }, extent = new Extent2D { // VkExtent2D extent width = 300, // int32_t width height = 300, // int32_t height } }, clearValueCount = 1, // uint32_t clearValueCount pClearValues = &clear_value // const VkClearValue *pClearValues }; vk.CmdBeginRenderPass(Vulkan.GraphicsCommandBuffers[i], ref render_pass_begin_info, SubpassContents.Inline); vk.CmdBindPipeline(Vulkan.GraphicsCommandBuffers[i], PipelineBindPoint.Graphics, Vulkan.GraphicsPipeline); vk.CmdDraw(Vulkan.GraphicsCommandBuffers[i], 3, 1, 0, 0); vk.CmdEndRenderPass(Vulkan.GraphicsCommandBuffers[i]); if (GetGraphicsQueue.Handle != GetPresentQueue.Handle) { var barrier_from_draw_to_present = new ImageMemoryBarrier { sType = StructureType.ImageMemoryBarrier, // VkStructureType sType pNext = IntPtr.Zero, // const void *pNext sourceAccessMask = AccessFlagBits.ColorAttachmentWriteBit, // VkAccessFlagBits srcAccessMask destinationAccessMask = AccessFlagBits.MemoryReadBit, // VkAccessFlagBits dstAccessMask oldLayout = ImageLayout.PresentSourceKhr, // VkImageLayout oldLayout newLayout = ImageLayout.PresentSourceKhr, // VkImageLayout newLayout sourceQueueFamilyIndex = GetGraphicsQueue.FamilyIndex, // uint32_t srcQueueFamilyIndex destinationQueueFamilyIndex = GetPresentQueue.FamilyIndex, // uint32_t dstQueueFamilyIndex image = swap_chain_images[i].Handle, // VkImage image subresourceRange = image_subresource_range // VkImageSubresourceRange subresourceRange }; vk.CmdPipelineBarrier( Vulkan.GraphicsCommandBuffers[i], PipelineStageFlagBits.ColorAttachmentOutputBit, PipelineStageFlagBits.BottomOfPipeBit, (DependencyFlagBits)0, 0, (MemoryBarrier *)0, 0, (BufferMemoryBarrier *)0, 1, &barrier_from_draw_to_present); } vk.EndCommandBuffer(Vulkan.GraphicsCommandBuffers[i]).CheckError(); } }