Пример #1
0
        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);
        }
Пример #2
0
        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 });
        }
Пример #3
0
        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);
        }
Пример #4
0
        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();
        }
Пример #5
0
		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;
			}
		}
Пример #6
0
        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();
        }
Пример #9
0
        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();
            }
        }
Пример #10
0
		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);
		}
Пример #11
0
        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);
        }
Пример #12
0
        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 });
        }
Пример #13
0
        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);
        }
Пример #14
0
        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 });
            });
        }
Пример #17
0
        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);
            }
        }
Пример #18
0
        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);
        }
Пример #19
0
        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);
        }
Пример #20
0
        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, &copy);

            // 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);
        }
Пример #21
0
        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);
        }
Пример #22
0
 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));
         }
     }
 }
Пример #23
0
 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));
     }
 }
Пример #24
0
        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);
        }
Пример #25
0
        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();
            }
        }